[英]Django: passing a URL parameter to every instance of a reverse URL lookup in a template tag
Sorry if the title is unclear, I'm not sure the best way to describe the issue.抱歉,如果标题不清楚,我不确定描述问题的最佳方式。 I have an application with a Ticket
model and a Team
model.我有一个带有Ticket
model 和Team
model 的应用程序。 All Ticket
s are associated with a single Team
.所有Ticket
都与一个Team
相关联。 The issue I'm having is a problem of URL reversing.我遇到的问题是 URL 倒车的问题。 I'm trying to set it up my URLs like so: /<team_pk>/tickets/
displays a list of tickets associated with the Team specified by team_pk
.我正在尝试像这样设置我的 URL: /<team_pk>/tickets/
显示与team_pk
指定的团队相关联的票证列表。 So /1/tickets/
would display all of the tickets for the first Team.所以/1/tickets/
将显示第一个团队的所有门票。 Both of these objects are in the app tracker
.这两个对象都在 app tracker
中。
To do this, I've set up my project/urls.py files like so:为此,我设置了我的 project/urls.py 文件,如下所示:
project/urls.py项目/urls.py
urlpatterns = [ path('<team_pk>/', include('tracker.urls', namespace='tracker')), ]
tracker/urls.py跟踪器/urls.py
urlpatterns = [ path('tickets/', views.TicketTable.as_view(), name='ticket_list'), ]
Then, inside my html templates, I have the following URL tag:然后,在我的 html 模板中,我有以下 URL 标签:
href="{% url 'tracker:ticket_list' %}"
This results in a NoReverseMatch error:这会导致 NoReverseMatch 错误:
NoReverseMatch at /1/tickets/
Reverse for 'ticket_list' with no arguments not found. 1 pattern(s) tried: ['(?P<team_pk>[^/]+)/tickets/$']
What I would like is for the reverse match to just use the current value for the team_pk
URL kwarg.我想要的是反向匹配只使用team_pk
URL kwarg 的当前值。
What I have tried to fix it:我试图解决的问题:
I have found the following solution to the problem, but it involves a lot of repetition, and I feel like there must be a DRYer way.我找到了以下解决问题的方法,但是它涉及到很多重复,我觉得必须有一个 DRYer 的方式。
First, I extend the get_context_data()
method for every view on the site.首先,我为站点上的每个视图扩展了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
Then I reference this context in every URL template tag:然后我在每个 URL 模板标签中引用这个上下文:
href="{% url 'tracker:ticket_list' team_pk=current_team_pk %}"
This results in the desired behavior, but it's a lot of repetition.这会产生所需的行为,但需要大量重复。 So, is there a better way?那么,有没有更好的方法呢?
Edit:编辑:
Based on Willem Van Onsem's suggestion, I changed the URL template tag to href="{% url 'tracker:ticket_list' team_pk=team_pk %}"
, referencing the URL kwarg directly. Based on Willem Van Onsem's suggestion, I changed the URL template tag to href="{% url 'tracker:ticket_list' team_pk=team_pk %}"
, referencing the URL kwarg directly. But this doesn't seem to be working reliably.但这似乎并不可靠。 On the index page /<team_pk>/
loads just fine, and it includes two relevant URLs: /<team_pk>/
and /<team_pk>/tickets/
.在索引页面上/<team_pk>/
加载得很好,它包括两个相关的 URL: /<team_pk>/
和/<team_pk>/tickets/
。 When I navigate to /<team_pk>/tickets/
, however, I get another NoReverseMatch error:但是,当我导航到/<team_pk>/tickets/
时,我收到另一个 NoReverseMatch 错误:
NoReverseMatch at /1/tickets/
Reverse for 'home' with keyword arguments '{'team_pk': ''}' not found. 1 pattern(s) tried: ['(?P<team_pk>[^/]+)/$']
It seems the URL kwarg <team_pk>
is not being passed for some reason.似乎 URL kwarg <team_pk>
由于某种原因没有通过。 But the only link to 'home'
is part of my base.html
, which the other templates are extending.但是到'home'
的唯一链接是我的base.html
的一部分,其他模板正在扩展。 So the relevant template tags are the same.所以相关的模板标签是一样的。
Edit 2:编辑2:
The view in question:有问题的观点:
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')
Edit 3:编辑3:
I found a solution to access the URL kwargs without modifying context data.我找到了一种无需修改上下文数据即可访问 URL kwargs 的解决方案。 I'm not sure why team_pk=team_pk
didn't work in the URL tag, but team_pk=view.kwargs.team_pk
does work.我不确定为什么team_pk=team_pk
在 URL 标签中不起作用,但team_pk=view.kwargs.team_pk
确实起作用。
Based on the comments and responses from Willem Van Onsem, a friend of mine, and some of my own digging, I found what I think is the DRYest way to do what I was trying to do.根据我的朋友 Willem Van Onsem 的评论和回复,以及我自己的一些挖掘,我发现了我认为最干的方法来做我想做的事情。 I created a custom mixin:我创建了一个自定义 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
Then I subclass this mixin with all my views.然后我用我所有的观点对这个 mixin 进行子类化。 Then I have a team_pk
template tag inside all my templates, and I just add team_pk=team_pk
to all my URL template tags.然后我的所有模板中都有一个team_pk
模板标签,我只需将team_pk=team_pk
添加到我所有的 URL 模板标签中。 The only advantage to using this instead of team_pk=view.kwargs.team_pk
is that I can add some additional logic for the case when the URL kwarg isn't available.使用它而不是team_pk=view.kwargs.team_pk
的唯一优点是,当 URL kwarg 不可用时,我可以添加一些额外的逻辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.