django 没有与过滤后的 ListView 的反向匹配

django no reverse match with filtered ListView

我现在已经解决了这个问题,这是我需要做的,我在下面留下了我原来的问题未经编辑的内容。所以我原来的观点很好,虽然我添加了一个 try except 块以便能够过滤所有:

class ProjectListView(ListView):

    def get_queryset(self):
        try:
            self.area = get_object_or_404(Area, name=self.kwargs['area'])
        except:
            return Project.objects.all()
        return Project.objects.filter(area=self.area)

我无法告诉您这是否是好的做法,但它确实有效。所以接下来,我不得不更改我的 urls.py 文件,因为我的 "project-create" url 正好匹配我的 "project-list" url,这是通过添加 "list/" 到我的项目列表:

urlpatterns = [
     path('list/<area>/', ProjectListView.as_view(), name='project-list'),
     path('project-create/',
          ProjectCreateView.as_view(), name='project-create'),
     path('<slug:slug>/update/', project_update_view, name='project-update'),
     path('search/', search, name='search'),
]

最后在我的模板中,我有一个用于过滤的下拉菜单,不幸的是它有点难看,但那是因为我在外键中使用了 related_name,但它有效:

<form method="GET">
        <fieldset>
          <p>
            <label>Area</label>
            <select name="select-area" onchange="location = this.value;">
              <option value="#">Select</option>
              <option value="{% url 'project-list' "All" %}">All</option>
              <option value="{% url 'project-list' "Digital" %}">Digital</option>
              <option value="{% url 'project-list' "Uplink" %}">Uplink</option>
              <option value="{% url 'project-list' "DTH VoD" %}">DTH VoD</option>
              <option value="{% url 'project-list' "Interactive" %}">Interactive</option>
              <option value="{% url 'project-list' "OTT Streaming" %}">OTT Streaming</option>
              <option value="{% url 'project-list' "OTT VoD" %}">OTT VoD</option>
              <option value="{% url 'project-list' "OTT Platform" %}">OTT Platform</option>
              <option value="{% url 'project-list' "Operational Improvement" %}">Operational Improvement</option>
              <option value="{% url 'project-list' "Archive" %}">Archive</option>
            </select>
          </p>
        </fieldset>
      </form>

关于第一个选项的快速说明是因为下拉菜单默认为执行下拉项时的第一个选项,虽然不理想但它可以工作。第二项专门使用 "All" 只是因为我的数据库中永远不会有它,它旨在触发视图中的 try except 块。希望这对某个地方的人有帮助。

我的原始问题从这里开始: 既然我已经在 ListView 上设置了过滤器,我正在尝试找出如何从模板传递 url。这是我覆盖 get_queryset() 以过滤 Project 模型的 area 属性的视图。这很好用,但是,在设置过滤之前,一切都很好,但是当然现在我有一个动态变量添加到 url,反向查找不再有效。

在理想情况下,它会传递一些东西来获得未过滤的列表视图,因为我也需要它作为下拉链接。

这是我的观点:

class ProjectListView(ListView):

    def get_queryset(self):
        self.area = get_object_or_404(Area, name=self.kwargs['area'])
        return Project.objects.filter(area=self.area)

这是我对这个应用的 url:

urlpatterns = [
     path('<area>/', ProjectListView.as_view(), name='project-list'),
     path('project-create/',
          ProjectCreateView.as_view(), name='project-create'),
     path('<slug:slug>/update/', project_update_view, name='project-update'),
     path('search/', search, name='search'),
]

这里是模板中的url:

<a href="{% url 'project-list' %}">
    <h2>Service Integration Development Project Portal</h2>
</a>

它在某种程度上不再像预期的那样工作 'area'。

这是我遇到的错误:

NoReverseMatch at /si/Operational Improvement/

Reverse for 'project-list' with no arguments not found. 1 pattern(s) tried: ['si/(?P<area>[^/]+)/$']

Request Method:     GET
Request URL:    http://127.0.0.1:8000/si/Operational%20Improvement/
Django Version:     2.2.1
Exception Type:     NoReverseMatch
Exception Value:    

Reverse for 'project-list' with no arguments not found. 1 pattern(s) tried: ['si/(?P<area>[^/]+)/$']

Exception Location:     /Users/me/anaconda3/envs/django_env/lib/python3.7/site-packages/django/urls/resolvers.py in _reverse_with_prefix, line 668
Python Executable:  /Users/me/anaconda3/envs/django_env/bin/python
Python Version:     3.7.3
Python Path:    

['/Users/me/Documents/Python/pcc_django',
 '/Users/me/.vscode/extensions/ms-python.python-2019.9.34474/pythonFiles',
 '/Users/me/anaconda3/envs/django_env/lib/python37.zip',
 '/Users/me/anaconda3/envs/django_env/lib/python3.7',
 '/Users/me/anaconda3/envs/django_env/lib/python3.7/lib-dynload',
 '/Users/me/anaconda3/envs/django_env/lib/python3.7/site-packages']

Server time:    Thu, 5 Sep 2019 09:52:37 +0000
Error during template rendering

In template /Users/me/Documents/Python/pcc_django/project_portal/templates/project_portal/base.html, error at line 60
Reverse for 'project-list' with no arguments not found. 1 pattern(s) tried: ['si/(?P<area>[^/]+)/$']

我应该在 url 中传递什么以获得 'all' 而不仅仅是过滤后的 'area'?

您似乎将 URL 定义为(请注意,它需要 URL 中 area 的值):

path('<area>/', ProjectListView.as_view(), name='project-list'),

但在您的模板中,您调用它时没有 area 的值(实际上,您没有将其他参数传递给 url 标记):

<a href="{% url 'project-list' %}">

解决方案 1:area 传递给您的 url 标签,像这样

// assuming that 'area' is an instance of the model 'Area'
<a href="{% url 'project-list' area.name %}">

方案二:加一个URL不加area

path('', ProjectListView.as_view(), name='project-list'),
path('<area>/', ProjectListView.as_view(), name='project-list-with-area'),

并修改您的视图以处理没有 area:

的情况
class ProjectListView(ListView):
    model = Project

    def get_queryset(self):
        qs = super().get_queryset()

        try:
            qs = qs.filter(area__name=self.kwargs['area'])
        except KeyError:
            # will land here if 'area' is not present, so we return all
            # instances and do not filter anything
            pass

        return qs

并且在您的模板中现在可以同时包含两个链接

<a href="{% url 'project-list' %}">
<a href="{% url 'project-list-with-area' area.name %}">