另一个考虑是基于类的通用视图的上下文数据将覆盖上下文处理器提供的数据。请参阅 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》频道 >>

Python编程 从入门到实践 第2版
python入门书籍,非常畅销,超高好评,python官方公认好书。