【问题标题】:Django: passing a URL parameter to every instance of a reverse URL lookup in a template tagDjango:将 URL 参数传递给模板标记中反向 URL 查找的每个实例
【发布时间】:2023-03-31 21:19:01
【问题描述】:

抱歉,如果标题不清楚,我不确定描述问题的最佳方式。我有一个带有Ticket 模型和Team 模型的应用程序。所有Tickets 都与一个Team 相关联。我遇到的问题是 URL 反转的问题。我正在尝试像这样设置我的 URL:/<team_pk>/tickets/ 显示与team_pk 指定的团队相关联的票证列表。所以/1/tickets/ 将显示第一支球队的所有门票。这两个对象都在应用程序tracker中。

为此,我设置了我的 project/urls.py 文件,如下所示:

project/urls.py

urlpatterns = [ path('<team_pk>/', include('tracker.urls', namespace='tracker')), ]

tracker/urls.py

urlpatterns = [ path('tickets/', views.TicketTable.as_view(), name='ticket_list'), ]

然后,在我的 html 模板中,我有以下 URL 标记:

href="{% url 'tracker:ticket_list' %}"

这会导致 NoReverseMatch 错误:

NoReverseMatch at /1/tickets/
Reverse for 'ticket_list' with no arguments not found. 1 pattern(s) tried: ['(?P<team_pk>[^/]+)/tickets/$']

我希望反向匹配只使用team_pk URL kwarg 的当前值。

我试图解决的问题:

我找到了下面这个问题的解决方法,但是涉及到很多重复,我感觉肯定有DRYer的方式。

首先,我为网站上的每个视图扩展了get_context_data() 方法。

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['current_team_pk'] = self.kwargs['team_pk']
    return context

然后我在每个 URL 模板标签中引用这个上下文:

href="{% url 'tracker:ticket_list' team_pk=current_team_pk %}"

这会产生所需的行为,但会重复很多。那么,有没有更好的办法呢?

编辑:

根据 Willem Van Onsem 的建议,我将 URL 模板标签更改为 href="{% url 'tracker:ticket_list' team_pk=team_pk %}",直接引用 URL kwarg。但这似乎并不可靠。在索引页面上/&lt;team_pk&gt;/ 加载得很好,它包括两个相关的 URL:/&lt;team_pk&gt;//&lt;team_pk&gt;/tickets/。但是,当我导航到 /&lt;team_pk&gt;/tickets/ 时,我收到另一个 NoReverseMatch 错误:

NoReverseMatch at /1/tickets/
Reverse for 'home' with keyword arguments '{'team_pk': ''}' not found. 1 pattern(s) tried: ['(?P<team_pk>[^/]+)/$']

似乎由于某种原因没有通过 URL kwarg &lt;team_pk&gt;。但是到'home' 的唯一链接是我的base.html 的一部分,其他模板正在扩展它。所以相关的模板标签都是一样的。

编辑 2:

有问题的观点:

class TicketTable(LoginRequiredMixin, SingleTableMixin, FilterView):
    table_class = my_tables.TicketTable
    template_name = 'tracker/ticket_list.html'
    filterset_class = TicketFilter
    context_object_name = 'page'
    table_pagination = {"per_page": 10}
    PAGE_TITLE = 'Open Tickets'
    TICKET_STATUS_TOGGLE = 'Show Closed Tickets'
    TICKET_STATUS_TOGGLE_URL = 'tracker:closed_ticket_list'
    DISPLAY_DEV_FILTER = True
    DISPLAY_STATUS_FILTER = True

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['page_title'] = self.PAGE_TITLE
        context['ticket_status_toggle'] = self.TICKET_STATUS_TOGGLE
        context['ticket_status_toggle_url'] = self.TICKET_STATUS_TOGGLE_URL
        context['display_dev_filter'] = self.DISPLAY_DEV_FILTER
        context['display_status_filter'] = self.DISPLAY_STATUS_FILTER
        return context

    def get_queryset(self):
        return models.Ticket.objects.filter_for_team(self.kwargs['team_pk']).filter_for_user(self.request.user).exclude(status='closed')

编辑 3:

我找到了一种无需修改上下文数据即可访问 URL kwargs 的解决方案。我不确定为什么 team_pk=team_pk 在 URL 标记中不起作用,但 team_pk=view.kwargs.team_pk 确实起作用。

【问题讨论】:

  • ,但您不必扩展 get_context_data,因为命名的 URL 参数也会直接传递给模板。

标签: python django


【解决方案1】:

根据我的朋友 Willem Van Onsem 的 cmet 和回复,以及我自己的一些挖掘,我发现了我认为最干燥的方法来做我想做的事情。我创建了一个自定义 mixin:

class CommonTemplateContextMixin:
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if self.kwargs.get('team_pk'):
            context.setdefault('team_pk', self.kwargs.get('team_pk'))
        else:
            context.setdefault('team_pk', self.request.user.teams.all()[0].pk)
        return context

然后我用我所有的视图子类化这个 mixin。然后我的所有模板中都有一个team_pk 模板标签,我只需将team_pk=team_pk 添加到我所有的URL 模板标签中。使用它而不是 team_pk=view.kwargs.team_pk 的唯一优点是我可以为 URL kwarg 不可用的情况添加一些额外的逻辑。

【讨论】:

    猜你喜欢
    • 2021-06-05
    • 2011-01-08
    • 2021-02-11
    • 2011-06-03
    • 2017-08-11
    • 1970-01-01
    • 2013-08-18
    • 2021-11-30
    相关资源
    最近更新 更多