Django -- Class-based Views 类视图

视图的任务

视图负责接受一个 HttpRequest,并返回 HttpResponse 或 抛出异常(Http404)

视图的实现

视图可以是一个函数

def index(reqest):
    # ....

视图可以是一个类

class IndexView(ListView):
    model = Author

当通过类实现,.as_view() 为类视图提供一个函数入口(function-like entry)

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
]

使用类视图的两种方式

URLConf

# 通过将 kwargs 传给 .as_view() 覆盖类中的属性
# 例子:重定向到首页
from django.views.generic.base import RedirectView

urlpatterns = [
    path('redirect-to-index', TemplateView.as_view(url="/")),
]

继承

# 通过继承修改属性/方法
from django.views.generic import TemplateView

class AboutView(TemplateView):
    template_name = "about.html"

类视图处理流程

在 URLConf 匹配 --> 调用相应的视图 .view_as() --> 调用类视图中的 .dispatch() 决定 Http 请求方法 --> 调用相应的类方法 get(), post(), head()

# 下面代码证明 类视图 支持 http head 请求方法
# 如果请求是 http get 方法,Django 返回 Listview 已经帮我们实现的 get()
# 如果请求时 http head 方法, Django 返回一个 头部带有 'Last-Modified' ,body 是空的响应,决定是否进行 http get 请求,下载全部书目

from django.http import HttpResponse
from django.views.generic import ListView
from books.models import Book

class BookListView(ListView):
    model = Book

    def head(self, *args, **kwargs):
        last_book = self.get_queryset().latest('publication_date')
        response = HttpResponse('')
        # RFC 1123 date format
        response['Last-Modified'] = last_book.publication_date.strftime('%a, %d %b %Y %H:%M:%S GMT')
        return response

1. Class-based Views

类视图并不是要替换函数视图,但是类视图可以简化代码和实现代码复用

装饰类视图

2种方式

装饰 .as_view()

from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView

from .views import VoteView

urlpatterns = [
    path('about/', login_required(TemplateView.as_view(template_name="secret.html"))),

    # 下面是因为 permission_required 本身返回一个函数,即变成 returned_func(VoteView.as_view())
    path('vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]

装饰 .dispatch()

装饰 .dispatch(), 但(函数)装饰器要先用 method_decorator() 转换成方法装饰器

from django.utils.decorators import method_decorator

# 装饰 dispatch()
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'


# 按顺序使用两个装饰器
decorators = [never_cache, login_required]

@method_decorator(decorators, name='dispatch')
class ProtectedView(TemplateView):
    template_name = 'secret.html'   

Class-based Views -- Intro

使用 Class-based Views

类视图使用方法 .get(), .post(), .head() 等响应不同的 Http 请求
函数视图使用 if request.method == 'POST'判断

from django.http import HttpResponse
from django.views import View

class MyView(View):
    def get(self, request):
        # 
        return HttpResponse('result')

通用视图介绍 Generic Views

Base Views

  • View
  • RedirectView:属性 url # 重定向到该地址
  • TemplateView:属性 template_name # 指定渲染的模板

View

View 是最基础的类视图,通常用于被其他视图继承
任务:
.as_view(): 提供函数接口;生成 self.request; 从 URL 中生成 self.args, self.kwargs
.dispatch():决定调用哪个方法(.get(), .post() ...) 响应请求

RedirectView

属性:

  • url: 重定向到该地址
  • pattern_name: 类似 django.urls.reverse,传递该类接受的 self.args, self.kwargs
  • permanentTrue/False 默认:False
  • query_string: True/False 是否将该类接收到的 query_string(?next=home&id=1)接到 url 后面,默认:False

方法:

get_redirect_url(*args, **kwargs) :返回重定向的 URL
默认实现:根据 query_string 生成 url

  1. 返回 url
  2. 根据 pattern_name 返回 url

例子:

# 更新计数器,并重定向
def get_redirect_url(self, *args, **kwargs):
    article = get_object_or_404(Article, pk=kwargs['pk'])
    article.update_counter()
    return super().get_redirect_url(*args, **kwargs)

RedirectView

TemplateView

重要属性:

  • extra_context :添加简单的 context 到模板
TemplateView.as_view(extra_context={'title': 'Custom Title'})
  • template_name [get_template_names()] :指定要使用的模板

重要方法:

  • get_context_data(): 返回一个字典(包含模板要用的 context)
def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['number'] = random.randrange(1, 100)
    return context

TemplateView

Form View

使用类视图的好处:可以简单修改属性(.as_view(form_class=OtherForm)),并重用其他逻辑

from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.views import View

from .forms import MyForm

class MyFormView(View):
    form_class = MyForm
    initial = {'key': 'value'}
    template_name = 'form_template.html'

    def get(self, request, *args, **kwargs):
        form = self.form_class(initial=self.initial)
        return render(request, self.template_name, {'form': form})

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)
        if form.is_valid():
            # 
            return HttpResponseRedirect('/success/')

        return render(request, self.template_name, {'form': form})

Mixin

Mixin 是一种多继承的形式
Django 提供多种 mixin 类,命名以 Mixin 结尾
Minix 类提供单一的功能,一些通用视图是通过继承多个 Mixin,然后进行适当地修改而来的
限制:继承时,只能继承一个通用视图,其他都应该是 Mixin

你可能感兴趣的:(Django -- Class-based Views 类视图)