django rest framework serializers

时间:2023-03-09 17:00:49
django rest framework serializers

django rest framework serializers序列化

serializers是将复杂的数据结构变成json或者xml这个格式的

serializers有以下几个作用:
- 将queryset与model实例等进行序列化,转化成json格式,返回给用户(api接口)。
- 将post与patch/put的上来的数据进行验证。
- 对post与patch/put数据进行处理。

实现序列化二个类:Serializer与ModelSerializer 比较

django rest framework serializers

ModelSerializer(Serializer) 即 ModelSerializer继承了Serializer的相关功能,是对model实现序列化的封装

一、serializers.fieild

我们知道在django中,form也有许多field,那serializers其实也是drf中发挥着这样的功能。我们先简单了解常用的几个field。

1. 常用的field

CharField、BooleanField、IntegerField、DateTimeField这几个用得比较多

django rest framework serializers
# 举例子
mobile = serializers.CharField(max_length=11, min_length=11)
age = serializers.IntegerField(min_value=1, max_value=100)
# format可以设置时间的格式,下面例子会输出如:2018-1-24 12:10
pay_time = serializers.DateTimeField(read_only=True,format='%Y-%m-%d %H:%M')
is_hot = serializers.BooleanField()
django rest framework serializers

serializer的field不仅在进行数据验证时起着至关重要的作用,在将数据进行序列化后返回也发挥着重要作用

2. Core arguments参数

read_only:True表示不允许用户自己上传,只能用于api的输出。如果某个字段设置了read_only=True,那么就不需要进行数据验证,只会在返回时,将这个字段序列化后返回 
举个简单的例子:在用户进行购物的时候,用户post订单时,肯定会产生一个订单号,而这个订单号应该由后台逻辑完成,而不应该由用户post过来,如果不设置read_only=True,那么验证的时候就会报错。

order_sn = serializers.CharField(readonly=True)

write_only: 与read_only对应 
required: 顾名思义,就是这个字段是否必填。 
allow_null/allow_blank:是否允许为NULL/空 。 
error_messages:出错时,信息提示。

name = serializers.CharField(required=True, min_length=6,
error_messages={
'min_length': '名字不能小于6个字符',
'required': '请填写名字'})

label: 字段显示设置,如 label=’验证码’ 
help_text: 在指定字段增加一些提示文字,这两个字段作用于api页面比较有用 
style: 说明字段的类型,这样看可能比较抽象,看下面例子:

# 在api页面,输入密码就会以*显示
password = serializers.CharField(
style={'input_type': 'password'})
# 会显示选项框
color_channel = serializers.ChoiceField(
choices=['red', 'green', 'blue'],
style={'base_template': 'radio.html'})

3. HiddenField

HiddenField的值不依靠输入,而需要设置默认的值,不需要用户自己post数据过来,也不会显式返回给用户,最常用的就是user!! 
我们在登录情况下,进行一些操作,假设一个用户去收藏了某一门课,那么后台应该自动识别这个用户,然后用户只需要将课程的id post过来,那么这样的功能,我们配合CurrentUserDefault()实现。

# 这样就可以直接获取到当前用户
user = serializers.HiddenField(
default=serializers.CurrentUserDefault())
4 多对多
class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__"
depth=1

备注:

1.定义一个depth=1  会将特殊字段  FK和M2M中每个对象的所有字段全部取出来。

2.对于FK字段,显示的是主键值,对于多对多字段,默认显示方式为:[pk1,pk2,...],一个列表中,包含所有字段对象的主键值。如果我们不想显示主键值,可以重写对应字段属性。

django rest framework serializers
django rest framework serializers
class BookModelSerializers(ModelSerializer):
class Meta:
model=Book
fields="__all__" authors=serializers.SerializerMethodField()
def get_authors(self,obj):
temp=[]
for obj in obj.authors.all():
temp.append(obj.name)
return temp
django rest framework serializers
django rest framework serializers

3.对于含有choices的字段,我们可以通过指定字段的source来显示展示的值

  比如:course_class = models.Integerfield(choices=((1,'初级'),(2,'中级')))

course_class = serializers.CharField(source='get_course_class_display')

二、save instance

save instance这是为post和patch所设置的。

post请求对应create方法,而patch请求对应update方法,这里提到的create方法与update方法,是指mixins中特定类中的方法。我们看一下源代码:

# 只截取一部分
class CreateModelMixin(object):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def perform_create(self, serializer):
serializer.save() class UpdateModelMixin(object):
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {} return Response(serializer.data) def perform_update(self, serializer):
serializer.save()

可以看出,无论是create与update都写了一行:serializer.save( ),那么,这一行,到底做了什么事情,分析一下源码。

# serializer.py
def save(self, **kwargs):
# 略去一些稍微无关的内容
···
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
···
else:
self.instance = self.create(validated_data)
···
return self.instance

显然,serializer.save的操作,它去调用了serializer的create或update方法,不是mixins中的!!!我们看一下流程图(以post为例)

aaarticlea/png;base64,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" alt="" />

讲了那么多,我们到底需要干什么!重载这两个方法!! 
如果你的viewset含有post,那么你需要重载create方法,如果含有patch,那么就需要重载update方法。

# 假设现在是个博客,有一个创建文章,与修改文章的功能, model为Article。
class ArticleSerializer(serializers.Serializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault())
name = serializers.CharField(max_length=20)
content = serializers.CharField() def create(self, validated_data):
# 除了用户,其他数据可以从validated_data这个字典中获取
# 注意,users在这里是放在上下文中的request,而不是直接的request
user = self.context['request'].user
name = validated_data['name ']
content = validated_data['content ']
return Article.objects.create(**validated_data) def update(self, instance, validated_data):
# 更新的特别之处在于你已经获取到了这个对象instance
instance.name = validated_data.get('name')
instance.content = validated_data.get('content')
instance.save()
return instance

可能会有人好奇,系统是怎么知道,我们需要调用serializer的create方法,还是update方法,我们从save( )方法可以看出,判断的依据是:

if self.instance is not None:pass

那么我们的mixins的create与update也已经在为开发者设置好了

# CreateModelMixin
serializer = self.get_serializer(data=request.data)
# UpdateModelMixin
serializer = self.get_serializer(instance, data=request.data, partial=partial)

也就是说,在update通过get_object( )的方法获取到了instance,然后传递给serializer,serializer再根据是否有传递instance来判断来调用哪个方法!

三、Validation自定义验证逻辑

1、单独的validate

在上面提到field,它能起到一定的验证作用,但很明显,它存在很大的局限性,举个简单的例子,我们要判断我们手机号码,如果使用CharField(max_length=11, min_length=11),它只能确保我们输入的是11个字符,那么我们需要自定义!

mobile_phone = serializers.CharField(max_length=11, min_length=11)

def validate_mobile_phone(self, mobile_phone):
# 注意参数,self以及字段名
# 注意函数名写法,validate_ + 字段名字
if not re.match(REGEX_MOBILE, mobile):
# REGEX_MOBILE表示手机的正则表达式
raise serializers.ValidationError("手机号码非法")
return mobile_phone

当然,这里面还可以加入很多逻辑,例如,还可以判断手机是否原本就存在数据库等等。

2、联合validate

上面验证方式,只能验证一个字段,如果是两个字段联合在一起进行验证,那么我们就可以重载validate( )方法。

start = serializers.DateTimeField()
finish = serializers.DateTimeField() def validate(self, attrs):
# 传进来什么参数,就返回什么参数,一般情况下用attrs
if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start")
return attrs

这个方法非常的有用,我们还可以再这里对一些read_only的字段进行操作,我们在read_only提及到一个例子,订单号的生成,我们可以在这步生成一个订单号,然后添加到attrs这个字典中。

order_sn = serializers.CharField(readonly=True)
def validate(self, attrs):
# 调用一个方法生成order_sn
attrs['order_sn'] = generate_order_sn()
return attrs

这个方法运用在modelserializer中,可以剔除掉write_only的字段,这个字段只验证,但不存在与指定的model当中,即不能save( ),可以在这delete掉!

3、Validators

validators可以直接作用于某个字段,这个时候,它与单独的validate作用差不多

def multiple_of_ten(value):
if value % 10 != 0:
raise serializers.ValidationError('Not a multiple of ten') class GameRecord(serializers.Serializer):
score = IntegerField(validators=[multiple_of_ten])

当然,drf提供的validators还有很好的功能:UniqueValidator,UniqueTogetherValidator等 
UniqueValidator: 指定某一个对象是唯一的,如,用户名只能存在唯一:

username = serializers.CharField(
max_length=11,
min_length=11,
validators=[UniqueValidator(queryset=UserProfile.objects.all())

UniqueTogetherValidator: 联合唯一,如用户收藏某个课程,这个时候就不能单独作用于某个字段,我们在Meta中设置。

class Meta:
validators = [
UniqueTogetherValidator(
queryset=UserFav.objects.all(),
fields=('user', 'course'),
message='已经收藏'
)]

四、ModelSerializer

讲了很多Serializer的,在这个时候,我还是强烈建议使用ModelSerializer,因为在大多数情况下,我们都是基于model字段去开发。

好处:

ModelSerializer已经重载了create与update方法,它能够满足将post或patch上来的数据进行进行直接地创建与更新,除非有额外需求,那么就可以重载create与update方法。 
ModelSerializer在Meta中设置fields字段,系统会自动进行映射,省去每个字段再写一个field。

class UserDetailSerializer(serializers.ModelSerializer):
"""
用户详情序列化
""" class Meta:
model = User
fields = ("name", "gender", "birthday", "email", "mobile")
# fields = '__all__': 表示所有字段
# exclude = ('add_time',): 除去指定的某些字段
# 这三种方式,存在一个即可

ModelSerializer需要解决的2个问题:

1,某个字段不属于指定model,它是write_only,需要用户传进来,但我们不能对它进行save( ),因为ModelSerializer是基于Model,这个字段在Model中没有对应,这个时候,我们需要重载validate! 
如在用户注册时,我们需要填写验证码,这个验证码只需要验证,不需要保存到用户这个Model中:

def validate(self, attrs):
del attrs["code"]
return attrs

2,某个字段不属于指定model,它是read_only,只需要将它序列化传递给用户,但是在这个model中,没有这个字段!我们需要用到SerializerMethodField。 
假设需要返回用户加入这个网站多久了,不可能维持这样加入的天数这样一个数据,一般会记录用户加入的时间点,然后当用户获取这个数据,我们再计算返回给它。

class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
# 方法写法:get_ + 字段
def get_days_since_joined(self, obj):
# obj指这个model的对象
return (now() - obj.date_joined).days class Meta:
model = User

这个的SerializerMethodField用法还相对简单一点,后面还会有比较复杂的情况。

关于外键的serializers

讲了那么多,终于要研究一下外键啦~ 
其实,外键的field也比较简单,如果我们直接使用serializers.Serializer,那么直接用PrimaryKeyRelatedField就解决了。 
假设现在有一门课python入门教学(course),它的类别是python(catogory)。

# 指定queryset
category = serializers.PrimaryKeyRelatedField(queryset=CourseCategory.objects.all(), required=True)

ModelSerializer就更简单了,直接通过映射就好了 
不过这样只是用户获得的只是一个外键类别的id,并不能获取到详细的信息,如果想要获取到具体信息,那需要嵌套serializer

category = CourseCategorySerializer()

注意:上面两种方式,外键都是正向取得,下面介绍怎么反向去取,如,我们需要获取python这个类别下,有什么课程。 
首先,在课程course的model中,需要在外键中设置related_name

class Course(model.Model):
category = models.ForeignKey(CourseCategory, related_name='courses')
# 反向取课程,通过related_name
# 一对多,一个类别下有多个课程,一定要设定many=True
courses = CourseSerializer(many=True)

有一个小问题:我们在上面提到ModelSerializer需要解决的第二个问题中,其实还有一种情况,就是某个字段属于指定model,但不能获取到相关数据。

假设现在是一个多级分类的课程,例如,编程语言–>python–>python入门学习课程,编程语言与python属于类别,另外一个属于课程,编程语言类别是python类别的一个外键,而且属于同一个model,实现方法:

parent_category = models.ForeignKey('self', null=True, blank=True,
verbose_name='父类目别',
related_name='sub_cat')

现在获取编程语言下的课程,显然无法直接获取到python入门学习这个课程,因为它们两没有外键关系。SerializerMethodField( )也可以解决这个问题,只要在自定义的方法中实现相关的逻辑即可!

courses = SerializerMethodField()
def get_courses(self, obj):
all_courses = Course.objects.filter(category__parent_category_id=obj.id)
courses_serializer = CourseSerializer(all_course, many=True,
context={'request': self.context['request']})
return courses_serializer.data

上面的例子看起来有点奇怪,因为我们在SerializerMethodField()嵌套了serializer,就需要自己进行序列化,然后再从data就可以取出json数据。

可以看到传递的参数是分别是:queryset,many=True多个对象,context上下文。这个context十分关键,如果不将request传递给它,在序列化的时候,图片与文件这些Field不会再前面加上域名,也就是说,只会有/media/img…这样的路径!

转载出处: www.careeru.cn/blog/article/?id=85