Django里rest_framework的视图组件ModelViewSet进行优化视图

使用视图组件进行接口优化

  1. 使用视图组件的generics进行接口逻辑优化

    1. 导入ModelViewSet

      from rest_framework.viewsets import ModelViewSet
      
    2. 定义序列化类

      class BookSerializer(serializers.ModelSerializer):
        	class Meta:
            	model = 指定模型类
              fields = (指定验证字段)
              extra_kwargs = {"field_name":{"write_only":True}}
      
    3. 导入序列化类

      from .app_serializers import BookSerializer
      
    4. 定义视图类

      # 如果你的类只需要get和post方法你继承generics.ListCreateAPIView就可以了
      class BookView(ModelViewSet):
        	# queryset和serializer_class是固定的写法
        	# 指定queryset
        	queryset = BookInfo.objects.all()
          # 指定序列化类
          serializer_class = BookSerializer
      

GET获取全部数据和POST新增一条数据案列GET获取一条数据和PUT修改一条数据和DELETE删除一条数据

  1. 建立url

     re_path(r"^books/$", BookView.as_view({
         "get": "list",
         "post": "create"
     })),
    
     re_path(r"^books/(?P\d+)/$", BookView.as_view({
         "get": "retrieve",
         "put": "update",
         "delete": "destroy"
     }))
    
  2. 正则不取名叫pk会报一个Expected view BookFilterView to be called with a URL keyword argument named “pk”.的错误
    Django里rest_framework的视图组件ModelViewSet进行优化视图_第1张图片

  3. 建立model

    from django.db import models
    
    from datetime import datetime
    # from django.contrib.auth.models import AbstractUser
    
    
    class AuthorInfo(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者名称")
        age = models.IntegerField(verbose_name="作者年龄")
    
        class Meta:
            db_table = "db_author_info"
            verbose_name = "作者信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class PublishInfo(models.Model):
        name = models.CharField(max_length=32, verbose_name="出版社名称")
        city = models.CharField(max_length=32, verbose_name="出版社所在城市")
        email = models.EmailField(verbose_name="出版社邮箱")
    
        class Meta:
            db_table = "db_publish_info"
            verbose_name = "出版社信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class BookInfo(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
        publishDate = models.DateField(default=datetime.now, verbose_name="出版日期")
    
        # max_digits小数位加整数位多少长度 decimal_places小数位长度为2
        price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="图书价格")
        publish = models.ForeignKey(PublishInfo, related_name="book", related_query_name="book_query", on_delete=models.CASCADE, verbose_name="出版社")
        # ManyToManyField多对多
        authors = models.ManyToManyField(AuthorInfo, verbose_name="图书作者")
    
        class Meta:
            db_table = "db_book_info"
            verbose_name = "图书信息"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.title
    
    
  4. 导入ModelViewSet

     from rest_framework.viewsets import ModelViewSet
    
  5. 定义序列化类

    from.models import BookInfo
    # 第一步: 导入模块
    from rest_framework import serializers
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            # 指定    要操作的模型类
            model = BookInfo
    
            # 指定序列化的字段
            fields = (
                "title",
                "price",
                "publishDate",
                "publish",
                "authors",
                "author_list",
                "publish_name",
                "publish_city"
            )
    
            # 指定那些字段是只写的
            # write_only只写的 (只写的 前端发送数据时要写它, 后端返回数据时没有它)
            extra_kwargs = {
                "publish": {"write_only": True},
                "authors": {"write_only": True}
            }
    
        # 自定义的字段
        # read_only只读的 (只读的 前端发送数据时不用写它, 后端返回数据时有它)
        publish_name = serializers.CharField(max_length=32, read_only=True, source="publish.name")
        publish_city = serializers.CharField(max_length=32, read_only=True, source="publish.city")
    
        author_list = serializers.SerializerMethodField()
    
        def get_author_list(self, book_obj):
            # 拿到queryset开始循环 [ {}, {}, {}]
            authors = []
    
            for author in book_obj.authors.all():
                authors.append(author.name)
            return authors
    
  6. 导入序列化类

    from .app_serializers import BookSerializer
    
  7. 定义视图类

    from rest_framework.viewsets import ModelViewSet
    
    from .models import BookInfo, PublishInfo, AuthorInfo
    from .app_serializers import BookSerializer
    
    class BookView(ModelViewSet):
        # queryset和serializer_class是固定的写法
        # 告诉它quertset是谁
        queryset = BookInfo.objects.all()
     
        # 告诉它序列化的类
        serializer_class = BookSerializer
    
  8. postman的GET请求所有数据
    Django里rest_framework的视图组件ModelViewSet进行优化视图_第2张图片

  9. postman的POST请求所有数据
    Django里rest_framework的视图组件ModelViewSet进行优化视图_第3张图片

  10. postman的GET请求获取一条数据
    Django里rest_framework的视图组件ModelViewSet进行优化视图_第4张图片

  11. postman的PUT请求修改一条数据
    Django里rest_framework的视图组件ModelViewSet进行优化视图_第5张图片

  12. postman的DELETE请求删除一条数据
    Django里rest_framework的视图组件ModelViewSet进行优化视图_第6张图片

viewset源码剖析

  • Django程序启动, 开始初始化, 读取url.py, 读取settings, 读取视图类
  • 执行as_views(), BookView没有, 需要到父类(ModelViewSet)中找
  • ModelViewSet继承了mixin的几个Modelmixin和GenericViewSet, 显然ModelMixin也没有, 只有GenericViewSet中有
  • GenericViewSet没有任何代码, 只继承了ViewSetMixin和generics, GenericAPIView
  • 继续去ViewSetMixin中查找, 找到了as_view类方法, 在重新封装view函数的过程中, 有一个self.action_map = actions
  • 这个actions就是我们给as_view()传递的从参数
  • 绑定url和视图函数(actions)之间的映射关系
  • 等待用户请求
  • 接受到用户请求, 根据url找到视图函数
  • 执行视图函数的dispatch方法(因为视图函数的返回值是: return self.dispatch())
  • dispatch分发请求, 查找到视图类的五个方法中的某个
  • 开始执行, 比如post请求, 返回: self.create(), 视图类本身没有, 则会到父类中查找
  • 最后在CreateModelMixin中查找
  • 执行create()方法, 获取queryset和serializer_class
  • 返回数据

这就是viewset优化方案, 整个优化方案最重要的地方就是url.py中我们传入的参数, 然后对参数进行映射关系绑定

你可能感兴趣的:(#,rest_framework)