rest框架-- serializer操作

Serializers把querysets和model instances这些复杂的数据结构转化为native Python 以便于以json,xml或其它内容类型的形式render出去。

  • 类似于Django的 Form 和ModelForm
  • Serializer和ModelSerializer

序列化对象
from datetime import datetime

classComment(object):def __init__(self, email, content, created=None):self.email = email
        self.content = content
        self.created = created or datetime.now()
from rest_framework import serializers

classCommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
comment =Comment(email='leila@example.com', content='foo bar')
serializer =CommentSerializer(comment)
serializer.data
# {'email': 'leila@example.com', 'content': 'foo bar', 'created': '2016-01-27T15:17:10.375877'}

把数据转化为json格式

from rest_framework.renderers importJSONRenderer

json =JSONRenderer().render(serializer.data)
json
# b'{"email":"leila@example.com","content":"foo bar","created":"2016-01-27T15:17:10.375877"}'

反序列化对象

把json数据转化为本地数据类型,也就是Django rest framework可以使用的数据类型

from django.utils.six importBytesIOfrom rest_framework.parsers importJSONParser

stream =BytesIO(json)
data =JSONParser().parse(stream)

让后进一步把这些数据绑定到serializers上面,serializer = CommentSerializer(data=data)之后使用serializer.is_valid()验证传进来的数据(上段代码的data是否符合CommentSerializer的格式,这里可以写一个try-exception.现在可以在serializer.validated_data找到传进来的数据。
在访问validated data或板寸validated data之前一定要检查serializer.is_valid()是否为true。如果为false的话错误信息包含在serializer.errors里。

serializer =CommentSerializer(data=data)
serializer.is_valid()# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}

 


保存instances

我们应该实现基本的create和update方法,把数据写入数据库

def create(self, validated_data):

  returnComment.objects.create(**validated_data)

def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)
        instance.save()return instance

 

如果不需要写入数据库,可以直接放回数据就好了

classCommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()def create(self, validated_data):returnComment(**validated_data)

  def update(self, instance, validated_data):
        instance.email = validated_data.get('email', instance.email)
        instance.content = validated_data.get('content', instance.content)
        instance.created = validated_data.get('created', instance.created)

     return instance

 

在命令行中的编写如下:
创建一个新的对象

serializer =CommentSerializer(data=data)
serializer.is_valid()# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}
comment = serializer.save()

 

更新已经存在的comment实例

serializer =CommentSerializer(comment, data=data)
serializer.is_valid()# True
serializer.validated_data
# {'content': 'foo bar', 'email': 'leila@example.com', 'created': datetime.datetime(2012, 08, 22, 16, 20, 09, 822243)}
comment = serializer.save()

 

在save的时候添加其它内容比如

serializer.save(owner=request.user)

owner数据被绑定在serializer.validated_data对象上,当create或update的时候就会被添加进数据库。
直接重写save()方法
有时候并不需要保存或则返回数据,这个时候save()方法就需要重写。比如执行发送邮件的任务。

classContactForm(serializers.Serializer):
    email = serializers.EmailField()
    message = serializers.CharField()def save(self):
        email =self.validated_data['email']
        message =self.validated_data['message']
        send_email(from=email, message=message)

 

请注意,在上述情况下,我们现在必须直接访问serializer_date属性。


验证
serializer =CommentSerializer(data={'email':'foobar','content':'baz'})
serializer.is_valid()# False
serializer.errors
# {'email': [u'Enter a valid e-mail address.'], 'created': [u'This field is required.']}

 

non_field_errors关键字有可能出现,可以在REST framework 框架的设置文件里面设置NON_FIELD_ERRORS_KEY。
is_valid()有默认的异常处理机制,raise_exception标志默认为true,框架自动帮你抛异常(serializers.ValidationError)。

# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True)

自定义验证
类似于Django表单的clean_<fieldname>方法,你可以添加validate<field_name>方法到你的Serializer子类里面。这个方法只接受要验证的数据这一个对象。抛出的异常也是serializers.ValidationError。

from rest_framework import serializers

classBlogPostSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=100)
    content = serializers.CharField()

  def validate_title(self, value):"""
        Check that the blog post is about Django.
        """if'django'notin value.lower():raise serializers.ValidationError("Blog post is not about Django")return value

 

注意:如果你不希望这个验证方法被使用,你可以在serializer上声明required=False,那么如果这个field没有包括进来这个验证步骤就不会起作用。(这里有点不清晰)
对象级验证
如果你的验证需要访问多个fileds,你可以添加serializer的子类validate().这个方法接收一个字典参数,你需要使用的多个fileds应该包含在这个字典参数里面。报错类型为serializers.ValidationError

from rest_framework import serializers

classEventSerializer(serializers.Serializer):
    description = serializers.CharField(max_length=100)
    start = serializers.DateTimeField()
    finish = serializers.DateTimeField()

  def validate(self, data):"""
        Check that the start is before the stop.
        """if data['start']> data['finish']:raise serializers.ValidationError("finish must occur after start")return data

 

验证器

  • 通过在字段实例上声明使用验证器
def multiple_of_ten(value):

   if value %10!=0:

   raise serializers.ValidationError('Not a multiple of ten')classGameRecord(serializers.Serializer):
score =IntegerField(validators=[multiple_of_ten])...

 

  • 作用于全部字段的验证器
    下载Meta里面
classEventSerializer(serializers.Serializer):
    name = serializers.CharField()
    room_number = serializers.IntegerField(choices=[101,102,103,201])
    date = serializers.DateField()classMeta:# Each room only has one event per day.
        validators =UniqueTogetherValidator(
            queryset=Event.objects.all(),
            fields=['room_number','date'])

 

posted @ 2018-09-26 10:47  forjie  阅读(1028)  评论(0编辑  收藏  举报