6

django框架之drf:04、序列化器常用字段及参数,序列化器高级用法之source、定制字段...

 1 year ago
source link: https://www.cnblogs.com/kangssssh/p/17087423.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Django框架之drf

一、序列化器常用字段及参数

# 序列化类---》字段类 CharField,除此之外还有哪些其他的

# 序列化类---》字段类,字段类上,传属性的 ,序列化类上,也可以写属性
    models.CharField(max_length=32)

1、常用字段

字段 字段构造方式
BooleanField BooleanField()
NullBooleanField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
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(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)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

2、常用字段参数

选项参数

参数名 说明
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
max_value 最大值
min_value 最小值

通用参数

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

3、字段参数针对性分类

选项参数:

# CharField及其子类的(EmailField) ---》反序列化的校验,字段自己的规则
    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


## 反序列化校验执行流程
	-1 先执行字段自己的校验规则----》最大长度,最小长度,是否为空,是否必填,最小数字。。。。
    -2 validators=[方法,] ----》单独给这个字段加校验规则
    	name=serializers.CharField(validators=[方法,])
    -3 局部钩子校验规则
    -4 全局钩子校验规则

二、序列化器高级用法之source

准备工作

### 创建关联表
class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.CharField(max_length=32)

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


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)
    phone = models.CharField(max_length=11)

# 迁移,录入数据

1、定制字段名

​ 在我们编写序列化器的时候,序列化类中的字段名字对应的是模型层下表名内对应的字段名,但有的时候我们需要确保数据的安全,并不想直接将真实的字段名返回给前端用户查看,这个时候我们就可以利用source参数来将返回给前端的字段名进行修改

source参数:可以指定序列化字段的名字

class BookSerializer(serializers.Serializer):
    # 自有字段: 直接写字段名
    book_name = serializers.CharField(source='name')
    book_price = serializers.CharField(source='price')

    # 外键字段:多对多,字段名字修改了,但是数据内容没办法显示
    book_author = serializers.CharField(source='author.all')
    # 外键字段:一对多,可以显示
    book_publish = serializers.CharField(source='publish.name')

2987296-20230202210135306-551523134.png

三、定制字段数据的两种的方法

定制关联字段的显示形式

  • 一对多:显示字典
  • 多对多:显示列表内套字典

1、在序列化器类中定制

使用:SerializerMethodField字段定制

from rest_framework import serializers


class BookSerializer(serializers.Serializer):
    # 自有字段
    book_name = serializers.CharField(source='name')
    book_price = serializers.CharField(source='price')

    # 外键字段
    book_publish = serializers.SerializerMethodField()

    def get_book_publish(self, obj):
        return {'name': obj.publish.name, 'address': obj.publish.address}

    book_author = serializers.SerializerMethodField()

    def get_book_author(self, obj):
        book_data_list = [{'name': author_obj.name, 'phone': author_obj.phone} for author_obj in obj.author.all()]
        return book_data_list
2987296-20230202210143664-144295266.png

2、在模型表中定制

在models.py文件下表的类中定制

### models.py 表的类中编写方法
    from django.db import models


    class Book(models.Model):
        name = models.CharField(max_length=32)
        price = models.CharField(max_length=32)

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

        def publish_detail(self):
            return {'name': self.publish.name, 'phone': self.publish.address}

        author = models.ManyToManyField(to='Author')

        def author_list(self):
            book_data_list = [{'name': author_obj.name, 'phone': author_obj.phone} for author_obj in self.author.all()]
            return book_data_list
    
    
### Serialiaer.py 序列化器中编写方法
    from rest_framework import serializers


    class BookSerializer(serializers.Serializer):
        # 自有字段
        book_name = serializers.CharField(source='name')
        book_price = serializers.CharField(source='price')

        # 外键字段
        publish_detail = serializers.DictField()
        author_list = serializers.ListField()
2987296-20230202210300923-2087095753.png

四、多表关联反序列化保存

前端传入数据格式

# 前端传入的数据格式:
	{'name':'红楼梦','price':19,'publish':1,'authors':[1,2]}

1、新增接口

### view.py 视图类
    class BookView(APIView):
        # 新增
        def post(self, request):
            ser_obj = BookSerializer(data=request.data)
            if ser_obj.is_valid():
                ser_obj.save()
                return Response({'code': 100, 'msg': '新增图书成功', 'result': ser_obj.data})
            return Response({'code': 101, 'msg': ser_obj.errors})
        
        
### serializer.py 序列化器类
    class BookSerializer(serializers.Serializer):
        # 自有字段
        name = serializers.CharField()
        price = serializers.CharField()

        # 设置write_only参数,只作为反序列化使用
        publish = serializers.CharField(write_only=True)
        author = serializers.ListField(write_only=True)

        # 外键字段,设置read_only参数,只作为序列化使用
        publish_detail = serializers.DictField(read_only=True)
        author_list = serializers.ListField(read_only=True)

        # 新增
        def create(self, validated_data):
            # 使用反序列化后的数据创建新的图书
            new_book_obj = Book.objects.create(name=validated_data.get('name'),             price=validated_data.get('price')    ,                     publish_id=validated_data.get('publish'))
            # 作者外键字段同步更新
           new_book_obj.author.add(*validated_data.get('author'))
            return new_book_obj

2、修改接口

### view.py 视图类:
    class BookDetailView(APIView):	
        # 修改
        def put(self, request, pk):
            # 获取指定图书
            target_book_obj = Book.objects.filter(pk=pk).first()
            if target_book_obj:
                ser_obj = BookSerializer(data=request.data, instance=target_book_obj)
                if ser_obj.is_valid():
                    ser_obj.save()
                    return Response(ser_obj.data)
                return Response({'code': 101, 'msg': ser_obj.errors})
            return Response({'code': 101, 'msg': '图书不存在'})
        
        
### serializer.py 序列化器类:
	class BookSerializer(serializers.Serializer):
        # 自有字段
        name = serializers.CharField()
        price = serializers.CharField()

        # 设置write_only参数,只作为反序列化使用
        publish = serializers.CharField(write_only=True)
        author = serializers.ListField(write_only=True)

        # 外键字段,设置read_only参数,只作为序列化使用
        publish_detail = serializers.DictField(read_only=True)
        author_list = serializers.ListField(read_only=True)
		  # 修改
		  def update(self, instance, validated_data):
            instance.name = validated_data.get('name')
            instance.price = validated_data.get('price')
            instance.publish_id = validated_data.get('publish')
            instance.author.clear()
            instance.author.add(*validated_data.get('author'))
            instance.save()
            return instance

五、反序列化字段校验(总结)

反序列化字段校验(共四层)

1、自有字段:可直接在字段后方参数填写校验规则
2、validators参数:同样在字段后方参数内填写,通过绑定函数体代码进行校验
3、局部钩子
4、全局钩子

六、ModelSerializer的使用

ModelSerializer继承自Serializer,帮助我们完成了很多操作

特点

  • 和表模型强关联
  • 帮助我们完成很多请求,不用再create和update

使用方法

class BookSerializer(serializers.ModelSerializer):
    # 控制字段的校验
    class Meta:
        # 与表进行关联
        model = Book
        # 填写__all__默认序列全部字段,如果Meta写了__all__ ,就相当于,复制了表模型中的所有字段,放在了这里,做了个映射
        # fields = '__all__'
        # 填写列表是校验部分字段
        fields = ['name', 'price', 'publish', 'author', 'publish_detail', 'author_list']

        # 给字段添加校验或限制
        extra_kwargs = {
            'name': {'max_length': 3},
            'price': {'min_length': 2},
            'publish': {'write_only': True},
            'author': {'write_only': True},
            'author_list': {'read_only': True},
            'publish_detail': {'read_only': True},
        }

    # 假如Meta类中已经对字段进行校验,任然可以在外部(内部的校验失效)重写校验,优先级高于Meta内部的校验
    name = serializers.CharField(max_length=8)
    # 同理,针对外键字段的方法也可以在外部重写
    # book_publish = serializers.SerializerMethodField()
    #
    # def get_book_publish(self, obj):
    #     return {'name': obj.publish.name, 'address': obj.publish.address}
    #
    # book_author = serializers.SerializerMethodField()
    #
    # def get_book_author(self, obj):
    #     book_data_list = [{'name': author_obj.name, 'phone': author_obj.phone} for author_obj in obj.author.all()]
    #     return book_data_list

    # 钩子函数(不会影响,正常编写即可)
    def validate_name(self, name):
        if name.startswith('sb'):
            raise ValidationError('不能sb')

        else:
            return name

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK