Hi all,

I'd like to discuss the API I'm proposing for the new url dispatcher I'm 
working on. I'll try to explain the API and some of the rationale behind it.

There is a working proof-of-concept 
at https://github.com/knbk/django/tree/url_dispatcher. Currently, all the 
names are chosen as not to conflict with the old implementation. A short 
description can be found 
at https://gist.github.com/knbk/96999abaab4ad4e5f8f9, which also contains a 
link to an example url configuration. 

My main goal was to create a simple, extensible API. In the old API, about 
90% of the work was done in the `resolve()`, `_reverse_with_prefix()` and 
`populate()` of the RegexURLResolver. This made for a tightly coupled 
design that was almost impossible to extend.

My starting point was the RegexURLResolver and RegexURLPattern. Both have a 
regex constraint that can match the current path and extract arguments. The 
former can then pass the remainder of the path to its list of resolvers and 
patterns; the latter can return a ResolverMatch containing the callback 
specified by that pattern. I've kept this distinction, with the `Resolver` 
and `View` classes. The change of name from `Pattern`  to `View` is because 
the `View` object has a bit more logic that determines how the view is 
called. It is a thin, callable wrapper that can optionally decorate the 
actual view function with a set of decorators passed down from parent 
resolvers, and when overwritten, can do some more processing before or 
after the view function is called. 

The hard-coded dependence on a regex pattern has been abstracted to a 
Constraint object. Each Resolver and View has a (set of) Constraint 
object(s), that can match the current url and extract arguments. A 
RegexPattern that simply mimics the old behaviour will be available, but 
other implementations, such as a Constraint that matches the request's host 
or method, are easily provided. A Constraint can also reverse a set of 
arguments to a partial url. That means that the full set of constraints 
used to match an url to a view, together with a suitable set of arguments, 
can be reversed to the url itself.

The main strength of a Constraint is that it can contain very specific 
logic about its arguments. For example, a Constraint may know that it 
resolves to a Model's primary key. If it then receives a Model instance of 
that particular type, it will know how to reverse that model instance to a 
valid string-based partial url, so that it can later be resolved to match 
the same object. It could also e.g. infer the regex pattern from the 
field's type. 

There's one final piece to the puzzle: the URL object. This is the state of 
the url in the process of resolving or reversing an url. It's a two-way 
street: when resolving, it starts out as a full path, and the Constraints 
chip away at the path, while the set of constraints and extracted argument 
grows. When reversing, it starts out as a set of constraints and arguments, 
and reconstructs the partial urls from those constraints and arguments 
until a full url path is reconstructed. It shifts some of the logic from 
the Resolver to the URL, so that it is easier to extend the Resolver. It is 
also a simple container that allows any Constraint access to the full 
request. Last but not least, it allows to dynamically build an url against 
the current request. This is useful if e.g. a constraint matches a 
different subdomain than the current request, so that a link automatically 
points to the right domain. 

I'm looking forwards to your feedback.

Thanks,
Marten

-- 
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/3cb36c11-16ee-4702-92a3-f9afb177bbca%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to