开发者

Altering one query parameter in a url (Django)

I have a search page that take开发者_Go百科s a variety of parameters. I want to create a new URL by just altering one parameter in the query. Is there an easy way to do this - something like:

# example request url
http://example.com/search?q=foo&option=bar&option2=baz&change=before

# ideal template code
{% url_with change 'after' %}

# resulting url
http://example.com/search?q=foo&option=bar&option2=baz&change=after

So this would take the request url, alter one query parameter and then return the new url. Similar to what can be achieved in Perl's Catalyst using $c->uri_with({change => 'after'}).

Or is there a better way?

[UPDATED: removed references to pagination]


I did this simple tag which doesn't require any extra libraries:

@register.simple_tag
def url_replace(request, field, value):

    dict_ = request.GET.copy()

    dict_[field] = value

    return dict_.urlencode()

Use as:

<a href="?{% url_replace request 'param' value %}">

It wil add 'param' to your url GET string if it's not there, or replace it with the new value if it's already there.

You also need the RequestContext request instance to be provided to your template from your view. More info here:

http://lincolnloop.com/blog/2008/may/10/getting-requestcontext-your-templates/


So, write a template tag around this:

from urlparse import urlparse, urlunparse
from django.http import QueryDict

def replace_query_param(url, attr, val):
    (scheme, netloc, path, params, query, fragment) = urlparse(url)
    query_dict = QueryDict(query).copy()
    query_dict[attr] = val
    query = query_dict.urlencode()
    return urlunparse((scheme, netloc, path, params, query, fragment))

For a more comprehensive solution, use Zachary Voase's URLObject 2, which is very nicely done.

Note: The urlparse module is renamed to urllib.parse in Python 3.


I improved mpaf's solution, to get request directly from tag.

@register.simple_tag(takes_context = True)
def url_replace(context, field, value):
    dict_ = context['request'].GET.copy()
    dict_[field] = value
    return dict_.urlencode()


This worked pretty well for me. Allows you to set any number of parameters in the URL. Works nice for a pager, while keeping the rest of the query string.

from django import template
from urlobject import URLObject

register = template.Library()

@register.simple_tag(takes_context=True)
def url_set_param(context, **kwargs):
    url = URLObject(context.request.get_full_path())
    path = url.path
    query = url.query
    for k, v in kwargs.items():
        query = query.set_param(k, v)
    return '{}?{}'.format(path, query)

Then in the template:

<a href="{% url_set_param page=last %}">


There are a number of template tags for modifying the query string djangosnippets.org:

http://djangosnippets.org/snippets/553/
http://djangosnippets.org/snippets/826/
http://djangosnippets.org/snippets/1243/

I would say those are the most promising looking. One point in all of them is that you must be using django.core.context_processors.request in your TEMPLATE_CONTEXT_PROCESSORS.


You can try https://github.com/dcramer/django-paging


In addition to the snippets mentioned by Mark Lavin, Here's a list of other implementations I could find for a Django template tag which modifies the current HTTP GET query string.

On djangosnippets.org:

  • #2237 Manipulate URL query strings using context variables using a template tag by JHsaunders
  • #2332 Querystring Builder - create urls with GET params by jibberia
  • my favorite: #2413 Yet another query string template tag by atms
  • #2428 Add GET parameters from current request by naktinis

On PyPI:

  • django-spurl by Jamie Matthews
  • django-urltags by Calloway Project/Corey Oordt
  • the add_query_param filter in django-rest-framework by Tom Christie

On GitHub:

  • update_querystring by David Gouldin
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜