使用视图组件进行接口优化
-
使用视图组件的mixin进行接口逻辑优化
-
导入mixin
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestoryModelMixin, RetrieveModelMixin from rest_framework.generics import GenericAPIView
-
定义序列化类
class BookSerializer(serializers.ModelSerializer): class Meta: model = 指定模型类 fields = (指定验证字段) extra_kwargs = {"field_name":{"write_only":True}}
-
导入序列化类
from .app_serializers import BookSerializer
-
定义视图类
# 由于这里用了mixin所以我们不能继承APIView, 只能继承GenericAPIView class BookView(ListModelMixin, CreateModelMixin, GenericAPIView): # queryset和serializer_class是固定的写法 # 指定queryset queryset = BookInfo.objects.all() # 指定序列化类 serializer_class = BookSerializer
-
GET获取全部数据和POST新增一条数据案列
-
建立url
re_path(r"^books/$", BookView.as_view()),
-
建立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
-
导入mixin和GenericAPIView
from rest_framework.mixin import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestoryModelMixin, RetrieveModelMixin from rest_framework.generics import GenericAPIView
-
定义序列化类
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
-
导入序列化类
from .app_serializers import BookSerializer
-
定义视图类
from rest_framework.mixins import ( # 创建 CreateModelMixin, # 修改 UpdateModelMixin, # 删除 DestroyModelMixin, # 获取所有 ListModelMixin, # 获取一条 RetrieveModelMixin ) from rest_framework.generics import GenericAPIView from .models import BookInfo, PublishInfo, AuthorInfo from .app_serializers import BookSerializer class BookView(ListModelMixin, CreateModelMixin, GenericAPIView): # GenericAPIView会帮我们去找queryset和serializer_class # queryset和serializer_class是固定的写法 # 告诉它quertset是谁 queryset = BookInfo.objects.all() # 告诉它序列化的类 serializer_class = BookSerializer def get(self, request, *args, **kwargs): # list是ListModelMixin方法, 拿到queryset 然后分页 进行序列化, 并且返回 return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): # create是CreateModelMixin方法, 拿到前端传递的数据传递给data, 然后序列化, 并且返回 return self.create(request, *args, **kwargs)
-
postman的GET请求所有数据
-
postman的POST请求所有数据
使用视图组件进行接口优化
-
使用视图组件的mixin进行接口逻辑优化
-
导入mixin
from rest_framework.mixin import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestoryModelMixin, RetrieveModelMixin from rest_framework.generics import GenericAPIView
-
定义序列化类
class BookSerializer(serializers.ModelSerializer): class Meta: model = 指定模型类 fields = (指定验证字段) extra_kwargs = {"field_name":{"write_only":True}}
-
导入序列化类
from .app_serializers import BookSerializer
-
定义视图类
# 由于这里用了mixin所以我们不能继承APIView, 只能继承GenericAPIView class BookView(ListModelMixin, CreateModelMixin, GenericAPIView): # queryset和serializer_class是固定的写法 # 指定queryset queryset = BookInfo.objects.all() # 指定序列化类 serializer_class = BookSerializer
-
GET获取一条数据和PUT修改一条数据和DELETE删除一条数据案列
-
建立url
re_path(r"^books/(?P<pk>\d+)/$", BookFilterView.as_view())
-
正则不取名叫pk会报一个Expected view BookFilterView to be called with a URL keyword argument named “pk”.的错误
-
建立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
-
导入mixin和GenericAPIView
from rest_framework.mixin import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestoryModelMixin, RetrieveModelMixin from rest_framework.generics import GenericAPIView
-
定义序列化类
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
-
导入序列化类
from .app_serializers import BookSerializer
-
定义视图类
from rest_framework.mixins import ( # 创建 CreateModelMixin, # 修改 UpdateModelMixin, # 删除 DestroyModelMixin, # 获取所有 ListModelMixin, # 获取一条 RetrieveModelMixin ) from rest_framework.generics import GenericAPIView from .models import BookInfo, PublishInfo, AuthorInfo from .app_serializers import BookSerializer class BookFilterView(UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, GenericAPIView): # GenericAPIView会帮我们去找queryset和serializer_class # queryset和serializer_class是固定的写法 # 告诉它quertset是谁 queryset = BookInfo.objects.all() # 告诉它序列化的类 serializer_class = BookSerializer def get(self, request, *args, **kwargs): # print(self.kwargs) {"pk": 1} # retrieve是RetrieveModelMixin的方法, 拿到queryset 进行序列化, 并且返回 return self.retrieve(request, *args, **kwargs) def put(self, request, *args, **kwargs): # update是UpdateModelMixin的方法, 拿到queryset # 序列化 # instance指定修改的对象(queryset) (data把你从前端接收到的数据赋值给这个data, # 前端传递的字段名必须跟model里字段名相同) # 验证, 保存数据库, 并且返回 return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): # destroy是DestroyModelMixin的方法, 拿到queryset并删除, 然后返回 return self.destroy(request, *args, **kwargs)
8. postman的GET请求获取一条数据
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190725194302119.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pzeDEzMTRsb3Zlenlm,size_16,color_FFFFFF,t_70)
9. postman的PUT请求修改一条数据
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190725194323649.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3pzeDEzMTRsb3Zlenlm,size_16,color_FFFFFF,t_70)
- postman的DELETE请求删除一条数据
mixin源码剖析
- Django程序启动, 开始初始化, 读取url.py, 读取settings, 读取视图类
- 执行as_views(), BookView没有, 需要到父类中找
- 几个ModelMixin也没有, GenericAPIView中没有, 继续到GenericAPIView(APIView)中找
- 找到了, 并且与之前的逻辑一样的, 同时发现GenericAPIView中定义了查找queryset和serializer_class类的方法
- as_view()方法返回重新封装的视图函数, 开始建立url和视图函数之间的映射关系
- 等待用户请求
- 接受到用户请求, 根据url找到视图函数
- 执行视图函数的dispatch方法(因为视图函数的返回值是: return self.dispatch())
- dispatch分发请求, 查找到视图类的五个方法中的某个
- 开始执行, 比如post请求, 返回: self.create(), 视图类本身没有, 则会到父类中查找
- 最后在CreateModelMixin中查找
- 执行create()方法, 获取queryset和serializer_class
- 返回数据
在对单条数据进行操作的几个方法中, 比如retrieve, 会执行get_object()方法, 该方法会根据lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field来查找操作对象, 可以通过修改self.lookup_url_kwarg变量名来自定义参数.