drf---序列化

序列化总结

1、序列化类 (做序列化):多条一定要写 many = True

2、序列化校验:ser.is_valid() 就会走校验

3、反序列化保存

  新增:

    ser = BookSerializer(data=request.data)
    ser.save()--->触发 序列化类中的 create---》为什么?内部做了判断:根据是否有instance
    create中,自己写保存到哪个表中:有数据--》保存到某个表中

  修改:

    ser = BookSerializer(instance=待修改对象,data=request.data)
    ser.save()--->触发 序列化类中的 update---》为什么?内部做了判断:根据是否有instance
    update中,有待修改对象,有数据---》修改完保存即可--》两种方式

 

反射

反序列化之更新

views

from .models import User
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializer import UserSerializer


class UserView(APIView):
    def get(self, request):
        # 获取数据
        user = User.objects.all()

        res = UserSerializer(instance=user,many=True)
        return Response(res.data)

    def post(self, request):
        #添加数据
        print(request.data)
        res = UserSerializer(data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code':10,'msg':'保存成功'})
        else:
            return Response({'code':11,'msg':res.errors})



class Userdetial(APIView):
    def get(self, request, pk):
        #获取单个值
        user = User.objects.filter(pk=pk).first()
        #序列化
        res = UserSerializer(instance=user)
        return Response(res.data)

    def delete(self, request, pk):
        #找到要删除的数据
        user = User.objects.filter(pk=pk).delete()
        return Response({'code':10,'msg':'删除成功'})

    def put(self, request, pk):
        #修改数据
        user = User.objects.filter(pk=pk).first()
        res = UserSerializer(instance=user,data = request.data)  #将前端获取的数据和旧的数据传过去
        if res.is_valid():
            res.save()
            return Response({'code':10,'msg':'修改成功'})
        else:
            return Response({'code':11,'mag':res.errors})

序列化类 

from rest_framework import serializers
from .models import User
from rest_framework.exceptions import ValidationError

'''
        -姓名不能以 sb开头
        -姓名最大8位,最小3位
        -密码不能超过100,最低不能低于10
'''


class UserSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8,min_length=3,required=False)
    age = serializers.IntegerField(required=False)
    password = serializers.CharField(max_length=100,min_length=10,required=False)
    hobby = serializers.CharField(required=False)

    #局部钩子
    def validate_name(self,value):
        if value.startswith('sb'):
            raise ValidationError('不能以sb开头')
        return value


    def create(self, validated_data):
        user = User.objects.create(**validated_data)
        return user
    def update(self, instance, validated_data):
        #方法一
        instance.name = validated_data['name']
        instance.password = validated_data['password']
        instance.hobby = validated_data['hobby']
        instance.age = validated_data['age']
        instance.save()

        # 方法二
        # #用反射的方法将数据循环
        # for i in validated_data:
        #     res = setattr(instance,i,validated_data.get(i))    #因为反射没有返回值,所以无法打印
        #     instance.save()
        return instance

 

高级用法source(了解)

字段类的属性

如下写法就能修改序列化的字段

方法一(在序列化类中):

 

 方法二(在序列化类中跨表查询):

# 用法二 :跨表查询
publish = serializers.CharField(source='publish.name')

# 自动对应成出版社的名字 可以通过 . 跨表查询

用法三(序列化字段中查询,在模型中加入方法)

 

 高级用法定制字段

定制返回的字段格式

方案一(使用SerializerMethodField 定制):

在序列化类中

 方案二:在表模型中定制

表模型

 序列化类

 

 多表关联序列化和反序列化

以后一个序列化类,想即做序列化,又做反序列化,会出现的问题:

  字段不匹配,尤其是多表关联的字段

有的字段即做序列化,又做反序列化

name = serializers.CharField()
price = serializers.IntegerField()

有的字段只用序列化(read_only表示 只做序列化)

publish_dict = serializers.DictField(read_only=True) # 只做序列化
author_list = serializers.ListField(read_only=True) # 只做序列化

有的字段只做反序列化(write_only),是什么类型取决于前端传入的格式是什么样

publish_id = serializers.IntegerField(write_only=True) # 反序列化
authors = serializers.ListField(write_only=True) # 反序列化

 

保存方法需要重写

def create(self, validated_data): # {"name":"11111","price":999,"publish":1,"authors":[1,2]}
authors=validated_data.pop('authors')
book = Book.objects.create(**validated_data)
增加中间表的记录:图书和作者的关系
book.authors.add(*authors) # 向中间表中存入:这个图书关联的做作者

return book

##也可以使用笨办法:

序列化用一个序列化类

反序列化换另一个序列化类

 

反序列化校验总结

什么情况用反序列化校验?
做反序列化的时候,才用----》校验前端传入的数据

三层:
字段自己:字段类属性---》可控制的比较小
局部钩子:单个字段校验
全局钩子:多个字段同时校验

作业

视图层

from django.shortcuts import render

# Create your views here.

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Book, Publish, Author
from .serializer import BookSerializer


class Bookview(APIView):
    # 查找全部数据
    def get(self, request, *args, **kwargs):
        book_list = Book.objects.all()

        # 序列化数据给出去
        res = BookSerializer(book_list, many=True)
        return Response({'code': 10, 'msg': '查询成功', 'result': res.data})

    # 创建数据
    def post(self, request, *args, **kwargs):
        # 反序列化传入
        res = BookSerializer(data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code': 10, 'msg': '添加成功'})
        else:
            return Response({'code': 11, 'msg': res.errors})


class BookDetialview(APIView):
    def get(self, request, pk, *args, **kwargs):
        book_list = Book.objects.filter(pk=pk).first()
        #序列化
        res = BookSerializer(book_list)
        return Response({'code': 10, 'msg': '查询成功', 'result': res.data})

    def put(self, request, pk, *args, **kwargs):
        #修改数据
        book_list = Book.objects.filter(pk=pk).first()
        res = BookSerializer(instance=book_list,data=request.data)
        if res.is_valid():
            res.save()
            return Response({'code':11,'msg':'修改成功','result':res.data})
        else:
            return Response({'code':12,'msg':'修改失败'})

    def delete(self, request, pk, *args, **kwargs):
        Book.objects.filter(pk=pk).delete()
        return Response({'code': 10, 'msg': '删除成功'})

模型层

from django.db import models

# Create your models here.

'''图书表、作者表、出版社表'''

class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.IntegerField(max_length=32)
    publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    def publish_dict(self):
        return {'name':self.publish.name,'addr':self.publish.addr}

    def author_list(self):
        l=[]
        for i in self.authors.all():
            l.append({'name':i.name,'age':i.age,'sex':i.sex})
        return l


class Publish(models.Model):
    name = models.CharField(max_length=32)
    addr = models.CharField(max_length=32)


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    sex = models.CharField(max_length=32)

序列化类

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.Serializer):
    #book表中的数据即做序列化又做反序列化
    name = serializers.CharField()
    price = serializers.IntegerField()

    #跨表中的图书表和作者表做序列化,用来查询
    publish_dict = serializers.DictField(read_only=True)
    author_list = serializers.ListField(read_only=True)

    #跨表中图书表和作者表做反序列化,用来创建及更新
    publish_id = serializers.IntegerField(write_only=True)
    authors = serializers.ListField(write_only=True)

    def create(self, validated_data):
        authors =validated_data.pop('authors')
        book =Book.objects.create(**validated_data)
        book.authors.add(*authors)

        return book

    def update(self, instance, validated_data):
        authors = validated_data.pop('authors')
        #通过反射
        for i in validated_data:
            rse = setattr(instance,i,validated_data.get(i))
        instance.authors.set(authors)
        instance.save()
        return instance

 

posted @ 2023-08-31 21:18  别管鱼油我了  阅读(15)  评论(0编辑  收藏  举报