Django class view and Middleware

Class view

1. Class view import

The view defined by function is called function view, which is easy to understand. However, when the path corresponding to a view provides support for many different HTTP request modes, you need to write different business logic in a function, and the code readability and reusability are poor.

def register(request):
    """Process registration"""
    # Get the request method and judge whether it is a GET/POST request
    if request.method == 'GET':
        # Process the GET request and return to the registration page
        return render(request, 'register.html')
    else:
        # Handle POST request and realize registration logic
        return HttpResponse('The registration logic is implemented here')

In Django, you can also use classes to define a view, called class view.
Using class view, different request modes corresponding to the view can be defined differently by different methods in the class. As follows;

from django.views.generic import View

class RegisterView(View):
    """Class view: processing registration"""
    def get(self, request):
        """handle GET Request, return to the registration page"""
        return render(request, 'register.html')

    def post(self, request):
        """handle POST Request to implement the registration logic"""
        return HttpResponse('The registration logic is implemented here')

Benefits of class view:

  • Good code readability
  • Class view has higher reusability than function view. If a specific logic of a class view needs to be used elsewhere, you can directly inherit the class view

2. Class view usage

To define a class View, you need to inherit from the parent class View provided by Django. You can use from Django views. Generic import View or from Django views. generic. Base import View import is defined as shown above.
When configuring a route, use the as of the class view_ View () method.

urlpatterns = [
    # View functions: registering
    # url(r'^register/$', views.register, name='register'),
    # Class view: registering
    url(r'^register/$', views.RegisterView.as_view(), name='register'),
]

3. Class view principle

@classonlymethod
    def as_view(cls, **initkwargs):
        """
        Main entry point for a request-response process.
        """
        ...Omit code...

        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
            # Call the dispatch method and call different request methods according to different request methods
            return self.dispatch(request, *args, **kwargs)

        ...Omit code...

        # Return to the real function view
        return view


    def dispatch(self, request, *args, **kwargs):
        # 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)

Class 4 views use decorators

There are two ways to add a decorator to a class view.
For convenience, let's first define a decorator for the function view (the decorated object is basically considered as the function view when designing the decorator) and a class view to be decorated.

def my_decorator(func):
    def wrapper(request, *args, **kwargs):
        print('Custom decorator called')
        print('Request path%s' % request.path)
        return func(request, *args, **kwargs)
    return wrapper

class DemoView(View):
    def get(self, request):
        print('get method')
        return HttpResponse('ok')

    def post(self, request):
        print('post method')
        return HttpResponse('ok')

4.1 decoration in URL configuration

urlpatterns = [
    url(r'^demo/$', my_decorate(DemoView.as_view()))
]

This method is the simplest, but because the decoration behavior is placed in the url configuration, you can't know that the view is also added with decorators when looking at the view alone, which is not conducive to the integrity of the code and is not recommended.
This method will add decorator behavior to all request methods in the class view (because it is at the entrance of the view, before distributing the request method)

4.2 decoration in class view

When using the decorator prepared for the function view in the class view, you can't add the decorator directly. You need to use method_ The decorator converts it into a decorator for class view methods.
method_ The decorator decorator uses the name parameter to indicate the decorated method

# Add decorator for all request methods
@method_decorator(my_decorator, name='dispatch')
class DemoView(View):
    def get(self, request):
        print('get method')
        return HttpResponse('ok')

    def post(self, request):
        print('post method')
        return HttpResponse('ok')

# Add decorators for specific request methods
@method_decorator(my_decorator, name='get')
class DemoView(View):
    def get(self, request):
        print('get method')
        return HttpResponse('ok')

    def post(self, request):
        print('post method')
        return HttpResponse('ok')

If you need to add decorators for multiple methods of the class view, but not all methods (refer to the above example for adding decorators for all methods), you can directly use method on the method that needs to add decorators_ Decorator, as shown below

from django.utils.decorators import method_decorator

# Add decorators for specific request methods
class DemoView(View):

    @method_decorator(my_decorator)  # Added decorator for get method
    def get(self, request):
        print('get method')
        return HttpResponse('ok')

    @method_decorator(my_decorator)  # A decorator has been added to the post method
    def post(self, request):
        print('post method')
        return HttpResponse('ok')

    def put(self, request):  # No decorator was added for the put method
        print('put method')
        return HttpResponse('ok')

5. Class view Mixin extension class

Using the feature of object-oriented multi inheritance, you can define a parent class (as an extended class) and define the methods you want to supplement to the class view in the parent class. The class view inherits these extended parent classes to realize code reuse.
The extended parent class name defined usually ends with Mixin.
Examples are as follows:

class ListModelMixin(object):
    """
    list Extension class
    """
    def list(self, request, *args, **kwargs):
        ...

class CreateModelMixin(object):
    """
    create Extension class
    """
    def create(self, request, *args, **kwargs):
        ...

class BooksView(CreateModelMixin, ListModelMixin, View):
    """
    Inherit two extension classes at the same time, reuse list and create method
    """
    def get(self, request):
        self.list(request)
        ...

    def post(self, request):
        self.create(request)
        ...

class SaveOrderView(CreateModelMixin, View):
    """
    inherit CreateModelMixin Extension class, reuse create method
    """
    def post(self, request):
        self.create(request)
        ...

Keywords: Python Django Middleware

Added by yashvant on Mon, 03 Jan 2022 14:01:00 +0200