02drf 序列化器,响应请求对象,

1 修改,删除,添加,单查询,多查询接口

1.1:urls.py


from django.urls import path,re_path
from app01 import views
urlpatterns = [

    path('books/', views.Book.as_view()),
    re_path('^book/(?P<id>\d+)/', views.Book.as_view()),
    ]

1.2:views.py

from app01.utils import  CommonResponse
class BookDetail(APIView):
    def get(self, request, id):
        res = models.Book.objects.all().filter(id=id).first()
        # 单个,去掉many=True
        # 加many=True和不加,ser不是同一个对象
        ser = BookSerializer(instance=res)
        print(type(ser))  # app01.serializer.BookSerializer
        return Response(ser.data)

    def put(self, request, id):
        # 通过id取到对象
        res = {'code': 100, 'msg': ''}
        try:
            book = models.Book.objects.get(id=id)
            ser = BookSerializer(instance=book, data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            res['msg'] = '修改成功'
            res['result'] = ser.data

        except Exception as e:
            res['code'] = 101
            res['msg'] = str(e)

        return Response(res)
    def delete(self,request,id):
        response = {'code': 100, 'msg': '删除成功'}
        models.Book.objects.filter(id=id).delete()
        return Response(response)

    
class Book(APIView):
    def get(self, request, *args, **kwargs):
        res = models.Book.objects.all()
        # 借助序列化器
        # 如果是多条,就是many=True
        # 如果是单个对象,就不写
        ser = BookSerializer(instance=res, many=True)
        print(type(ser))  # rest_framework.serializers.ListSerializer
        # 通过序列化器得到的字典
        # ser.data
        print(ser.data)
        return Response(ser.data)

    def post(self, request):
        # post提交的数据都在request.data 是个字典
        print(request.data)
        ser = BookSerializer(data=request.data)
        if ser.is_valid():  # 校验数据是否合法
            ser.save()  # 保存到数据库中
            return Response(ser.data)
        else:
            # 没有校验通过的错误信息
            return Response(ser.errors)

1.3:serializer.py

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    title = serializers.CharField(max_length=32,min_length=2)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    publish = serializers.CharField(max_length=32)

    def create(self, validated_data):
        res=models.Book.objects.create(**validated_data)
        print(res)
        return res

    def update(self, book, validated_data):
        book.title=validated_data.get('title')
        book.price=validated_data.get('price')
        book.publish=validated_data.get('publish')
        book.save()
        return book

2 高级用法之source

1 修改返回到前端的字段名
	# source=title    字段名就不能再叫title
	name = serializers.CharField(max_length=32,min_length=2,source='title')
2 如果表模型中有方法
	# 执行表模型中的test方法,并且把返回值赋值给xxx
	xxx=serializers.CharField(source='test')
3 sourc支持跨表操作
	addr=serializers.CharField(source='publish.addr')
    
# 希望你们去看以下源码,内部如何实现的

2-1:示例

2.1.1models.py

from django.db import models


# Create your models here.
class Book(models.Model):
    id = models.AutoField(primary_key=True,help_text='pk')
    title = models.CharField(max_length=32, null=True,help_text='标题')
    price = models.DecimalField(max_digits=5, decimal_places=2, null=True,help_text='价格')
    # publish = models.CharField(max_length=32)
    publish = models.ForeignKey(to='Publish', null=True, on_delete=models.CASCADE,help_text='出版社')

    def test(self):
        # python是动态强类型语言,不支持字符串和数字直接相加
        return self.title + str(self.price)


class Publish(models.Model):
    name = models.CharField(max_length=32,help_text='出版社名称')
    addr = models.CharField(max_length=32,help_text='出版社地址')

    def __str__(self):
        return self.name

2.1.2serializer.py

from rest_framework import serializers
from . import models


class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False,help_text='pk')
    name = serializers.CharField(max_length=32,min_length=2,source='title',help_text='标题')
    price = serializers.DecimalField(max_digits=5, decimal_places=2,help_text='价格')
    publish = serializers.CharField(max_length=32,source='publish.name',help_text='出版社')
    xo=serializers.CharField(source='test',help_text='可以执行模型中的方法,但是不能传参')
    publish_addr=serializers.CharField(source='publish.addr')

    def create(self, validated_data):
        res=models.Book.objects.create(**validated_data)
        print(res)
        return res

    def update(self, book, validated_data):
        book.title=validated_data.get('title')
        book.price=validated_data.get('price')
        book.publish=validated_data.get('publish')
        book.save()
        return book

2.2.3views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from . import models
from .serializer import BookSerializer
from .utils import  CommonResponse

# Create your views here.

class Book(APIView):
    def get(self, request, *args, **kwargs):
        res = models.Book.objects.all()
        # 借助序列化器
        # 如果是多条,就是many=True
        # 如果是单个对象,就不写
        ser = BookSerializer(instance=res, many=True)
        print(type(ser))  # rest_framework.serializers.ListSerializer
        # 通过序列化器得到的字典
        # ser.data
        print(ser.data)
        return Response(ser.data)

    def post(self, request):
        # post提交的数据都在request.data 是个字典
        print(request.data)
        ser = BookSerializer(data=request.data)
        if ser.is_valid():  # 校验数据是否合法
            ser.save()  # 保存到数据库中
            return Response(ser.data)
        else:
            # 没有校验通过的错误信息
            return Response(ser.errors)



class BookDetail(APIView):
    def get(self, request, id):
        res = models.Book.objects.all().filter(id=id).first()
        # 单个,去掉many=True
        # 加many=True和不加,ser不是同一个对象
        ser = BookSerializer(instance=res)
        print(type(ser))  # app01.serializer.BookSerializer
        return Response(ser.data)

    def put(self, request, id):
        # 通过id取到对象
        res = {'code': 100, 'msg': ''}
        try:
            book = models.Book.objects.get(id=id)
            ser = BookSerializer(instance=book, data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            res['msg'] = '修改成功'
            res['result'] = ser.data

        except Exception as e:
            res['code'] = 101
            res['msg'] = str(e)

        return Response(res)
    def delete(self,request,id):
        response = {'code': 100, 'msg': '删除成功'}
        models.Book.objects.filter(id=id).delete()
        return Response(response)

2.2.4urls.py

from django.contrib import admin
from django.urls import path
from work import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.Book.as_view()),
    path('book/<int:id>/', views.BookDetail.as_view()),
]

2.2.5utils.py

# 自定义响应接口
class CommonResponse:
    def __init__(self):
        self.code=100
        self.msg=''
    @property
    def get_dic(self):
        return self.__dict__

3 模型类序列化器

1 原来用的Serilizer跟表模型没有直接联系, 模型类序列化器ModelSerilizer,跟表模型有对应关系

2 使用
	class BookModelSerializer(serializers.ModelSerializer):
        class Meta:
            model=表模型    # 跟哪个表模型建立关系
            fields=[字段,字段] # 序列化的字段,反序列化的字段
            fields='__all__' # 所有字段都序列化,反序列化
            exclude=[字段,字段] # 排除哪些字段(不能跟fields同时使用)
            read_only_fields=['price','publish']  # 序列化显示的字段
			write_only_fields=['title']           # 反序列化需要传入的字段
            extra_kwargs ={'title':{'max_length':32,'write_only':True}}
            depth=1  # 了解,跨表1查询,最多建议写3
        # 重写某些字段
        publish = serializers.CharField(max_length=32,source='publish.name')
        # 局部钩子,全局钩子,跟原来完全一样
3 新增,修改
	-统统不用重写create和update方法了,在ModelSerializer中重写了create和update

3-1:示例

serializer

class BookModelSerializer(serializers.ModelSerializer):

    publish = serializers.CharField(max_length=32,source='publish.name',read_only=True)
    addr = serializers.CharField(max_length=20,source='publish.addr',read_only=True)
    class Meta:
        model = models.Book  # 该序列化类跟Book表建立了关系
        fields = ['id','title','price','publish','addr']

4 高级用法之SerializerMethodField

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(required=False)
    name = serializers.CharField(max_length=32,min_length=2,source='title')
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    publish = serializers.SerializerMethodField()  # 配套方法get_publish
    def get_publish(self,obj):
        dic={'name':obj.publish.name,'addr':obj.publish.addr}
        return dic


class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'
    publish = serializers.SerializerMethodField()
    def get_publish(self,obj):
        dic={'name':obj.publish.name,'addr':obj.publish.addr}
        return dic
    
    
    
## 第三中方案,使用序列化类的嵌套
class PublishSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Publish
        # fields = '__all__'
        fields = ['name','addr']


class BookModelSerializer(serializers.ModelSerializer):
    publish = PublishSerializer()

    class Meta:
        model = models.Book
        fields = '__all__'

5 drf的请求与响应

5.1:Request

# Request
	-data :前端以post请求提交的数据都在它中
    -FILES :前端提交的文件
    -query_params:就是原来的request.GET
    -重写了 __getattr__
    	-使用新的request.method其实取得就是原生request.method(通过反射实现)

image-20201121201758292

5.2:Response

# Response
	-from rest_framework.response import Response
    -data:响应的字典
    -status:http响应的状态码
    	-drf提供给你了所有的状态码,以及它的意思
        from rest_framework.status import HTTP_201_CREATED
    -template_name:模板名字(一般不动),了解
    -headers:响应头,字典
    -content_type:响应的编码方式,了解

f

5.3:封装响应对象

 # 自己封装一个Response对象
      class CommonResponse:
        def __init__(self):
            self.code=100
            self.msg=''
        @property
        def get_dic(self):
            return self.__dict__
# 自己封装一个response,继承drf的Response

5.4:根据不同的请求走不同的响应对象

# 通过配置,选择默认模板的显示形式(浏览器方式,json方式)
	-配置文件方式(全局)
        -如果没有配置,默认有浏览器和json
            -drf有默认配置文件
            from rest_framework.settings import DEFAULTS
            REST_FRAMEWORK = {
            'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
                'rest_framework.renderers.JSONRenderer',  # json渲染器
                'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
            )
        	}
    -在视图类中配置(局部)
    	-粒度更小
        -class BookDetail(APIView):
    		renderer_classes=[JSONRenderer,]

7 many=True源码分析,局部全局钩子源码解析

7.1:man=True源码分析

1 many=True
	-__init__----->一路找到了BaseSerializer---》__new__决定了生成的对象是谁
    

image-20201122115153915

image-20201122121529651

image-20201122121643145

7.2:序列化局部钩子和全局钩子

2 入口是is_valid()---》BaseSerializer--》is_valid---》self._validated_data = self.run_validation(self.initial_data)
	-Serializer这个类的:self.run_validation
def run_validation(self, data=empty):
        value = self.to_internal_value(data)  # 局部字段自己的校验和局部钩子校验
        try:
            self.run_validators(value)
            value = self.validate(value)  # 全局钩子的校验
        except (ValidationError, DjangoValidationError) as exc:
            raise ValidationError(detail=as_serializer_error(exc))
        return value

image-20201121212559282

image-20201121210904016

image-20201122114806534

image-20201122113526344

posted @ 2020-12-29 16:13  为了等  阅读(221)  评论(1编辑  收藏  举报