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 -~----------~----~----~----~------~----~------~--~---