【问题标题】:In Django, can a url tag have an arbitrary number of arguments?在 Django 中,一个 url 标签可以有任意数量的参数吗?
【发布时间】:2017-12-14 02:51:15
【问题描述】:

背景:我正在通过使用 Django 1.11 开发一个简单的待办事项列表应用程序来学习 Django。该应用程序具有“组”和“项目”,其中项目是单独的待办事项,每个项目都属于一个组。 URL 最终可能会像这样工作:

# snippet from urls.py
url(r'^groups$', views.all_groups, name="all_groups"),
url(r'^groups/(\d+)/$', views.view_group, name="view_group"),
url(r'^items$', views.all_items, name="all_items"),
url(r'^items/(\d+)/$', views.view_item, name="view_item"),

上述每个页面都将显示一个或两个列表(例如,所有项目,或特定组中的所有项目等),其中每个表元素都是指向页面的链接,以显示特定组或特定项目。

我对上述每个 URL 都有一个单独的视图,但是我能够使用一个 HTML 模板来成功呈现每个表。根据 URL,URL 标签有 0 个或 1 个参数:{% url 'my_url' %} 或 {% url 'my_url' arg1 %}

这是一个 HTML 模板的 sn-p,它可以用任意数量的行和列呈现表格,但 url 标签最多两个参数:

# lists.html - works for several different views
# every table entry is a dictionary with an 'page_ref' key and a 'display_text' key

<table>
    {% for row in url_table %}
      <tr>
        {% for col in row %}
          {% if col.arg2 %}
          <td><a href="{% url col.page_ref col.arg1 col.arg2 %}">{{col.display_text}}</a></td>
          {% elif col.arg1 %}
          <td><a href="{% url col.page_ref col.arg1 %}">{{col.display_text}}</a></td>
          {% else %}
          <td><a href="{% url col.page_ref %}">{{col.display_text}}</a></td>
          {% endif %}
        {% endfor %}
      </tr>
    {%  endfor %}
</table>

我的问题:

1) 我在 HTML 模板中处理 {% url 'my_url' %} vs. {% url 'my_url' arg1 %} vs. {% url 'my_url' arg1 arg2 %} 的代码有效,但它很丑陋且有限URL 上最多 2 层。这对我想要的可能没问题,但我不喜欢代码。有没有更简洁的方法来处理任意数量的参数?当我尝试在不需要时简单地不传递 arg1/arg2 时,我收到了一个关于无法反转 '' 的异常(或一些类似的错误消息)。

2) 一般来说,制作这样的通用模板是个坏主意吗?即,每个视图有一个特定的 HTML 模板而不使其更通用是一种更好的做法?我的猜测是否定的,但我想我会问。

我也可以提供视图代码,但我认为我的问题不需要它。

谢谢

【问题讨论】:

    标签: python django django-templates


    【解决方案1】:

    由于您有不同的视图,但您使用的是相同的模板

    所以你可以做的是从模板中删除条件从每个视图发送相同的上下文变量名称,其中包含与您的视图相关的不同绝对 URL。

    # view1 no arguments
    class AllGroupView(TemplateView):
        template_name = 'path/to/your.html'
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['my_url'] = reverse('all_groups')
            return context
    #view2 one argument
    class GroupView(TemplateView):
        template_name = 'path/to/your.html'
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['my_url'] = reverse('view_group', args=[arg1])
            return context
    ...
    #view3 two argument
    class ItemView(TemplateView):
        template_name = 'path/to/your.html'
    
        def get_context_data(self, **kwargs):
            context = super().get_context_data(**kwargs)
            context['my_url'] = reverse('view_item', args=[arg1, arg2])
            return context
    

    在 html 中只使用这个变量

    # use my_url absolute: http://localhost:8000/...
    <td><a href="{{ my_url }}">{{display_text}}</a></td>
    

    【讨论】:

    • 谢谢。我会尝试一下,尽管我需要切换到基于类的视图(无论如何我都想学习)。一旦我得到它的工作,我会接受答案。我确实尝试将答案标记为有用,但我没有足够的积分让它公开注册(这是我的第一个 SO 问题......)。
    • @DaveB 你也可以对基于函数的视图做同样的事情。重点是,在视图本身中创建 url,以便我们可以从模板中移除开销。
    • 它几乎可以工作了(在我的基于函数的视图中)。我需要在反向函数中使用调整你的语法:reverse('view_name', args=[arg1]) 但我得到一个 NoReverseMatch 异常:Reverse for '/app/items/1/' not found。 '/app/items/1/' 不是有效的视图函数或模式名称但是,is 是直接访问时有效的有效 URL,并且我的 urls.py 文件中有此模式: url(r'^items/(\d+)/$', views.view_item, name="view_item") 我会继续挖掘,但如果你看到我做错了什么,请告诉我。
    • 您是否已向 url 声明了命名空间?如果是,您必须像 reverse('items:view_item', args=[arg1]) 一样使用它,这里 items 是命名空间
    • 呃,我发现了我的愚蠢错误。我错误地将我的模板 href 保留为 {% url my_url %},而不是按照您的描述将其更改为 {{my_url}}。现在可以工作了,而且更干净。非常感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 2021-01-16
    • 2016-07-02
    • 2015-09-01
    • 1970-01-01
    • 2013-08-24
    相关资源
    最近更新 更多