Django redirect using reverse() to a URL that relies on query strings
我正在编写一个带有\\'http:// localhost / entity / id /?overlay = other_id \\'这样的URL的Django应用程序。其中id是特定实体的主键,而overlay是要在显示中覆盖的第二个实体的可选查询参数。通过叠加层查看对象时,用户只能更新实体。当发布到/ update / id时,我想重定向回/ entity / id,但是我不想在重定向过程中丢失查询参数,因为视图中的更改会令人讨厌。
例如,我的url.py中包含以下内容:
1 2 3 4 | ... (r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update'), (r'^entity/(?P<id>.+)/$', 'view'), ... |
因为更新时需要overlay_id,它是URL的一部分,而不是查询参数。在django视图中,我想在POST成功后进行重定向,并使用reverse()以避免在我的python代码中引用URL。一般的想法是:
1 2 3 4 5 6 7 | return HttpResponseRedirect( reverse('views.view', kwargs={ 'id': id, }, ) ) |
但是我如何通过反向传递我的查询参数呢?
谢谢Craig
您可以使用Django QueryDict对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 2 3 4 | 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 ) |
查询字符串args应该正确地转义,而不仅仅是连接!
通过字符串连接使用查询字符串构建url与通过字符串连接构建SQL查询一样是个坏主意。使用用户提供的(不受信任的)输入时,它是复杂的,模糊的,尤其危险。不幸的是Django无法将查询参数传递给反向函数。
Python标准urllib但是提供了所需的查询字符串编码功能。
在我的应用程序中,我创建了一个帮助器这样的功能:
1 2 | def url_with_querystring(path, **kwargs): return path + '?' + urllib.urlencode(kwargs) |
然后在视图中按如下方式调用它:
1 2 3 4 5 | 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 |
请注意空格和感叹号等特殊字符的正确编码!
您不应该自己生成url字符串。给定您的urls.py,您可以使用以下方式进行反向操作:
1 2 3 4 5 | 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标识符断开连接:
1 2 3 4 | # urls.py ... (r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update', name="update_foo"), ... |
使用像这样反向:
1 | print reverse("update_foo", kwargs={"id":"id_value","overlay_id":"overlay_id_value"}) |