DRF【视图组件】
通用配置
总路由
from django.urls import path, include
import xadmin
xadmin.autodiscover()
# version模块自动注册需要版本控制的 Model
from xadmin.plugins import xversion
xversion.register_models()
urlpatterns = [
# path('admin/', admin.site.urls),
path(r'xadmin/', xadmin.site.urls),
path('books/', include("SerDemo.urls")),
]
模型
from django.db import models
__all__ = ["Book", "Publisher", "Author"]
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name="图书名称")
CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
category = models.IntegerField(choices=CHOICES, verbose_name="图书的类别")
pub_time = models.DateField(verbose_name="图书的出版日期")
publisher = models.ForeignKey(to="Publisher", on_delete=None)
author = models.ManyToManyField(to="Author")
def __str__(self):
return self.title
class Meta:
db_table = "book"
verbose_name_plural = "图书表"
class Publisher(models.Model):
title = models.CharField(max_length=32, verbose_name="出版社的名称")
def __str__(self):
return self.title
class Meta:
db_table = "publisher"
verbose_name_plural = "出版社表"
class Author(models.Model):
name = models.CharField(max_length=32, verbose_name="作者的姓名")
def __str__(self):
return self.name
class Meta:
db_table = "author"
verbose_name_plural = "作者表"
多个get/post/..请求多个函数的实例
5个方法结构图

子路由
只写一个类 BookModelViewSet
请求 list 接口的 get 请求,找这个类 BookModelViewSet 的 list 函数
请求 retrieve/<int:pk> 接口的 get 请求 找这个类 BookModelViewSet 的 retrieve 函数
from django.urls import path, include
from .views import BookModelViewSet
urlpatterns = [
path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
# <int:pk> 必须起名为pk,如果是id就报错
path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
]
继承【ModelViewSet】的视图
继承 ModelViewSet
from .serializers import BookSerializer
from .models import Book
from rest_framework.viewsets import ModelViewSet
class BookModelViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
序列化器
没有改变
class BookSerializer(serializers.ModelSerializer):
"""继承ModelSerializer,序列化器会与models进行结合"""
class Meta:
"""先对序列化器的model进行配置"""
model = Book
fields = "__all__" # 返回__all__所有字段,或者指定字段["id", "title", "pub_time"]
# depth = 1 #代表外键嵌套层数为1层,有可能外键关联的表还会外键关联第三张表,这代表停到第一层就停止
extra_kwargs = {
"category": {"write_only": True}, # category 字段不写的话,会返回出去,这个字段不想通过接口提供出去
"publisher": {"write_only": True}, # 就写在这里,这个字段作为反序列化post请求过来修改字段用
"author": {"write_only": True}
}
############ SerializerMethodField 取出关联表想要的字段,不想要的可以不要 ,下面的变量名会带着值变成返回给前端 ##########
category_display = serializers.SerializerMethodField(read_only=True)
# 如果拿出想外键对应表中的字段,不是外键id,下面需要继续定义 def get_<publisher/字段名> 函数,返回想要关联表(外键/manytomany)的字段
publisher_info = serializers.SerializerMethodField(read_only=True)
# manytomany字段对应表中的值,下面需要继续定义 def get_<authors/字段名> 函数
authors = serializers.SerializerMethodField(read_only=True)
def get_category_display(self,obj):
return obj.get_category_display() # orm方法 get_字段_display ,获取chiose中文 ((1,张三),(2,李四))
def get_publisher_info(self, obj):
"""
函数以 get_字段命名
obj是序列化的每个book对象,因为Class meta 中定义了model=book
"""
publisher_obj = obj.publisher # 根据publisher外键取 Publisher 表里的值
return {
"id": publisher_obj.id,
"title": publisher_obj.title
}
def get_authors(self, obj):
"""
函数以 get_字段命名
obj是序列化的每个book对象,因为Class meta 中定义了model=book
"""
authors_query_set = obj.author.all()
return [{"id": author_obj.id, "name": author_obj.name} for author_obj in authors_query_set]
DRF【路由组件】
解决路由太多的问题
如果总路由还是 'books' 进行路由分发
那么子路由 使用 DefaultRouter 模块
传入视图类
from .views import BookModelViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r"", BookModelViewSet)
urlpatterns = [
]
urlpatterns += router.urls
视图和序列化器不变,那么请求url就改变了
比如查看所有数据 books/ 查看单条数据 books/1 或者books/xx
缺点
如果自动生成路由的话,但是业务还没有这么多需求,就会暴露很多接口,会有风险
只有业务匹配度很高才能这么用
浙公网安备 33010602011771号