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
精彩评论