Apparently in the current trunk reversed urllookup is kind of(!!)
working.
After toying with it a little bit I found one issue:
The main method, reverse, only returns the resulting matched url. Not
the rule (the regex and extra arguments) it matched. There is no
reliable way of knowing which kwargs got matched and which ones have
been ignored. I needed to know to pass the unmatched arguments as
querystring. Moreover it would be nice to know what arguments have been
passed to the rule. For example adding the parameter https:True would
then allow me to build the urls as https.
But never mind, it already s quite usefull as it is. I made a template
helper tag, to use it in your templates.
"""
reversed urllookup tag
Usage:
---
{% load urlhelpers %}
{% url_for 'main.views.index' "request.method" request.path foo ok=
"bar" method=request.method sub=9 %}
---
The first parameter is the view the url will point to.
For the second and following parameters you can use named parameters
like foo=bar.
Parameters and named parameters will be evaluated. If it doesn't
evaluate then the string is used.
In the above example this means, assuming you use requestContext as
your context, that
"request.method" => request.method
foo => foo
"bar" => bar
request.method => GET
I'd be nice to have a middleware that prepopulated the named paramaters
if they have already been given for a certain view
If you copy/paste this code, be sure to remove references to logging,
rclogging (request cycly logging if you wondered) is my homebrewn
interface to python logging.
"""
from django.template import Library, Node, resolve_variable,
TemplateSyntaxError
from django.core.urlresolvers import reverse
from django.db.models import get_model
from lib.rclogging import logger
import re
register = Library()
def find_url_for_view(view , *args , **kwargs):
# url = reverse(view, *args , **kwargs )
# logger.debug(args)
# logger.debug(kwargs)
from django.conf import settings
urlconf = settings.ROOT_URLCONF
url = reverse(view, args = args , kwargs = kwargs)
# logger.debug(re.split(r"[/.]" , url))
# now i want to append a query string
# i want to use the unmatched kwargs for this
# ideally reverse would also return the matched regexp, sadly it
doesn't
# i'll naively see what values have been matched
query_string = "&".join(["=".join([k, str(v)]) for k , v in
kwargs.items() if not str(v) in re.split(r"[/.]" , url)])
logger.debug(query_string)
if len(query_string) > 0:
query_string = "?" + query_string
return url + query_string
class ReversedUrlNode(Node):
def __init__(self , view , *args , **kwargs):
self.args = args
self.kwargs = kwargs
self.view = view
def safe_resolve(self , var , context):
try:
outvar = resolve_variable(var , context)
except:
outvar = var
logger.debug("%s = %s" % (var ,outvar) )
return outvar
def render(self , context):
args = [self.safe_resolve(v , context) for v in self.args]
kwargs = dict([(k, self.safe_resolve(v , context)) for k , v in
self.kwargs.items()])
view = self.safe_resolve(self.view , context)
try:
url = find_url_for_view(view , *args , **kwargs)
except:
logger.warn("reversed lookup did a booboo")
url = "n/a"
# url = find_url_for_view(self.view , *args , **kwargs)
return url
@register.tag()
def url_for(parser , token):
raw = re.sub(r'\s*=\s*' , "=" , token.contents)
# logger.debug(raw)
bits=raw.split()
if len(bits) < 2:
raise TemplateSyntaxError, "url_for need atleast one argument:
url_for my.view"
args = []
kwargs = {}
view = bits[1]
for bit in bits[2:]:
pos_is = bit.find("=")
if pos_is == -1:
args.append(bit)
else:
kwargs[bit[:pos_is]] = bit[1+pos_is:]
# logger.debug("kwargs[%s] = %s" % (bit[:pos_is] ,
bit[1+pos_is:]))
return ReversedUrlNode(view , *args , **kwargs)
A few gotcha's: As I didn't feel like rewriting the lookup
procedure (I guess it is still alpha at best anyways) I use an
extremely naïve way of determining whether an keyword argument
matched. I then build a querystring with the remaining armuments.
Needless to say, this might slipup..
The second: if the view you want to create the url for a view that does
does not already exists reversed urllookup will not work. (wile
unreversed throws a cuyu error page)
The third: I didn't want to throw errors, so if reverse lookup goes
wrong, "n/a" will be the url. I guess you'll want to change that
behaviour.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django users" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-users
-~----------~----~----~----~------~----~------~--~---