How to add the current query string to an URL in a Django template?

PythonDjango

Python Problem Overview


When I load a page, there is a link "sameLink" that I want to append to it the query string of its containing page.

I have following URL:

somedomain/reporting/article-by-month?variable1=2008

How can I do that?

Python Solutions


Solution 1 - Python

To capture the QUERY_PARAMS that were part of the request, you reference the dict that contains those parameters (request.GET) and urlencode them so they are acceptable as part of an href. request.GET.urlencode returns a string that looks like ds=&date_published__year=2008 which you can put into a link on the page like so:

<a href="sameLink/?{{ request.GET.urlencode }}">

Solution 2 - Python

If you register a templatetag like follows:

@register.simple_tag
def query_transform(request, **kwargs):
    updated = request.GET.copy()
    updated.update(kwargs)
    return updated.urlencode()

you can modify the query string in your template:

<a href="{% url 'view_name' %}?{% query_transform request a=5 b=6 %}">

This will preserve anything already in the query string and just update the keys that you specify.

Solution 3 - Python

I found that @Michael's answer didn't quite work when you wanted to update an existing query parameter.

The following worked for me:

@register.simple_tag
def query_transform(request, **kwargs):
    updated = request.GET.copy()
    for k, v in kwargs.items():
        updated[k] = v

    return updated.urlencode()

Solution 4 - Python

Following on from @Prydie (thank you!) I wanted to do the same, but in Python 3 & Django 1.10, with the addition of being able to strip querystring keys as well as modify them. To that end, I use this:

@register.simple_tag
def query_transform(request, **kwargs):
    updated = request.GET.copy()
    for k, v in kwargs.items():
        if v is not None:
            updated[k] = v
        else:
            updated.pop(k, 0)  # Remove or return 0 - aka, delete safely this key

    return updated.urlencode()

The python 3 bit being kwargs.items() over .iteritems()

Solution 5 - Python

Based on @Prydie's solution (which itself uses @Michael's), I constructed the tag to return the complete URL instead of just the parameter string.

My myproject/template_tags.py

from django import template


register = template.Library()


# https://stackoverflow.com/a/24658162/2689986
@register.simple_tag
def add_query_params(request, **kwargs):
    """
    Takes a request and generates URL with given kwargs as query parameters
    e.g.
    1. {% add_query_params request key=value %} with request.path=='/ask/'
        => '/ask/?key=value'
    2. {% add_query_params request page=2 %} with request.path=='/ask/?key=value'
        => '/ask/?key=value&page=2'
    3. {% add_query_params request page=5 %} with request.path=='/ask/?page=2'
        => '/ask/?page=5'
    """
    updated = request.GET.copy()
    for k, v in kwargs.items():
        updated[k] = v

    return request.build_absolute_uri('?'+updated.urlencode())

My settings.py

TEMPLATES = [
    {
        ...
        'OPTIONS': {
            ...
            # loads custom template tags
            'libraries': {
                'mytags': 'config.template_tags',
            }
        },
    },
]

Sample usage in templates:

{% load mytags %}
<a href="{% add_query_params request page=2 %}">

Tested with Python3.6 in Django1.11.10

Solution 6 - Python

Informed by other answers but not needing the request passed in and only updates existing parameters.

@register.simple_tag(takes_context=True)
def querystring(context, **kwargs):
    """
    Creates a URL (containing only the querystring [including "?"]) derived
    from the current URL's querystring, by updating it with the provided
    keyword arguments.

    Example (imagine URL is ``/abc/?gender=male&name=Tim``)::

        {% querystring "name"="Diego" "age"=20 %}
        ?name=Diego&gender=male&age=20
    """
    request = context['request']
    updated = request.GET.copy()
    for k, v in kwargs.items():  # have to iterate over and not use .update as it's a QueryDict not a dict
        updated[k] = v

    return '?{}'.format(updated.urlencode()) if updated else ''

Solution 7 - Python

Just a workaround if you don't want loops or string concatenations.

String representation of url is something like '<WSGIRequest: GET \'our_url\'>' So if you want our_url, you just need to use regex for it.

our_url = re.search(r'\/.*(?=\'>)', str(request)).group()

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionViktor ApoyanView Question on Stackoverflow
Solution 1 - PythonDrTyrsaView Answer on Stackoverflow
Solution 2 - PythonMichaelView Answer on Stackoverflow
Solution 3 - PythonPrydieView Answer on Stackoverflow
Solution 4 - PythonCarl MarshallView Answer on Stackoverflow
Solution 5 - Pythonshad0w_wa1k3rView Answer on Stackoverflow
Solution 6 - PythonIntiView Answer on Stackoverflow
Solution 7 - PythonRaymond ReddingtonView Answer on Stackoverflow