=================================Introduction to class-based views=================================Class-based views provide an alternative way to implement views as Pythonobjects instead of functions. They do not replace function-based views, buthave certain differences and advantages when compared to function-based views:* Organization of code related to specific HTTP methods (``GET``, ``POST``,etc.) can be addressed by separate methods instead of conditional branching.* Object oriented techniques such as mixins (multiple inheritance) can beused to factor code into reusable components.The relationship and history of generic views, class-based views, and class-based generic views===============================================================================================In the beginning there was only the view function contract, Django passed yourfunction an :class:`~django.http.HttpRequest` and expected back an:class:`~django.http.HttpResponse`. This was the extent of what Django provided.Early on it was recognized that there were common idioms and patterns found inview development. Function-based generic views were introduced to abstractthese patterns and ease view development for the common cases.The problem with function-based generic views is that while they covered thesimple cases well, there was no way to extend or customize them beyond someconfiguration options, limiting their usefulness in many real-worldapplications.Class-based generic views were created with the same objective asfunction-based generic views, to make view development easier. However, the waythe solution is implemented, through the use of mixins, provides a toolkit thatresults in class-based generic views being more extensible and flexible thantheir function-based counterparts.If you have tried function based generic views in the past and found themlacking, you should not think of class-based generic views as a class-basedequivalent, but rather as a fresh approach to solving the original problemsthat generic views were meant to solve.The toolkit of base classes and mixins that Django uses to build class-basedgeneric views are built for maximum flexibility, and as such have many hooks inthe form of default method implementations and attributes that you are unlikelyto be concerned with in the simplest use cases. For example, instead oflimiting you to a class-based attribute for ``form_class``, the implementationuses a ``get_form`` method, which calls a ``get_form_class`` method, which inits default implementation returns the ``form_class`` attribute of the class.This gives you several options for specifying what form to use, from anattribute, to a fully dynamic, callable hook. These options seem to add hollowcomplexity for simple situations, but without them, more advanced designs wouldbe limited.Using class-based views=======================At its core, a class-based view allows you to respond to different HTTP requestmethods with different class instance methods, instead of with conditionallybranching code inside a single view function.So where the code to handle HTTP ``GET`` in a view function would looksomething like::from django.http import HttpResponsedef my_view(request):if request.method == 'GET':# <view logic>return HttpResponse('result')In a class-based view, this would become::from django.http import HttpResponsefrom django.views import Viewclass MyView(View):def get(self, request):# <view logic>return HttpResponse('result')Because Django's URL resolver expects to send the request and associatedarguments to a callable function, not a class, class-based views have an:meth:`~django.views.generic.base.View.as_view` class method which returns afunction that can be called when a request arrives for a URL matching theassociated pattern. The function creates an instance of the class, calls:meth:`~django.views.generic.base.View.setup` to initialize its attributes, andthen calls its :meth:`~django.views.generic.base.View.dispatch` method.``dispatch`` looks at the request to determine whether it is a ``GET``,``POST``, etc, and relays the request to a matching method if one is defined,or raises :class:`~django.http.HttpResponseNotAllowed` if not::# urls.pyfrom django.urls import pathfrom myapp.views import MyViewurlpatterns = [path('about/', MyView.as_view()),]It is worth noting that what your method returns is identical to what youreturn from a function-based view, namely some form of:class:`~django.http.HttpResponse`. This means that:doc:`http shortcuts </topics/http/shortcuts>` or:class:`~django.template.response.TemplateResponse` objects are valid to useinside a class-based view.While a minimal class-based view does not require any class attributes toperform its job, class attributes are useful in many class-based designs,and there are two ways to configure or set class attributes.The first is the standard Python way of subclassing and overriding attributesand methods in the subclass. So that if your parent class had an attribute``greeting`` like this::from django.http import HttpResponsefrom django.views import Viewclass GreetingView(View):greeting = "Good Day"def get(self, request):return HttpResponse(self.greeting)You can override that in a subclass::class MorningGreetingView(GreetingView):greeting = "Morning to ya"Another option is to configure class attributes as keyword arguments to the:meth:`~django.views.generic.base.View.as_view` call in the URLconf::urlpatterns = [path('about/', GreetingView.as_view(greeting="G'day")),].. note::While your class is instantiated for each request dispatched to it, classattributes set through the:meth:`~django.views.generic.base.View.as_view` entry point areconfigured only once at the time your URLs are imported.Using mixins============Mixins are a form of multiple inheritance where behaviors and attributes ofmultiple parent classes can be combined.For example, in the generic class-based views there is a mixin called:class:`~django.views.generic.base.TemplateResponseMixin` whose primary purposeis to define the method:meth:`~django.views.generic.base.TemplateResponseMixin.render_to_response`.When combined with the behavior of the :class:`~django.views.generic.base.View`base class, the result is a :class:`~django.views.generic.base.TemplateView`class that will dispatch requests to the appropriate matching methods (abehavior defined in the ``View`` base class), and that has a:meth:`~django.views.generic.base.TemplateResponseMixin.render_to_response`method that uses a:attr:`~django.views.generic.base.TemplateResponseMixin.template_name`attribute to return a :class:`~django.template.response.TemplateResponse`object (a behavior defined in the ``TemplateResponseMixin``).Mixins are an excellent way of reusing code across multiple classes, but theycome with some cost. The more your code is scattered among mixins, the harderit will be to read a child class and know what exactly it is doing, and theharder it will be to know which methods from which mixins to override if youare subclassing something that has a deep inheritance tree.Note also that you can only inherit from one generic view - that is, only oneparent class may inherit from :class:`~django.views.generic.base.View` andthe rest (if any) should be mixins. Trying to inherit from more than one classthat inherits from ``View`` - for example, trying to use a form at the top of alist and combining :class:`~django.views.generic.edit.ProcessFormView` and:class:`~django.views.generic.list.ListView` - won't work as expected.Handling forms with class-based views=====================================A basic function-based view that handles forms may look something like this::from django.http import HttpResponseRedirectfrom django.shortcuts import renderfrom .forms import MyFormdef myview(request):if request.method == "POST":form = MyForm(request.POST)if form.is_valid():# <process form cleaned data>return HttpResponseRedirect('/success/')else:form = MyForm(initial={'key': 'value'})return render(request, 'form_template.html', {'form': form})A similar class-based view might look like::from django.http import HttpResponseRedirectfrom django.shortcuts import renderfrom django.views import Viewfrom .forms import MyFormclass MyFormView(View):form_class = MyForminitial = {'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():# <process form cleaned data>return HttpResponseRedirect('/success/')return render(request, self.template_name, {'form': form})This is a minimal case, but you can see that you would then have the optionof customizing this view by overriding any of the class attributes, e.g.``form_class``, via URLconf configuration, or subclassing and overriding one ormore of the methods (or both!).Decorating class-based views============================The extension of class-based views isn't limited to using mixins. You can alsouse decorators. Since class-based views aren't functions, decorating them worksdifferently depending on if you're using ``as_view()`` or creating a subclass.Decorating in URLconf---------------------You can adjust class-based views by decorating the result of the:meth:`~django.views.generic.base.View.as_view` method. The easiest place to dothis is in the URLconf where you deploy your view::from django.contrib.auth.decorators import login_required, permission_requiredfrom django.views.generic import TemplateViewfrom .views import VoteViewurlpatterns = [path('about/', login_required(TemplateView.as_view(template_name="secret.html"))),path('vote/', permission_required('polls.can_vote')(VoteView.as_view())),]This approach applies the decorator on a per-instance basis. If youwant every instance of a view to be decorated, you need to take adifferent approach... _decorating-class-based-views:Decorating the class--------------------To decorate every instance of a class-based view, you need to decoratethe class definition itself. To do this you apply the decorator to the:meth:`~django.views.generic.base.View.dispatch` method of the class.A method on a class isn't quite the same as a standalone function, so you can'tjust apply a function decorator to the method -- you need to transform it intoa method decorator first. The ``method_decorator`` decorator transforms afunction decorator into a method decorator so that it can be used on aninstance method. For example::from django.contrib.auth.decorators import login_requiredfrom django.utils.decorators import method_decoratorfrom django.views.generic import TemplateViewclass ProtectedView(TemplateView):template_name = 'secret.html'@method_decorator(login_required)def dispatch(self, *args, **kwargs):return super().dispatch(*args, **kwargs)Or, more succinctly, you can decorate the class instead and pass the nameof the method to be decorated as the keyword argument ``name``::@method_decorator(login_required, name='dispatch')class ProtectedView(TemplateView):template_name = 'secret.html'If you have a set of common decorators used in several places, you can definea list or tuple of decorators and use this instead of invoking``method_decorator()`` multiple times. These two classes are equivalent::decorators = [never_cache, login_required]@method_decorator(decorators, name='dispatch')class ProtectedView(TemplateView):template_name = 'secret.html'@method_decorator(never_cache, name='dispatch')@method_decorator(login_required, name='dispatch')class ProtectedView(TemplateView):template_name = 'secret.html'The decorators will process a request in the order they are passed to thedecorator. In the example, ``never_cache()`` will process the request before``login_required()``.In this example, every instance of ``ProtectedView`` will have loginprotection. These examples use ``login_required``, however, the same behaviorcan be obtained by using:class:`~django.contrib.auth.mixins.LoginRequiredMixin`... note::``method_decorator`` passes ``*args`` and ``**kwargs``as parameters to the decorated method on the class. If your methoddoes not accept a compatible set of parameters it will raise a``TypeError`` exception.