DRF中序列化与反序列化

442 阅读3分钟

DRF中序列化与反序列化

1.序列化

序列化:展示特殊的数据(choices,ForeignKey,ManyToMany)可以使用的三种方法

1.source方法(常用于ForeignKey,与choices获取对应的中文)
user__avatar = serializers.CharField(source='user.avatar',read_only=True)  # user__avatar命名可以自定义
user_id = serializers.CharField(source='user.id',read_only=True)
user_nickname = serializers.CharField(source='user.nickname',read_only=True)
特例:对于choices      get_字段名_display  获取choices对应的中文
auction_start_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
auction_end_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
#不加read_only=True,也只是序列化,反序列化不会影响

即:对数据进行序列化,返回给前端,数据字段名称可自定义,通过source指定对应的字段,read_only 指定该表中字段不进行校验,而只进行序列化 通常为ForeignKey

注:使用read_only=True后,仅对数据进行序列化

2.SerializerMethodField:定义钩子方法。(一对多,多对多推荐)
   user = serializers.SerializerMethodField()  #新增数据库不存在字段或已有字段自定义命名
     .....
    def get_user(self, obj):
        if not obj.user:
            return
        return model_to_dict(obj.user, fields=['id', 'nickname', 'avatar'])

serializers.SerializerMethodField和钩子方法结合,可以实现对ModelSerializer类的一些字段进行二次加工,将数据序列化返回给前端

注:只有序列化时回使用,反序列化时不会影响

3.序列化嵌套
 # 简单省事可全部返回
class GoodsCategorySerializers(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = "__all__"
​
​
class GoodsListSerializers(serializers.ModelSerializer):
    category = GoodsCategorySerializers()
​
    class Meta:
        model = Goods
        fields = "__all__"

默认情况下,嵌套序列化器是只读的( !!!严重怀疑官网写错了,只读的话嵌套序列化必须指定read_only=true,不然反序列化的时候提示该序列化需必填),本人亲测,若不对请指正,谢谢

如果希望支持对嵌套序列化器字段的写操作,则需要创建create()和/或update()方法,以便显式指定应该如何保存子关系。

如果要实现可写,就要去掉read_only=true,同时添加create方法,如下:

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ('order', 'title', 'duration')
​
class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True)
​
    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')
​
    def create(self, validated_data): 
        tracks_data = validated_data.pop('tracks')
        album = Album.objects.create(**validated_data)
        for track_data in tracks_data:
            Track.objects.create(album=album, **track_data)
        return album

2.反序列化

def  validate_字段名(): # 表单校验
        # 对前端请求数据进行校验,serializers中使用
        # value 可为请求的model对象,通过value.xx 获取对应的字段
        
  def validate_coupon(self, value):
        user_object = self.context['request'].user
        coupon_obj = models.Coupon.objects.filter(id=value.id).first()
        if coupon_obj.deleted != 0:
            raise exceptions.ValidationError(detail='已删除')
        if coupon_obj.status != 2:
            raise exceptions.ValidationError(detail='未开始或已结束')
        exists = models.UserCoupon.objects.filter(user=user_object, coupon=coupon_obj).exists()
        if exists:
            raise exceptions.ValidationError(detail='已领取优惠券')
        if coupon_obj.count - coupon_obj.apply_count <= 0:
            raise exceptions.ValidationError(detail='优惠券已经申请完')
        return value
auction_id = serializers.IntegerField(label='拍卖ID')
   
   def validate_auction_id(self, value):
        user_object = self.context['request'].user
        exists = models.DepositRecord.objects.filter(user=user_object, auction_id=value, item__isnull=True).exists()
        if exists:
            raise exceptions.ValidationError(detail='已支付过全场保证金')
        return value
​
# 这里的value即为获取的请求具体的字段

3.终极大法,分开写serializer_class

# 视图函数中分开写serializer_class,序列化是一个serializer_class.反序列化也是一个serializer_class
def get_serializer_class(self):
        if self.action == "list":
            return CouponSerializer
        else:
            return CouponCreatSerializer
​
单表序列化总结
1. 序列化与反序列化功能可以整合到一个类,该类继承ModelSerializer
2. 继承ModelSerializer类的资源序列化类,内部包含三部分
    Meta字类、局部钩子、全局钩子
    注:createupdate方法ModelSerializer已经重写了,使用时不需要重写
3. 在Meta字类中:
    用model来绑定关联的Model类
    用fields来设置所有的序列化反序列化字段
    用extra_kwargs来设置系统的校验规则
4. 重要的字段校验规则:
    read_only校验规则,代表该字段只参与序列化
    write_only校验规则,代表该字段只参与反序列化
    required校验规则,代表该字段在反序列化时是必填(True)还是选填(False),不能和read_only一起使用(规则冲突)
    规则细节:
        如果一个字段有默认值或可以为空,没设置required,默认为False,反之为True
        如果一个Model字段既没有设置read_only也没有设置write_only,该字段默认参与序列化及反序列化
5. 自定义序列化字段:在Model类中,定义方法属性(返回特殊值,还可以完成连表操作),在序列化类的fields属性中可以选择性插拔
6. 自定义反序列化字段:在Serializer类中,自定义校验字段,校验规则也只能在声明字段时设置,自定义的反序列化字段(pwd),必须设置write_only为True
"""

\