开发者

Link to Current Page in Django, with Additional GET Params?

How do I place an HTML link what refers to the current page, and which adds additional GET parameters (or overwriting existing ones, if they already exist)?

Right now I have something like:

 <a href="{{ request.path }}?Key=Value"> My Link </a>

Currently, request is passed to the page. If reques开发者_如何学Pythont.path is https://stackoverflow.com/, then the resulting link becomes https://stackoverflow.com/?Key=Value

The problem?

But of course, if the current URL is https://stackoverflow.com/?PrevKey=PrevValue then it becomes:

https://stackoverflow.com/?PrevKey=PrevValue?Key=Value

Notice the incorrect second question mark -- it should in fact be:

https://stackoverflow.com/?PrevKey=PrevValue&Key=Value

Furthermore, if there is already a key with the same name, then instead of overwriting it, my current solution ignores it -- which is wrong.

How do I solve these two problems?


You'll need a custom tag. There are a couple on djangosnippets - this one looks pretty comprehensive.


For anyone seeing this in future: https://bitbucket.org/monwara/django-url-tools


You can use: {{ request.get_full_path }} to get the current path with additional parameters.


I'm just a beginner with Django, so you'll have to take my response with a grain of salt.

Firstly, request.path should return the path to the page without the domain, according to the documentation. So if the request is for http://example.com/, request.path should be just "/". Correct me if I'm wrong.

But that's not relevant. More importantly, request.path won't have any query parameters, so if the page requested is http://example.com/?PrevKey=PrevValue, then request.path will still be "/". If you want to get the query parameters, you have to make use of the dictionary-like access of the GET and POST properties (in this case GET) of the request object. Or better yet, access them through the QueryDict methods.

What I would do here, and this is by no means the best method nor code, is to prepare a custom template filter in which you pass the current request object and the key-value pair to test against.

This is how your template code would look. Note that you can still hard code the key value pair, although here it is formatted as a string with "key colon value". The filter function can handle (if you need to) more than just one set of key-value pairs.

<a href="{{ request | addQueryParameter:'Key:Value'}}">My Link</a>

The filter function:

from urllib import urlencode

def addQueryParameter(request, parameter):
    # parse the key-value pair(s) in parameter (which looks like a JSON string)
    # then add to dictionary d
    # note i am not taking into account white-space.
    for param in string.split(','):
        key, value = param.split(':', 1)
        d[key] = value

    # check if any keys in d are already in the request query parameters
    # if so, delete from d. If I misunderstood your question, then refactor 
    # to delete from request.GET instead:
    for key in d.keys():
        if key in request.GET.keys():
             del d[key]

    # add the keys in request.GET into d:
    d.extend(request.GET.items())

    # convert dictionary of key value pairs into a query string for urls, 
    # prepend a ?
    queryString = "?%s" % urlencode(d)
    return "%s%s" % (request.path, queryString if queryString else "")

I should point out that if the request is for the page http://example.com/login/?prev=news and your template looks like

<a href="{{ request | addQueryParameter:'goto:dashboard,feature:products'}}">My Link</a>

Then the output would be (hopefully, if it works):

<a href="/login/?prev=news&goto=dashboard&feature=products">
My Link</a>
<!-- the order of the above parameters may differ -->

Note that there is no domain (i.e. the http://example.com/ part) in this link. That is because the filter doesn't add it. But you can modify it to do so.

I'll leave it to you to register this template filter. More here. Hope this helps.


A JavaScript solution is much suitable in this case. Example :

 <div class="pagination">
        <span class="step-links">
            {% if page_obj.has_previous %}
                <a page_number="1">First Page</a>
                <a page_number="{{ page_obj.previous_page_number }}">Last Page</a>
            {% endif %}
            {% if page_obj.has_previous or page_obj.has_next %}
                <span class="current">{{ page_obj.number }}/{{ page_obj.paginator.num_pages }}</span>
            {% endif %}
            {% if page_obj.has_next %}
                <a page_number="{{ page_obj.next_page_number }}">Next Page</a>
                <a page_number="{{ page_obj.paginator.num_pages }}">End Page</a>
            {% endif %}
        </span>
        <script type="text/javascript">
        document.querySelectorAll('.pagination a').forEach(link => {
            let page_number = link.getAttribute('page_number');
            const gotopageUrl = new URL(location.href);
            gotopageUrl.searchParams.set("page", page_number);
            link.href = gotopageUrl.href;
        });
        </script>
    </div>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜