I've attached a new urlresolvers.py to this e-mail. It's intended to
replace the one in django/core, and it works with magic-removal only.
(To use it with trunk, just replace the import line at the top to
import Http404 from django.core.exceptions instead of django.http.)
I've also attached unit tests.
Given a view name (e.g. 'myproject.polls.views.poll_detail', as a
string) and any number of positional or keyword arguments, this code
generates the URL according to the first URL pattern in your URLconf
that matches.
The method is reverse() on both the RegexURLPattern and
RegexURLResolver classes.
Here's an example of how it works. Given this root URLconf:
urlpatterns = patterns('',
(r'^foo/$', 'path.to.foo_view'),
(r'^dates/(\d{4})/(\w{3})/$', 'path.to.month_view'),
(r'^people/(?P<state>\w\w)/(?P<name>\w+)/$', 'path.to.person_view'),
)
Here's how to use it:
>>> from django.conf import settings
>>> from django.core import urlresolvers
>>> resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF)
>>> resolver.reverse('path.to.foo_view')
'foo/'
>>> resolver.reverse('path.to.month_view', '2005', 'apr')
'dates/2005/apr/'
>>> resolver.reverse('path.to.person_view', state='il', name='adrian')
'people/il/adrian/'
>>> resolver.reverse('path.to.person_view', 'il', 'adrian')
'people/il/adrian/'
# In the following, 'invalidstate' fails the regex test (it isn't two
characters long).
>>> resolver.reverse('path.to.person_view', 'invalidstate', 'adrian')
Traceback (most recent call last):
...
NoReverseMatch
Ideally there'd be a template-tag interface to this. Something like:
{% link 'path.to.month_view' 2005 'apr' %}
{% link 'path.to.person_view' state='il' name='adrian' %}
It's implemented by analyzing the regular expression, which was quite
fun. This means it'll probably break for wacky regexes, but I think a
95% solution is fine.
Thoughts?
Adrian
--
Adrian Holovaty
holovaty.com | djangoproject.com
>Ideally there'd be a template-tag interface to this. Something like:
>
> {% link 'path.to.month_view' 2005 'apr' %}
> {% link 'path.to.person_view' state='il' name='adrian' %}
>
>
It's unbelievable :-). I was thinking about it just 15 minutes ago but
only with 'url' instead of 'link' :-). And without that much details...
Wow.
This is frickin' amazing, Adrian; it's exactly what I kept trying to
come up with and couldn't think all the way through.
/me has another "I wish I'd thought of that" moment... :)
Jacob
On Apr 6, 2006, at 3:24 PM, Adrian Holovaty wrote:
> Ideally there'd be a template-tag interface to this. Something like:
>
> {% link 'path.to.month_view' 2005 'apr' %}
> {% link 'path.to.person_view' state='il' name='adrian' %}
One thing we could do -- to make this even easier -- would be to grab
data from an object passed into the {% link %} tag. So in your
example urlconf::
(r'^people/(?P<state>\w\w)/(?P<name>\w+)/$', 'path.to.person_view'),
If a Person object had ``state`` and ``name`` attributes, you could do::
{% link path.to.person_view person %}
(where ``some_person`` is an object in the context) as a shortcut to::
{% link path.to.person_view state=person.state name=person.name %}
That way if you set up your URLconfs in a logical manner -- I'd bet
90% of my urlconfs already work this way -- the shortcut version
would Just Work™.
Jacob
Unfortunately the Generic Views don't fit this too well...
'object_id' is not 'id'.
--
--Max Battcher--
http://www.worldmaker.net/
All progress is based upon a universal innate desire on the part of
every organism to live beyond its income. --Samuel Butler
>>> from django.core.urlresolvers import link
>>> link('path.to.month_view', '2005', 'apr')
'dates/2005/apr/'
I think it's not difficult.
+1
--
I like python!
My Blog: http://www.donews.net/limodou
My Django Site: http://www.djangocn.org
NewEdit Maillist: http://groups.google.com/group/NewEdit
Yes, we'd expose a simpler API to this -- the example I gave in my
e-mail was low-level.
Adrian Holovaty wrote:
> On the plane from London to Chicago yesterday, I implemented something
> that's been discussed on this list lately -- "reverse" URL creation.
On conceptual level it looks similar to what I started to implement for
my site with a small insignificant difference --- your code actually
works and mine doesn't. :D
> Ideally there'd be a template-tag interface to this. Something like:
>
> {% link 'path.to.month_view' 2005 'apr' %}
> {% link 'path.to.person_view' state='il' name='adrian' %}
And this is the best part. It didn't occur to me to use template tags to
utilize the reverse lookup, and I didn't even plan for it. Wow! Thank
you for impressing me once again!
As soon as it matures let's create a repository for reusable Django apps.
Thanks,
Eugene
Wow, another amazing idea.
> Thanks,
>
> Eugene
This is actually how it all started. Many people in Django community
implemented really good applications (hugo, sune, limodou, ...) but in
order to reuse them we have to modify their code customizing them for
our web sites. For example on my web site there are private apps, which
reuse some of my blog components. The easiest way to reuse them was ...
to copy them to a different location with slight modifications, so they
will not clash with the existing instances and produce different URLs. I
don't think this is a proper solution.
While many problems can be solved with existing Django facilities + a
healthy dose of discipline and conventions (e.g., use externally
specified db_table, so a user can assign different tables for different
instances of a model), the reverse URL lookup required a support from
Django. It looks like we have it now. If we resolve the missing parts,
we can have reusable applications, which can be easily installed and
integrated in Django-powered web sites.
What is missing? The convention for database table names assignment is
missing of course. Anything else? i18n-related parameters? The way to
specify custom parameters? How to instantiate several instances of the
same app? How to package an app? Can we reuse Python Eggs for that? Can
Paste help us? I have more questions than answers, but now I can see the
light at the end of the tunnel.
Thanks,
Eugene
Hi,
Is there any reason this is not added to the repository?
--
Thanks!
Medhat
We did a feature-freeze for magic-removal for a while, but, now that
it's been merged, I can get back to work on this.