基于类的视图 Class Based View

2018-10-16  本文已影响0人  叶田的学习笔记

在实际Web开发过程中,View的作用:
1、从数据库提取数据,
2、指定显示内容的模板,
3、提供模板渲染页面所需的内容对象(context object)。

6个常用通用视图——
ListView 展示对象列表(比如所有用户,所有文章)
DetailView 展示某个对象的详细信息(比如用户资料,比如文章详情)
CreateView 通过表单创建某个对象(比如创建用户,新建文章)
UpdateView 通过表单更新某个对象信息(比如修改密码,修改文字内容)
FormView 用户填写表单后转到某个完成页面
DeleteView 删除某个对象

前2个属于展示类视图(Display view), 后面4个属于编辑类视图(Edit view)。

٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶ ٩(͡๏̯͡๏)۶

如果你要使用Edit view,请务必在模型models里定义get_absolute_url()方法,否则会出现错误。这是因为通用视图在对一个对象完成编辑后,需要一个返回链接。

from django.urls import reverse
    def get_absolute_url(self):
        return reverse('pic:pic_detail',args=[str(self.pk)])

    def get_absolute_url(self):
        return reverse('author-detail', kwargs={'pk': self.pk})

ListView

from django.views.generic.list import ListView

ListView用来展示一个对象的列表。
展示所有文章列表,views.py可以简化为:

from django.views.generic.list import ListView
from .models import Article

class IndexView(ListView):

    model = Article

model = Article,声明本类用到的数据模型,能得到对应的数据表中的所有记录,相当于实现了Course.objects.all()功能,将所有记录都读出来。

默认模板名称为:app_name/model_name_list.html,可以通过重写template_name来自定义。
默认对象名称为:object_list,可以通过重写context_object_name来自定义。

from django.views.generic.list import ListView
from .models import Article
from django.utils import timezone

class IndexView(ListView):

    template_name = 'blog/article_list.html'
    context_object_name = 'latest_articles'

    def get_queryset(self):
        return Article.objects.filter(author=self.request.user).order_by('-pub_date')

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['now'] = timezone.now()
        return context

重写 get_context_data() 方法来为上下文对象添加额外的变量以便在模板中访问(添加字段)。
重写 get_queryset ()方法获得需要的对象列表,也可以重写queryset,如:

queryset = Article.objects.filter(author=self.request.user).order_by('-pub_date')

DetailView

from django.views.generic.detail import DetailView

DetailView用来展示一个具体对象的详细信息
用来展示某篇文章详细内容的view可以简写为:

from django.views.generic import DetailView
from .models import Article

class ArticleDetailView(DetailView):

    model = Article

默认模板名称为:model_name_detail.html,可以通过重写template_name来自定义。
默认对象名称为:object,可以通过重写context_object_name来自定义。

from django.views.generic.detail import DetailView
from django.http import Http404
from .models import Article
from django.utils import timezone

class ArticleDetailView(DetailView):

   queryset = Article.objects.all().order_by("-pub_date")
   template_name = 'blog/article_detail.html'
   context_object_name = 'article'

   def get_object(self, queryset=None):
       obj = super().get_object(queryset=queryset)
       if obj.author != self.request.user:
           raise Http404()
       return obj

   def get_context_data(self, **kwargs):
       context = super().get_context_data(**kwargs)
       context['now'] = timezone.now()
       return context

可以通过更具体的get_object()方法来返回一个更具体的对象。上面的代码中,如果希望一个用户只能看到自己发表的文章详情。当用户查看别人的文章详情时,返回http 404错误,可以重写get_object()。

CreateView

from django.views.generic.edit import CreateView

CreateView一般通过某个表单创建某个对象,通常完成后会转到对象列表。
一个最简单的文章创建CreateView可以写成:

from django.views.generic.edit import CreateView
from .models import Article

class ArticleCreateView(CreateView):
    model = Article
    fields = ['title', 'body', 'pub_date']

默认模板名称为:model_name_form.html,可以通过重写template_name来自定义。
默认对象名称为:form,可以通过重写context_object_name来自定义。

当用户提交的数据是有效的时候,你可以通过定义form_valid方法做些别的事情,比如发送邮件,存取额外的数据。

from django.views.generic.edit import CreateView
from .models import Article
from .forms import ArticleCreateForm

class ArticleCreateView(CreateView):
    model = Article
    template_name = 'blog/article_create_form.html'
    form_class = ArticleCreateForm

    def form_valid(self, form):
       form.do_sth()
       return super().form_valid(form)

form_valid()方法一个常见用途就是就是将创建对象的用户与model里的user结合,见下面例子。

class ArticleCreateView(CreateView):
    model = Article
    template_name = 'blog/article_create_form.html'
    form_class = ArticleCreateForm

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

UpdateView

from django.views.generic.edit import UpdateView

UpdateView一般通过某个表单更新现有对象的信息,更新完成后会转到对象详细信息页面。它需要URL提供访问某个对象的具体参数(如pk, slug值)。
一个最简单的文章更新的UpdateView如下所示。

from django.views.generic.edit import UpdateView
from .models import Article

class ArticleUpdateView(UpdateView):
    model = Article
    fields = ['title', 'body', 'pub_date']

UpdateView和CreateView很类似,比如
默认模板名称为:model_name_form.html,可以通过重写template_name来自定义。
默认对象名称为:form,可以通过重写context_object_name来自定义。

但是区别有两点:
1、CreateView显示的表单是空表单,UpdateView中的表单会显示现有对象的数据。
2、用户提交表单后,CreateView转向对象列表,UpdateView转向对象详细信息页面。

from django.views.generic.edit import UpdateView
from .models import Article
from .forms import ArticleUpdateForm

class ArticleUpdateView(UpdateView):
    model = Article
    template_name = 'blog/article_update_form.html'
    form_class = ArticleUpdateForm

    def form_valid(self, form):
       form.do_sth()
       return super().form_valid(form)

DeleteView

from django.views.generic.edit import DeleteView

DeleteView一般用来删除某个具体对象。它要求用户点击确认后再删除一个对象。使用这个通用视图,你需要定义模型的名称model和成功删除对象后的返回的URL。

from django.urls import reverse_lazy
from django.views.generic.edit import DeleteView
from .models import Article

class ArticleDeleteView(DeleteView):
    model = Article
    success_url = reverse_lazy('index')

默认模板名称为:model_confirm_delete.html,可以通过重写template_name来自定义。
默认对象名称为:object,可以通过重写context_object_name来自定义。

上面的代码有问题,用户可以删除任意文章,包括别人发表的文章。如果我们想用户只能删除自己的文章,可以通过get_queryset方法筛选出作者自己的文章即可。

from django.urls import reverse_lazy
from django.views.generic.edit import DeleteView
from .models import Article

class ArticleDeleteView(DeleteView):
    model = Article
    success_url = reverse_lazy('index')

    def get_queryset(self):
        return self.model.objects.filter(author=self.request.user)

在默认状态下,DeleteView类接收以pk或者slug作为参数传入的值,并且通过GET方式访问一个删除的确认页面,然后以POST方式提交删除表单,才能完成删除。

FormView

from django.views.generic.edit import FormView

FormView一般用来展示某个表单,而不是某个模型对象。当用户输入信息未通过表单验证,显示错误信息。当用户输入信息通过表单验证提交成功后,转到其它页面。
使用FormView一般需要定义template_name, form_class和跳转的success_url。

from myapp.forms import ContactForm
from django.views.generic.edit import FormView

class ContactView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm
    success_url = '/thanks/'

    def form_valid(self, form):
        # This method is called when valid form data has been POSTed.
        # It should return an HttpResponse.
        form.send_email()
        return super().form_valid(form)
上一篇 下一篇

猜你喜欢

热点阅读