rest_framework中的Serializer

研究了许久,记录一下

serializer类是最简单的序列化基类,封装也是最低级的,由此可以推出也就是灵活的,因为你自己要写的东西很多,就很灵活。

1、首先 ,用这个类你要实现两个方法,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

解释一下,create是新建的的时候用的,参数validated_data就是客户端传过来的参数。update中instance就是数据库中查询出来的model的object,调用方式如下:

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

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

2、有时候你可能需要传入的validated_data不仅包含模型中的字段,还有额外的需要用的,这个时候直接穿进去就行,用的时候直接validated_data.*  就可以出来了 见下面:

serializer.save(owner=request.user)
然后:
serializer中validated_data.owner就可以取到userid的值判断了
3、你可以对serializer中的每一个字段进行验证,对整个serializer进行判断,就是对传入的参数做一些限制的意思。

对某一个字段判断 -覆盖validate_title 判断就好:

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判断,直接覆盖validate方法就好:

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

以上的验证都要抛出异常raise serializers.ValidationError("finish must occur after start")

4、有的时候调用更新update方法时,参数是写死的,第一个必须是模型对象,第二个可以不是传入所有key,传入一下key的values这时候要指定参数了,,不然会报错
# Update `comment` with partial data
serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)
5、处理那种嵌套的格式的数据时,应该指定serializer就行,见下面这样就可以
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()

如果嵌套的那个地方可能是空 要指定参数required

class CommentSerializer(serializers.Serializer):
    user = UserSerializer(required=False)  # May be an anonymous user.
    content = serializers.CharField(max_length=200)
    created = serializers.DateTimeField()
如果是多个要指定 Many=True

有嵌套的时候,create和update就比较麻烦了,因为要分开存储和更新,和下面一样

class UserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()

    class Meta:
        model = User
        fields = ('username', 'email', 'profile')

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = User.objects.create(**validated_data)
        Profile.objects.create(user=user, **profile_data)
        return user
def update(self, instance, validated_data):
        profile_data = validated_data.pop('profile')
        # Unless the application properly enforces that this field is
        # always set, the follow could raise a `DoesNotExist`, which
        # would need to be handled.
        profile = instance.profile

        instance.username = validated_data.get('username', instance.username)
        instance.email = validated_data.get('email', instance.email)
        instance.save()

        profile.is_premium_member = profile_data.get(
            'is_premium_member',
            profile.is_premium_member
        )
        profile.has_support_contract = profile_data.get(
            'has_support_contract',
            profile.has_support_contract
         )
        profile.save()

        return instance

下面这个地方没明白:记录下后续研究
Including extra context
There are some cases where you need to provide extra context to the serializer in addition to the object being serialized. One common case is if you're using a serializer that includes hyperlinked relations, which requires the serializer to have access to the current request so that it can properly generate fully qualified URLs.

You can provide arbitrary additional context by passing a context argument when instantiating the serializer. For example:

serializer = AccountSerializer(account, context={'request': request})
serializer.data
# {'id': 6, 'owner': u'denvercoder9', 'created': datetime.datetime(2013, 2, 12, 09, 44, 56, 678870), 'details': 'http://example.com/accounts/6/details'}
The context dictionary can be used within any serializer field logic, such as a custom .to_representation() method, by accessing the self.context attribute.

重要~~上面只是serializer的翻译,其实实际使用大多是ModelSerializer

你可能感兴趣的:(rest_framework中的Serializer)