目录

django.views.generic.TemplateView.. 1

django.views.generic.View.. 2

类的继承和覆盖:... 5

自定义LoginRequiredMixin... 5

通用视图:... 6

django.views.generic.ListView.. 6

django.views.generic.DetailView.. 8

django.views.generic.FormView... 9

django.views.generic.CreateView... 9

django.views.generic.UpdateView... 9

 

 

 

cbvclass based view

基于类的视图,使编写view更简洁,有复杂的继承关系;

 

CBVFBV两者各有优劣;

 

102django_cbv_第1张图片

 

 

 

django.views.generic.TemplateView

 

102django_cbv_第2张图片

UML图;

Mixin增强功能,提供一些方法,如TemplateResponseMixin提供了render_to_response()渲染模板,ContextMixin提供get_context_data()

View提供get,post访问入口;

 

 

例,ver1

def about(request):   #ver1FBV用法

    return render(request, 'blog/about.html')

 

url(r'^about/', views.about, name='about'),

 

 

例,ver2

from django.views.generic import TemplateView

 

app_name = 'blog'

 

urlpatterns = [

    url(r'^$', views.index, name='index'),

    url(r'^login/', views.auth_login, name='login'),

    url(r'^logout/', views.auth_logout, name='logout'),

    # url(r'^about/', views.about, name='about'),

    url(r'^about/', TemplateView.as_view(template_name='blog/about.html')),   #ver2CBV用法1

]

 

 

例,ver3

from django.views.generic import TemplateView

 

class AboutView(TemplateView):   #ver3CBV用法2

template_name = 'blog/about.html'

 

 

url(r'^about/', AboutView.as_view()),

 

 

django.views.generic.View

 

View源码:

该类在没更改原来django逻辑的情况下,可用于编写view,每个http请求会使用对应类的同名的方法进行处理;

class View(object):

    """

    Intentionally simple parent class for all views. Only implements

    dispatch-by-method and simple sanity checking.

    """

 

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

 

    def __init__(self, **kwargs):   #检查as_view()传入的参数是否在类中定义

        """

        Constructor. Called in the URLconf; can contain helpful extra

        keyword arguments, and other things.

        """

        # Go through keyword arguments, and either save their values to our

        # instance, or raise an error.

        for key, value in six.iteritems(kwargs):

            setattr(self, key, value)

 

@classonlymethod

    def as_view(cls, **initkwargs):   #返回的是一个函数对象(装饰器);template_name=’blog/about.html’模板名作为参数传,或在类属性中定义,传入的参数可覆盖类中定义的属性

        """

        Main entry point for a request-response process.

        """

        for key in initkwargs:

            if key in cls.http_method_names:

                raise TypeError("You tried to pass in the %s method name as a "

                                "keyword argument to %s(). Don't do that."

                                % (key, cls.__name__))

            if not hasattr(cls, key):

                raise TypeError("%s() received an invalid keyword %r. as_view "

                                "only accepts arguments that are already "

                                "attributes of the class." % (cls.__name__, key))

 

        def view(request, *args, **kwargs):

            self = cls(**initkwargs)

            if hasattr(self, 'get') and not hasattr(self, 'head'):

                self.head = self.get

            self.request = request

            self.args = args

            self.kwargs = kwargs

            return self.dispatch(request, *args, **kwargs)

        view.view_class = cls

        view.view_initkwargs = initkwargs

 

        # take name and docstring from class

        update_wrapper(view, cls, updated=())

 

        # and possible attributes set by decorators

        # like csrf_exempt from dispatch

        update_wrapper(view, cls.dispatch, assigned=())

        return view

 

    def dispatch(self, request, *args, **kwargs):   #根据用户的request method路由到getpost方法

        # Try to dispatch to the right method; if a method doesn't exist,

        # defer to the error handler. Also defer to the error handler if the

        # request method isn't on the approved list.

        if request.method.lower() in self.http_method_names:

            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)

        else:

            handler = self.http_method_not_allowed

        return handler(request, *args, **kwargs)

 

    def http_method_not_allowed(self, request, *args, **kwargs):

        logger.warning(

            'Method Not Allowed (%s): %s', request.method, request.path,

            extra={'status_code': 405, 'request': request}

        )

        return http.HttpResponseNotAllowed(self._allowed_methods())

 

    def options(self, request, *args, **kwargs):

        """

        Handles responding to requests for the OPTIONS HTTP verb.

        """

        response = http.HttpResponse()

        response['Allow'] = ', '.join(self._allowed_methods())

        response['Content-Length'] = '0'

        return response

 

    def _allowed_methods(self):

        return [m.upper() for m in self.http_method_names if hasattr(self, m)]

 

 

例,ver1FBV

def my_view(request):

    if request.method == 'GET':

        return HttpResponse('get it')

    elif request.method == 'POST':

        return HttpResponse('post it')

    elif request.method == 'HEAD':

        return HttpResponse('head it')

 

 

例,ver2CBV,省去了if判断:

 

from django.views.generic import View

 

class MyView(View):

 

    def get(self, request):

        return HttpResponse('get it')

 

    def post(self, request):

        return HttpResponse('post it')

 

    def head(self, request):

        return HttpResponse('head it')

 

 

    # url(r'^myview', views.my_view),

    url(r'^myview', MyView.as_view()),

 

 

类的继承和覆盖:

 

class GreetingView(View):

    greeting = 'good day'

    def get(self, request):

        return HttpResponse(self.greeting)

 

class MorningGreetingView(GreetingView):

    greeting = 'morning to yo'

 

 

 

自定义LoginRequiredMixin

 

class LoginRequiredMixin:

    @classmethod

    def as_view(cls, **initkwargs):

        view = super(LoginRequiredMixin, cls).as_view(**initkwargs)

        return login_required(view)

   

class MyView(LoginRequiredMixin, View):

    pass

 

 

装饰类:

from django.utils.decorators import method_decorator

 

class ProtectedView(TemplateView):

    template_name = 'blog/about.html'

   

    @method_decorator(login_required)

    def dispatch(self, *args, **kwargs):

        return super(ProtectedView, self).dispatch(*args, **kwargs)

 

 

 

通用视图:

 

generic class based viewclass based view概念上不是一回事;

class based view是用类的方式写view

generic class based view是用class based view方式将常用的CRUD封装成可扩展的类,使用时直接继承,快速实现;

 

 

django.views.generic.ListView

 

多对象;

默认提供的上下文是object_list,也可用context_object_name指定;

querysetget_querysetmodel

可指定template_name

 

102django_cbv_第3张图片

 

例,ver1

def publisher_list(request):

    publishers = Publisher.objects.all()

    return render(request, 'books/publishers.html', {'publishers': publishers})

 

例,ver2

from django.views.generic import ListView

 

class PublisherList(ListView):   #默认去找suffixlist的模板,即publisher_list.htmlpublisher_list.html模板;默认的contextobject_list

    model = Publisher   #返回Publisher.object.all(),多对象

    # template_name = 'books/publishers.html'   #

         # context_object_name =    #提供上下文

         # queryset = Publisher.objects.all()   #model|queryset|get_queryset()三者关系

         # def get_queryset(self):

         #       return Publisher.objects.all()

 

 

   

            {% for publisher in object_list %}

           

    {{ publisher }}

            {% endfor %}

       

 

 

    # url(r'^$', views.publisher_list, name='publishers'),

    url(r'^$', PublisherList.as_view(), name='publisher'),

 

 

django.views.generic.DetailView

 

单个对象的详情;

get_context_data()

context_object_name

 

102django_cbv_第4张图片

 

   

           

    {{ publisher }}

            {% for book in book_list %}

            {{ book }}

            {{ book.publisher }}

            {% endfor %}

       

 

 

from django.views.generic import DetailView

from .models import Book

 

class PublisherDetail(DetailView):

    model = Publisher

    context_object_name = 'publisher'

 

    def get_context_data(self, **kwargs):

        context = super(PublisherDetail, self).get_context_data(**kwargs)

        context['book_list'] = Book.objects.all()

        return context

 

 

    url(r'^$', PublisherList.as_view(), name='publisher'),

    url(r'^(?P[0-9]+)/$', PublisherDetail.as_view()),

 

 

django.views.generic.FormView

 

class PublisherForm(forms.Form):

    name = forms.CharField(label=_('Your name'), max_length=30)

    address = forms.CharField(max_length=50)

    city = forms.CharField(max_length=60)

    state_province = forms.CharField(max_length=30)

    country = forms.CharField(max_length=20)

    website = forms.CharField(max_length=50)

 

    def send_mail(self):

        print('~~~~~~~~~~~send_mail()   OK')

 

 

from django.views.generic import FormView

 

class PublisherView(FormView):

    form_class = PublisherForm

    template_name = 'books/books_add.html'

    success_url = '/books/'

 

    def form_valid(self, form):

        form.send_mail()

        return super(PublisherView, self).form_valid(form)

 

 

    url(r'^$', PublisherList.as_view(), name='publisher'),

url(r'^add', PublisherView.as_view()),

 

 

django.views.generic.CreateView

 

根据modelfields动态构建form,另form_class = forms.AuthorForm等价于modelfields

model + fields = form_class,另get_form_classget_form

template_name,不指定默认找suffix_form.html

success_urlget_success_url

form_valid()form_invalid(),注意重写都要调用父类方法;

get_context_data

success_messageget_success_message

 

102django_cbv_第5张图片

 

from django.views.generic import CreateView

from .models import Author

 

class AuthorCreate(CreateView):

    model = Author

    fields = ['first_name', 'last_name', 'email']

    success_url = '/books/'

 

    def form_valid(self, form):

        return super().form_valid(form)

 

    def get_context_data(self, **kwargs):

        context = {'extra': 'some context'}

        kwargs.update(context)

        return super().get_context_data(**kwargs)

 

 

    url(r'^author/', AuthorCreate.as_view()),

 

 

django.views.generic.UpdateView

 

102django_cbv_第6张图片

 

django.views.generic.DeleteView

 

要有删除确认页面;

 

102django_cbv_第7张图片