Изменение одного параметра запроса в URL-адресе (Django)

У меня есть страница поиска, которая принимает множество параметров. Я хочу создать новый URL, просто изменив один параметр в запросе. Есть ли простой способ сделать это - что-то вроде:

# 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

Таким образом, это займет URL-адрес запроса, изменит один параметр запроса и затем вернет новый URL-адрес. Аналогично тому, что может быть достигнуто в Perl Catalyst с использованием $c->uri_with({change => 'after'}).

Или есть лучший способ?

[ОБНОВЛЕНО: удалены ссылки на разбивку на страницы]

Ответ 1

Итак, напишите тег шаблона вокруг этого:

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))

Для более полного решения используйте Zachary Voase URLObject 2, который очень хорошо выполнен.

Ответ 2

Я сделал этот простой тег, который не требует дополнительных библиотек:

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

    dict_ = request.GET.copy()

    dict_[field] = value

    return dict_.urlencode()

Использовать как:

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

Он добавит 'param' к вашей строке GET url, если он там отсутствует, или замените его новым значением, если оно уже существует.

Вам также нужно, чтобы экземпляр запроса RequestContext был предоставлен вашему шаблону из вашего представления. Подробнее здесь:

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

Ответ 3

Я улучшил решение mpaf, чтобы получить запрос непосредственно из тега.

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

Ответ 4

Существует несколько шаблонных тегов для изменения строки запроса djangosnippets.org:

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

Я бы сказал, что это самые перспективные взгляды. Один из них заключается в том, что вы должны использовать django.core.context_processors.request в TEMPLATE_CONTEXT_PROCESSORS.

Ответ 5

Это работало очень хорошо для меня. Позволяет задать любое количество параметров в URL-адресе. Работает хорошо для пейджера, сохраняя остальную часть строки запроса.

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)

Затем в шаблоне:

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

Ответ 7

В дополнение к фрагментам, упомянутым Марк Лавином, вот список других реализаций, которые я мог бы найти для тега шаблона Django, который изменяет текущую строку запроса HTTP GET.

На djangosnippets.org:

В PyPI:

В GitHub: