14、Django_rest framework_ModelSe

2019-11-15  本文已影响0人  猪儿打滚

一、进一步封装优化序列化器

二、ModelSerializer

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        # 需要序列化的model类
        model = User

        # 序列化所有的字段
        # fields = '__all__'

        # 序列化指定字段
        # fields = ('name', 'password', 'email', 'sex')

        # 排除哪些字段不进行序列化
        exclude = ('email',)

注意:由于对应了model类的字段,会存在必填字段,所以fileds=__all__exclude慎重使用

2.1、明确指定字段

当觉得全自动的字段不满足需求时,可以通过在ModelSerializer类上显式声明字段,从而增加额外的字段或者重写默认的字段,就和在Serializer类一样的。
比如:

class UserSerializer(serializers.ModelSerializer):
    c_time = serializers.DateTimeField(label='创建时间', help_text='创建时间', read_only=True)

    class Meta:
        model = User
        fields = '__all__'
明确指定ctime
2.2、指定只读字段

当我们希望批量将某些字段指定为只读,而不是显式的逐一为每个字段添加read_only=True属性,这种情况就可以使用Metaread_only_fields选项。
该选项的值是字段名称所组成的列表或元组,并像下面这样声明:

class UserSerializer(serializers.ModelSerializer):
    c_time = serializers.DateTimeField(label='创建时间', help_text='创建时间', read_only=True)

    class Meta:
        model = User
        fields = '__all__'
        read_only_fields = ('sex', 'password')
批量指定只读

注意: 有一种特殊情况,其中一个只读字段是模型级别unique_together约束的一部分。在这种情况下,序列化器需要该字段的值才能验证约束,但也是不能由用户编辑的。
处理此问题的正确方法是在序列化器上显式指定该字段,同时提供read_only=True和default=…关键字参数。
这种情况的一个例子就是对于一个和其他标识符unique_together的当前认证的User是只读的。 在这种情况下可以像下面这样声明user字段:

user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
from rest_framework import serializers

from projects.models import Projects
from interfaces.models import Interfaces


class InterfaceModelSerializer(serializers.ModelSerializer):
    # 从表指定输出主表外键输出的值
    project = serializers.StringRelatedField(label='所属项目', read_only=True)
    # 新增model不存在的字段,前端传递的是project_id,并且和project表是一个反向关联关系,所以需要添加一个显示字段
    project_id = serializers.PrimaryKeyRelatedField(queryset=Projects.objects.all(), write_only=True,
                                                    label='所属项目id', help_text='所属项目id')

    class Meta:
        model = Interfaces
        fields = ('id', 'name', 'tester', 'create_time', 'desc', 'project', 'project_id')

        extra_kwargs = {
            'create_time': {
                'read_only': True
            }
        }

    def create(self, validated_data):
        """
        前端传的是project_id,而对应的字段应该是project,所以需要处理下这里
        :param validated_data:
        :return:
        """
        project_id = validated_data.pop('project_id')
        validated_data['project'] = project_id
        interface_obj = super().create(validated_data)
        return interface_obj
2.3、添加关键字参数

可以通过使用extra_kwargs选项快捷地在字段上指定任意附加的关键字参数。这个选项是一个将具体字段名称当作键值的字典。

class UserSerializer(serializers.ModelSerializer):
    c_time = serializers.DateTimeField(label='创建时间', help_text='创建时间', read_only=True)

    class Meta:
        model = User
        fields = '__all__'
        extra_kwargs = {
            # model的任意字段
            "name": {
                "write_only": True,  # 字段名别写错
                "error_messages": {  #  字段名别写错
                    "max_length": "用户名最多不能超过50个字符"
                }
            }
        }
添加关键字参数
2.4、添加序列化器自定义的校验
class UserSerializer(serializers.ModelSerializer):
    c_time = serializers.DateTimeField(label='创建时间', help_text='创建时间', read_only=True)

    class Meta:
        model = User
        fields = '__all__'
        extra_kwargs = {
            # model的任意字段
            "name": {
                "write_only": True,  # 字段名别写错
                "error_messages": {  #  字段名别写错
                    "max_length": "用户名最多不能超过50个字符"
                }
            }
        }

    # 自定义字段级别的验证
    def validate_name(self, value):
        """
        用户名需要以“用户”开头
        :return:
        """
        if not str(value).startswith('用户'):
            # 抛出erializers.ValidationError异常
            raise serializers.ValidationError(detail='用户名需要以用户两个字开头')
        # 返回一个验证过的数据
        else:
            return attrs

    # 自定义多个字段的组合验证规则
    def validate(self, attrs):
        """
        password和email必需含有“lzl”这三个字母
        :return:
        """
        if "lzl" not in attrs['password'] or "lzl" not in attrs['email']:
            raise serializers.ValidationError(detail='password和email必需含有“lzl”这三个字母')
        else:
            return attrs
2.5、views.py的修改
2.6、指定外键序列化输出的值(从表指定主表外键)

主表:projcet
从表:interface
在interface副表中,外键是projcet
当使用ModelSerializer进行序列化时,默认会对project外键进行处理,默认生成的是PrimaryKeyRelatedField序列化器字段,序列化输出的是该interface对应的project表的id。
如果需要修改,那么需要显示处理:

from rest_framework import serializers

from interfaces.models import Interfaces
from projects.serializer import ProjectModelSerializer

class InterfaceModelSerializer(serializers.ModelSerializer):
    # 指定外键序列化输出内容(project是interface的外键字段)
    # 1、StringRelatedField:此字段会被序列化为关联对象字符串表达形式,也就是__str__方法的内容
    project = serializers.StringRelatedField(label='所属项目')
    # 2、SlugRelatedField:指定序列化返回的字段,比如下面序列化的结果是关联project表的leader字段的值
    project = serializers.SlugRelatedField(label='所属项目',  slug_field='leader')
    # 3、  指定返回关联的project序列化器(需要指定read_only,不然前端就需要输入一个project序列化器)
    project = ProjectModelSerializer((label='所属项目',  read_only=True)

    class Meta:
        model = Interfaces
        fields = '__all__'
2.6、指定外键序列化输出的值(主表指定从表)

主表中不会默认生成从表的关联字段,需要手动指定,并且字段名是从表名_set。其它方法和和在从表指定主表的一样。

class ProjectModelSerializer(serializers.ModelSerializer):
    #注意字段名,并且由于是从表,多的一方,要指定many=True
    interfaces_set = serializers.StringRelatedField(label='项目接口', many=True)
    class Meta:
        model = Interfaces
        fields = '__all__'
上一篇 下一篇

猜你喜欢

热点阅读