## 1 . 序列器 ```python from rest_framework import serializers serializers.Serializer, serializers.ModelSerializer """ 序列化器: 对数据校验、转换、 入库 试图: 对模型LCURD进行封装 序列化器: 和模型类字段名称一样 和模型类类型名称一样 和模型类选项名称一样 *field(选项1,选项2) """ ``` ## 2.Serializer: ```python from rest_framework import serializers class UserSerializer(serializers.Serializer): name = serializers.CharField(min_length=4, label='姓名') ... ``` ### 2.1序列化: (用于响应 无需校验) #### 1. 序列化关联外键 ```python 1. ##### 序列外键 class UserSerializer(serializers.Serializer): name = serializers.CharField(min_length=4) addr = serializers.PrimaryKeyField() # args: read_only=True, # addr=Address.objects.filter(user__id=id) -> 通过pk自动查找, 返回addr的pk ``` #### 2.序列关联模型类的__str__ ``` class UserSerializer(serializers.Serializer): name = serializers.CharField(min_length=4) addr = serializers.StringRelatedField() # many=True # args: read_only=True, queryset=Address.objects.all() -> 通过pk自动查找, 返回addr__str__ ``` #### 3.使用关联模型类的序列化器 ```PYTHON class UserSerializer(serializers.Serializer): name = serializers.CharField(min_length=4) addr = AddrSerializer() # 一对多序列化 spus = GoodsSpuSerializer(source='goodsspu_set') spus = serializers.StringRelatedField(many=True) ``` #### 4.序列化m2m/fk字段: ```PYTHON class BookSerializer(serializers.Serializer): name = serializers.CharField(min_length=4) author = serializers.SerializerMethodField() def get_author(self, obj): # get_字段名 args: obj是Book实例对象 ...... ``` #### 5.序列化单个模型对象 ```python user = User.objects.get(id=1) serializer = UserSerializer(instance=user) # instance参数表示将模型对象序列化 ``` #### 6.序列列化多个模型对象 ``` 列化多个模型对象: users = User.objects.all() serializers = UserSerializer(instance=users, many=True) # many=True, 意味着序列多个 serializers.data ``` #### 例: ```python # models.py class Area(models.Model): name = models.CharField(verbose_name='地域', max_length=25) parent = models.ForeignKey('self', related_name='subs', null=True) # 自关联 def __str__(self): return self.name # serializers.py class AreaSerializer(serializers.ModelSerializer): parent = serializers.StringRelatedField() subs = serializers.SerializerMethodField() class Meta: model = Area fields = ('name', 'parent', 'subs') def get_subs(self, obj): subs = Area.objects.filter(parent=obj).all() return AreaSerializer(subs, many=True).data """ obj 是当前验证的实例 parent = serializers.SerializerMethodField() def get_parent(self, obj): if obj.parent is None: obj.parent = '' // 此时会报错,因为parent必须是Area instance return AreaSerializer(obj) """ views.py get: def get(self, request): querys = self.get_queryset() serializer = self.get_serializer(querys, many=True) context = { 'data': serializer.data, 'meta': { 'msg': '获取成功', 'status': status.HTTP_200_OK } } return Response(context) ``` ### 2.2反序列化: (用于校验、入库) ```python views.py data_dict = { name = 'xs', ... } serializer = BookSerializer(data=data_dict) # data参数表示对数据进行校验 serializer.is_valid(raise_exception=True) 会依次进行5种校验, args一般都添加, 校验失败直接报错 serializer.data # 校验的数据 validated_data # 校验通过的数据 serializer.errors # 校验失败的错误信息, 在is_valid()之后调用 """ 5种校验规则: 字段类型的校验 字段选项的校验 单字段校验 多字段校验 自定义字段校验 """ ``` #### 1.单字段校验: validate_字段名 ```python def validated_name(self, value): # value是要校验的该字段的值 ... if value not in [1, 2, 3]: raise serializers.ValidationError("校验失败") return value "return即通过, raise即失败" ``` #### 2.多字段校验: 用于多字段之间的比较 ```python def validate(self, attrs): # attrs是要校验的数据 name = attrs.get('name') age = attrs.get('age') if name != 'alex' or age < 18: raise serializers.ValidationError("校验失败") return value "return即通过, raise即失败" ``` #### 3.自定义字段校验: 定义在序列化器类之外, 可通过单字段校验函数取代 ```PYTHON def check_name(value): ... return value # 序列化器类 class UserSerializer(serializers.Serializer): name = serializers.CharField(min_length=4, validators=[check_name]) ``` #### 4.create()方法 ```python # serializers.py class UserSerializer(serializers.Serializer): name = serializers.CharField(min_length=4, validators=[check_name]) def create(self, validated_data): user = User.objects.create(**validated_data) user.save() return user # views.py data_dict = { name = 'xs', ... } serializer = UserSerializer(data=data_dict) # data参数表示对数据进行校验 serializer.is_valid(raise_exception=True) serializer.save() # 调用序列化器create() ``` #### 5.update()方法 ```python # serializers.py class UserSerializer(serializers.Serializer): name = serializers.CharField(min_length=4, validators=[check_name]) def update(self, instance, validated_data): # instance 是当前的实例对象, validated_data是校验的数据 instance.** = validated_data.get(**) instance.save() return instance # views.py data_dict = { name = 'xs', ... } user = User.objects.get(id=3) serializer = UserSerializer(instance=user, data=data_dict) # instance与data 表示对instance修改数据 serializer.is_valid(raise_exception=True) serializer.save() # 调用序列化器update() ``` ## 3.serializers.ModelSerializer 已经实现了create和update ```python class UserSerializer(serializers.ModelSerializer): mobile = serializers.CharField(max_length=11, min_length=11) # 扩展mobile字段 class Meta: model=Blog fields = '__all__' read_only_field = () write_only_field = () extra_kwargs = { # 约束选项 'name': { 'min_length': 4, .... } } ``` ```python # views.py data_dict = { name = 'xs', ... } # serializer = UserSerializer(instance=data_dict) # instance表示将dict序列化返回, serializer.data serializer = UserSerializer(data=data_dict) # data参数表示对数据进行校验 serializer.is_valid(raise_exception=True) serializer.save() # 调用序列化器create() ``` ```python user = User.objects.get(id=3) serializer = UserSerializer(instance=user, data=data_dict) # instance与data 表示对instance修改数据 serializer.is_valid(raise_exception=True) serializer.save() # 调用序列化器update() ``` ```python # StringRelatedField 在反序列化要求是关联类对象(GoodsType), 单一的int/str在is_valid无法通过校验 # 1. 通过validate自定义校验规则 class GoodsSkuSerializer4Params(serializers.ModelSerializer): type = serializers.StringRelatedField() class Meta: model = GoodsSpu fields = '__all__' extra_kwargs = { 'detail': { 'read_only': True, } } def validate(self, attrs): _type = self.initial_data.get('type', "") if _type: try: gt = GoodsType.objects.get(id=_type) except Exception as e: raise ValueError attrs.update({'type': gt}) return attrs # 2. 通过update自定义更新 class GoodsSkuSerializer(serializers.ModelSerializer): type = serializers.StringRelatedField() goodsSpu = serializers.StringRelatedField() # sta = serializers.BooleanField(source='status') # all_type = serializers.SerializerMethodField() class Meta: model = GoodsSku fields = ('id', 'type', 'goodsSpu', 'name', 'desc', 'price', 'sales', 'stock', 'unite', 'status', 'image') def update(self, instance, validated_data): for k, v in validated_data.items(): setattr(instance, k, v) if self.initial_data.get('type'): instance.type_id = self.initial_data.get('type') if self.initial_data.get('goodsSpu'): instance.goodsSpu_id = self.initial_data.get('goodsSpu') instance.save() return instance ``` ## 4.自定义获取字段 ```python # encoding=utf-8 from orders.models import OrderInfo, OrderGoods from rest_framework import serializers from areas.models import Address4Users class AddrSerializer(serializers.ModelSerializer): class Meta: model = Address4Users fields = ('receiver', 'addr', 'phone') class OrderInfoSerializer(serializers.ModelSerializer): user = serializers.StringRelatedField() addr = serializers.SerializerMethodField() create = serializers.SerializerMethodField() order_status = serializers.SerializerMethodField() pay_method = serializers.SerializerMethodField() class Meta: model = OrderInfo fields = ('order_id', 'user', 'addr', 'total_price', 'order_status', 'trade_no', 'pay_method', 'create',) extra_kwargs = { 'order_id': { 'read_only': True, }, 'user': { 'read_only': True, }, 'addr': { 'read_only': True, }, 'total_price': { 'read_only': True, }, 'trade_no': { 'read_only': True, }, 'pay_method': { 'read_only': True, }, 'create': { 'read_only': True, }, } def get_addr(self, obj): addr = obj.addr return AddrSerializer(instance=addr).data def get_create(self, obj): return obj.create_time.strftime('%Y-%m-%d %H:%M:%S') def get_order_status(self, obj): return obj.get_order_status_display() def get_pay_method(self, obj): return obj.get_pay_method_display() def update(self, instance, validated_data): instance.order_status = self.initial_data.get('order_status') instance.save() return instance ```
浙公网安备 33010602011771号