View的其他子类

ListView

  • 继承自MultipleObjectTemplateResponseMixin

    • 该类继承自TemplateResponseMixin
    • 获取模板名字

      • 首先根据template_name获取
      • 如果没找到

        • 自己根据应用的名字,关联模型的名字,_list.html去查找
        • 例如:App/book_list.html去查找
  • 继承自BaseListView

    • 继承自MultipleObjectMixin

      • 继承自ContextMixin

        • 该类做了模型查询,以及分页等等功能
        • get_queryset查询结果集
        • model/query_Set
    • 继承自View
    • 默认实现了get,渲染成了response

View的子类中有ListView:

class ListView(MultipleObjectTemplateResponseMixin, BaseListView):
    """
    Render some list of objects, set by `self.model` or `self.queryset`.
    `self.queryset` can actually be any iterable of items, not just a queryset.
    """

这个类比较奇怪,只写了注释没有其他的代码,现在进行LIstView的实验。

使用ListView来渲染列表

所需内容

需要集合数据和模板

集合数据

在Models.py中创建模型:

from django.db import models
class Book(models.Model):
    ba_name =models.CharField(max_length=32)

迁移数据库

views.py中新建HelloListView类继承自ListView:

class HelloListView(ListView):
    template_name='BookList.html'
    model = Book

urls.py添加:

    url(r'^listview/',views.HelloListView.as_view(),name='listview'),

模板

新建BookList.html页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BookList</title>
</head>
<body>
{% for book in object_list %}
<li>{{ book.ba_name }}</li>
{% endfor %}
</body>
</html>

访问测试



所以现在加载列表不需要再去写查询语句,只需要调用Listview所带的方法。

DetailView

  • 继承自SingleObjectTemplateResponseMixin单个对象模板响应的复合类

    • 继承自TemplateResponseMixin
    • 重写了获取模板名字的方法
  • 继承自BaseDetailView

    • 继承自View
    • 继承自SingleObjectMixin
    class DetailView(SingleObjectTemplateResponseMixin, BaseDetailView):
      """
      Render a "detail" view of an object.
    
      By default this is a model instance looked up from `self.queryset`, but the
      view will support display of *any* object by overriding `self.get_object()`.
      """

    实验:使用DetailView来查询具体的一本书

    urls:

      url(r'single/(?P<pk>\d+)/',views.HelloDetailView.as_view(),name='single')

    views:

      <meta charset="UTF-8">
      <title>book</title>
    </head>
    <body>
    <h2>{{ book.ba_name }}</h2>
    </body>
    </html>

    访问测试



    这样我们就可以通过Detailview来实现访问某一具体的对象的页面。

实验:书籍列表与每本书详情页面联动

BookList.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>BookList</title>
</head>
<body>
{% for book in object_list %}
<li><a href="{% url 'cbv:single' pk=book.id %}">{{ book.ba_name }}</a></li>
{% endfor %}
</body>
</html>

测试:


换一种思路改写

利用DetailView继承的SingleObjectTemplateResponseMixin子类(39到43行中):

class SingleObjectTemplateResponseMixin(TemplateResponseMixin):
    template_name_field = None
    template_name_suffix = '_detail'

    def get_template_names(self):
        """
        Return a list of template names to be used for the request. May not be
        called if render_to_response is overridden. Returns the following list:

        * the value of ``template_name`` on the view (if provided)
        * the contents of the ``template_name_field`` field on the
          object instance that the view is operating upon (if available)
        * ``<app_label>/<model_name><template_name_suffix>.html``
        """
        try:
            names = super(SingleObjectTemplateResponseMixin, self).get_template_names()
        except ImproperlyConfigured:
            # If template_name isn't specified, it's not a problem --
            # we just start with an empty list.
            names = []

            # If self.template_name_field is set, grab the value of the field
            # of that name from the object; this is the most specific template
            # name, if given.
            if self.object and self.template_name_field:
                name = getattr(self.object, self.template_name_field, None)
                if name:
                    names.insert(0, name)

            # The least-specific option is the default <app>/<model>_detail.html;
            # only use this if the object in question is a model.
            if isinstance(self.object, models.Model):
                object_meta = self.object._meta
                names.append("%s/%s%s.html" % (
                    object_meta.app_label,
                    object_meta.model_name,
                    self.template_name_suffix
                ))
            elif hasattr(self, 'model') and self.model is not None and issubclass(self.model, models.Model):
                names.append("%s/%s%s.html" % (
                    self.model._meta.app_label,
                    self.model._meta.model_name,
                    self.template_name_suffix
                ))

由39到43行中,我们可以看到可以在Template文件夹中新建App文件夹,创建"model_name"+"_detail.html"
文件,然后就可以自动实现每本书的详情页面。

步骤

views:

class HelloDetailView(DetailView):
    model = Book

新建html:


测试:

我们还可以用queryset来代替model查询:
views.py:

class HelloDetailView(DetailView):
    # template_name = 'Book.html'
    # model = Book
    queryset = Book.objects.all()
最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏