为了账号安全,请及时绑定邮箱和手机立即绑定

Django rest framework之Serializers笔记(一)

标签:
Python

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

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

序列化对象
from datetime import datetime

class Comment(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

class CommentSerializer(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 import JSONRenderer

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 import BytesIO
from rest_framework.parsers import JSONParser

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):
        return Comment.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

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

class CommentSerializer(serializers.Serializer):
    email = serializers.EmailField()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

    def create(self, validated_data):
        return Comment(**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()方法就需要重写。比如执行发送邮件的任务。

class ContactForm(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

class BlogPostSerializer(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' not in 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

class EventSerializer(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')

class GameRecord(serializers.Serializer):
    score = IntegerField(validators=[multiple_of_ten])
    ...
  • 作用于全部字段的验证器
    下载Meta里面
class EventSerializer(serializers.Serializer):
    name = serializers.CharField()
    room_number = serializers.IntegerField(choices=[101, 102, 103, 201])
    date = serializers.DateField()

    class Meta:
        # Each room only has one event per day.
        validators = UniqueTogetherValidator(
            queryset=Event.objects.all(),
            fields=['room_number', 'date']
        )
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消