Python 学习笔记(十六)--Django REST Framework之serializers

1.序列化组件介绍

序列化:序列化器会把模型对象转换成字典,经过response以后变成json字符串。

反序列化:把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型。反序列化,可以完成数据校验功能。

2.引入方式

from rest_framework import serializers

3.类的方法和属性

 4.序列化类的使用

(1)序列化类,继承 serializers.Serializer (或 serializers.ModelSerializer);

 (2)在类中,

         为 serializers.Serializer是,明确需要序列化的字段(逐一指明需要的字段);

         为 serializers.ModelSerializer,明确 class Meta: 信息。

(3)在视图类中使用:导入序列化类,把要序列化的对象传入, 实例化得到序列化类的对象。【要序列化谁,就把谁传过来,其实就是调用类的__init__,看源码是需注意:这个方法来自父类BaseSerializer

(4)序列化类的对象.data是一个字典(注意:不是json)。

(5)使用rest_framework.response中的Response,会以Json的形式把字典里面的数据返回。      from rest_framework.response import Response  【如果不使用这个Response,就需要使用JsonResponse (from django.http import JsonResponse)】

5.序列化类的常见字段类型

serializers.CharField()

serializers.IntegerField()

serializers.IntegerField()

serializers.BooleanField()

serializers.ChoiceField()

serializers.JSONField()

7.数据验证(一般用在反序列化)

Serializer中的validate方法:
    def validate(self, attrs):
        return attrs

父类BaseSerializer有个is_valid方法

    def is_valid(self, raise_exception=False):
        assert hasattr(self, 'initial_data'), (
            'Cannot call `.is_valid()` as no `data=` keyword argument was '
            'passed when instantiating the serializer instance.'
        )

        if not hasattr(self, '_validated_data'):
            try:
                self._validated_data = self.run_validation(self.initial_data)
            except ValidationError as exc:
                self._validated_data = {}
                self._errors = exc.detail
            else:
                self._errors = {}

        if self._errors and raise_exception:
            raise ValidationError(self.errors)

        return not bool(self._errors)
is_valid 返回true 表示验证通过。
注意:不能直接对象.save() , 否则会报错 --NotImplementedError: 'update()' must be implemented。

8.报错原因

Serializer中没有save方法,只是父类BaseSerializer有个save方法.

    def save(self, **kwargs):
        assert hasattr(self, '_errors'), (
            'You must call `.is_valid()` before calling `.save()`.'
        )

        assert not self.errors, (
            'You cannot call `.save()` on a serializer with invalid data.'
        )

        # Guard against incorrect use of `serializer.save(commit=False)`
        assert 'commit' not in kwargs, (
            "'commit' is not a valid keyword argument to the 'save()' method. "
            "If you need to access data before committing to the database then "
            "inspect 'serializer.validated_data' instead. "
            "You can also pass additional keyword arguments to 'save()' if you "
            "need to set extra attributes on the saved model instance. "
            "For example: 'serializer.save(owner=request.user)'.'"
        )

        assert not hasattr(self, '_data'), (
            "You cannot call `.save()` after accessing `serializer.data`."
            "If you need to access data before committing to the database then "
            "inspect 'serializer.validated_data' instead. "
        )

        validated_data = {**self.validated_data, **kwargs}

        if self.instance is not None:
            self.instance = self.update(self.instance, validated_data)
            assert self.instance is not None, (
                '`update()` did not return an object instance.'
            )
        else:
            self.instance = self.create(validated_data)
            assert self.instance is not None, (
                '`create()` did not return an object instance.'
            )

        return self.instance

父类中还有个update()

    def update(self, instance, validated_data):
        raise NotImplementedError('`update()` must be implemented.')

就是这个汇报的错误。

 所以,需要在序列化类中,重新这个update方法。重写时,需要注意,instance代表的是序列化类对象,validated_data是校验后的数据。赋值后,不要忘记保存和返回。

        instance.save()
        return instance

9. 有必要看下父类BaseSerializer的代码,特别是__init__,需要留意的是data参数。

在视图类中,一般通过     序列化类(instance=model的对象, data=request.data),这种格式进行反序列化。

class BaseSerializer(Field):
    """
    The BaseSerializer class provides a minimal class which may be used
    for writing custom serializer implementations.

    Note that we strongly restrict the ordering of operations/properties
    that may be used on the serializer in order to enforce correct usage.

    In particular, if a `data=` argument is passed then:

    .is_valid() - Available.
    .initial_data - Available.
    .validated_data - Only available after calling `is_valid()`
    .errors - Only available after calling `is_valid()`
    .data - Only available after calling `is_valid()`

    If a `data=` argument is not passed then:

    .is_valid() - Not available.
    .initial_data - Not available.
    .validated_data - Not available.
    .errors - Not available.
    .data - Available.
    """

    def __init__(self, instance=None, data=empty, **kwargs):
        self.instance = instance
        if data is not empty:
            self.initial_data = data
        self.partial = kwargs.pop('partial', False)
        self._context = kwargs.pop('context', {})
        kwargs.pop('many', None)
        super().__init__(**kwargs)

10. 通过 钩子函数 丰富验证

局部钩子

通过 validate_字段名(self,接受一个参数), 定义一个钩子函数,丰富对字段的验证。

全局钩子

就是重写serializers.Serializer 中的 validate 方法

    def validate(self, attrs):
        return attrs

11.举例(重新update+钩子函数)

class UserDetailSerializer(serializers.ModelSerializer):
    def update(self, instance, validated_data):
        for attr, value in validated_data.items():
            if attr == "password":
                instance.set_password(value)
            elif attr in ("groups", "user_permissions", "resource_group"):
                getattr(instance, attr).set(value)
            else:
                setattr(instance, attr, value)
        instance.save()
        return instance

    def validate_password(self, password):
        try:
            validate_password(password)
        except ValidationError as msg:
            raise serializers.ValidationError(msg)
        return password

    class Meta:
        model = Users
        fields = "__all__"
        extra_kwargs = {
            "password": {"write_only": True, "required": False},
            "username": {"required": False},
        }

例子来自:https://gitee.com/rtttte/Archery/blob/master/sql_api/serializers.py

 

热门相关:邪王独宠:纨绔异能妃   写给鼹鼠先生的情书   魔葫   陆鸣至尊神殿   我有一张沾沾卡