内置基于类的通用视图


当前第2页 返回上一页

另一个考虑是基于类的通用视图的上下文数据将覆盖上下文处理器提供的数据。请参阅 get_context_data()示例。

查看对象的子集

现在,让我们仔细看看model我们一直使用的参数。该model参数指定了将对视图进行操作的数据库模型,该参数可用于对单个对象或对象集合进行操作的所有通用视图。但是,model参数不是指定视图将操作的对象的唯一方法–您还可以使用queryset参数指定对象列表:

from django.views.generic import DetailView
from books.models import Publisher
?
class PublisherDetail(DetailView):
?
  context_object_name = 'publisher'
  queryset = Publisher.objects.all()

指定是简短的说法。但是,通过使用定义对象的过滤列表,您可以更详细地了解视图中将显示的对象(有关对象的更多信息,请参见进行查询,有关完整的详细信息 ,请参见 基于类的视图参考)。model = Publisher``queryset = Publisher.objects.all()``querysetQuerySet

举个例子,我们可能想按出版日期订购书籍清单,以最新的为准:

from django.views.generic import ListView
from books.models import Book
?
class BookList(ListView):
  queryset = Book.objects.order_by('-publication_date')
  context_object_name = 'book_list'

这是一个非常小的例子,但是很好地说明了这个想法。当然,通常您不仅仅需要对对象重新排序,还需要做更多的事情。如果要显示特定出版商的书籍列表,则可以使用相同的技术:

from django.views.generic import ListView
from books.models import Book

class AcmeBookList(ListView):

    context_object_name = 'book_list'
    queryset = Book.objects.filter(publisher__name='ACME Publishing')
    template_name = 'books/acme_list.html'

请注意,除了filter之外queryset,我们还使用了自定义模板名称。如果我们不这样做,则通用视图将使用与“香草”对象列表相同的模板,而这可能不是我们想要的。

另请注意,这不是制作出版商特定书籍的一种非常优雅的方法。如果我们要添加另一个发布者页面,则需要在URLconf中再加上几行,并且不止几个发布者会变得不合理。我们将在下一部分中解决这个问题。

注意:如果在请求时收到404,请/books/acme/检查以确保您实际上拥有名称为'ACME Publishing'的发布商。通用视图allow_empty对此情况有一个参数。

动态过滤

另一个常见的需求是通过URL中的某个键过滤列表页面中给定的对象。之前我们在URLconf中硬编码了出版商的名称,但是如果我们想编写一个视图来显示某个任意出版商的所有书籍,该怎么办?

方便地,我们ListView有一个get_queryset()可以覆盖的 方法。默认情况下,它返回queryset属性的值,但是我们可以使用它添加更多的逻辑。

进行这项工作的关键部分是,当调用基于类的视图时,各种有用的东西都存储在self;以及request(self.request)包括根据URLconf捕获的position(self.args)和基于名称的(self.kwargs)参数。

在这里,我们有一个URLconf,其中包含一个捕获的组:

# urls.py
from django.urls import path
from books.views import PublisherBookList

urlpatterns = [
    path('books/<publisher>/', PublisherBookList.as_view()),
]

接下来,我们将编写PublisherBookList视图本身:

# views.py
from django.shortcuts import get_object_or_404
from django.views.generic import ListView
from books.models import Book, Publisher

class PublisherBookList(ListView):

    template_name = 'books/books_by_publisher.html'

    def get_queryset(self):
        self.publisher = get_object_or_404(Publisher, name=self.kwargs['publisher'])
        return Book.objects.filter(publisher=self.publisher)

使用get_queryset向查询集选择添加逻辑既方便又强大。例如,如果需要的话,我们可以使用 self.request.user当前用户或其他更复杂的逻辑进行过滤。

我们还可以同时将发布者添加到上下文中,因此我们可以在模板中使用它:

# ...

def get_context_data(self, **kwargs):
    # Call the base implementation first to get a context
    context = super().get_context_data(**kwargs)
    # Add in the publisher
    context['publisher'] = self.publisher
    return context

执行额外的工作

我们将看到的最后一个常见模式涉及在调用通用视图之前或之后做一些额外的工作。

想象一下,我们last_accessed在Author模型上有一个字段,用于跟踪任何人上次查看该作者的时间:

# models.py
from django.db import models

class Author(models.Model):
    salutation = models.CharField(max_length=10)
    name = models.CharField(max_length=200)
    email = models.EmailField()
    headshot = models.ImageField(upload_to='author_headshots')
    last_accessed = models.DateTimeField()

DetailView当然,泛型类对此字段一无所知,但是我们可以再次轻松编写一个自定义视图以使该字段保持更新。

首先,我们需要在URLconf中添加作者详细信息位以指向自定义视图:

from django.urls import path
from books.views import AuthorDetailView

urlpatterns = [
    #...
    path('authors/<int:pk>/', AuthorDetailView.as_view(), name='author-detail'),
]

然后,我们将编写新视图– get_object是检索对象的方法–因此我们将其覆盖并包装调用:

from django.utils import timezone
from django.views.generic import DetailView
from books.models import Author

class AuthorDetailView(DetailView):

    queryset = Author.objects.all()

    def get_object(self):
        obj = super().get_object()
        # Record the last accessed date
        obj.last_accessed = timezone.now()
        obj.save()
        return obj

注意:URLconf在此使用命名组pk-该名称是默认名称,DetailView用于查找用于过滤查询集的主键的值。

详情参考: https://docs.djangoproject.com/en/3.0/



标签:Django

返回前面的内容

相关阅读 >>

Django 安装

Django 教程介绍

Django 创建第一个项目

使用wsgi进行部署

使用基于类的视图进行表单处理

内置基于类的通用视图

将mixins与基于类的视图一起使用

部署静态文章

Django 使用表单模板

Django 模型

更多相关阅读请进入《Django》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...