Ticket #2615: urlhelpers.py

File urlhelpers.py, 3.4 KB (added by norjee@…, 9 years ago)

url_for template tag. More as an example than to be fully useful (it has my own debug code in it)

Line 
1"""
2reversed urllookup tag
3
4Usage:
5---
6{% load urlhelpers %}
7{% url_for 'main.views.index' "request.method" request.path foo ok= "bar" method=request.method sub=9 %}
8---
9The first parameter is the view the url will point to.
10For the second and following parameters you can use named parameters like foo=bar.
11Parameters and named parameters will be evaluated. If it doesn't evaluate then the string is used.
12In the above example this means, assuming you use requestContext as your context, that
13"request.method" => request.method
14foo => foo
15"bar" => bar
16request.method => GET
17
18I'd be nice to have a middleware that prepopulated the named paramaters if they have already been given for a certain view
19
20If 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.
21"""
22
23from django.template import Library, Node, resolve_variable, TemplateSyntaxError
24from django.core.urlresolvers import reverse_match
25from django.db.models import get_model
26from lib.rclogging import logger
27import re
28
29register = Library()
30
31
32def find_url_for_view(view , *args , **kwargs):
33     # url = reverse(view, *args , **kwargs )
34     # logger.debug(args)
35     # logger.debug(kwargs)
36     
37     match = reverse_match(view,  args = args ,  kwargs = kwargs)
38     url = match.get_url()
39     logger.debug(match.get_unmatched_kwargs(kwargs))
40     logger.debug(match.get_default_args())
41     # logger.debug(re.split(r"[/.]" , url))
42     
43     # now i want to append a query string
44     # i want to use the unmatched kwargs for this
45     query_string = "&".join(["=".join([k, str(v)]) for k , v in match.get_unmatched_kwargs(kwargs).items()])
46     logger.debug(query_string)
47     if len(query_string) > 0:
48         query_string = "?" + query_string
49         
50     return url + query_string
51
52class ReversedUrlNode(Node):
53    def __init__(self , view , *args , **kwargs):
54        self.args = args
55        self.kwargs = kwargs
56        self.view = view
57       
58    def safe_resolve(self , var , context):
59        try:
60            outvar = resolve_variable(var , context)
61        except:
62            outvar = var
63        logger.debug("%s = %s" % (var ,outvar) )
64        return outvar
65   
66    def render(self , context):
67        args = [self.safe_resolve(v , context) for v in self.args]
68        kwargs = dict([(k, self.safe_resolve(v , context)) for k , v in self.kwargs.items()])
69        view = self.safe_resolve(self.view , context)
70        # try:
71        url = find_url_for_view(view , *args , **kwargs)
72        # except:
73        #    logger.warn("reversed lookup did a booboo")
74        #    url = "n/a"
75        # url = find_url_for_view(self.view , *args , **kwargs)
76        return url
77   
78@register.tag()
79def url_for(parser , token):
80    raw = re.sub(r'\s*=\s*' , "=" , token.contents)
81    # logger.debug(raw)
82    bits=raw.split()
83    if len(bits) < 2:
84        raise TemplateSyntaxError, "url_for need atleast one argument: url_for my.view"
85    args = []
86    kwargs = {}
87    view = bits[1]
88    for bit in bits[2:]:
89        pos_is = bit.find("=")
90        if pos_is == -1:
91            args.append(bit)
92        else:
93            kwargs[bit[:pos_is]] = bit[1+pos_is:]
94            # logger.debug("kwargs[%s] = %s" % (bit[:pos_is] , bit[1+pos_is:]))
95       
96    return ReversedUrlNode(view , *args , **kwargs)
Back to Top