Django REST Framework 边看边译

Serializers
       序列化程序允许将复杂的数据(如查询和模型实例)转换为原始python数据类型,然后可以轻松地将其呈现为json、xml或其他内容类型。在首次对输入的数据进行验证后,serializers也提供反序列化能够将解析后的数据转换回复杂的数据类型。

Declaring Serializers
首先创建一个简单的object用于示例:

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()

comment = Comment(email='leila@example.com', content='foo bar')

 我们将声明一个用于对Comment进行序列化和反序列话的Serializer

from rest_framework import serializers

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

Serializing objects 

我们现在使用CommentSerializer对一个或一组comment进行序列化

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

 此时,我们已经将模型实例翻译成python数据类型。为了完成序列化过程,我们将数据呈现到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"}'

 Deserializing objects

反序列化类似。首先,我们将流解析成python本地数据类型...

import io
from rest_framework.parsers import JSONParser

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

..然后,我们将这些本机数据类型恢复到经验证的数据字典中。

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)}

Saving instances

如果我们希望能够返回基于验证的完整的对象实例,我们需要实现create()和update()方法。例如:

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

如果您的对象实例对应于django模型,您还需要确保这些方法将对象保存到数据库中。例如,如果comment是django模型,方法可能如下所示:

    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

现在反序列化数据时,我们可以调用.save()返回已经验证的对象实例

comment = serializer.save()

调用.save()将创建新实例或更新现有实例,具体取决于实例化序列化类时是否传递了现有实例:

# .save() will create a new instance.
serializer = CommentSerializer(data=data)

# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)

 呃呃呃呃呃 太慢了 记录要点吧

Passing additional attributes to .save()

在保存实例时还可以在.save()中添加字段参数

serializer.save(owner=request.user)

Overriding .save() directly.

在某些情况下create()和update()方法名可能没有意义。例如,在联系人表单中,我们可能不会创建新的实例,而是发送电子邮件或其他消息。

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)

(毛啊没看懂)

Validation

对数据进行反序列化,使用验证数据前需要先调用is_valid(),若发生错误, .errors()返回一个字典类型的错误信息

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

When deserializing a list of items, errors will be returned as a list of dictionaries representing each of the deserialized items.

Raising an exception on invalid data

The .is_valid() method takes an optional raise_exception flag that will cause it to raise a serializers.ValidationErrorexception if there are validation errors.

These exceptions are automatically dealt with by the default exception handler that REST framework provides, and will return HTTP 400 Bad Request responses by default.

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

Field-level validation

 .validate_<field_name>

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

Object-level validation

对多个字段做验证,add a method called .validate() to your Serializersubclass.

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 start is before finish.
        """
        if data['start'] > data['finish']:
            raise serializers.ValidationError("finish must occur after start")
        return data

Validators

serializer的单个字段能够包含validators,

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])

Serializer classes也能包含可以复用的验证器, 能够作用于完整的字段集, 在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']
        )

Partial updates

默认情况下,序列化时必须传递所有required字段的值,但是可以使用partial来部分更新

# Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': 'foo bar'}, partial=True)

Dealing with nested objects

一个对象嵌套在另一个对象里, 就是一个对象是另一个对象的一个字段

class UserSerializer(serializers.Serializer):
    email = serializers.EmailField()
    username = serializers.CharField(max_length=100)

class CommentSerializer(serializers.Serializer):
    user = UserSerializer()
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
class CommentSerializer(serializers.Serializer):
    user = UserSerializer(required=False)  # May be an anonymous user.
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
class CommentSerializer(serializers.Serializer):
    user = UserSerializer(required=False)
    edits = EditItemSerializer(many=True)  # A nested list of 'edit' items.
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()

Writable nested representations

嵌套对象的字段错误也被嵌套

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

实在是太慢了

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值