And*_*lke 29 django url reverse query-string
我有http://example.com/depict?smiles=CO&width=200&height=200(以及其他几个可选参数)等网址
我的urls.py包含:
urlpatterns = patterns('',
(r'^$', 'cansmi.index'),
(r'^cansmi$', 'cansmi.cansmi'),
url(r'^depict$', cyclops.django.depict, name="cyclops-depict"),
Run Code Online (Sandbox Code Playgroud)
我可以转到该URL并获得构建的200x200 PNG,因此我知道该部分有效.
在我的"cansmi.cansmi"响应的模板中,我想给出一些查询参数的命名模板"cyclops-depict"的URL.我以为我能做到
{%url cyclops-depict smiles = input_smiles width = 200 height = 200%}
其中"input_smiles"是通过表单提交输入模板的.在这种情况下,它是字符串"CO",我认为它将创建一个类似于顶部的URL.
此模板因TemplateSyntaxError而失败:
在渲染时捕获异常:反向'cyclops-depict',带参数'()'和关键字参数'{'smiles':u'CO','height':200,'width':200}'未找到.
这是StackOverflow和其他地方的一个相当常见的错误消息.在我发现的每种情况下,人们都在URL路径regexp中使用带参数的情况,这与参数进入查询的情况不同.
这意味着我做错了.我该怎么做?也就是说,我想使用模板中的内容构造完整的URL,包括路径和查询参数.
以供参考,
% python manage.py shell
Python 2.6.1 (r261:67515, Feb 11 2010, 00:51:29)
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.core.urlresolvers import reverse
>>> reverse("cyclops-depict", kwargs=dict())
'/depict'
>>> reverse("cyclops-depict", kwargs=dict(smiles="CO"))
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Library/Python/2.6/site-packages/django/core/urlresolvers.py", line 356, in reverse
*args, **kwargs)))
File "/Library/Python/2.6/site-packages/django/core/urlresolvers.py", line 302, in reverse
"arguments '%s' not found." % (lookup_view_s, args, kwargs))
NoReverseMatch: Reverse for 'cyclops-depict' with arguments '()' and keyword arguments '{'smiles': 'CO'}' not found.
Run Code Online (Sandbox Code Playgroud)
gee*_*ekQ 46
如某些答案所建议的那样,通过字符串连接构建具有查询字符串的URL与通过字符串连接构建SQL查询一样糟糕.用户提供的(不可信的)输入是复杂的,不优雅的并且特别危险.不幸的是,Django没有提供将查询参数传递给反向函数的简单方法.
但是,Python标准urllib提供了所需的查询字符串编码功能.
在我的应用程序中,我创建了一个辅助函数:
def url_with_querystring(path, **kwargs):
return path + '?' + urllib.urlencode(kwargs) # for Python 3, use urllib.parse.urlencode instead
Run Code Online (Sandbox Code Playgroud)
然后我在视图中调用它如下:
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
Run Code Online (Sandbox Code Playgroud)
请注意空格和感叹号等特殊字符的正确编码!
Dav*_*cic 20
你的正常表达没有占位符(这就是你获得NoReverseMatch的原因):
url(r'^depict$', cyclops.django.depict, name="cyclops-depict"),
Run Code Online (Sandbox Code Playgroud)
你可以这样做:
{% url cyclops-depict %}?smiles=CO&width=200&height=200
Run Code Online (Sandbox Code Playgroud)
或者,如果您希望使用{%url%}标记,则应将您的网址格式重组为类似的内容
r'^depict/(?P<width>\d+)/(?P<height>\d+)/(?P<smiles>\w+)$'
Run Code Online (Sandbox Code Playgroud)
然后你可以做点什么
{% url cyclops-depict 200 200 "CO" %}
Run Code Online (Sandbox Code Playgroud)
跟进:
自定义标记的简单示例:
from django.core.urlresolvers import reverse
from django import template
register = template.Library()
@register.tag(name="myurl")
def myurl(parser, token):
tokens = token.split_contents()
return MyUrlNode(tokens[1:])
class MyUrlNode(template.Node):
def __init__(self, tokens):
self.tokens = tokens
def render(self, context):
url = reverse('cyclops-depict')
qs = '&'.join([t for t in self.tokens])
return '?'.join((url,qs))
Run Code Online (Sandbox Code Playgroud)
您可以在模板中使用此标记,如下所示:
{% myurl width=200 height=200 name=SomeName %}
Run Code Online (Sandbox Code Playgroud)
并希望它应该输出类似的东西
/depict?width=200&height=200&name=SomeName
Run Code Online (Sandbox Code Playgroud)
imp*_*ren 13
我建议使用builtin django的QueryDict.它还可以正确处理列表.结束自动转义一些特殊字符(如=,?,/,"#"):
from django.http import QueryDict
from django.core.urlresolvers import reverse
q = QueryDict('', mutable=True)
q['some_key'] = 'some_value'
q.setlist('some_list', [1,2,3])
'%s?%s' % (reverse('some_view_name'), q.urlencode())
# '/some_url/?some_list=1&some_list=2&some_list=3&some_key=some_value'
q.appendlist('some_list', 4)
q['value_with_special_chars'] = 'hello=w#rld?'
'%s?%s' % (reverse('some_view_name'), q.urlencode())
# '/some_url/?value_with_special_chars=hello%3Dw%23rld%3F&some_list=1&some_list=2&some_list=3&some_list=4&some_key=some_value'
Run Code Online (Sandbox Code Playgroud)
要在模板中使用此功能,您需要创建自定义模板标记
这两个原始答案都没有解决在视图代码中解析URL的相关问题.对于未来的搜索者,如果您尝试这样做,请使用kwargs,例如:
__CODE__
小智 7
之前答案的工作变化以及我处理这些问题的经验。
from django.urls import reverse
from django.utils.http import urlencode
def build_url(*args, **kwargs):
params = kwargs.pop('params', {})
url = reverse(*args, **kwargs)
if params:
url += '?' + urlencode(params)
return url
Run Code Online (Sandbox Code Playgroud)
如何使用:
>>> build_url('products-detail', kwargs={'pk': 1}, params={'category_id': 2})
'/api/v1/shop/products/1/?category_id=2'
Run Code Online (Sandbox Code Playgroud)
使用urllib的答案确实很好,但是当它试图避免字符串连接时,它使用了它path + '?' + urllib.urlencode(kwargs).我相信当path已经有一些查询parmas 时,这可能会产生问题.
修改后的函数看起来像:
def url_with_querystring(url, **kwargs):
url_parts = list(urlparse.urlparse(url))
query = dict(urlparse.parse_qsl(url_parts[4]))
query.update(kwargs)
url_parts[4] = urllib.urlencode(query)
return urlparse.urlunparse(url_parts)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
34066 次 |
| 最近记录: |