Inital commit
[patchwork] / apps / patchwork / templatetags / listurl.py
1 # Patchwork - automated patch tracking system
2 # Copyright (C) 2008 Jeremy Kerr <jk@ozlabs.org>
3 #
4 # This file is part of the Patchwork package.
5 #
6 # Patchwork is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # Patchwork is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with Patchwork; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20 from django import template
21 from django.utils.html import escape
22 from django.utils.safestring import mark_safe
23 from django.utils.encoding import smart_str
24 from patchwork.filters import filterclasses
25 from django.conf import settings
26 from django.core.urlresolvers import reverse, NoReverseMatch
27 import re
28
29 register = template.Library()
30
31 # params to preserve across views
32 list_params = [ c.param for c in filterclasses ] + ['order', 'page']
33
34 class ListURLNode(template.defaulttags.URLNode):
35     def __init__(self, kwargs):
36         super(ListURLNode, self).__init__(None, [], {})
37         self.params = {}
38         for (k, v) in kwargs.iteritems():
39             if k in list_params:
40                 self.params[k] = v
41
42     def render(self, context):
43         view_name = template.Variable('list_view.view').resolve(context)
44         kwargs = template.Variable('list_view.view_params') \
45                       .resolve(context)
46
47         str = None
48         try:
49             str = reverse(view_name, args=[], kwargs=kwargs)
50         except NoReverseMatch:
51             try:
52                 project_name = settings.SETTINGS_MODULE.split('.')[0]
53                 str = reverse(project_name + '.' + view_name,
54                                args=[], kwargs=kwargs)
55             except NoReverseMatch:
56                 raise
57         
58         if str is None:
59             return ''
60
61         params = []
62         try:
63             qs_var = template.Variable('list_view.params')
64             params = dict(qs_var.resolve(context))
65         except Exception:
66             pass
67
68         for (k, v) in self.params.iteritems():
69             params[smart_str(k,'ascii')] = v.resolve(context)
70
71         if not params:
72             return str
73
74         return str + '?' + '&'.join(['%s=%s' % (k, escape(v)) \
75                         for (k, v) in params.iteritems()])
76
77 @register.tag
78 def listurl(parser, token):
79     bits = token.contents.split(' ', 1)
80     if len(bits) < 1:
81         raise TemplateSyntaxError("'%s' takes at least one argument"
82                                   " (path to a view)" % bits[0])
83     kwargs = {}
84     if len(bits) > 1:
85         for arg in bits[1].split(','):
86             if '=' in arg:
87                 k, v = arg.split('=', 1)
88                 k = k.strip()
89                 kwargs[k] = parser.compile_filter(v)
90             else:
91                 raise TemplateSyntaxError("'%s' requires name=value params" \
92                                           % bits[0])
93     return ListURLNode(kwargs)
94
95 class ListFieldsNode(template.Node):
96     def __init__(self, params):
97         self.params = params
98
99     def render(self, context):
100         self.view_name = template.Variable('list_view.view').resolve(context)
101         try:
102             qs_var = template.Variable('list_view.params')
103             params = dict(qs_var.resolve(context))
104         except Exception:
105             pass
106
107         params.update(self.params)
108
109         if not params:
110             return ''
111
112         str = ''
113         for (k, v) in params.iteritems():
114             str += '<input type="hidden" name="%s" value="%s"\>' % \
115                    (k, escape(v))
116
117         return mark_safe(str)
118
119 @register.tag
120 def listfields(parser, token):
121     bits = token.contents.split(' ', 1)
122     if len(bits) < 1:
123         raise TemplateSyntaxError("'%s' takes at least one argument"
124                                   " (path to a view)" % bits[0])
125     params = {}
126     if len(bits) > 2:
127         for arg in bits[2].split(','):
128             if '=' in arg:
129                 k, v = arg.split('=', 1)
130                 k = k.strip()
131                 params[k] = parser.compile_filter(v)
132             else:
133                 raise TemplateSyntaxError("'%s' requires name=value params" \
134                                           % bits[0])
135     return ListFieldsNode(bits[1], params)
136