Django的通用模板

本文介绍了Django的通用视图,包括TemplateView、ListView和DetailView的使用。TemplateView主要用于返回模板,ListView用于显示数据库列表,DetailView用于展示单个对象详情。通过这些通用视图,可以简化视图开发,提高代码复用性。同时,文章还展示了如何处理静态网页和从数据库获取并显示数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在某些情况下编写视图代码,正如我们所看到前面工作真的很繁重。想象一下,只需要一个静态页面或列表页。 Django还提供了一种简单的方法来设置这些简单的视图被称为通用视图。

不同于传统的视图,一般的视图是一个类但没有函数。Django还提供了一组类 django.views.generic 通用视图,以及每一个普通视图是这些类或从它们中的一个类继承的。

有10+泛型类−

>>> import django.views.generic
>>> dir(django.views.generic)

['ArchiveIndexView', 'CreateView', 'DateDetailView', 'DayArchiveView', 
   'DeleteView', 'DetailView', 'FormView', 'GenericViewError', 'ListView', 
   'MonthArchiveView', 'RedirectView', 'TemplateView', 'TodayArchiveView', 
   'UpdateView', 'View', 'WeekArchiveView', 'YearArchiveView', '__builtins__', 
   '__doc__', '__file__', '__name__', '__package__', '__path__', 'base', 'dates', 
   'detail', 'edit', 'list']


基于函数的视图的问题在于,虽然它们很好地覆盖了简单的情形,但是不能扩展或自定义它们,即使是一些简单的配置选项,这让它们在现实应用中受到很多限制。基于类的通用视图然后应运而生,目的与基于函数的通用视图一样,就是为了使得视图的开发更加容易。

下面三个是最常使用的基于类的通用视图:

TemplateView,ListView,DetailView

TemplateView

TemplateView 一般只在需要返回模板时使用。

class ProtectView(TemplateView):
    template_name = 'polls/name.html'  

TemplateView 可以方便的定义要返回的模板但它不能把数据库中的内容查询展示出来,所以需要使用 DetailViewListView

所有基于类的通用视图中定义的方法需要在类视图调用 as_view() 方法后会被自动调用,因为 DjangoURL 解析器将请求和关联的参数发送给一个可调用的函数而不是一个类,所以基于类的视图有一个 as_view() 类方法用来作为类的可调用入口。

ListView

ListView 用于获取存储在数据库中的某个 Model 的列表。

class IndexView(ListView):  
    """
        首页视图函数,继承 ListView ,展示从数据库中获取的文章列表   
    """
    template_name = "blog/index.html"
    context_object_name = "article_list"
    model = Article

template_name 属性指定了需要渲染的模板,context_object_name 指定了模板中使用的上下文变量,model 指定了数据的来源。它的功能相当于取出了 modelArticle 的所有数据,使用变量 article_list 传递给了 blog/index.html 模板。ListView 中默认使用 object_list 作为上下文变量,可以使用 context_object_name 来自定义上下文变量,一般使用默认的对模板设计者不友好,所以都是自定义上下文变量的。model 属性指定了要获取表中的所有数据,它的功能相当于 article_list = Article.objects.all(),但是当你需要使用过滤条件或者对数据进行一定的操作时,则需要重写 ListView 中获取数据的方法(get_queryset 方法),像下面这样:

class IndexView(ListView):  
    """
        首页视图函数,继承 ListView ,展示从数据库中获取的文章列表   
    """
    template_name = "blog/index.html"
    context_object_name = "article_list"

    def get_queryset(self):
        """
            重写 get_queryset 方法,取出发表的文章并转换文章格式
        """
        article_list = Article.objects.filter(status='p')
        for article in article_list:
            article.body = markdown2.markdown(article.body, extras=['fenced-code-blocks'], )
        return article_list

    def get_context_data(self, **kwargs):
        kwargs['category_list'] = Category.objects.all().order_by('name')
        return super(IndexView, self).get_context_data(**kwargs)

此次重写了 get_context_data 方法,这个方法是用来添加额外的内容传递到模板文件的上下文对象(context)中。上面的例子中将 category_list 添加到上下文变量中,则在模板中可以使用 {{ }} 来展示 category_list 中的内容。

ListView 主要用来获取某个 model 中的所有数据,通过 template_name 属性来指定需要渲染的模板,通过 context_object_name 属性来指定上下文变量(默认为 object_list),通过重写 get_queryset 方法来对 model 中的数据增加其他逻辑,通过重写 get_context_data 方法来为上下文对象添加额外的对象。

DetailView

ListView 用来获取某个 model 中的所有数据,而 DetailView 则是获取每个数据的详细信息,比如 ListView 获取所有文章列表,DetailView 用来获取文章的详细信息。

class ArticleDetailView(DetailView):
    """
        文章详情页
    """

    model = Article
    template_name = 'blog/detail.html'
    context_object_name = "article"
    # 在 urlpattern 中定义的
    pk_url_kwarg = 'article_id'
    
    def get_object(self, queryset=None):
        """ 
            获取对应文章的信息
        """
        obj = super(ArticleDetailView, self).get_object()
        obj.body = markdown2.markdown(obj.body, extras=['fenced-code-blocks'], )
        return obj 

    # 增加 form 到 context
    def get_context_data(self, **kwargs):
        kwargs['comment_list'] = self.object.blogcomment_set.all()  #获取评论
        return super(ArticleDetailView, self).get_context_data(**kwargs)

pk_url_kwarg 定义用来获取对应的单条数据,需要传递主键的值。get_object 方法获取 pk_url_kwarg 中所要查找的对象,类似于 ListView 中的 get_queryset 方法,get_context_data 方法和 ListView 中的功能相同。

DetailView 主要用在获取某个 model 的单个对象中,需要在 URL 中传递一个主键值进行查询。


你可以使用通用视图。让我们来看一些例子来看看它是如何工作的。

静态网页

让我们从“static.html”模板发布静态页面。

我们的 static.html −

<html>
   <body> 
      This is a static page!!! 
   </body>
</html> 

如果我们这样做,按以前学过的方式,我们将不得不改变 myapp/views.py −

from django.shortcuts import render

def static(request):
   return render(request, 'static.html', {}) 

myapp/urls.py 如下 −

from django.conf.urls import patterns, url

urlpatterns = patterns("myapp.views", url(r'^static/', 'static', name = 'static'),) 

最好的办法就是使用通用视图。对于这一点,我们的 myapp/views.py 将变成为 −

from django.views.generic import TemplateView

class StaticView(TemplateView):
   template_name = "static.html" 

而我们的 myapp/urls.py 将如下 −

from myapp.views import StaticView
from django.conf.urls import patterns

urlpatterns = patterns("myapp.views", (r'^static/$', StaticView.as_view()),) 

当访问 /myapp/static 将得到 −

出于同样的结果,我们也可以,执行下列操作 −

  • 不需要修改 views.py
  • 更改url.py文件为 -
from django.views.generic import TemplateView
from django.conf.urls import patterns, url

urlpatterns = patterns("myapp.views",
   url(r'^static/',TemplateView.as_view(template_name = 'static.html')),)
正如你所看到的,只需要改变url.py文件中的第二个方法。

从数据库列表和显示数据

我们要列出所有条目在Dreamreal模型。这样使用ListView通用视图类变得容易。编辑url.py文件,并对其进行更新 -

from django.views.generic import ListView
from django.conf.urls import patterns, url

urlpatterns = patterns(
   "myapp.views", url(r'^dreamreals/', ListView.as_view(model = Dreamreal, 
      template_name = "dreamreal_list.html")),
) 

重要的是要注意,在这一点上是变量通由通用视图到模板为object_list。如果你想自己的名字,将需要一个 context_object_name 参数添加到as_view方法。然后 url.py 成为 -

from django.views.generic import ListView
from django.conf.urls import patterns, url

urlpatterns = patterns("myapp.views",
   url(r'^dreamreals/', ListView.as_view(
      template_name = "dreamreal_list.html")),
      model = Dreamreal, context_object_name = ”dreamreals_objects” ,) 

然后关联的模板将成为 −

{% extends "main_template.html" %}
{% block content %}
Dreamreals:<p>
{% for dr in object_list %}
{{dr.name}}</p>
{% endfor %}
{% endblock %} 

访问 /myapp/dreamreals/ 将产生如下页面 −

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值