├── .gitignore ├── CHANGES.txt ├── LICENSE ├── MANIFEST.in ├── README.rst ├── django_example ├── __init__.py ├── settings.py ├── templates │ └── home.html ├── urls.py ├── views.py └── wsgi.py ├── manage.py ├── query_parameters ├── __init__.py ├── templatetags │ ├── __init__.py │ └── query_parameters.py └── tests.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.pot 3 | *.pyc 4 | local_settings.py 5 | venv 6 | MANIFEST 7 | dist 8 | -------------------------------------------------------------------------------- /CHANGES.txt: -------------------------------------------------------------------------------- 1 | v0.1.0, 2014-03-26 -- Initial release. 2 | v0.1.1, 2014-03-26 -- Improved documentation. 3 | v0.1.2, 2014-03-26 -- Clarified documentation. 4 | v0.1.3, 2014-03-26 -- Bug fix and unit tests 5 | v0.2.0, 2014-03-26 -- Added ability to load and store input/outputs with context variables 6 | v0.2.1, 2014-03-26 -- Robustified handling of keys with illegal variable names 7 | v0.2.2, 2015-07-21 -- Templatetags no longer attempt to replace key arguments with matching context variables 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 jskopek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include CHANGES.txt 3 | include README.rst 4 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | django-query-parameters 2 | ======================= 3 | 4 | Adds two template tags that simplify the manipulation of GET parameters on a querystring. Allows easy addition, manipulation, and deletion of parameters onto an existing querystring. 5 | 6 | The module is comprised of two template tags: ``set_query_parameters`` and ``del_query_parameters``. 7 | 8 | set_query_parameters 9 | -------------------- 10 | 11 | Takes a 1+ list of ``key=value`` pairs and generates an updated querystring that includes those pairs. If a key does not already exist in the querystring, it will be added. If a key exists, it will be updated with the new value. For example:: 12 | 13 | # current page is http://localhost/?page=1&limit=20 14 | {% load query_parameters %} 15 | ... 16 | # => ... 17 | 18 | del_query_parameters 19 | -------------------- 20 | 21 | Takes a 1+ list of keys and generates an updated querystring that removes those keys. If a key does not exist in the query string, it will be ignored. For example:: 22 | 23 | # current page is http://localhost/?page=1&limit=20 24 | {% load query_parameters %} 25 | ... 26 | # => ... 27 | 28 | 29 | 30 | Installing 31 | ========== 32 | 33 | Installing is a simple as running an ``easy_install`` or ``pip install`` command:: 34 | 35 | pip install django-query-parameters 36 | 37 | Include the project in the ``INSTALLED_APPS`` list in your project's ``settings.py`` file:: 38 | 39 | INSTALLED_APPS = (..., 'query_parameters', ...) 40 | 41 | 42 | 43 | Storing the output in the template context 44 | ========================================== 45 | 46 | By default, both template tags output the result directly. If an optional ``as`` key is specified, the results will be stored in a context variable instead. For example:: 47 | 48 | {% set_query_parameters page=2 as=next_page %} 49 | Next Page 50 | 51 | {% del_query_parameters color size as=reset_filters %} 52 | Reset Filters 53 | 54 | The ``as`` key may be modified in Django's ``settings.py`` file:: 55 | 56 | QUERY_PARAMETERS_VARIABLE_OUTPUT_KEY = 'output' 57 | 58 | ... 59 | 60 | {% set_query_parameters color=red output=next_page %} 61 | 62 | 63 | 64 | Using a user defined query string 65 | ================================= 66 | 67 | By default, both template tags pull the query string from the request context. If an optional ``with`` key is specified, the query string will be loaded from the context variable instead. For example:: 68 | 69 | {% set_query_parameters color=red as=filter %} 70 | {% set_query_parameters size=large with=filter as=modified_filter %} 71 | Apply Filter 72 | 73 | The ``with`` key may be modified in Django's ``settings.py`` file:: 74 | 75 | QUERY_PARAMETERS_VARIABLE_INPUT_KEY = 'input' 76 | 77 | ... 78 | 79 | {% set_query_parameters color=red input=custom_querystring %} 80 | -------------------------------------------------------------------------------- /django_example/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jskopek/django-query-parameters/4c86661c9630c18af7f56f6a79d523ace93f26ec/django_example/__init__.py -------------------------------------------------------------------------------- /django_example/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | BASE_DIR = os.path.dirname(os.path.dirname(__file__)) 3 | 4 | ## SECURITY WARNING: keep the secret key used in production secret! 5 | SECRET_KEY = '#2nxx4w+zut-=v6696%1d(9x^!$9dr_+jz%$me91q+dcke5pv!' 6 | 7 | ## SECURITY WARNING: don't run with debug turned on in production! 8 | DEBUG = True 9 | 10 | ## Application definition 11 | INSTALLED_APPS = ( 12 | 'django.contrib.auth', 13 | 'django.contrib.contenttypes', 14 | 'django.contrib.sessions', 15 | 'django.contrib.messages', 16 | 'django_example', 17 | 'query_parameters' 18 | ) 19 | 20 | ROOT_URLCONF = 'django_example.urls' 21 | TEMPLATES = [ 22 | { 23 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 24 | 'DIRS': [os.path.join(BASE_DIR, 'django_example', 'templates')], 25 | 'APP_DIRS': True, 26 | 'OPTIONS': { 27 | 'context_processors': [ 28 | 'django.template.context_processors.debug', 29 | 'django.template.context_processors.request', 30 | 'django.contrib.auth.context_processors.auth', 31 | 'django.contrib.messages.context_processors.messages', 32 | ] 33 | } 34 | }, 35 | ] 36 | -------------------------------------------------------------------------------- /django_example/templates/home.html: -------------------------------------------------------------------------------- 1 | {% load query_parameters %} 2 | 3 |

Testing Django-Query-Parameters

4 | 5 | {% with 'blah' as example_value %} 6 | Reload page with query4 querystring property 7 |

overriding query1,query2,query3 querystring values:

{% set_query_parameters query1=example_value query2='ᛖᚴ ᚷᛖᛏ ᛖᛏᛁ ᚧ ᚷᛚᛖᚱ ᛘᚾ ᚦᛖᛋᛋ ᚨᚧ ᚡᛖ ᚱᚧᚨ ᛋᚨᚱ' query3=no %}

8 |

deleting query1,query2 querystring values:

{% del_query_parameters query1 query2 %}

9 |

overriding query1 with simple value:

{% set_query_parameters query1=simple_variable %}

10 |

overriding query1 with dict value:

{% set_query_parameters query1=dict_variable.hello %}

11 |

setting query5 to query4 querystring value:

{% set_query_parameters query5=request.GET.query4 %}

12 | {% endwith %} 13 | -------------------------------------------------------------------------------- /django_example/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from .views import TestView 3 | 4 | urlpatterns = [ 5 | path('', TestView.as_view()), 6 | ] 7 | -------------------------------------------------------------------------------- /django_example/views.py: -------------------------------------------------------------------------------- 1 | from django.views.generic import TemplateView 2 | 3 | 4 | class TestView(TemplateView): 5 | template_name = 'home.html' 6 | 7 | def get_context_data(self, **kwargs): 8 | context = super().get_context_data(**kwargs) 9 | context['simple_variable'] = 'hello world' 10 | context['dict_variable'] = {'hello': 'world'} 11 | return context 12 | -------------------------------------------------------------------------------- /django_example/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for django_example project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_example.settings") 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | application = get_wsgi_application() 15 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == "__main__": 6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_example.settings") 7 | 8 | from django.core.management import execute_from_command_line 9 | 10 | execute_from_command_line(sys.argv) 11 | -------------------------------------------------------------------------------- /query_parameters/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jskopek/django-query-parameters/4c86661c9630c18af7f56f6a79d523ace93f26ec/query_parameters/__init__.py -------------------------------------------------------------------------------- /query_parameters/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jskopek/django-query-parameters/4c86661c9630c18af7f56f6a79d523ace93f26ec/query_parameters/templatetags/__init__.py -------------------------------------------------------------------------------- /query_parameters/templatetags/query_parameters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from django import template 4 | from django.http import QueryDict 5 | from django.conf import settings 6 | import re 7 | 8 | register = template.Library() 9 | 10 | # SETTING PARAMETERS 11 | @register.tag 12 | def set_query_parameters(parser, token): 13 | """ 14 | Takes a 1+ list of key=value pairs and generates an updated querystring that includes those pairs. If a key does not already exist 15 | in the querystring, it will be added. If a key exists, it will be updated with the new value 16 | 17 | e.g. querystring = http://localhost/?page=1&limit=20 18 | {% set_query_parameters page=2 order=desc %} => page=2&limit=20&order=desc 19 | """ 20 | 21 | params = token.split_contents()[1:] 22 | 23 | # check to see if a special variable output key has been passed (default to `as`); 24 | # if so, we will store the result in the context variable define by the value 25 | VARIABLE_OUTPUT_KEY = getattr(settings, 'QUERY_PARAMETERS_VARIABLE_OUTPUT_KEY', 'as') 26 | params, as_var = pluck_property(params, VARIABLE_OUTPUT_KEY) 27 | 28 | # check to see if a special variable input key has been passed (default to `with`); 29 | # if so, we will pull the query string from the context variable defined by the value 30 | VARIABLE_INPUT_KEY = getattr(settings, 'QUERY_PARAMETERS_VARIABLE_INPUT_KEY', 'with') 31 | params, with_var = pluck_property(params, VARIABLE_INPUT_KEY) 32 | 33 | try: 34 | key_value_dict = dict(key_value_pair.split('=') for key_value_pair in params) 35 | except ValueError: 36 | raise template.TemplateSyntaxError('%r tag requires arguments to be in `key=value` pairs' % token.contents.split()[0]) 37 | 38 | return QueryStringSetNode(key_value_dict, as_var, with_var) 39 | 40 | class QueryStringSetNode(template.Node): 41 | def __init__(self, parameter_dict, as_var, with_var): 42 | self.parameter_dict = parameter_dict 43 | self.as_var = as_var 44 | self.with_var = with_var 45 | 46 | def contextual_parameter_dict(self, context): 47 | """ 48 | Searches the context for any variables named after the provided parameters; if any found, 49 | replaces the parameter name with the corresponding variable value 50 | 51 | e.g. 52 | first_property = 'test' 53 | {first_property: 'value_1', 'key_2': first_property} => {'test': 'value_1', 'key_2': 'test'} 54 | """ 55 | 56 | value_parameter_dict = {} 57 | for key, value in self.parameter_dict.items(): 58 | value_parameter_dict[key] = get_value(value, context) 59 | return value_parameter_dict 60 | 61 | def render(self, context): 62 | # if we have been passed a querystring from the context, load it; otherwise, pull from the context 63 | if self.with_var: 64 | query_string = get_value(self.with_var, context) 65 | else: 66 | query_string = get_query_string(context) 67 | 68 | existing_query_dict = QueryDict(query_string.encode('utf8')).copy() 69 | 70 | for key, value in self.contextual_parameter_dict(context).items(): 71 | existing_query_dict[key] = value 72 | 73 | result = existing_query_dict.urlencode() 74 | 75 | # if we are storing result as a context property, do so and reutrn a blank string; otherwise, return the value 76 | if self.as_var: 77 | context[self.as_var] = result 78 | return '' 79 | else: 80 | return result 81 | 82 | # DELETING PARAMETERS 83 | @register.tag 84 | def del_query_parameters(parser, token): 85 | """ 86 | Takes a 1+ list of keys and generates an updated querystring that removes those keys. 87 | 88 | e.g. querystring = http://localhost/?page=1&limit=20 89 | {% del_query_parameters page order %} => limit=20 90 | """ 91 | 92 | params = token.split_contents()[1:] 93 | 94 | # check to see if a special variable output key has been passed (default to `as`); 95 | # if so, we will store the result in the context variable define by the value 96 | VARIABLE_OUTPUT_KEY = getattr(settings, 'QUERY_PARAMETERS_VARIABLE_OUTPUT_KEY', 'as') 97 | params, as_var = pluck_property(params, VARIABLE_OUTPUT_KEY) 98 | 99 | # check to see if a special variable input key has been passed (default to `with`); 100 | # if so, we will pull the query string from the context variable defined by the value 101 | VARIABLE_INPUT_KEY = getattr(settings, 'QUERY_PARAMETERS_VARIABLE_INPUT_KEY', 'with') 102 | params, with_var = pluck_property(params, VARIABLE_INPUT_KEY) 103 | 104 | return QueryStringDeleteNode(params, as_var, with_var) 105 | 106 | class QueryStringDeleteNode(template.Node): 107 | def __init__(self, parameter_delete_list, as_var, with_var): 108 | self.parameter_delete_list = parameter_delete_list 109 | self.as_var = as_var 110 | self.with_var = with_var 111 | 112 | def contextual_parameter_delete_list(self, context): 113 | """ 114 | Searches the context for any variables named after the provided parameters; if any found, 115 | replaces the parameter name with the corresponding variable value 116 | 117 | e.g. 118 | first_property = 'test' 119 | [first_property,'second_property'] => ['test','second_property'] 120 | """ 121 | parameters = map(lambda key: get_value(key, context), self.parameter_delete_list) 122 | return parameters 123 | 124 | def render(self, context): 125 | # if we have been passed a querystring from the context, load it; otherwise, pull from the context 126 | if self.with_var: 127 | query_string = get_value(self.with_var, context) 128 | else: 129 | query_string = get_query_string(context) 130 | 131 | existing_query_dict = QueryDict(query_string).copy() 132 | 133 | for parameter in self.contextual_parameter_delete_list(context): 134 | if existing_query_dict.get(parameter): 135 | del existing_query_dict[parameter] 136 | 137 | result = existing_query_dict.urlencode() 138 | 139 | if self.as_var: 140 | # if we are storing result as a context property, do so and reutrn a blank string 141 | context[self.as_var] = result 142 | return '' 143 | else: 144 | # ... otherwise return the value 145 | return result 146 | 147 | 148 | # HELPER METHDOS 149 | def get_query_string(context): 150 | """ 151 | Return the query string from the request context 152 | """ 153 | request = context.get('request', None) 154 | if request is None: 155 | return '' 156 | else: 157 | return request.GET.urlencode() 158 | 159 | def get_value(key, context): 160 | """ 161 | Return the value of variable `key` from the context if it exists; otherwise, returns the key name 162 | """ 163 | try: 164 | value = template.Variable(key) 165 | value = value.resolve(context) 166 | except template.VariableDoesNotExist: 167 | return key 168 | except template.TemplateSyntaxError: 169 | return key 170 | else: 171 | return value 172 | 173 | def pluck_property(params, property_key): 174 | """ 175 | Searches a list of params for a `property_key=value` match. If one is found, it stores the value and removes from the list of params 176 | Returns a tuple of (params, value). If no property_key is found, value is None. The returne params will be plucked of the match, if one is found 177 | """ 178 | for val in list(params): 179 | match = re.match('%s=(\w+)' % property_key, val) 180 | if match: 181 | params.pop(params.index(val)) 182 | return (params, match.group(1)) 183 | return (params, None) 184 | 185 | 186 | -------------------------------------------------------------------------------- /query_parameters/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | from django.core.urlresolvers import reverse 3 | from django.template import Template 4 | from django.template import Context 5 | from django.template import RequestContext 6 | from django.test.client import Client 7 | from django.http import HttpRequest 8 | from django.http import QueryDict 9 | 10 | class SetQueryParametersTestCase(TestCase): 11 | def test_empty_querystring(self): 12 | result = self.template_generator( 13 | query_string='', 14 | set_query_parameters_value='prop1=val1' 15 | ) 16 | self.assertEqual(result, 'prop1=val1') 17 | 18 | def test_add_nothing(self): 19 | result = self.template_generator( 20 | query_string='prop2=val2', 21 | set_query_parameters_value='' 22 | ) 23 | self.assertEqual(result, 'prop2=val2') 24 | 25 | def test_new_property(self): 26 | result = self.template_generator( 27 | query_string='prop2=val2', 28 | set_query_parameters_value='prop1=val1' 29 | ) 30 | self.assertEqual(result, 'prop1=val1&prop2=val2') 31 | 32 | def test_invalid_parameters(self): 33 | from django.template import TemplateSyntaxError 34 | self.assertRaises(TemplateSyntaxError, Template, '{% load query_parameters %}{% set_query_parameters prop1 %}') 35 | 36 | def test_multiple_new_properties(self): 37 | result = self.template_generator( 38 | query_string='prop3=val3', 39 | set_query_parameters_value='prop1=val1 prop2=val2' 40 | ) 41 | self.assertEqual(result, 'prop1=val1&prop2=val2&prop3=val3') 42 | 43 | def test_illegal_variable_name(self): 44 | result = self.template_generator( 45 | query_string='', 46 | set_query_parameters_value='_prop1=val1' 47 | ) 48 | self.assertEqual(result, '_prop1=val1') 49 | 50 | 51 | def test_update_property(self): 52 | result = self.template_generator( 53 | query_string='prop1=val2', 54 | set_query_parameters_value='prop1=val1' 55 | ) 56 | self.assertEqual(result, 'prop1=val1') 57 | 58 | def test_update_and_add_property(self): 59 | result = self.template_generator( 60 | query_string='prop1=val1&prop2=val2', 61 | set_query_parameters_value='prop1=val1_modified prop3=val3' 62 | ) 63 | self.assertEqual(result, 'prop1=val1_modified&prop2=val2&prop3=val3') 64 | 65 | def test_save_in_context(self): 66 | t = Template( 67 | '{% load query_parameters %}' 68 | '{% set_query_parameters prop1=val1 as=result %}' 69 | ) 70 | request = HttpRequest() 71 | request.GET = QueryDict('prop2=val2') 72 | 73 | c = RequestContext(request) 74 | result = t.render(c) 75 | self.assertEqual(result, '') 76 | self.assertEqual(c['result'], 'prop1=val1&prop2=val2') 77 | 78 | def test_load_from_context(self): 79 | t = Template( 80 | '{% load query_parameters %}' 81 | '{% set_query_parameters prop1=val1 with=existing_querystring %}' 82 | ) 83 | request = HttpRequest() 84 | request.GET = QueryDict('prop2=val2') 85 | 86 | c = RequestContext(request, {'existing_querystring':'prop3=val3'}) 87 | result = t.render(c) 88 | self.assertEqual(result, 'prop1=val1&prop3=val3') 89 | 90 | def test_context_chaining(self): 91 | t = Template( 92 | '{% load query_parameters %}' 93 | '{% set_query_parameters prop1=val1 as=result %}' 94 | '{% set_query_parameters prop3=val3 with=result as=modified_result %}' 95 | ) 96 | request = HttpRequest() 97 | request.GET = QueryDict('prop2=val2') 98 | 99 | c = RequestContext(request) 100 | result = t.render(c) 101 | self.assertEqual(result, '') 102 | self.assertEqual(c['result'], 'prop1=val1&prop2=val2') 103 | self.assertEqual(c['modified_result'], 'prop1=val1&prop2=val2&prop3=val3') 104 | 105 | def template_generator(self, query_string, set_query_parameters_value): 106 | """ 107 | Helper method to simplify generating a template with a mock `query_string` and `set_query_parameters_value` 108 | """ 109 | t = Template( 110 | '{% load query_parameters %}' 111 | '{% set_query_parameters ' + set_query_parameters_value + ' %}' 112 | ) 113 | request = HttpRequest() 114 | request.GET = QueryDict(query_string) 115 | 116 | c = RequestContext(request) 117 | result = t.render(c) 118 | return result 119 | 120 | 121 | 122 | class DelQueryParametersTestCase(TestCase): 123 | def test_empty_querystring(self): 124 | result = self.template_generator( 125 | query_string='', 126 | del_query_parameters_value='prop1' 127 | ) 128 | self.assertEqual(result, '') 129 | 130 | def test_delete_querystring(self): 131 | result = self.template_generator( 132 | query_string='prop1=value1', 133 | del_query_parameters_value='prop1' 134 | ) 135 | self.assertEqual(result, '') 136 | 137 | def test_delete_querystring_with_remainders(self): 138 | result = self.template_generator( 139 | query_string='prop1=value1&prop2=value2', 140 | del_query_parameters_value='prop1' 141 | ) 142 | self.assertEqual(result, 'prop2=value2') 143 | 144 | def test_delete_multiple_querystrings_with_remainders(self): 145 | result = self.template_generator( 146 | query_string='prop1=value1&prop2=value2&prop3=value3', 147 | del_query_parameters_value='prop1 prop2' 148 | ) 149 | self.assertEqual(result, 'prop3=value3') 150 | 151 | def test_delete_nothing(self): 152 | result = self.template_generator( 153 | query_string='prop1=value1', 154 | del_query_parameters_value='' 155 | ) 156 | self.assertEqual(result, 'prop1=value1') 157 | 158 | def test_delete_in_context(self): 159 | t = Template( 160 | '{% load query_parameters %}' 161 | '{% del_query_parameters prop2 as=a_result %}' 162 | ) 163 | request = HttpRequest() 164 | request.GET = QueryDict('prop1=val1&prop2=val2') 165 | 166 | c = RequestContext(request) 167 | result = t.render(c) 168 | self.assertEqual(result, '') 169 | self.assertEqual(c['a_result'], 'prop1=val1') 170 | 171 | def test_load_from_context(self): 172 | t = Template( 173 | '{% load query_parameters %}' 174 | '{% del_query_parameters prop1 with=existing_querystring %}' 175 | ) 176 | request = HttpRequest() 177 | request.GET = QueryDict('prop2=val2') 178 | 179 | c = RequestContext(request, {'existing_querystring':'prop3=val3&prop1=val1'}) 180 | result = t.render(c) 181 | self.assertEqual(result, 'prop3=val3') 182 | 183 | def template_generator(self, query_string, del_query_parameters_value): 184 | """ 185 | Helper method to simplify generating a template with a mock `query_string` and `del_query_parameters_value` 186 | """ 187 | t = Template( 188 | '{% load query_parameters %}' 189 | '{% del_query_parameters ' + del_query_parameters_value + ' %}' 190 | ) 191 | request = HttpRequest() 192 | request.GET = QueryDict(query_string) 193 | 194 | c = RequestContext(request) 195 | result = t.render(c) 196 | return result 197 | 198 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name='django-query-parameters', 5 | version='0.2.3', 6 | author='Jean-Marc Skopek', 7 | author_email='jean-marc@skopek.ca', 8 | packages=['query_parameters','query_parameters.templatetags'], 9 | scripts=[], 10 | url='https://github.com/jskopek/django-query-parameters', 11 | license='LICENSE', 12 | description='Django templatetags to simplify creating, updating, and removing query parameters from querystring', 13 | long_description=open('README.rst').read(), 14 | install_requires=['Django >= 1.4'] 15 | ) 16 | 17 | 18 | --------------------------------------------------------------------------------