1
- """
2
- Allows setting/changing/removing of chosen url query string parameters,
3
- while maintaining any existing others.
4
-
5
- Expects the current request to be available in the context as ``request``.
6
-
7
- Examples:
8
-
9
- {% set_url_param page=next_page %}
10
- {% set_url_param page="" %}
11
- {% set_url_param filter="books" page=1 %}
12
- """
13
-
14
- import urllib
15
- import tokenize
16
- import StringIO
17
- from django import template
18
- from django .utils .safestring import mark_safe
19
-
20
- register = template .Library ()
21
-
22
- class SetUrlParamNode (template .Node ):
23
- def __init__ (self , changes ):
24
- self .changes = changes
25
-
26
- def render (self , context ):
27
- request = context .get ('request' , None )
28
- if not request : return ""
29
-
30
- # Note that we want params to **not** be a ``QueryDict`` (thus we
31
- # don't use it's ``copy()`` method), as it would force all values
32
- # to be unicode, and ``urllib.urlencode`` can't handle that.
33
- params = dict (request .GET )
34
- for key , newvalue in self .changes .items ():
35
- newvalue = newvalue .resolve (context )
36
- if newvalue == '' or newvalue is None : params .pop (key , False )
37
- else : params [key ] = unicode (newvalue )
38
- # ``urlencode`` chokes on unicode input, so convert everything to
39
- # utf8. Note that if some query arguments passed to the site have
40
- # their non-ascii characters screwed up when passed though this,
41
- # it's most likely not our fault. Django (the ``QueryDict`` class
42
- # to be exact) uses your projects DEFAULT_CHARSET to decode incoming
43
- # query strings, whereas your browser might encode the url
44
- # differently. For example, typing "ä" in my German Firefox's (v2)
45
- # address bar results in "%E4" being passed to the server (in
46
- # iso-8859-1), but Django might expect utf-8, where ä would be
47
- # "%C3%A4"
48
- def mkstr (s ):
49
- if isinstance (s , list ): return map (mkstr , s )
50
- else : return (isinstance (s , unicode ) and [s .encode ('utf-8' )] or [s ])[0 ]
51
- params = dict ([(mkstr (k ), mkstr (v )) for k , v in params .items ()])
52
- # done, return (string is already safe)
53
- return '?' + urllib .urlencode (params , doseq = True )
54
-
55
- def do_seturlparam (parser , token ):
56
- bits = token .contents .split ()
57
- qschanges = {}
58
- for i in bits [1 :]:
59
- try :
60
- a , b = i .split ('=' , 1 ); a = a .strip (); b = b .strip ()
61
- keys = list (tokenize .generate_tokens (StringIO .StringIO (a ).readline ))
62
- if keys [0 ][0 ] == tokenize .NAME :
63
- if b == '""' : b = template .Variable ('""' ) # workaround bug #5270
64
- else : b = parser .compile_filter (b )
65
- qschanges [str (a )] = b
66
- else : raise ValueError
67
- except ValueError :
68
- raise template .TemplateSyntaxError , "Argument syntax wrong: should be key=value"
69
- return SetUrlParamNode (qschanges )
70
-
1
+ """
2
+ Allows setting/changing/removing of chosen url query string parameters,
3
+ while maintaining any existing others.
4
+
5
+ Expects the current request to be available in the context as ``request``.
6
+
7
+ Examples:
8
+
9
+ {% set_url_param page=next_page %}
10
+ {% set_url_param page="" %}
11
+ {% set_url_param filter="books" page=1 %}
12
+ """
13
+
14
+ import urllib
15
+ import tokenize
16
+ import StringIO
17
+ from django import template
18
+ from django .utils .safestring import mark_safe
19
+
20
+ register = template .Library ()
21
+
22
+ class SetUrlParamNode (template .Node ):
23
+ def __init__ (self , changes ):
24
+ self .changes = changes
25
+
26
+ def render (self , context ):
27
+ request = context .get ('request' , None )
28
+ if not request : return ""
29
+
30
+ # Note that we want params to **not** be a ``QueryDict`` (thus we
31
+ # don't use it's ``copy()`` method), as it would force all values
32
+ # to be unicode, and ``urllib.urlencode`` can't handle that.
33
+ params = dict (request .GET )
34
+ for key , newvalue in self .changes .items ():
35
+ newvalue = newvalue .resolve (context )
36
+ if newvalue == '' or newvalue is None : params .pop (key , False )
37
+ else : params [key ] = unicode (newvalue )
38
+ # ``urlencode`` chokes on unicode input, so convert everything to
39
+ # utf8. Note that if some query arguments passed to the site have
40
+ # their non-ascii characters screwed up when passed though this,
41
+ # it's most likely not our fault. Django (the ``QueryDict`` class
42
+ # to be exact) uses your projects DEFAULT_CHARSET to decode incoming
43
+ # query strings, whereas your browser might encode the url
44
+ # differently. For example, typing "ä" in my German Firefox's (v2)
45
+ # address bar results in "%E4" being passed to the server (in
46
+ # iso-8859-1), but Django might expect utf-8, where ä would be
47
+ # "%C3%A4"
48
+ def mkstr (s ):
49
+ if isinstance (s , list ): return map (mkstr , s )
50
+ else : return (isinstance (s , unicode ) and [s .encode ('utf-8' )] or [s ])[0 ]
51
+ params = dict ([(mkstr (k ), mkstr (v )) for k , v in params .items ()])
52
+ # done, return (string is already safe)
53
+ return '?' + urllib .urlencode (params , doseq = True )
54
+
55
+ def do_seturlparam (parser , token ):
56
+ bits = token .contents .split ()
57
+ qschanges = {}
58
+ for i in bits [1 :]:
59
+ try :
60
+ a , b = i .split ('=' , 1 ); a = a .strip (); b = b .strip ()
61
+ keys = list (tokenize .generate_tokens (StringIO .StringIO (a ).readline ))
62
+ if keys [0 ][0 ] == tokenize .NAME :
63
+ if b == '""' : b = template .Variable ('""' ) # workaround bug #5270
64
+ else : b = parser .compile_filter (b )
65
+ qschanges [str (a )] = b
66
+ else : raise ValueError
67
+ except ValueError :
68
+ raise template .TemplateSyntaxError , "Argument syntax wrong: should be key=value"
69
+ return SetUrlParamNode (qschanges )
70
+
71
71
register .tag ('set_url_param' , do_seturlparam )
0 commit comments