Views#3-通过类编写的视图函数

Class-based views

官方推荐使用通用视图类

  • 简单示例
    # models.py
    from django.db import models
    
    class Publisher(models.Model):
        name = models.CharField(max_length=30)
        address = models.CharField(max_length=50)
        city = models.CharField(max_length=60)
        state_province = models.CharField(max_length=30)
        country = models.CharField(max_length=50)
        website = models.URLField()
    
        class Meta:
            ordering = ["-name"]
    
        def __str__(self):              # __unicode__ on Python 2
            return self.name
    
    # views.py
    from django.views.generic import ListView
    from books.models import Publisher
    
    class PublisherList(ListView):
        # model类属性指定了使用的数据模型
        model = Publisher
        # 如不指定template_name属性,Django会自动为该类指定一个模板路径(比方该类的默认路径为"books/publisher_list.html",books是app名称)
        # 同时会自动将查找的结果指向'object_list'变量,从而可以在模板中直接使用
    
    # urls.py
    from django.conf.urls import url
    from books.views import PublisherList
    
    urlpatterns = [
        # PublisherList并不是视图函数,因此不能直接调用,而需要调用as_view()类方法
        url(r'^publishers/$', PublisherList.as_view()),
    ]
    

  • 指定模板使用的环境变量名
    class PublisherList(ListView):
        model = Publisher
        # 通过context_object_name类属性来指定
        context_object_name = 'my_favorite_publishers'
    
  • 添加额外的环境变量
    重载get_context_data()方法
    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()
            # 最终返回context
            return context
    

  • 指定视图类使用的对象
    除了使用model属性外,通过queryset属性也可以指定视图类处理的对象

    from django.views.generic import ListView
    from books.models import Book
    
    class BookList(ListView):
        # 该视图类处理的对象由queryset指定,这样做的好处是可以更明确地处理返回结果
        queryset = Book.objects.order_by('-publication_date')
        context_object_name = 'book_list'
    
  • 自动筛选对象
    如果通过model或者queryset来指定查找对象,面对不同的筛选条件,需要定义不同的视图类,这样做就会显得很繁琐
    Django提供了get_queryset()方法来处理不同的筛选条件

    当调用视图类时,绝大多数的信息将保存在self中(如self.request);其中self.args将保存URLconf传入的位置参数,self.kwargs将保存URLconf传入的关键字参数

    # urls.py
    urlpatterns = [
        # 正则表达式中有一个位置参数,将保存到其调用的视图类(PublisherBookList)的self.args中
        url(r'^books/([\w-]+)/$', PublisherBookList.as_view()),
    ]
    
    # 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属性指向所得结果是为了在后续方法中也可以使用该对象
            # self.args保存的是位置参数列表
            self.publisher = get_object_or_404(Publisher, name=self.args[0])
            return Book.objects.filter(publisher=self.publisher)
    
        # 该方法添加环境变量
        def get_context_data(self, **kwargs):
            # Call the base implementation first to get a context
            context = super(PublisherBookList, self).get_context_data(**kwargs)
            # Add in the publisher
            # 此处就使用到了上文中定义的self.publisher对象
            context['publisher'] = self.publisher
            return context
    

  • 对象预处理/善后
    get_object()方法可以获得将要处理的对象,通过对该方法的重载,可以对对象进行一些额外的处理
    # urls.py
      urlpatterns = [
        # 对于DetailView的视图类,需要通过pk关键字参数(django默认为pk,也可以指定为其它)来指定所需的对象
        url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetailView.as_view(), name='author-detail'),
    ]
    
    # views.py
    from django.views.generic import DetailView
    from django.utils import timezone
    from books.models import Author
    
    class AuthorDetailView(DetailView):
    
        # 指定处理对象(实质上是model=Author的另一种表现)
        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 object
    

  • 通用编辑视图
    主要用于表单视图
    • FormView
    • CreateView
    • UpdateView
    • DeleteView
      主要通过视图类来处理表单
  • 基础表单
    # forms.py
    from django import forms
    
    class ContactForm(forms.Form):
        name = forms.CharField()
        message = forms.CharField(widget=forms.Textarea)
    
        def send_eamil(self):
            # send email using the self.cleaned_data dictionary
            pass
    
    对于上述表单可以通过FormView来创建视图
    # views.py
    from myapp.forms import ContactForm
    from django.views.generic.edit import FormView
    
    class ContactView(FormView):
        template_name = 'contact.html'
        # form_class指定自定义的表单
        # 也可以通过指定model、queryset属性或者重载get_object()方法来使用Django自动生成的表单
        form_class = ContactForm
        # 若表单提交成功,将会转向success_url页面
        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(ContactView, self).form_valid(form)
    
    对于实现了get_absolute_url()方法的数据模型,CreateView或者UpdateView视图函数都无需指定success_url属性
    # models.py
    from django.urls import reverse
    from django.db import models
    
    class Author(models.Model):
        name = models.CharField(max_length=200)
    
        def get_absolute_url(self):
            return reverse('author-detail', kwargs={'pk': self.pk})
    
    # views.py
    from django.views.generic.edit import CreateView, UpdateView, DeleteView
    from django.urls import reverse_lazy
    from myapp.models import Author
    
    # AuthorCreate和AuthorUpdate表单在成功提交会,会自动转向get_absolute_url()方法返回的页面
    class AuthorCreate(CreateView):
        model = Author
        # fields的用法和ModelForm的Meta类中定义的fields属性一致;
        # 若ModelForm中没有定义fields属性(即自动生成ModelForm时),则需要在Generic editing views中显示指定
        # 因此,若在同一个视图类中同时指定fields和form_class属性,会引发ImproperlyConfigured异常
        fields = ['name']
        # 可以通过指定template_name属性来设置使用的模板
        # 此处并未指定,因此AuthorCreate和AuthorUpdate类默认使用myapp/author_form.html
        # AuthorDelete类会默认使用myapp/author_confirm_delete.html
    
    class AuthorUpdate(UpdateView):
        model = Author
        fields = ['name']
    
    class AuthorDelete(DeleteView):
        model = Author
        success_url = reverse_lazy('author-list')
    
    # urls.py
    urlpatterns = [
        # URLconf的设置同DetailView一致,需要传入pk关键字参数指定使用的具体数据
        url(r'author/add/$', AuthorCreate.as_view(), name='author-add'),
        url(r'author/(?P<pk>[0-9]+)/$', AuthorUpdate.as_view(), name='author-update'),
        url(r'author/(?P<pk>[0-9]+)/delete/$', AuthorDelete.as_view(), name='author-delete'),
    ]
    

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容