码迷,mamicode.com
首页 > 其他好文 > 详细

django restframework序列化

时间:2018-07-29 22:34:43      阅读:276      评论:0      收藏:0      [点我收藏+]

标签:item   ide   处理   new   serial   objects   not   choices   display   

序列化

序列化用于对用户请求数据进行验证和数据进行序列化,序列化器(serializers)类似于Django forms

模型设计

from django.db import models

# Create your models here.
class User(models.Model):
    """
    用户信息
    """
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    level_choices = (
        (1, 'common'),
        (2, 'vip'),
        (3, 'svip')
    )
    level = models.PositiveSmallIntegerField(choices=level_choices, default=1)

    group = models.ForeignKey(to='Group')
    roles = models.ManyToManyField(to='Role')

    def __str__(self):
        return self.name

class UserToken(models.Model):
    """
    用户令牌
    """
    user = models.OneToOneField(to=User)
    token = models.CharField(max_length=64)

    def __str__(self):
        return self.token

class Role(models.Model):
    """
    角色
    """
    r_name = models.CharField(max_length=32, verbose_name='角色名')

    def __str__(self):
        return self.r_name

class Group(models.Model):
    """组"""
    g_name = models.CharField(max_length=32, verbose_name='组名称')

    def __str__(self):
        return self.g_name

序列化

序列化一般可以继承两个类,serializers.ModelSerializerserializers.Serializer。继承 serializers.Serializer需要手写字段,继承serializers.ModelSerializer 可以复用数据库字段,并且可以创建和更新数据。

serializers.Serializer

class GroupSerializer(serializers.Serializer):
    """
    用户序列化类
    """
    # g_name 名称和数据库表Group的字段名称需要一致
    g_name = serializers.CharField()

serializers.ModelSerializer

class UserSerializer(serializers.ModelSerializer):
    """
    {
    "code": 1000,
    "data": [
        {
            "id": 1,
            "name": "jack",
            "pwd": "123",
            "level": 3,
            "group": 1,
            "roles": [
                1,
                2
            ]
        },
        {
            "id": 2,
            "name": "lily",
            "pwd": "123",
            "level": 1,
            "group": 2,
            "roles": [
                2
            ]
        },
        {
            "id": 3,
            "name": "lisa",
            "pwd": "123",
            "level": 1,
            "group": 3,
            "roles": [
                4
            ]
        }
    ],
    "error": null
}
    """
    class Meta:
        model = User
        # fields 也可以接受一个列表
        fields = '__all__'

source

source只能得到单个值,不能处理多对多字段

class UserSerializer(serializers.ModelSerializer):
    level = serializers.CharField(source='get_level_display')
    # group 名称和数据库表一样会覆盖,不一样(写成g_name)就会显示g_name 和 group 两个
    group = serializers.CharField(source='group.g_name')

    class Meta:
        model = User
        # fields 也可以接受一个列表
        fields = ['level', 'group', 'roles', 'name', 'pwd','id']

多对多字段

class UserSerializer(serializers.ModelSerializer):
    level = serializers.CharField(source='get_level_display')
    # group 名称和数据库表一样会覆盖,不一样(写成g_name)就会显示g_name 和 group 两个
    group = serializers.CharField(source='group.g_name')
    roles = serializers.SerializerMethodField()

    class Meta:
        model = User
        # fields 也可以接受一个列表
        fields = ['level', 'group', 'roles', 'name', 'pwd','id']

    def get_roles(self, obj):
        return [i.r_name for i in obj.roles.all()]

超链接API:Hyperlinked

class UserSerializer(serializers.ModelSerializer):
    group = serializers.HyperlinkedIdentityField(
        view_name='sg',   
        lookup_field='group_id',
        lookup_url_kwarg='pk'
    )
    class Meta:
        model = User
        # depth = 1
        # fields 也可以接受一个列表
        fields = ['level', 'group', 'roles', 'name', 'pwd','id']

对应的urls.py的url: url(r‘group/(?P<pk>\d+)$‘, SingleGroupView.as_view(), name=‘sg‘)

views.py

class UserView(APIView):
    """用户视图"""
    def get(self, request, *args, **kwargs):
        ret = {'code': 1000, 'data':None, 'error': None}
        users = User.objects.all()
        try:
            users = User.objects.all()
            # 单个对象many=False
            gs = UserSerializer(users, many=True)
            ret['data'] = gs.data
        except Exception as e:
            ret['code'] = 1001
            ret['error'] = '发生错误'
        return Response(ret)

    def post(self, request, *args, **kwargs):
        ret = {'code': 1000, 'data': None, 'error': None}
        # request.data 是一个纯正的字典
        gs = UserSerializer(data=request.data)
        if gs.is_valid():
            # gs.validated_data 是rderedDict,因为roles字段重写成SerializerMethodField,
            # 所以默认的validated_data是获取不到值的,需要手动赋值
            gs.validated_data['roles'] = request.data['roles']
            # 会自动调用create , update 具体是什么方法根据传的参数来定
            gs.save()
            ret['data'] = request.data
        else:
            ret['error'] = gs.errors
        return Response(ret)

其中gs.data是列表套有序字典的形式,通过Response会做简单的转换成列表套普通字段的形式

重写create和update

    def create(self, validated_data):
        roles_list = validated_data.pop('roles')
        group = validated_data['group']['g_name']
        level = validated_data.pop('get_level_display')
        validated_data.pop('group')
        obj = User.objects.create(group_id=group,level=level, **validated_data)
        obj.roles.add(*roles_list)
        return obj

    def update(self, instance, validated_data):
        group = validated_data['group']['g_name']
        validated_data.pop('group')
        validated_data['group_id'] = group
        if 'get_level_display' in validated_data:
            validated_data['level'] = validated_data.pop('get_level_display')

        for attr, value in validated_data.items():
            setattr(instance, attr, value)
        instance.save()

        return instance

自定义验证字段

class XXValidator(object):
    def __init__(self, base):
        self.base = base

    def __call__(self, value):
        if not value.startswith(self.base):
            message = '标题必须以 %s 为开头。' % self.base
            raise serializers.ValidationError(message)

    def set_context(self, serializer_field):
        """
        This hook is called by the serializer instance,
        prior to the validation call being made.
        """
        # 执行验证之前调用,serializer_fields是当前字段对象
        pass

class UserGroupSerializer(serializers.Serializer):
    # title必须以jack开头,否则调用is_valid()就无法通过
    title = serializers.CharField(error_messages={'required':'标题不能为空'},validators=[XXValidator('jack'),])

源码流程

技术分享图片

实例化序列类对象的时候,先执行__new__,再执行__init__,根据many的不同分别调用Serializer类处理和ListSerializer类处理。ser.data会调用这两个对象的to_representation方法
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片
技术分享图片

django restframework序列化

标签:item   ide   处理   new   serial   objects   not   choices   display   

原文地址:https://www.cnblogs.com/longyunfeigu/p/9387576.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!