Django

Code

Ticket #3530 (new)

Opened 2 years ago

Last modified 8 months ago

django.db.models.permalink should use request.urlconf if defined

Reported by: Herbert Poul <herbert.poul@gmail.com> Assigned to: neoj
Milestone: Component: Core framework
Version: SVN Keywords: urlconf permalink ROOT_URLCONF reverse
Cc: herbert.poul@gmail.com, joesaccount@gmail.com Triage Stage: Accepted
Has patch: 1 Needs documentation: 0
Needs tests: 1 Patch needs improvement: 1

Description

#3187 made it possible to use a middleware to overwrite settings.ROOT_URLCONF by setting request.urlconf

permalink currently only uses settings.ROOT_URLCONF which obviously leads to problems.. with e.g. syndication-feed framework or sitemaps so imho permalink should also use request.urlconf if defined.

Attachments

permalink_with_additional_function_arg.diff (1.3 kB) - added by Herbert Poul <herbert.poul@gmail.com> on 02/24/07 03:04:27.
simple patch to allow passing an additional function arg which returns the request object, or directly an urlconf list
permalink_with_additional_function_arg_fixed.diff (1.3 kB) - added by Herbert Poul <herbert.poul@gmail.com> on 04/05/07 14:00:25.
discovered a small bug in the patch
urlresolvers_reverse_urlconf_func.diff (1.0 kB) - added by neoj on 12/02/07 14:00:26.
allows the user to specify a function in settings.py that returns the urlconf to be used in reverse.

Change History

02/21/07 15:14:32 changed by SmileyChris

  • needs_better_patch changed.
  • stage changed from Unreviewed to Accepted.
  • needs_tests changed.
  • needs_docs changed.

Looks valid to me.

02/24/07 03:04:27 changed by Herbert Poul <herbert.poul@gmail.com>

  • attachment permalink_with_additional_function_arg.diff added.

simple patch to allow passing an additional function arg which returns the request object, or directly an urlconf list

02/24/07 03:11:09 changed by Herbert Poul <herbert.poul@gmail.com>

i've attached a simple patch which can receive an additional function parameter which is ment to be used with a thread local middleware like: http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser - all that is needed is a function that returns the current request object.. seems to work fine for me

04/05/07 14:00:25 changed by Herbert Poul <herbert.poul@gmail.com>

  • attachment permalink_with_additional_function_arg_fixed.diff added.

discovered a small bug in the patch

04/05/07 14:02:03 changed by Herbert Poul <herbert.poul@gmail.com>

  • has_patch set to 1.

i found a small problem in my old patch - it is fixed in permalink_with_additional_function_arg_fixed.diff

anyway . .is there any chance this patch gets into django one day ? .. if not i would simply include it in my own codebase instead of patching django.. would be nice to know your opinion ..

04/05/07 18:40:39 changed by Simon G. <dev@simon.net.nz>

  • stage changed from Accepted to Ready for checkin.

07/31/07 16:16:58 changed by anonymous

Is there a reason this is still waiting to be checked in?

08/20/07 05:05:24 changed by mtredinnick

  • stage changed from Ready for checkin to Accepted.

There's a bit more needed before this is ready to go in.

Firstly, it would no longer work as a decorator after this change. It looks like the new signature for permalink will have to be

def permalink(func=None, get_urlconf_func=None):

so that you can call it as

@permalink(get_urlconf_func = blah)
def get_absolute_url(self):
   # ...

In other words, both these forms have to work

get_absolute_url = permalink(get_absolute_url, blah)
get_absolute_url = permalink(get_urlconf_func = blah)(get_absolute_url)

We'll have to use a named parameter in the second case (and the decorator-with-argument case) because we can't type check the args to see which form is being used: both arguments are callables.

Secondly, let's just have get_urlconf_func return the urlconf directly. The user's function can worry about whether that means returning request.urlconf or something else (I'm trying to avoid tying it tightly to any assumptions about usage).

No need to type-check the result (by the way, using isinstance() is preferred to type() checks), since anything that acts appropriately is fine and we shouldn't restrict that unnecessarily.

So, the inner function now looks like this:

   def inner(*args, **kwargs):
      if get_urlconf_func:
           urlconf = get_urlconf_func()
      else:
           urlconf = None
      bits = func(*args, **kwargs)
      return reverse(bits[0], urlconf, *bits[1:3])

Half the length and with less assumptions. That still needs to be wrapped in the necessary code to make it work as a decorator, though.

Finally, some documentation needs to be added in the appropriate place in model_api.txt.

08/20/07 10:21:14 changed by ubernostrum

FWIW I'd be -1 on adding a new required argument to permalink. That's a decorator that needs to stay as simple as possible for the common case. (adding the get_urlconf_func bit as an optional argument for advanced use would be OK, though).

08/20/07 10:40:30 changed by Herbert Poul <herbert.poul@gmail.com>

the get_urlconf_func argument was meant to be optional anyway .. although i haven't tested it with the "@decorator" syntax - that's probably what isn't working.. (sorry, i don't have much experience with decorators yet.. or python in general actually)

but i think the code part

urlconf = get_urlconf_func() 
if type(urlconf) != list: 
    # If type is no list, we assume it is a request object and 
    # look for a 'urlconf' attribute 
    urlconf = getattr(urlconf, 'urlconf', None) 

isn't that bad imho (except.. the usage of type(..)) - because it allows to use the request object instead of directly the urlconf variable .. and the logic that there can be a 'urlconf' attribute in the request object is already within django (BaseHandler?) .. so it makes no additional assumptions

but anyway .. i have no problem if it directly requires the urlconf dictionary ..

08/21/07 01:01:39 changed by mtredinnick

@ubernostrum: the extra function arg is optional in both Herbet's and my version. It's fully backwards compatible.

@Herbet: I'd leave it out. It an extra assupmtion in the permalink() function we have to remember and maintain and it's not needed (i.e. it doesn't really make any external code significantly more complex if we leave it out). The reduced version says 'give me what I need', your original interface was 'give me what I need or something that is kind of like what I need and I'll rummage around inside and pull out what I need'. We don't need the second option.

It's the difference between get_urlconf_function being

lambda : get_current_user()   # with your API

versus

lambda : get_current_user().urlconf   # with my API
# or lambda : getattr(get_current_urse(), 'urlconf', None) to be really robust

and it saves at least two lines of code in permalink().

My preference is to keep the core code as simple as possible and if we're adding a new interface, as here, add the smallest interface necessary. I realise neither way is a disaster, but neatness counts.

09/16/07 16:42:00 changed by ubernostrum

#5034 was duped for this; both patches should roll together into a single solution which fixes reverse somehow.

09/24/07 18:33:50 changed by gwilson

  • needs_better_patch set to 1.
  • needs_tests set to 1.

12/02/07 14:00:26 changed by neoj

  • attachment urlresolvers_reverse_urlconf_func.diff added.

allows the user to specify a function in settings.py that returns the urlconf to be used in reverse.

12/02/07 14:13:56 changed by neoj

  • keywords changed from urlconf permalink ROOT_URLCONF to urlconf permalink ROOT_URLCONF reverse.
  • owner changed from nobody to neoj.

My patch allows the programmer to specify a function in settings.py that will return the urlconf to be used by reverse.

Example: A middleware would save request.urlconf in thread locals. A function would return that value from thread locals. That function would be specified in settings.py like this:

DYNAMIC_URLCONF_FUNCTION = 'djangosite.middleware.url_locale.dynamic_urlconf'

02/21/08 15:11:44 changed by SmileyChris

See also: #5034

10/31/08 19:01:57 changed by jos3ph

  • cc changed from herbert.poul@gmail.com to herbert.poul@gmail.com, joesaccount@gmail.com.

Add/Change #3530 (django.db.models.permalink should use request.urlconf if defined)




Change Properties
Action