drf serializer 的序列化

drf serializer 的序列化

1、序列化类 常用字段类 及字段参数

1.1、常用字段类

# BooleanField	BooleanField()
# NullBooleanField	NullBooleanField()
# CharField	CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
# EmailField	EmailField(max_length=None, min_length=None, allow_blank=False)
# RegexField	RegexField(regex, max_length=None, min_length=None, allow_blank=False)
# SlugField	SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
# URLField	URLField(max_length=200, min_length=None, allow_blank=False)
# UUIDField	UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
# IPAddressField	IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
# IntegerField	IntegerField(max_value=None, min_value=None)
# FloatField	FloatField(max_value=None, min_value=None)
# DecimalField	DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
# DateTimeField	DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
# DateField	DateField(format=api_settings.DATE_FORMAT, input_formats=None)
# TimeField	TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
# DurationField	DurationField()
# ChoiceField	ChoiceField(choices) choices与Django的用法相同
# MultipleChoiceField	MultipleChoiceField(choices)
# FileField	FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
# ImageField	ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)

常用字段
CharField
BooleanField
IntegerField
DecimalField

ListField: {name:'lqz',age:19,hobby:['篮球','足球']}
DictField:{name:'lqz',age:19,wife:{'name':'刘亦菲','age':33}}

1.2、常用字段参数

给CharField 字段用的参数

参数名称作用
max_length最大长度
min_lenght最小长度
allow_blank是否允许为空
trim_whitespace是否允许为空

给IntegerField字段用的参数

参数名称作用
max_value最小值
min_value最小值

**通用参数 **

参数名称作用
required表明该字段在反序列化时必须输入,默认True
default反序列化时使用的默认值
allow_null表明该字段是否允许传入None,默认False
validators该字段使用的验证器【不需要了解】
error_messages包含错误编号与错误信息的字典
label用于HTML展示API页面时,显示的字段名称
help_text用于HTML展示API页面时,显示的字段帮助提示信息

重点

参数名称作用
read_only表明该字段仅用于序列化输出,默认False
write_only表明该字段仅用于反序列化输入,默认False

2、 序列化类高级用法之source

修改序列化字段名字
使用source,字段参数,可以指定序列化表中得哪个字段

book_name = serializers.CharField(max_length=8, min_length=3,source='name')
  • source指定的可以是字段,也可以是方法,用于重命名
  • source可以做跨表查询

演示

class BookSerializer(serializers.Serializer):
    name_detail = serializers.CharField(max_length=8, min_length=3,source='name')
    # 或
    publish_name = serializers.CharField(max_length=8, min_length=3,source='publish.name')
    # 或
    xx = serializers.CharField(max_length=8, min_length=3,source='xx') #source的xx表示表模型中得方法

3、序列化类高级用法之定制序列化字段的两种方式

前端显示形式

{
        "name": "西游记",
        "price": 33,
        "publish": {name:xx,city:xxx,email:sss}
}

方式一:
在【序列化类】中写SerializerMethodField

publish = serializers.SerializerMethodField()
    def get_publish(self, obj):
        # obj 是当前序列化的对象
        return {'name': obj.publish.name, 'city': obj.publish.city, 'email': obj.publish.email}

方式二:
在【表模型】中写方法(又多一些)

def publish_detail(self):
        return {'name': self.publish.name, 'city': self.publish.city, 'email': self.publish.email}
    在序列化中取
    publish_detail=serializers.DictField

在模型类中写逻辑代码,称之为ddd,领域驱动模型

3.1、方式一 演示:

class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8, min_length=3)
    price = serializers.IntegerField(min_value=10, max_value=99)
    publish_date = serializers.DateField()
    # publish要序列化成 {name:北京出版社,city:北京,email:2@qq.com}
    # 方式一:SerializerMethodField必须配合一个方法(get_字段名,需要接受一个参数),方法返回什么,这个字段就是什么
    publish = serializers.SerializerMethodField()
    def get_publish(self, obj):
        # obj 是当前序列化的对象
        return {'name': obj.publish.name, 'city': obj.publish.city, 'email': obj.publish.email}

    # 练习,用方式一,显示所有作者对象  []
    authors = serializers.SerializerMethodField()
    def get_authors(self, obj):
        res_list = []
        for author in obj.authors.all():
            res_list.append({'id': author.id, 'name': author.name, 'age': author.age})
        return res_list

2.2、方式二 演示

# 表模型中
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish_date = models.DateField(null=True)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    # 写了个方法,可以包装成数据属性,也可以不包
    def publish_detail(self):
        return {'name': self.publish.name, 'city': self.publish.city, 'email': self.publish.email}

    def author_list(self):
        res_list = []
        for author in self.authors.all():
            res_list.append({'id': author.id, 'name': author.name, 'age': author.age})
        return res_list

序列化类中

class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8, min_length=3)
    price = serializers.IntegerField(min_value=10, max_value=99)
    publish_date = serializers.DateField()

    # 方式二:在表模型中写方法
    publish_detail = serializers.DictField(read_only=True)
    # 练习,使用方式二实现,显示所有作者
    author_list = serializers.ListField(read_only=True)

3、反序列化

序列化和反序列化字段 不一样【】

publish = serializers.CharField(write_only=True)
authors = serializers.ListField(write_only=True)

重写create
使用继承Serializer的序列化类保存需要重写create方法

def create(self, validated_data): 
            # validated_data 校验过后的数据  
              {"name":"三国1演义",
                "price":19,
                "publish_date": "2022-09-27",
                "publish":1,
                "authors":[1,2]
                }
            book = Book.objects.create(name=validated_data.get('name'),
                                       price=validated_data.get('price'),
                                       publish_date=validated_data.get('publish_date'),
                                       publish_id=validated_data.get('publish'),
                                       )
            authors = validated_data.get('authors')
            book.authors.add(*authors)
            return book

5、模型类序列化器(ModelSerializer))使用

比继承Serializers序列化方法更方便

class BookModelSerializer(serializers.ModelSerializer): #ModelSerializer继承Serializer
    # 不需要写字段了,字段从表模型映射过来
    class Meta:
        model = Book  # 要序列化的表模型
        # fields='__all__' # 所有字段都序列化
        fields = ['name', 'price', 'publish_date', 'publish', 'authors', 'publish_detail',
                  'author_list']  # 列表中有什么,就是序列化哪个字段
        # 给authors和publish加write_only属性
        # name加max_len属性
        extra_kwargs = {
            'name': {'max_length': 8},
            'publish': {'write_only': True},
            'authors': {'write_only': True},
        }  

6、反序列化之数据校验

跟 form数据校验 方法很像

# 字段自己的校验规则
	-如果继承的是Serializer,写法如下
    	name=serializers.CharField(max_length=8,min_length=3,error_messages={'min_length': "太短了"})
    -如果继承的是ModelSerializer,写法如下
       extra_kwargs = {
            'name': {'max_length': 8, 'min_length': 3, 'error_messages': {'min_length': "太短了"}},
        }
        
        
# 局部钩子
    -如果继承的是Serializer,写法一样
    -如果继承的是ModelSerializer,写法一样
	def validate_name(self, name):
        if name.startswith('sb'):
            # 校验不通过,抛异常
            raise ValidationError('不能以sb卡头')
        else:
            return name

        
# 全局钩子
	-如果继承的是Serializer,写法一样
    -如果继承的是ModelSerializer,写法一样
	def validate(self, attrs):
        if attrs.get('name') == attrs.get('publish_date'):
            raise ValidationError('名字不能等于日期')
        else:
            return attrs

局部钩子
继承的是Serializer 与继承ModelSerializer写法一样

def validate_name(self, name):
        if name.startswith('sb'):
            # 校验不通过,抛异常
            raise ValidationError('不能以sb卡头')
        else:
            return name

全局钩子
继承的Serializer与继承ModelSerializer 写法一样

def validate(self, attrs):
        if attrs.get('name') == attrs.get('publish_date'):
            raise ValidationError('名字不能等于日期')
        else:
            return attrs

7、断言 assert

在框架源码中,大量使用断言

断言,作用的判断,断定一个变量必须是xx,如果不是就报错
assert :

普通写法

name = 'lqz1'
if not name == 'ming':
    raise Exception('name不等于ming')
print('程序执行完了')

断言写法

name = 'lqz1'
assert name == 'lqz', 'name不等于lqz'
print('程序执行完了')

作业

写出book表(带关联关系)5 个接口

Serializer
ModelSerializer(简单,不用重写create和update)
name最大8,最小3,名字中不能带sb
price最小9,最大199,不能为66

1、写出book表(带关联关系)5 个接口

1.1、Serializer 方法

serializer.py

from rest_framework import serializers
from app01.models import Book,Author,Author_Detail,Publish

from rest_framework.exceptions import ValidationError


class BookSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=8,min_length=3)
    price = serializers.IntegerField(max_value=199,min_value=9)
    publish_date = serializers.DateField()

    publish_out = serializers.SerializerMethodField(read_only=True,)
    def get_publish_out(self, obj):
        return {'name': obj.publish.name, 'city': obj.publish.city, 'email': obj.publish.email}


    author_out = serializers.SerializerMethodField(read_only=True)
    def get_author_out(self, obj):
        author_list = []
        for author_obj in obj.author.all():
            author_list.append({'name': author_obj.name, 'age': author_obj.age})
        return author_list

    publish = serializers.IntegerField(write_only=True)
    author = serializers.ListField(write_only=True)

    def validate_price(self,price):
        if price == 66:
            raise ValidationError('不饿能为66')
        else:
            return price

    def validate_name(self,name):
        if name.count('sb')>=1:
            raise ValidationError('名字中有铭感词汇')
        else:
            return name

    def create(self, validated_data):
        book=Book.objects.create(name=validated_data.get('name'),
                            price=validated_data.get('price'),
                            publish_date=validated_data.get('publish_date'),
                            publish_id=validated_data.get('publish'),
                            )
        author_list = validated_data.get('author')
        book.author.add(*author_list)
        return book

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name')
        instance.price = validated_data.get('price')
        instance.publish_date = validated_data.get('publish_date')
        instance.publish_id = validated_data.get('publish')
        instance.author.set(validated_data.get('author'))
        instance.save()
        return instance

view.py

from app01.models import Book

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.serializer import BookSerializer


class BookView(APIView):
    def get(self, request):
        book = Book.objects.all()
        ser = BookSerializer(instance=book, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)


class Book_View(APIView):
    def get(self,request,pk):
        book_obj = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book_obj)
        return Response(ser.data)

    def put(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book_obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).delete()
        return Response()
1.2、ModelSerialize方法

serializer.py

from rest_framework import serializers
from app01.models import Book,Author,Author_Detail,Publish

from rest_framework.exceptions import ValidationError

class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['name', 'price', 'publish_date', 'publish', 'author', 'publish_int', 'author_li']
        extra_kwargs = {
            'name':{'max_length':8,'min_length':3,'error_messages':{
                'max_length':'名字太长了',
                'min_length':'名字太短了'
            }},
            'price':{'max_value':199,'min_value':9,'error_messages':{
                'max_value':'最大值为199',
                'min_value':'最小值为9',
            }},
            'publish':{'write_only':True},
            'author':{'write_only':True},
        }

    def validate_price(self, price):
        if price == 66:
            raise ValidationError('不饿能为66')
        else:
            return price

    def validate_name(self, name):
        if name.count('sb')>=1:
            raise ValidationError('名字中有铭感词汇')
        else:
            return name

views.py

from app01.models import Book

from rest_framework.views import APIView
from rest_framework.response import Response
from app01.serializer import BookModelSerializer


class BookView(APIView):
    def get(self, request):
        book = Book.objects.all()
        ser = BookModelSerializer(instance=book, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = BookModelSerializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)


class Book_View(APIView):
    def get(self,request,pk):
        book_obj = Book.objects.filter(pk=pk).first()
        ser = BookModelSerializer(instance=book_obj)
        return Response(ser.data)

    def put(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).first()
        ser = BookModelSerializer(instance=book_obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)

    def delete(self, request, pk):
        book_obj = Book.objects.filter(pk=pk).delete()
        return Response()

2、出版社,作者,作者详情 5个接口写完(ModelSerializer好些一些)

class Publish_Mser(serializers.ModelSerializer):
    class Meta:
        model = Publish
        fields = ['name','city','email',]


class Author_Mser(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ['name','age']

class Author_Detail_MSer(serializers.ModelSerializer):
    class Meta:
        model = Author_Detail
        fields = ['phone','addr']
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值