Apologies in advance: This is a long email, and I may tend to ramble.
Try to bear with me, please.

In testing out a framework for creating Netvibes widgets (just to see
if I could), I had what I thought to be a great idea for resolving
URLs to methods on a Widget instance. Essentially, each view a widget
provides would be just a method on the object, which was declared
using a decorator to supply a regex. This exact method isn't the
purpose of this email, but it helps to have some history.

import widgets

class ExampleWidget(widgets.Widget):
    template = 'widgets/example.html'

    pref = widgets.TextPreference()

    @widgets.urlpattern('^(?P<number>\d+)/$')
    def test(request, number):
        # Do something interesting here and return a response

Then I'd like the urls.py entry to look like this:

(r'^widget/', ExampleWidget()),

and have /widget/13/ be routed to ExampleWidget().test(request, number=13).

Unfortunately, due to the way RegexURLResolver works, this could never
happen, since there's not a real, importable module that contains the
urlpatterns. Now, I could get around this by writing a custom object
with a specific key in sys.modules, then passing that key off to
RegexURLResolver, and it would probably work. I hope nobody wants me
to do that.

So, I considered alternatives and I came up with a fairly simple way
to go about it that could solve a few other issues that have been
raised in the past, and some that exist in a present/future alternate
dimension (the newforms-admin branch), but it's still a bit hackish,
and I wanted some input before I go too far with it.

Right now, in django.conf.urls.defaults, include() simply returns a
list containing a single item, the module name passed to it. This
seemed odd to me, until I noticed that patterns() checks to see if one
of the tuple items is a list, and if it is, pass it off to
RegexURLResolver. This in and of itself seemed quite hackish to me,
and thankfully my proposal addresses this as well.

Basically, I'd like to cut out the middle man -- the list -- and
simply have include() return a RegexURLResolver instance. patterns()
would then be able to use isinstance(t[1], RegexURLResolver) to make
its choice, which seems much cleaner to me. But the main advantage to
this is that patterns() would be able to accept anything that
subclasses RegexURLResolver, and process it accordingly.

The default RegexURLResolver would be used when include() is called,
but if my base Widget class subclassed RegexURLResolver, I could pass
an instance and all would work well.

I also did a bit of cursory research on the issue before writing this.
I've noticed requests for more flexible URL resolution, most notably
for dealing with subdomains. The technique I describe would allow a
snippet, say SubDomainURLResolver, to subclass RegexURLResolver and
lookup the destination view from urlpatterns in subdomain-specific
files.

Also, there was some recent talk about the desire to relegate a URL to
different views based on the HTTP method used. This approach could
simplify that process, and may also help with the REST API project,
though I admit I have no research on that to back me up.

And yes, I know there is a problem with those scenarios, I'll get back
to that in a minute.

The newforms-admin connection comes in when I remember back to some
discussion on what ended up being #4516. That ticket proposes a
separate method for handling URL resolution, but with this new
approach, ModelAdmin and AdminSite could become RegexURLResolver
subclasses, allowing a more flexible approach, while also getting rid
of that if/elif/else block, and simultaneously removing the need to
specify (.*)$ in the admin's urlpattern, bringing it more in line with
how the existing admin's urlpattern works. Those last two are more
cosmetic, but they seem, to me at least, to be benefits.

Now for the known problems.

Technically this is backwards-incompatible for one specific case. If
anyone out there is specifying their included urlconfs as a
single-item list, instead of using include(), their code would break.
I expect this is a low number, and should probably be discouraged
anyway, but it's a definite possibility. The only way around it would
be to keep the existing type check, and just add an elif to handle the
RegexURLResolver subclasses. I'm not a fan of doing this, but it's a
simple way to maintain backwards compatibility, so there you have it.

Currently, RegexURLResolver is instantiated with the supplied regex as
one of its arguments. Since this approach would have to allow
instantiating it without the regex, it would have to be applied after
the fact, during processing in patterns(). For my test code, I just
set the attribute manually (both there and in the base handler), but
there might be a better way to do it.

Two of my benefit scenarios would rely on the resolver having access
to more information than it currently gets. In order to relegate based
on subdomain or HTTP method, the resolve() method would need to
receive the HttpRequest object, not just the path. This should be a
fairly easy change, but probably isn't necessary for most uses. It'd
just be a nice-to-have to make this even more flexible.

I haven't yet considered how reverse lookups would work under this
approach. This is my first delve into URL resolution, so I'm still
fairly naive on exactly how that works. I definitely plan to do more
research on it and see if there are any shortcomings on that front.

I have some basic working code at the moment (it only takes about a
dozen lines total), but it's littered with debuggings and abandoned
code, so I just wanted to get some feedback before I clean it up and
open a ticket. Sorry for the length of this email, and I appreciate
any feedback.

-Gul

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To post to this group, send email to django-developers@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to