To respond to the other issues raised:

On 2 March 2015 at 17:14, Tim Graham <timog...@gmail.com> wrote:

> I think it would be helpful to motivate this with some pseudocode of 
> specific use cases you are aiming to solve. Have you looked into whether 
> there are any related third-party projects related to your ideas from which 
> you could draw inspiration?
>

There isn't too much out there for Django, the few apps that are out there 
usually work around the url dispatcher, e.g. with additional middleware. 
I've mostly looked at other frameworks like flask and ruby-on-rails for 
features. My previous post has some (pseudo)code that covers most features 
I'm planning on implementing. 

On Monday, March 2, 2015 at 8:20:20 PM UTC+1, Marc Tamlyn wrote:
>
> A collection of thoughts:
>
> I think allowing the url dispatcher to inspect the database for the 
> existence of certain objects is potentially somewhat dangerous. However, 
> good support for a view raising a "continue resolving" exception along the 
> lines of https://github.com/jacobian-archive/django-multiurl might be 
> interesting.
>

How so? I guess the potential to do other things than just fetching the 
object can be dangerous. If overused it can certainly cause performance 
issues, so matching against an object should generally be the last step in 
the url resolver. 

I prefer to think of it as a view preprocessor: if the url matches, you 
convert the string arguments to the values that are actually used, with an 
option to continue resolving. Maybe the implementation should clearly 
separate these two steps. A "continue resolving" exception in the view, if 
carelessly used, opens up the possibility that a view is partly processed 
and then control is passed to another view. Not to mention the view 
middleware, which received the first view. It just feels to me like a 
"continue resolving" exception should be part of the resolving process, not 
of the view. 

I also don't want to separate it into too many steps, that's why I wanted 
to include this step in the url resolver. However, it might warrant its own 
step in the whole handling process. 

Related to this, a check for potentially conflicting url mappings could be 
> interesting.


I could definitely use some regex patterns to check for potentially 
conflicting regex patterns (maybe I should use jQuery as well) :P Kidding 
aside, regexes are hard to compare by nature. We could factor out static 
prefixes, and maybe check for common patterns. It would be easier with 
alternate matching schemes. E.g., flask uses a simple `<int:id>` to match 
an integer and capture it in the `id` parameter. Support to check for 
conflicts would be a lot simpler with those patterns. It would definitely 
be a best-effort feature. 

Middleware currently has complex and unintuitive behaviour in the event of 
> exceptions. You talk about the middleware/decorator split, but not how to 
> make either make sense.
>

I guess I'm not too familiar with real-world usage of middleware. Could you 
elaborate on this complex and unintuitive behaviour? Initially I simply 
thought of middleware and decorators as site-wide and per-view wrappers, 
but further investigation reminded me that there are more distinctions. The 
current middleware doesn't fully "fit in" with what I had in mind, 
especially the fact that request middleware is executed before the url is 
resolved, so this can't even be changed in the resolver. The middleware 
requires some more thought and discussion. 

Supporting generic sets of views has some logic, although in my experience 
> it is extremely rare that you can sensibly use a generic view with no 
> alterations at all - it almost always needs extra context or some other 
> tweaks. I'm not really convinced that a one liner to get CRUD for a 
> particular model will actually be that useful in the wild - you're likely 
> to end up changing too many things. I don't find the "one line in a urlconf 
> for each view" convention to be particularly problematic, however writing 
> all the regexes is potentially more prone to problems.
>

Yeah, the generic views should be more of a fallback. The fact that it is a 
one-liner for generic views is more of an added nicety, I should've put 
that differently. As I elaborated in my previous post. the real power is 
that you can reverse urls based on models or model instances, rather than 
having to specify the parameters in the exact way the url expects. One huge 
benefit (can't believe I only thought of this just now) is that, if you 
decide to change the url structure, e.g. to use the slug instead of the pk, 
you don't have to run though your entire codebase to change every instance 
where you reverse that url. That might be an even larger benefit than 
url-agnostic reversing for third-party apps. No more regex duplication? Not 
bad either. 
 

> If you are intending on introducing alternative URL resolvers, some 
> example ideas would be needed. The lack of a consistent way to reverse a 
> slug for example is a good idea to address, but we need to establish how.
>

If necessary, pure string-based comparison (e.g. for static prefixes) might 
give that little performance boost over regular expressions that can make 
it fast instead of average. Alternative, simpler syntax can also be 
provided (e.g. based on the `parse` library that Curtis mentioned). I don't 
really understand what you're getting at with slugs, though. Do you mean a 
lack of a consistent way to reverse the slugify process, or just reversing 
slug-based urls in general? 
 

> How are you intending to support different resolvers in the same project? 
> It seems to me that it is rather inefficient in large projects to loop 
> through all resolvers for all urls.
>

Even now, routing works with a recursive design. Different resolvers will 
provide the same API to their direct "parent" (namely `resolve` and 
`reverse`) so they are a drop-in replacement for any other resolvers. Only 
if the replacement resolver itself is inefficient, would it be a problem.
 

> Namespacing urls is currently over complex for the 90% use case, and the 
> docs are hard to understand as a result. Alternative designs in this area 
> could be interesting.
>

Definitely. One design that springs to mind is to remove the difference in 
namespaces and names: a namespace is simply a resolver with a name, that 
contains other named resolvers - instead of an app_name and possibly a 
namespace in `include`, you would just supply a `name` to the `url` that 
wraps `include`. 
 

> Overall there are lots of interesting starts of ideas here, but I feel one 
> or two dead ends. It's a potentially very varied project and the crux of 
> the proposal needs to focus on ensuring that some specific tasks are well 
> designed and achievable, with others being extensions later on.
>
> Marc
>

I think the initial redesign and the public API should definitely be part 
of the project. The decorator/middleware features, as well as passing the 
`request` object would require changes to the API if done later on, so 
those are good candidates as well imo - though specifics, such as the 
`SubdomainResolver` in my example above are an easy extension later on. The 
same goes for model routers and other alternative routers. 

On Tuesday, March 3, 2015 at 2:56:39 AM UTC+1, Curtis Maloney wrote:
>
> There was a "continue resolving" sort of exception proposed/implemented 
> that would obviate this, allowing the logic to remain in views [or view 
> decorators]... a much simpler solution, IMHO.
>

I believe I might have mentioned it before somewhere in this post or the 
last one, but that would mess with view middleware, and I don't 
 particularly like that resolving and view handling are mixed that way. 
Could just be me though. Either way, I think we all agree that a "continue 
resolving" option is a good addition, one way or another. 
 

> This has certainly been on the "wanted" list for many years now, however I 
> expect it would require the middleware re-design that so far has proven too 
> invasive to land.
>
> That said, providing the "new" middleware-as-wrapper interface around url 
> patterns lists could be a good stepping stone to eventually removing the 
> existing middleware API.
>

I guess I'm lucky that I haven't used middleware that much, except as a 
fire-and-forget setting. As I mentioned I'm more of a decorator kind of 
guy. It'd be interesting to hear about all the struggles, and maybe I can 
help. 
 

> Are you talking about pre-cooked url patterns for the various CBV?  Or 
> plugin routers for groups of CBV?  I'm certainly in favour of some tool 
> that makes it easier to express "common" regex matches [satisfying the 
> "protect from the tedium" rule of frameworks]
>

What I had in mind would go more towards a router than just some pre-cooked 
url patterns, including specific handling of resolving and reversing urls 
based on the model that the router connects to. I don't know yet just how 
far this should eventually go. If added as a later extension, that would 
certainly allow for plenty of time to think it through and refine it. I 
like this feature, though, so I'd definitely want to reach the next feature 
freeze deadline even if it was added after the initial patch. 

As mentioned elsewhere, I would very much like to see a resolver system 
> based on the "parse" library [essentially, the inverse of str.format - 
> https://pypi.python.org/pypi/parse], and to do so would indeed require 
> some formal analysis / documentation of the existing resolver architecture.
>  
> --
> Curtis
>

Interesting, definitely worth taking a look. A revamped framework would 
also allow for an easy extension later on that adds resolvers based on 
this, in case it isn't included initially. 

I'll be at the Django sprint in Amsterdam this Saturday, maybe some 
interesting ideas or insights will roll out. I'll be sure to revisit my 
proposal and this thread afterwards. 

Marten

On Wednesday, March 4, 2015 at 2:37:46 AM UTC+1, Marten Kenbeek wrote:
>
> First of all, thanks for the feedback. There are some good points here 
> that I hadn't thought about.
>
> Behaviour similar to a `ContinueResolving` exception is one of the things 
> I was aiming at. However, I can't see how to raise this in a view while 
> maintaining backwards compatibility with view middleware. E.g. the 
> CsrfViewMiddleware might have bailed out before the first view was 
> executed, while the second view might be csrf exempt. Executing the view 
> middleware twice might cause problems as well.
>
> As for alternate url resolvers: they'll provide the same functions 
> (`resolve` and `reverse`) that are required for any new-style resolvers, so 
> they can be freely mixed and replaced, for example:
>
> urlpatterns = patterns('',
>     SubdomainResolver('accounts.', include('some.url.config.urls'), 
> decorators=[login_required]),
>     url(r'^$', 'my.view.function'),
>     ModelRouter(r'^mymodel/', model=MyModel, field='some_field',
>         views = {
>             'detail': MyDetailView.as_view(),
>             'list':   MyListView.as_view(),
>             'edit':   MyUpdateView.as_view(),
>             'new':    MyCreateView.as_view(),
>             'delete': None,
>         }
>     ),
> )
>
> As for the model router: a real-world example can be as simple as this. 
> You can either specify a field and based on the field, `detail` and `edit` 
> will accept only numbers or strings or whatever, or you can specify your 
> own regex that is repeated for all single-object views. The magic is that 
> the model router will automatically reverse the url based on a model or 
> model instance if that model uses a model router, similar to how 
> `get_absolute_url` provides the same functionality for a single view per 
> model.
>
> However, looking at ruby-on-rails and django-rest-framework, routers are 
> tightly coupled with controllers/viewsets, which provide all the views for 
> a specific model. Django's own `ModelAdmin` combines the two, though it is 
> more of a router-and-controller-and-much-more in one. Controllers and 
> viewsets are both tightly coupled with the routers, so it might be 
> warranted that a possible viewset simply implements the `resolve` and 
> `reverse` methods for its contained views.
>
> The `decorators` parameter above also shows what I had in mind in that 
> regard. After looking for concrete examples, I can't seem to think of a 
> proper use case for the same behaviour for middleware, at least not with 
> Django's built-in middleware. For decorators, though, it's a great 
> addition, if there is a proper way to add, reorder or remove inherited 
> decorators (reorder mostly because of csrf_exempt).
>
> That's it for today.
>
> Marten
>
> On Tuesday, March 3, 2015 at 2:56:39 AM UTC+1, Curtis Maloney wrote:
>>
>>
>>
>> On 3 March 2015 at 03:57, Marten Kenbeek <marte...@gmail.com> wrote:
>>
>>> Hey all,
>>>
>>> I'm working on a proposal to extend the URL dispatcher. Here, I'd like 
>>> to provide a quick overview of the features I propose. 
>>>
>>> I'd like to:
>>> - Allow matching based on request attributes such as the subdomain or 
>>> protocol, and business logic such as the existence of a database object.
>>>
>>
>> There was a "continue resolving" sort of exception proposed/implemented 
>> that would obviate this, allowing the logic to remain in views [or view 
>> decorators]... a much simpler solution, IMHO.
>>  
>>
>>> - Make middleware configurable for a subset of views. It should be easy 
>>> to add, reorder or replace middleware at any level in the (currently 
>>> recursive) matching algorithm. 
>>>
>>
>> This has certainly been on the "wanted" list for many years now, however 
>> I expect it would require the middleware re-design that so far has proven 
>> too invasive to land.
>>
>> That said, providing the "new" middleware-as-wrapper interface around url 
>> patterns lists could be a good stepping stone to eventually removing the 
>> existing middleware API.
>>  
>>
>>> - Provide conventions for common patterns, such as an easy-to-configure 
>>> URL router for all generic Model views. For generic views, this should be a 
>>> one-liner. For custom views and other non-default options, this should 
>>> still be relatively easy to configure compared to writing out all patterns. 
>>>
>>
>> Are you talking about pre-cooked url patterns for the various CBV?  Or 
>> plugin routers for groups of CBV?  I'm certainly in favour of some tool 
>> that makes it easier to express "common" regex matches [satisfying the 
>> "protect from the tedium" rule of frameworks]
>>  
>>
>> In the process, I'd like to formalize some classes used in the 
>>> dispatcher. Currently, the RegexURLPattern and RegexURLResolver classes 
>>> provide most of the functionality of the URL dispatcher. By abstracting 
>>> these classes, and factoring out the loading mechanism and some other 
>>> internals, I hope to provide an extensible dispatching framework for 
>>> third-party apps.
>>>
>>
>> As mentioned elsewhere, I would very much like to see a resolver system 
>> based on the "parse" library [essentially, the inverse of str.format - 
>> https://pypi.python.org/pypi/parse], and to do so would indeed require 
>> some formal analysis / documentation of the existing resolver architecture.
>>  
>> --
>> Curtis
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/ad11fbf7-b15d-4b70-8100-2dbd8bc520d6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to