如何使用查询参数构造 Django 反向/url?

发布于 2024-09-01 04:45:20 字数 1964 浏览 5 评论 0原文

我的网址类似于 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"),

我可以转到该 URL 并获取构建的 200x200 PNG,所以我知道该部分有效。

在“cansmi.cansmi”响应的模板中,我想在给定一些查询参数的情况下为命名模板“cyclops-depict”构造一个 URL。我以为我能做到

{% url cyclops-depict smiles=input_smiles width=200 height=200 %}

其中“input_smiles”是通过表单提交对模板的输入。在本例中,它是字符串“CO”,我认为它会创建一个像顶部那样的 URL。

此模板失败并出现 TemplateSyntaxError:

渲染时捕获异常:使用参数 '()' 和关键字参数 '{'smiles': u'CO', 'height': 200, 'width': 200}' 反转 'cyclops-depict' 不会找到了。

这是 StackOverflow 和其他地方相当常见的错误消息。在我发现的每种情况下,人们都将它们与 URL 路径正则表达式中的参数一起使用,而我在参数进入查询时的情况并非如此。

这意味着我做错了。我怎样做才正确?也就是说,我想使用模板中的某些内容构建完整的 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.

I have URLs like http://example.com/depict?smiles=CO&width=200&height=200 (and with several other optional arguments)

My urls.py contains:

urlpatterns = patterns('',
    (r'^

I can go to that URL and get the 200x200 PNG that was constructed, so I know that part works.

In my template from the "cansmi.cansmi" response I want to construct a URL for the named template "cyclops-depict" given some query parameters. I thought I could do

{% url cyclops-depict smiles=input_smiles width=200 height=200 %}

where "input_smiles" is an input to the template via a form submission. In this case it's the string "CO" and I thought it would create a URL like the one at top.

This template fails with a TemplateSyntaxError:

Caught an exception while rendering: Reverse for 'cyclops-depict' with arguments '()' and keyword arguments '{'smiles': u'CO', 'height': 200, 'width': 200}' not found.

This is a rather common error message both here on StackOverflow and elsewhere. In every case I found, people were using them with parameters in the URL path regexp, which is not the case I have where the parameters go into the query.

That means I'm doing it wrong. How do I do it right? That is, I want to construct the full URL, including path and query parameters, using something in the template.

For reference,

% 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.
, 'cansmi.index'), (r'^cansmi

I can go to that URL and get the 200x200 PNG that was constructed, so I know that part works.

In my template from the "cansmi.cansmi" response I want to construct a URL for the named template "cyclops-depict" given some query parameters. I thought I could do

{% url cyclops-depict smiles=input_smiles width=200 height=200 %}

where "input_smiles" is an input to the template via a form submission. In this case it's the string "CO" and I thought it would create a URL like the one at top.

This template fails with a TemplateSyntaxError:

Caught an exception while rendering: Reverse for 'cyclops-depict' with arguments '()' and keyword arguments '{'smiles': u'CO', 'height': 200, 'width': 200}' not found.

This is a rather common error message both here on StackOverflow and elsewhere. In every case I found, people were using them with parameters in the URL path regexp, which is not the case I have where the parameters go into the query.

That means I'm doing it wrong. How do I do it right? That is, I want to construct the full URL, including path and query parameters, using something in the template.

For reference,


, 'cansmi.cansmi'),
    url(r'^depict

I can go to that URL and get the 200x200 PNG that was constructed, so I know that part works.

In my template from the "cansmi.cansmi" response I want to construct a URL for the named template "cyclops-depict" given some query parameters. I thought I could do

{% url cyclops-depict smiles=input_smiles width=200 height=200 %}

where "input_smiles" is an input to the template via a form submission. In this case it's the string "CO" and I thought it would create a URL like the one at top.

This template fails with a TemplateSyntaxError:

Caught an exception while rendering: Reverse for 'cyclops-depict' with arguments '()' and keyword arguments '{'smiles': u'CO', 'height': 200, 'width': 200}' not found.

This is a rather common error message both here on StackOverflow and elsewhere. In every case I found, people were using them with parameters in the URL path regexp, which is not the case I have where the parameters go into the query.

That means I'm doing it wrong. How do I do it right? That is, I want to construct the full URL, including path and query parameters, using something in the template.

For reference,


, cyclops.django.depict, name="cyclops-depict"),

I can go to that URL and get the 200x200 PNG that was constructed, so I know that part works.

In my template from the "cansmi.cansmi" response I want to construct a URL for the named template "cyclops-depict" given some query parameters. I thought I could do

{% url cyclops-depict smiles=input_smiles width=200 height=200 %}

where "input_smiles" is an input to the template via a form submission. In this case it's the string "CO" and I thought it would create a URL like the one at top.

This template fails with a TemplateSyntaxError:

Caught an exception while rendering: Reverse for 'cyclops-depict' with arguments '()' and keyword arguments '{'smiles': u'CO', 'height': 200, 'width': 200}' not found.

This is a rather common error message both here on StackOverflow and elsewhere. In every case I found, people were using them with parameters in the URL path regexp, which is not the case I have where the parameters go into the query.

That means I'm doing it wrong. How do I do it right? That is, I want to construct the full URL, including path and query parameters, using something in the template.

For reference,

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

北城半夏 2024-09-08 04:45:20

正如某些答案所建议的那样,通过字符串连接构建查询字符串的 url 与通过字符串连接构建 SQL 查询一样糟糕。它很复杂、不优雅,而且对于用户提供的(不受信任的)输入尤其危险。不幸的是,Django 没有提供一种简单的方法来将查询参数传递到 reverse< /a> 函数。

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

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

def url_with_querystring(path, **kwargs):
    return path + '?' + urllib.urlencode(kwargs) # for Python 3, use urllib.parse.urlencode instead

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

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

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

Building an url with query string by string concatenation as suggested by some answers 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.

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

In my application I've created a helper function:

def url_with_querystring(path, **kwargs):
    return path + '?' + urllib.urlencode(kwargs) # for Python 3, use urllib.parse.urlencode instead

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!

冬天旳寂寞 2024-09-08 04:45:20

您的常规表达式没有占位符(这就是您获得 NoReverseMatch 的原因):

url(r'^depict

您可以这样做:

{% url cyclops-depict %}?smiles=CO&width=200&height=200

URLconf 搜索不包含 GET 或 POST 参数

或者,如果您希望使用 {% url %} 标记,您应该将 url 模式重构为类似这样的

r'^depict/(?P<width>\d+)/(?P<height>\d+)/(?P<smiles>\w+)

内容你可以做类似

{% url cyclops-depict 200 200 "CO" %}

后续:

自定义标签的简单示例:

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

你可以在模板中使用此标签,如下所示:

{% myurl width=200 height=200 name=SomeName %}

并希望它应该输出类似的内容

/depict?width=200&height=200&name=SomeName
, cyclops.django.depict, name="cyclops-depict"),

您可以这样做:


URLconf 搜索不包含 GET 或 POST 参数

或者,如果您希望使用 {% url %} 标记,您应该将 url 模式重构为类似这样的


内容你可以做类似



后续:

自定义标签的简单示例:


你可以在模板中使用此标签,如下所示:


并希望它应该输出类似的内容


 

内容你可以做类似


后续:

自定义标签的简单示例:

你可以在模板中使用此标签,如下所示:

并希望它应该输出类似的内容

, cyclops.django.depict, name="cyclops-depict"),

您可以这样做:

URLconf 搜索不包含 GET 或 POST 参数

或者,如果您希望使用 {% url %} 标记,您应该将 url 模式重构为类似这样的

内容你可以做类似


后续:

自定义标签的简单示例:

你可以在模板中使用此标签,如下所示:

并希望它应该输出类似的内容

Your regular expresion has no place holders (that's why you are getting NoReverseMatch):

url(r'^depict

You could do it like this:

{% url cyclops-depict %}?smiles=CO&width=200&height=200

URLconf search does not include GET or POST parameters

Or if you wish to use {% url %} tag you should restructure your url pattern to something like

r'^depict/(?P<width>\d+)/(?P<height>\d+)/(?P<smiles>\w+)

then you could do something like

{% url cyclops-depict 200 200 "CO" %}

Follow-up:

Simple example for custom tag:

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

You could use this tag in your templates like so:

{% myurl width=200 height=200 name=SomeName %}

and hopefully it should output something like

/depict?width=200&height=200&name=SomeName
, cyclops.django.depict, name="cyclops-depict"),

You could do it like this:


URLconf search does not include GET or POST parameters

Or if you wish to use {% url %} tag you should restructure your url pattern to something like


then you could do something like



Follow-up:

Simple example for custom tag:


You could use this tag in your templates like so:


and hopefully it should output something like


 

then you could do something like


Follow-up:

Simple example for custom tag:

You could use this tag in your templates like so:

and hopefully it should output something like

, cyclops.django.depict, name="cyclops-depict"),

You could do it like this:

URLconf search does not include GET or POST parameters

Or if you wish to use {% url %} tag you should restructure your url pattern to something like

then you could do something like


Follow-up:

Simple example for custom tag:

You could use this tag in your templates like so:

and hopefully it should output something like

一身软味 2024-09-08 04:45:20

我建议使用内置 django 的 QueryDict。它还可以正确处理列表。 End 自动转义一些特殊字符(例如 =?/、'#'):

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'

要在模板中使用它,您需要创建自定义模板标签

I recommend to use builtin django's QueryDict. It also handles lists properly. End automatically escapes some special characters (like =, ?, /, '#'):

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'

To use this in templates you will need to create custom template tag

柠檬心 2024-09-08 04:45:20

以前的答案的工作变化以及我处理这些东西的经验。

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

使用方法:

>>> build_url('products-detail', kwargs={'pk': 1}, params={'category_id': 2})
'/api/v1/shop/products/1/?category_id=2'

Working variation of previous answers and my experience with dealing this stuff.

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

How to use:

>>> build_url('products-detail', kwargs={'pk': 1}, params={'category_id': 2})
'/api/v1/shop/products/1/?category_id=2'
静若繁花 2024-09-08 04:45:20

使用 urllib 的答案确实很好,但是当它试图避免字符串连接时,它在 path + '?' 中使用了它+ urllib.urlencode(kwargs)。我相信当 path 已经有一些查询参数时,这可能会产生问题。

修改后的函数如下所示:

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)

The answer that used urllib is indeed good, however while it was trying to avoid strings concatenation, it used it in path + '?' + urllib.urlencode(kwargs). I believe this may create issues when the path has already some query parmas.

A modified function would look like:

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)
两仪 2024-09-08 04:45:20

两个原始答案都没有解决解决视图代码中 URL 的相关问题。对于未来的搜索者,如果您尝试执行此操作,请使用 kwargs,例如:

reverse('myviewname', kwargs={'pk': value})

Neither of the original answers addresses the related issue resolving URLs in view code. For future searchers, if you are trying to do this, use kwargs, something like:

reverse('myviewname', kwargs={'pk': value})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文