Django перенаправляет с помощью reverse() URL-адрес, который использует строки запроса
Я пишу приложение django с URL-адресом типа http://localhost/entity/id/? overlay = other_id. Где id является первичным ключом конкретной сущности, а overlay - необязательный параметр запроса для второго объекта, который должен быть наложен на дисплей. Пользователь может обновлять объект только при просмотре объектов с помощью наложения. Когда POSTing to/update/id, я хочу перенаправить обратно в /entity/id, но я не хочу потерять свой параметр запроса во время перенаправления, так как изменение в представлении будет раздражать.
Например, у меня есть следующее в url.py:
...
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update'),
(r'^entity/(?P<id>.+)/$', 'view'),
...
Так как overlay_id требуется при обновлении, это часть URL-адреса, а не параметр запроса. В представлении django я хочу перенаправить после успешного POST и использовать reverse(), чтобы избежать ссылок на URL-адреса в моем коде python. Общая идея:
return HttpResponseRedirect(
reverse('views.view',
kwargs={
'id': id,
},
)
)
Но как передать свой параметр запроса, хотя обратный?
Спасибо,
Craig
Ответы
Ответ 1
Не можете ли вы просто проверить overlay_id
и добавить его в свой URL?
redirect_url = reverse( ... )
extra_params = '?overlay=%s' % overlay_id if overlay_id else ''
full_redirect_url = '%s%s' % (redirect_url, extra_params)
return HttpResponseRedirect( full_redirect_url )
Ответ 2
Вы можете использовать объект Django QueryDict:
from django.http import QueryDict
# from scratch
qdict = QueryDict('',mutable=True)
# starting with our existing query params to pass along
qdict = request.GET.copy()
# put in new values via regular dict
qdict.update({'foo':'bar'})
# put it together
full_url = reversed_url + '?' + qdict.urlencode()
И, конечно же, вы можете написать удобный для него метод, аналогичный предыдущему.
Ответ 3
Аргументы строки запроса должны быть правильно экранированы, а не только конкатенированы!
Построение URL-адреса с строкой запроса путем конкатенации строк - это также плохая идея, как построение SQL-запросов путем конкатенации строк. Это сложный, неудобный и особенно опасный с предоставленным пользователем (ненадежным) вводом. К сожалению, Django не предлагает простой возможности передать параметры запроса в функцию reverse.
Стандарт Python urllib однако обеспечивает требуемую функциональность кодировки строки запроса.
В моем приложении я создал вспомогательную функцию, подобную этой:
def url_with_querystring(path, **kwargs):
return path + '?' + urllib.urlencode(kwargs)
Затем я вызываю его в виде следующим образом:
quick_add_order_url = url_with_querystring(reverse(order_add),
responsible=employee.id, scheduled_for=datetime.date.today(),
subject='hello world!')
# http://localhost/myapp/order/add/?responsible=5&
# scheduled_for=2011-03-17&subject=hello+world%21
Обратите внимание на правильную кодировку специальных символов, таких как пробел и восклицательный знак!
Ответ 4
Вы не должны генерировать строку url самостоятельно. Учитывая ваш urls.py, вы можете использовать обратное так:
from django.core.urlresolvers import reverse
print reverse('view_function_name', kwargs={"id":"id_value", "overlay_id": "overlay_id_value"})
# or to pass view function arguments as an array:
print reverse('view_function_name', args=("id_value","overlay_id_value",))
Если вы используете именованные шаблоны url, которые отлично подходят для отключения функций просмотра от идентификаторов URL:
# urls.py
...
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update', name="update_foo"),
...
Используйте обратное так:
print reverse("update_foo", kwargs={"id":"id_value", "overlay_id": "overlay_id_value"})