In-depth understanding of Mixin classes in DRF

DRF official website address:

Home - Django REST framework

 Generic views - Django REST framework

1. Introduction to Mixin class

1.1 Introduction to Mixin class

Mixin classes are a common design pattern that are useful when sharing functionality or behavior between multiple classes.

A Mixin class usually contains a set of methods or properties that can be imported and used by other classes through multiple inheritance. By encapsulating these common functions into Mixin classes, code reuse and modularity can be achieved while maintaining the single responsibility principle of the class.

In the Django framework, Mixin classes are widely used in views, forms, models, etc. to add or modify specific functions. Similarly, in other Python frameworks or codes, similar purposes can also be achieved by defining Mixin classes.

1.2 Example of using Mixin class

Suppose we are creating a simple e-commerce website where there are different types of users: regular users (RegularUser), member users (PremiumUser) and administrator users (AdminUser). We want to provide some specific functionality for each user type. We can use Mixin class to achieve this goal.

# 用户基类
class User:
    def __init__(self, username):
        self.username = username

    def get_username(self):
        return self.username


# Mixin类:普通用户功能
class RegularUserMixin:
    def add_to_cart(self, item):
        print(f"{self.get_username()} 添加 {item} 到购物车")

    def view_orders(self):
        print(f"{self.get_username()} 查看订单历史")


# Mixin类:会员用户功能
class PremiumUserMixin:
    def apply_discount(self, amount):
        print(f"{self.get_username()} 应用折扣:{amount}%")

    def access_premium_content(self):
        print(f"{self.get_username()} 访问高级内容")


# Mixin类:管理员用户功能
class AdminUserMixin:
    def delete_user(self, user):
        print(f"{self.get_username()} 删除用户:{user}")


# 普通用户
class RegularUser(User, RegularUserMixin):
    pass


# 会员用户
class PremiumUser(User, PremiumUserMixin):
    pass


# 管理员用户
class AdminUser(User, AdminUserMixin):
    pass


# 创建用户并使用功能
regular_user = RegularUser("Alice")
regular_user.add_to_cart("商品A")
regular_user.view_orders()

premium_user = PremiumUser("Bob")
premium_user.apply_discount(15)
premium_user.access_premium_content()

admin_user = AdminUser("Admin")
admin_user.delete_user("Alice")

In the above example, we defined 3 Mixin classes: RegularUserMixin, PremiumUserMixin, and AdminUserMixin, which respectively contain functions specific to ordinary users, member users, and administrator users. Then, through multiple inheritance, we combined these Mixin classes with the corresponding user base class (User) to create concrete user classes: RegularUser, PremiumUser, and AdminUser.

By using the Mixin class, we can modularize the specific functions of different types of users and inherit them into the corresponding user classes. In this way, different types of users can share common user attributes, but also each have access to their own specific functions.

Note that this is just a simple example to demonstrate the concept of Mixin classes. In actual development, the Mixin class can be more complex and contain more methods and attributes for adding various functions.

2. DRF (Django REST Framework) framework introduction

DRF (Django REST Framework) is a Python-based open source framework for quickly building powerful Web APIs. It is built on the basis of the Django framework and provides developers with a complete set of tools and libraries that simplify the process of building and managing APIs.

DRF provides a rich feature set, including serialization, request processing, authentication, permission control, version management, etc., making it easier to build highly customizable and extensible APIs. It follows RESTful design principles, supports various HTTP methods (such as GET, POST, PUT, DELETE) and data formats (such as JSON, XML), and can easily interact with front-end frameworks (such as React, Angular, Vue.js).

The importance of DRF is reflected in the following aspects:

  1. Rapid development: DRF provides a set of concise and powerful APIs, enabling developers to quickly build high-quality Web APIs. Using DRF, you can easily handle the logic of URL routing, request, response, etc., reducing the tedious coding work.
  2. Powerful serializers: DRF's serializers allow complex data structures to be converted into simple Python data types for serialization and deserialization. It also supports functions such as validating input data and automatically generating documents, which simplifies the process of data processing.
  3. Authentication and permission control: DRF provides various authentication methods (such as Token, OAuth, JWT) and permission control mechanisms, enabling developers to easily protect the security of APIs and limit user access to resources.
  4. Document generation: DRF can automatically generate API documents, including interface description, request parameters, return results and other information. This greatly facilitates team collaboration and communication, and reduces communication costs between development and the front end.
  5. Active community: DRF has a large and active community, with a large number of tutorials, sample codes, and answers to questions. This makes it easier to learn and use DRF, and can quickly solve problems encountered in development.

In short, DRF is a powerful and easy-to-use framework that provides developers with a wealth of tools and libraries that simplify the process of building and managing APIs. Whether building small projects or large applications, DRF is a go-to framework worth considering.

3. The role and significance of the Mixin class in DRF

Mixin classes play a very important role in DRF, they provide a flexible and reusable way to extend and combine the functionality of view classes. The Mixin class is a special type of class whose purpose is to add some common functions to the view class through multiple inheritance, so as to avoid code duplication and confusion.

In DRF, Mixin classes are used to add common functionality and behavior to view classes. These functions include the implementation of common HTTP methods (such as GET, POST, PUT, DELETE), data query, serialization, authentication, permission control, etc. By encapsulating these functions in mixin classes, view classes can be made more concise, readable, and easy to maintain.

The usage of Mixin class is very simple. Just implement multiple inheritance between the Mixin class and the DRF view class, and implement the corresponding methods. When the view class needs some specific functions, you only need to introduce the corresponding Mixin class without rewriting a lot of code.

DRF provides many built-in Mixin classes, such as ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, etc. These Mixin classes provide the implementation of common CRUD operations (create, read, update, delete), making it easier to build APIs.

Using Mixin classes can make the code better organized and maintainable. By dividing the functions into multiple Mixin classes, they can be combined on demand to flexibly extend and customize the functions of the view classes. This modular design is very conducive to code reuse and can reduce the amount of repetitive work in development.

In short, the role of the Mixin class in DRF is to provide a flexible and reusable way to extend and combine the functions of the view class. By using the Mixin class, you can avoid code redundancy and confusion, and make the implementation of the view class more concise, readable and easy to maintain.


4. What is a Mixin class

4.1 Concept and basic principle of Mixin class

Mixin class is a design pattern in object-oriented programming, which refers to a class containing a set of specific functions, which can be shared or reused by other classes through multiple inheritance. Mixin classes usually only focus on a specific functionality, and don't care about specific implementation details or logic.

 

The basic principle of the Mixin class is to inject its functionality into the target class through multiple inheritance. When a class needs to use the functions in the Mixin class, it can inherit the Mixin class and other necessary classes at the same time through multiple inheritance. In this way, the methods and properties defined in the Mixin class can be directly invoked in the target class to obtain corresponding functions.

The basic steps to use the Mixin class are as follows:

  1. Define a Mixin class: A Mixin class is an ordinary Python class that contains a set of specific functions (for example, common CRUD operations, authentication, permission control, etc.). Mixin classes usually do not require an initialization method, but only contain definitions of various methods and properties.
  2. Define the target class: The target class is the class that needs to obtain the functions of the Mixin class . In the definition of the target class, inherit the Mixin class and other necessary parent classes through multiple inheritance. In this way, the target class can obtain the methods and properties defined in the Mixin class.
  3. Use Mixin function: In the target class, you can directly call the methods and properties defined in the Mixin class to use the functions provided by the Mixin class. Since the function of the Mixin class is independent of that of the target class, you can easily add, delete or replace Mixin classes to meet specific needs.

The concept and rationale of Mixin classes make the code better organized and maintainable. By dividing the functions into multiple Mixin classes, they can be combined on demand to flexibly extend and customize the functions of the classes. This modular design can reduce code redundancy, improve code reusability, and make the code structure clearer.

It should be noted that when using Mixin classes, some norms and best practices should be followed. For example, the name of a Mixin class usually ends with Mixin to clearly indicate its special role as a Mixin class. In addition, it is not recommended to inherit the Mixin class without inheriting other classes, because the Mixin class itself is not complete and can only be used by other classes.

 
5. Mixin classes commonly used in DRF

In Django REST Framework (DRF), commonly used Mixin classes provide some basic functions that allow us to write API views more conveniently. The following introduces these Mixin classes one by one, and explains their functions and usage scenarios:

3.1 APIView

APIView is one of the most basic Mixin classes in DRF. It provides basic methods for handling HTTP requests, such as GET, POST, PUT, DELETE, etc. At the same time, APIView can also be used as the base class of other Mixin classes and combined with other Mixin classes through multiple inheritance to achieve more complex functions.

Although APIView is called a Mixin class in DRF, it is usually used as the base class of other Mixin classes and used in combination with other Mixin classes to meet the needs of different API views. By inheriting APIView and combining other Mixin classes, we can implement flexible and customized API views, including operations such as obtaining lists, creating objects, obtaining details, updating objects, and deleting objects.

 

Application of APIView in Django project:

When we use Django to develop web applications, we can use APIView provided by Django Rest Framework (DRF) to create API views. Here is an example showing how to create a simple API view using DRF's APIView:

from rest_framework.views import APIView
from rest_framework.response import Response

class HelloWorldAPIView(APIView):
    def get(self, request):
        data = {
            'message': 'Hello, World!'
        }
        return Response(data)


In this example, we define a class called HelloWorldAPIView that inherits from the APIView provided by DRF. We handle GET requests by overriding the get method and return a response with a message.

In this case, Django's URL configuration maps requests to this view, which then handles the request and generates a response. Since this view inherits from DRF's APIView, we can take advantage of some functions provided by DRF, such as automatically processing serialization of requests and responses, authentication and permission control, etc.

APIView can be used to easily write class-based API views, and can be extended and customized according to specific needs.

3.2 ListModelMixin

ListModelMixin: ListModelMixin is a Mixin class for serializing and returning a list of query results. It provides a list() method for taking a queryset and serializing it back. Usage scenarios include displaying list pages, searching functions, filtering and sorting list data, and other operations.

class ListModelMixin:
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

3.3 CreateModelMixin

CreateModelMixin: CreateModelMixin is a Mixin class for creating new resources. It provides the create() method for validating and saving the incoming data. Usage scenarios include processing POST requests and creating new resources.

class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

3.4 RetrieveModelMixin

RetrieveModelMixin: RetrieveModelMixin is used to obtain a single resource Mixin class. It provides the retrieve() method to get detailed information of the specified object. Usage scenarios include handling GET requests and getting detailed information about a single resource.

class RetrieveModelMixin:
    """
    Retrieve a model instance.
    """
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

3.5 UpdateModelMixin

UpdateModelMixin: The Mixin class that UpdateModelMixin is used to update resources. It provides the update() method for validating and updating the data of an existing resource. Usage scenarios include processing PUT requests and updating resources.

class UpdateModelMixin:
    """
    Update a model instance.
    """
    def update(self, request, *args, **kwargs):
        partial = kwargs.pop('partial', False)
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data, partial=partial)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(instance, '_prefetched_objects_cache', None):
            # If 'prefetch_related' has been applied to a queryset, we need to
            # forcibly invalidate the prefetch cache on the instance.
            instance._prefetched_objects_cache = {}

        return Response(serializer.data)

    def perform_update(self, serializer):
        serializer.save()

    def partial_update(self, request, *args, **kwargs):
        kwargs['partial'] = True
        return self.update(request, *args, **kwargs)

3.6 DestroyModelMixin

DestroyModelMixin: DestroyModelMixin is a Mixin class used to delete resources. It provides the destroy() method for validating and removing existing resources. Usage scenarios include processing DELETE requests and deleting resources.

class DestroyModelMixin:
    """
    Destroy a model instance.
    """
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.perform_destroy(instance)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def perform_destroy(self, instance):
        instance.delete()

These Mixin classes can be used in combination with APIView or other View classes to realize the combination of functions through multiple inheritance. For example, use ListAPIView to inherit from APIView and ListModelMixin to obtain list query and serialization functions.

ListAPIView(APIView,ListModelMixin)

The advantage of Mixin classes is that they abstract common functions and provide them to us through multiple inheritance. In this way, we can combine them according to different needs, reduce code redundancy, and improve development efficiency. At the same time, the Mixin class also makes the code more readable and maintainable, facilitating subsequent function expansion and modification.

It should be noted that when using Mixin classes, it is usually necessary to select an appropriate Mixin class for combination according to specific requirements to meet the functional requirements of the API view.


4. How to use the Mixin class

4.1 Methods and steps of using Mixin class

Using Mixin classes is a common code reuse technique to add some common functionality and behavior to classes through multiple inheritance. Here are the steps and sample code for using the Mixin class:

1. Define the Mixin class:

First, we need to define a Mixin class, which usually ends with Mixin to clarify its special purpose as a Mixin class. Mixin classes should only contain some helper methods, properties or override certain methods, and should not define constructors or stand-alone functionality.

class MyMixin:
    def common_method(self):
        # 实现通用方法逻辑
        pass

    def common_property(self):
        # 实现通用属性逻辑
        pass

    # 其他辅助方法...

2. Create a view class and inherit the Mixin class:

Next, create a view class and use multiple inheritance to extend the mixin class and other necessary parent classes. In multiple inheritance, the Mixin class is usually placed first, so that the methods and properties of the Mixin class can be inherited preferentially.

from django.views import View

class MyView(MyMixin, View):
    def get(self, request):
        # 处理GET请求的业务逻辑
        self.common_method()
        return ...

    # 其他HTTP方法和逻辑...

3. Pay attention to the order of Mixin classes:

When using multiple mixin classes, their order matters. Because Python's method parsing order is from left to right, if there are methods or attributes with the same name, the methods and attributes in the first inherited Mixin class will be used first.

class MyOtherMixin:
    def common_method(self):
        # 另一个实现通用方法逻辑
        pass

class MyView(MyMixin, MyOtherMixin, View):
    def get(self, request):
        # 处理GET请求的业务逻辑
        self.common_method()  # 调用的是MyMixin中的common_method()
        return ...

4. Follow the naming convention:

To keep the code readable and easy to understand, Mixin classes usually end with Mixin and are named according to their functionality. At the same time, care should be taken to avoid duplication of method or property names between Mixin classes to avoid naming conflicts or accidental overriding.


Using Mixin classes requires following some good programming practices:

  • Try to keep the independence of the Mixin class, and don't introduce too many additional dependencies in the Mixin class.
  • The Mixin class should focus on the functions of a single field and provide common methods or properties to facilitate reuse.
  • During the development process, multiple Mixin classes can be created to combine different functions, making the code more modular and easy to maintain.
  • Pay attention to the order and naming conventions of Mixin classes to avoid confusion and conflicts.

By using the Mixin class reasonably, we can effectively realize code reuse, reduce repetitive development work, and improve code maintainability and scalability.

 

5. Advanced usage of Mixin class

Advanced usage of Mixin classes includes customizing and extending the functionality of Mixin classes, which can be achieved in the following ways:

5.1. Override the Mixin class method:

If you need to customize the method of the Mixin class in the specific view class, you can reimplement the method of the Mixin class in the specific view class. In this way, the default implementation in the Mixin class can be overridden, and customized extensions can be made according to requirements.

class MyMixin:
    def common_method(self):
        # 默认实现
        pass

class MyView(MyMixin, View):
    def common_method(self):
        # 个性化定制
        pass

5.2 Add new methods and properties:

New methods and properties can be added to concrete view classes to extend the functionality of mixin classes. In this way, on the basis of the Mixin class, the functions under specific requirements can be further added.

class MyMixin:
    def common_method(self):
        # 实现通用方法逻辑
        pass

class MyView(MyMixin, View):
    def specific_method(self):
        # 特定功能方法
        pass

5.3 Combining multiple Mixin classes:

Multiple Mixin classes can be combined to achieve more complex function extensions. Through multiple inheritance, methods and properties of multiple Mixin classes can be combined into concrete view classes to achieve richer functions.

class OtherMixin:
    def other_method(self):
        # 其他功能方法
        pass

class MyView(MyMixin, OtherMixin, View):
    pass

5.4 Custom Mixin class order:

In multiple inheritance, the order of Mixin classes determines the method resolution order. According to requirements, the order of Mixin classes can be adjusted to ensure that methods of specific Mixin classes are called first.

class MyView(OtherMixin, MyMixin, View):
    pass

5.5 Inherit other Mixin classes:

Mixin classes can also inherit other Mixin classes to further build more complex functional combinations. In this way, a hierarchical Mixin class structure can be formed for better code reuse and extension.

class BaseMixin:
    def base_method(self):
        # 基础方法
        pass

class EnhancedMixin(BaseMixin):
    def enhanced_method(self):
        # 进一步增强的方法
        pass

class MyView(EnhancedMixin, View):
    pass

Using the advanced usage of Mixin class can customize and extend functions more flexibly, customize according to needs, combine different Mixin classes to achieve richer functions, and improve code reusability and maintainability. But in the process of use, pay attention to follow good naming conventions, control the complexity of Mixin classes, and understand the relationship between Mixin classes to avoid confusion and conflicts.

Guess you like

Origin blog.csdn.net/qq_39208536/article/details/131673622