## 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 < 18raise 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


```