标签: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.ModelSerializer
和 serializers.Serializer
。继承 serializers.Serializer
需要手写字段,继承serializers.ModelSerializer
可以复用数据库字段,并且可以创建和更新数据。
class GroupSerializer(serializers.Serializer):
"""
用户序列化类
"""
# g_name 名称和数据库表Group的字段名称需要一致
g_name = serializers.CharField()
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只能得到单个值,不能处理多对多字段
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()]
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‘)
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会做简单的转换成列表套普通字段的形式
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方法
标签:item ide 处理 new serial objects not choices display
原文地址:https://www.cnblogs.com/longyunfeigu/p/9387576.html