Django 通用视图:何时使用 ListView 与 DetailView

Posted

技术标签:

【中文标题】Django 通用视图:何时使用 ListView 与 DetailView【英文标题】:Django Generic Views: When to use ListView vs. DetailView 【发布时间】:2012-04-04 08:22:05 【问题描述】:

我在博客应用程序中使用 Django 的基于类的通用视图。我的一个视图显示了具有特定标签的帖子列表。我可以将此视图写为ListView 的帖子,按标签过滤。或者我可以将此视图写为标签的DetailView,并将相关帖子添加到上下文中。

有一种方式比另一种方式更合适——或者 Pythonic——吗?

ListView 方法似乎更具语义性,因为我想要的是一个帖子的列表,但它也稍微复杂一些。它要求我覆盖两种方法。 DetailView 方法只需要我覆盖一个方法。

class PostTagView(ListView):
    """Display all blog posts with a given tag."""
    queryset = Post.objects.published()

    def get_context_data(self, **kwargs):
        context = super(PostTagView, self).get_context_data(**kwargs)
        context['tag'] = get_object_or_404(Tag, slug=self.kwargs['slug'])
        return context

    def get_queryset(self, **kwargs):
        queryset = super(PostTagView, self).get_queryset()
        return queryset.filter(tags__slug=self.kwargs['slug'])


class TagDetailView(DetailView):
    """Display all blog posts with a given tag."""
    model = Tag

    def get_context_data(self, **kwargs):
        context = super(TagDetailView, self).get_context_data(**kwargs)
        context['object_list'] = Post.objects.published().filter(tags__slug=self.kwargs['slug'])
        return context

【问题讨论】:

【参考方案1】:

有趣的问题。不幸的是,答案并不那么有趣:选择对您和您的应用最有意义的那个。任何一种方法都可以平等地争论,所以这实际上只是一个判断电话。

【讨论】:

【参考方案2】:

根据经验,请查看 URL 中的参数。如果您使用的是slugTag,那么您很可能处理的是DetailView 而不是ListView

在这种情况下,第二种方法使用的代码更少,而且更优雅。但是,这也取决于您稍后将如何处理视图。如果您要添加表单来编辑帖子,则改用ListView 可能更有意义。但是没有技术上的理由偏爱其中一种,只是您最终可能会在一种方法中编写比另一种方法更多的代码。

【讨论】:

将其与 URL 参数匹配是有意义的。 很好的答案。现在你将如何对其进行分页?使用列表视图,这很简单。将其作为详细视图进行操作,我迷路了:( @DanGayle:DetailView 不应该分页,它只能用于一个对象。 除了这个答案中的上述逻辑。我正在查看一个标签的详细视图,该标签恰好有大量我想要分页的帖子。我可以很容易地把它写成一个列表视图,但是我不得不将标签 back 添加到上下文中。这似乎倒退了。 @DanGayle 您可以将MultipleObjectMixin 添加到您的DetailView,这样您就可以重复使用分页。您只需要确保将self.object_list 设置为您想要分页的过滤对象的查询集。【参考方案3】:

文章中完美描述了基于类的通用视图的用例:

https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views

在上述文章中,您将能够了解何时/为什么以及如何使用 ListView/DetailView 以及简单的示例。

【讨论】:

【参考方案4】:

ListView 和 DetailView 在技术上是不一样的, 例如,您不能在 urls.py 中提供如下所示的 DetailView 的路径,

path('schools_detail/',views.SchoolDetailView.as_view(),name = "detail"),

这将给出以下错误,

通用详细视图 SchoolDetailView 必须使用 URLconf 中的对象 pk 或 slug。

这意味着如果我们有一个名为 Student 的表和另一个名为 School 的表,我们可以使用 ListView 列出所有学校,如下所示,

path('list/',views.SchoolListView.as_view(),name = "list"),

如果我们想在单击学校图标时列出个别学校的学校详细信息,那么我们可以使用 Django 在内部创建的 School 的主键并在 url 模式中捕获它,在我的例子中是 url 模式将是“list/school.id”,因此为了捕捉到这一点,我们必须为 DetailsView 提供如下路径,

path('list/<int:pk>/',views.SchoolDetailView.as_view(),name = "detail"),

所以底线是,在大多数情况下,您可以将 ListView 用作普通视图,如果您想访问另一个视图但只访问该视图中使用主键引用的特定详细信息,那么您可以使用 DetailsView( DetailsView 的 url 模式将通过在 url 中提供主键信息来生成,如果 url 中没有主键,它将无法工作,因为它不会获取所有信息,而只会获取与 url 中的主键相关的信息)

【讨论】:

以上是关于Django 通用视图:何时使用 ListView 与 DetailView的主要内容,如果未能解决你的问题,请参考以下文章

Django通用类视图实现忘记密码重置密码功能

使用Python Django框架创建一个小型博客

如何在 Django 通用列表视图类中使用 slugfield 创建链接?

Django:基于通用视图的“as_view()”方法

子类化 Django ListView

django 中用于简单通用视图的 extra_context 函数