Подтвердить что ты не робот

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

4b9b3361

Ответ 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"})