Package: django-querystring-tag
django-querystring-tagThis tiny package adds the{% querystring %}tag: A powerful, well tested template tag for modifying and rendering safe, suitably-encoded querystring values.It's the clean and simple way to create pagination links, filters and other state-preserving links, without cluttering up your view code!InstallationInstall the package from pypi:With Poetry$poetryadddjango-querystring-tagWith pip$pipinstalldjango-querystring-tagAdd"querystring_tag"to theINSTALLED_APPSlist in your Django project settings.Add querystring_tag to builtins (optional)To use the{% querystring %}tag freely, without having to add{% load querystring_tag %}to all of your templates, you can add"querystring_tag.templatetags.querystring_tag"to the['OPTIONS']['builtins']list for your chosen template backend.Here's an example.How to useFirst, load the tag into the template you want to use it in:{% load querystring_tag %}You can then use the tag like this:{% querystring param_one='value' param_two+='add-to-existing' param_three-="remove-from-existing" %}The basicsThe tag usesrequest.GETas the data source by default. Check out thesource_dataoption if you have other ideas.The examples below are deliberately simple: You can make as many modifications in the same tag as you need. GO CRAZY!You may be wondering "I want to use this in an include template, where the parameter name is dynamic. Will that work?".Yes it will!I know it's unusual, but you canuse tempalate variables for parameter namestoo.You don't want to preserve Google tracking parameters in links, do you? I thought not. Any parameters starting withutm_are removed by default. Addremove_utm=Falseif you would rather keep them.You're probably not interested in preserving blank parameters in links either, are you? See? I read your mind! Blank values are removed by default too. Addremove_blank=Falseif you would rather keep them.Want to variabalize the return value instead of rendering it? Go ahead any try the 'as' option. It works just as you would expect.Use=to set or replace a parameterThe most common requirement is to completely replace the value for a specific parameter. This is done using a regular keyword argument, with an=operator between the parameter name and value. For example, if your querystring looked like this:?q=test&baz=1Any you wanted to add afoovariable with the valuebar{% querystring foo="bar" %}Which would result in the following output:?q=test&baz=1&foo=barUse-=to remove values from a multi-value parameterWhen working with multi-value parameters, you may find yourself having toremovea specific value, without affecting any of the others.In these situations, you can use the-=operator instead of the usual=. For example, if the current querystring looked something like this:?q=test&bar=1&bar=2&bar=3And you wanted to remove&bar=2, your querystring tag might look like this:{% querystring bar-=2 %}Which would result in the following output:?q=test&bar=1&bar=3If the specified value isn't present, the instruction will simply be ignored.Use+=to add values to a multi-value parameterWhen working with multi-value parameters, you may find yourself having toadda specific value for a parameter, without affecting any of the others.In these situations, you can use the+=operator instead of the usual=. For example, if the current querystring looked something like this:?q=test&bar=1&bar=2&bar=3And you wanted to add&bar=4, your querystring tag might look like this:{% querystring bar+=4 %}Which would result in the following output:?q=test&bar=1&bar=2&bar=3&bar=4If the specified value is already present, the instruction will simply be ignored.Useonlyto specify parameters you want to keepUseonlyat the start of your{% querystring %}tag when you want the querystring to include values for specific parameters only.For example, say the current querystring looked like this:?q=keywords&group=articles&category=2&published_after=2022-01-01And you only wanted to include theqandgroupparams in a link. You could do:{% querystring only 'q' 'group' %}Which would result in the following output:?q=keywords&group=articlesYou can combineonlywith any number of modifications too. Just be sure to keep theonlykeyword and related parameter names as the left-most parameters, like so:{% querystring only 'q' group="group_value" clear_session="true" %}Usediscardto specify parameters you want to loseUsediscardat the start of your{% querystring %}tag when you want to exclude specific parameters from the querystring.For example, say the current querystring looked like this:?q=keywords&group=articles&category=2&published_after=2022-01-01And you wanted to preserve everything except forgrouppublished_after. You could do:{% querystring discard 'group' 'published_after' %}Which would result in the following output:?q=keywords&group=articlesYou can combinediscardwith any number of modifications too. Just be sure to keep thediscardkeyword and related parameter names as the left-most parameters, like so:{% querystring discard 'published_after' group="group_value" clear_session="true" %}Using template variables for parameter namesUnlike a lot of custom template tags,{% querystring %}supports the use of template variables in keys as well as values. For example, if the tag was being used to generate pagination links, andpage_param_nameandpage_numwere variables available in the template, you could use them both like so:{% querystring page_param_name=page_num %}Supported value typesValues can be strings, booleans, integers, dates, datetimes, Django model instances, or iterables of either of these values.When encountering a Django model instance,{% querystring %}will automatically take thepkvalue from it, and use that to modify the querystring. To use a different field value, you can use the tag'smodel_value_fieldoption (see further down for details). Alternatively, you can add aquerystring_value_fieldattribute to your model class. For example:classCategory(models.Model):name=models.CharField(max_length=50)slug=models.SlugField(max_length=50,unique=True)# use 'slug' values in querystringsquerystring_value_field="slug"Specifying multiple valuesAs mentioned above, you can provide an iterable as a value to specify multiple values for a parameter at once. That could be a native Python type, such as alist,tupleorset, but could also be anything that implements the__iter__method to support iteration, for example, aQuerySet.For example, if the context contained a variabletag_list, which was list of strings (['tag1', 'tag2', 'tag3']), you can include all
of those values by referencing the list value. For example:{% querystring tags=tag_list %}The output of the above would be:"?tags=tag1&amp;tags=tag2&amp;tags=tag3"Options referencesource_dataSupported value types:QueryDict,dict,strDefault value:request.GETThe tag defaults to usingrequest.GETas the data source for the querystring, but thesource_datakeyword argument can be used to specify use an alternativeQueryDict,dictor string value.For example, say you were using a Django form to validate query data, and only want valid data to be included. You could use the Form'scleaned_datato generate a querystring instead:{% querystring source_data=form.cleaned_data page=2 %}remove_blankSupported value types:boolDefault value:TrueAny parameter values with a value ofNoneor""(an empty string) are removed from the querystring default.To retain blank values, includeremove_blank=Falsein your{% querystring %}tag.remove_utmSupported value types:boolDefault value:TrueParameter names starting with"utm_"(the format used for Google Analytics tracking parameters) are exluded from the generated querystrings by default, as it's unlikley that you'll want these to be repeated in links to other pages.To retain these parameters instead, includeremove_utm=Falsein your{% querystring %}tag.model_value_fieldSupported value types:strDefault value:"pk"By default, when encountering a Django model instance as a value,{% querystring %}will take thepkvalue from the instance to use in the querystring. If you'd like to use a different field value, you can use themodel_value_fieldoption to specify an alternative field.For example, if the model had aslugfield that you were using as the public-facing identifier, you could specify thatslugvalues be used in the querystring, like so:{% querystring tags=tag_queryset model_field_value='slug' %}Testing the code locallyIf you have a recent version of Python 3 installed, you can use a simple virtualenv to run tests locally. After cloning the repository, navigate to the project's root directory on your machine, then run the following:Set up the virtualenv$virtualenvvenv$sourcevenv/bin/activate$pipinstall-e'.[test]'-URun tests$pytestWhen you're done$deactivate