在Django模板中使用关键字参数进行反向URL查找

0 投票
1 回答
2254 浏览
提问于 2025-04-18 15:31

我想在Django模板中使用反向URL查找,使用关键字参数,而不是位置参数。

我现在用位置参数已经能正常工作,代码如下:

HTML:

    <a href="{% url 'download' customer.pk %}">download</a>

URL:

    (r'^generator/download/(?P<customer_id>\d+)/$', 'generator.views.send_file', name='download'),

视图定义:

    def send_file(request, customer_id):

问题是,我发现了一个安全隐患,现在任何人都可以简单地输入这样的URL:

    /generate/download/<any number>/

然后下载本来只应该给其他人的文件。我知道通过使用用户权限等方法可以降低这种风险,但我还是想再加一层安全措施,以防万一。也许我认为关键字参数在这方面更安全是错的,因为它并不是简单地可以在URL中传递的……但这就是我的想法。

我认为代码应该是这样的:

HTML:

    <a href="{% url 'download' customer_id=customer.pk %}">download</a>

URL:

    (r'^generator/download/$', 'generator.views.send_file', name='download'),

视图定义:

    def send_file(request, customer_id=None):
        customer = get_object_or_404(Customer, pk=customer_id)
        ... other code

这意味着如果在URL中输入/generate/download/(没有附带的关键字参数),就会返回404错误。

但是当我尝试使用这段代码时,出现了以下错误:

Reverse for 'download' with arguments '()' and keyword arguments '{u'customer_id': 33}' not found. 1 pattern(s) tried: ['generator/download/$']

我相信这一定是我在Django URL调度文档中忽略了什么简单的东西,或者可能是我定义视图的方式有问题(也许我需要把**kwargs作为参数?),但我怎么也找不到。

非常感谢你的帮助。

1 个回答

1

你的想法其实是完全错误的。关键字参数确实是通过网址传递的,只不过它们以不同的方式发送给视图函数——是以kwargs的形式,而不是args。

解决你问题的最简单方法就是直接在下载函数里检查用户。

def download(request, pk):
    obj = Download.objects.get(pk)
    if obj.customer_id != request.user.id:
        return HttpResponseForbidden()

撰写回答