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

时间:2022-09-04 12:32:38

I'm writing a django application with a URL like 'http://localhost/entity/id/?overlay=other_id'. Where id is the primary key of the particular entity and overlay is an optional query parameter for a second entity to be overlaid in the display. The user can only ever update an entity when viewing objects through an overlay. When POSTing to /update/id, I want to redirect back to /entity/id, but I don't want to lose my query parameter during the redirect, as the change in view would be jarring.

我正在编写一个django应用程序,其URL为'http:// localhost / entity / id /?overlay = other_id'。其中id是特定实体的主键,而overlay是第二个实体要覆盖在显示中的可选查询参数。用户只能在通过叠加层查看对象时更新实体。当POST到/ update / id时,我想重定向回/ entity / id,但我不希望在重定向期间丢失我的查询参数,因为视图中的更改会变得不和谐。

For example, I've got the following in my url.py:

例如,我在url.py中有以下内容:

...
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update'),
(r'^entity/(?P<id>.+)/$', 'view'),
...

Because overlay_id is required when updating, it's part of the URL, not a query parameter. In the django view I want to redirect after a successful POST and use reverse() to avoid referencing URLs in my python code. The general idea is:

因为更新时需要overlay_id,所以它是URL的一部分,而不是查询参数。在django视图中,我想在POST成功后重定向并使用reverse()来避免在我的python代码中引用URL。一般的想法是:

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

But how do I pass my query parameter though reverse?

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

Thanks, Craig

谢谢,克雷格

4 个解决方案

#1


5  

Can't you just check for an overlay_id and add it to your url?

你不能只检查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


18  

You can use a Django QueryDict object:

您可以使用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()

And of course you could write a convenience method for it similar to the previous answer.

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

#3


4  

Query string args should be properly escaped and not just concatenated!

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

Building an url with query string by string concatenation is as bad idea as building SQL queries by string concatenation. It is complicated, unelegant and especially dangerous with a user provided (untrusted) input. Unfortunately Django does not offer an easy possibility to pass query parameters to the reverse function.

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

Python standard urllib however provides the desired query string encoding functionality.

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

In my application I've created a helper function like this:

在我的应用程序中,我创建了一个这样的辅助函数:

def url_with_querystring(path, **kwargs):
    return path + '?' + urllib.urlencode(kwargs)

Then I call it in the view as follows:

然后我在视图中调用它如下:

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

Please note the proper encoding of special characters like space and exclamation mark!

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

#4


3  

You shouldn't generate the url string yourself. Given your urls.py you can use reverse like so:

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

If you use named url patterns, which are great for disconnecting your view functions from url identifiers:

如果您使用命名的url模式,这对于断开视图函数与URL标识符的连接非常有用:

# urls.py
...
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update', name="update_foo"),
...

Use reverse like so:

像这样使用反向:

print reverse("update_foo", kwargs={"id":"id_value", "overlay_id": "overlay_id_value"})

#1


5  

Can't you just check for an overlay_id and add it to your url?

你不能只检查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


18  

You can use a Django QueryDict object:

您可以使用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()

And of course you could write a convenience method for it similar to the previous answer.

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

#3


4  

Query string args should be properly escaped and not just concatenated!

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

Building an url with query string by string concatenation is as bad idea as building SQL queries by string concatenation. It is complicated, unelegant and especially dangerous with a user provided (untrusted) input. Unfortunately Django does not offer an easy possibility to pass query parameters to the reverse function.

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

Python standard urllib however provides the desired query string encoding functionality.

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

In my application I've created a helper function like this:

在我的应用程序中,我创建了一个这样的辅助函数:

def url_with_querystring(path, **kwargs):
    return path + '?' + urllib.urlencode(kwargs)

Then I call it in the view as follows:

然后我在视图中调用它如下:

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

Please note the proper encoding of special characters like space and exclamation mark!

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

#4


3  

You shouldn't generate the url string yourself. Given your urls.py you can use reverse like so:

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

If you use named url patterns, which are great for disconnecting your view functions from url identifiers:

如果您使用命名的url模式,这对于断开视图函数与URL标识符的连接非常有用:

# urls.py
...
(r'^update/(?P<id>.+)/(?P<overlay_id>.+)/$', 'update', name="update_foo"),
...

Use reverse like so:

像这样使用反向:

print reverse("update_foo", kwargs={"id":"id_value", "overlay_id": "overlay_id_value"})