Home >  > Django Class View

Django Class View

以前自己用django开发网站,都是用的函数view,最近在学习Class View。

ListView 用于获取某个 model 的列表,获取的是一系列对象。

  • 复写 get_queryset 方法(获取视图的对象列表,重写这个方法可以实现动态过滤)以增加获取 model 列表的其他逻辑
  • 复写 get_context_data (添加额外的上下文)方法来为上下文对象添加额外的数据以便在模板中访问
  • DetailView用于获取某个 model 的单个对象中,比如 Blog 里点击某篇文章后进入文章的详情页。

  • 复写 get_object 方法以增加获取单个 model 对象的其他逻辑
  • 复写 get_context_data 方法来为上下文对象添加额外的变量以便在模板中访问
  • 一、最简单的Class View
    其实最简单位的view是这样的

    class PublisherList(ListView):
        model = Publisher
    

    url的设置是这样的:

    urlpatterns = [
        url(r'^publishers/$', PublisherList.as_view()),
    ]
    

    如果你没有指定模板,则django会自动寻找books/publisher_list.html这个模板。

    二、context_object_name有什么用?

    如果你不使用context_object_name,你模板中的写法是这样的:

    <ul>
        {% for publisher in object_list %}
            <li>{{ publisher.name }}</li>
        {% endfor %}
    </ul>
    

    如果你使用context_object_name,你模板中的写法是这样的:

    <ul>
        {% for publisher in publisher_list %}
            <li>{{ publisher.name }}</li>
        {% endfor %}
    </ul>
    

    也就是说:

    Using function based view:

    def index(request):
        product_list = Product.objects.all()
        return render(request, 'product/index.html', {'product_list': **product_list**})
    

    Using class based view

    
    class ProductListView(ListView):
        model = Product
        template_name = 'product/index.html'
        context_object_name = 'product_list'
    
    

    三、get_context_data 呈现额外信息
    给传递到模板文件的上下文对象(context)添加额外的内容的,例如,你想在每个Publisher(出版商)详细信息页面上显示所有书籍的列表。

    
    from django.views.generic import DetailView
    from books.models import Publisher, Book
    
    class PublisherDetail(DetailView):
    
        model = Publisher
    
        def get_context_data(self, **kwargs):
            # Call the base implementation first to get a context
            context = super(PublisherDetail, self).get_context_data(**kwargs)
            # Add in a QuerySet of all the books
            context['book_list'] = Book.objects.all()
            return context
    

    还看到有人这样写的:

    class IndexView(ListView):
        template_name = "blog/index.html"
        context_object_name = "article_list"
        model = Article
     
        def get_context_data(self, **kwargs):
            kwargs['category_list'] = Category.objects.all().order_by('name')
            return super(IndexView, self).get_context_data(**kwargs)
    

    参考:https://blog.csdn.net/ros_donggua/article/details/81024650

    四、自定义显示queryset

    class BookList(ListView):
        queryset = Book.objects.order_by('-publication_date')
        context_object_name = 'book_list'
    
    
    
    class AcmeBookList(ListView):
    
        context_object_name = 'book_list'
        queryset = Book.objects.filter(publisher__name='ACME Publishing')
        template_name = 'books/acme_list.html'
    

    五、动态过滤 get_queryset

    但是如果我们想编写一个视图来显示某个任意出版商的所有书籍怎么办?

    
    # urls.py
    from django.conf.urls import url
    from books.views import PublisherBookList
    
    urlpatterns = [
        url(r'^books/([\w-]+)/$', PublisherBookList.as_view()),
    ]
    
    class PublisherBookList(ListView):
    
        template_name = 'books/books_by_publisher.html'
    
        def get_queryset(self):
            self.publisher = get_object_or_404(Publisher, name=self.args[0])
            return Book.objects.filter(publisher=self.publisher)
    
    

    参考:https://docs.djangoproject.com/en/1.10/topics/class-based-views/generic-display/#making-friendly-template-contexts

    例2:
    通过get_queryset实现只显示已发表的文章。

    六、执行额外的工作get_object
    如果需要在获取过程中对获取的对象做一些处理,比如对文章做 markdown 拓展,通过复写 get_object 即可实现。

    比如我们的 Author 模型中有一个 last_accessed 字段,我们用它来跟踪任何人最后一次查看该作者的时间。

    
    # 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()
    
    
    from django.conf.urls import url
    from books.views import AuthorDetailView
    
    urlpatterns = [
        #...
        url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetailView.as_view(), name='author-detail'),
    ]
    

    然后我们将编写我们的新视图——get_object 是检索对象的方法——所以我们只需覆盖它并包装调用:

    
    from django.views.generic import DetailView
    from django.utils import timezone
    from books.models import Author
    
    class AuthorDetailView(DetailView):
    
        queryset = Author.objects.all()
    
        def get_object(self):
            # Call the superclass
            object = super(AuthorDetailView, self).get_object()
            # Record the last accessed date
            object.last_accessed = timezone.now()
            object.save()
            # Return the object
            return object
    

    暧昧帖

    本文暂无标签