Django使用reverse()重定向到依赖于查询字符串的URL

时间:2010-12-18 07:14:34

标签: django django-views

我正在编写一个django应用程序,其URL为'http:// localhost / entity / id /?overlay = other_id'。其中id是特定实体的主键,而overlay是第二个实体要覆盖在显示中的可选查询参数。用户只能在通过叠加层查看对象时更新实体。当POST到/ 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()来避免在我的python代码中引用URL。一般的想法是:

return HttpResponseRedirect(
  reverse('views.view',
    kwargs={
      'id': id,
    },
  )
)

但是如何通过反向传递我的查询参数?

谢谢, 克雷格

4 个答案:

答案 0 :(得分:21)

您可以使用Django QueryDict object

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

当然,你可以为它编写一个方便的方法,类似于之前的答案。

答案 1 :(得分:6)

您不能只检查overlay_id并将其添加到您的网址吗?

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 :(得分:4)

查询字符串args应该被正确转义,而不仅仅是连接!

通过字符串连接构建具有查询字符串的URL与通过字符串连接构建SQL查询一样糟糕。用户提供的(不可信的)输入是复杂的,不优雅的并且特别危险。不幸的是,Django没有提供将查询参数传递给reverse函数的简单方法。

然而,

Python标准urllib提供了所需的查询字符串编码功能。

在我的application中,我创建了一个这样的辅助函数:

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

请注意空格和感叹号等特殊字符的正确编码!

答案 3 :(得分:3)

您不应该自己生成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",))

如果您使用named url patterns,这非常适合从网址标识符中断开您的视图功能:

# 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"})