Use DRF deserializer

Use deserializer

Use serializer two stages:

  1. When the client request can be completed using a sequence of data deserialization.
  2. When the server responds, can be accomplished using the serializer to serialize the data.

Use of the basic sequence

Or a blog post on the database used in the use of

  • First check out a student objects

    from students.models import Student
    
    student = Student.objects.get(id=3)
  • Configured serialized objects

    from .serializers import StudentSerializer
    
    serializer = StudentSerializer(instance=student)
  • Get serialized data

    Data may be obtained by the serialized data property

    serializer.data
    # {'id': 4, 'name': '盖伦', 'age': 18, 'sex': True, 'description': '德玛西亚'}
  • Full View Code

    from django.views import View
    from students.models import Student
    from .serializers import StudentSerializer
    from django.http.response import JsonResponse
    class StudentRetrieveView(View):
        """使用序列化器序列化转换单个模型数据"""
        def get(self,request,pk):
            # 获取数据
            student = Student.objects.get(pk=pk)
            # 数据转换[序列化过程]
            serializer = StudentSerializer(instance=student)
            print(serializer.data)
            # 响应数据
            return JsonResponse(serializer.data)
  • If that is to be serialized including a plurality of sets of data query QuerySet, by adding many = True parametric description

    class StudentView(View):    
        """使用序列化器序列化转换多个模型数据"""
        def get(self,request):
            # 获取数据
            student_list = Student.objects.all()
    
            # 转换数据[序列化过程]
            # 如果转换多个模型对象数据,则需要加上many=True
            serializer = StudentSerializer(instance=student_list,many=True)
            print( serializer.data ) # 序列化器转换后的数据
    
            # 响应数据给客户端
            # 返回的json数据,如果是列表,则需要声明safe=False
            return JsonResponse(serializer.data,safe=False)

Deserialization

data verification

  • When using the serializer to deserialize, you must first validate the data before it can obtain verification of successful data or saved as an object model class.
  • Before getting deserialized data, you must call is_valid () method to verify, verify successful return True, otherwise False.
  • Verification fails, the object serialization errors attribute acquiring error information returned dictionary containing fields and field errors. If the field is non-error, by modifying the REST framework configuration NON_FIELD_ERRORS_KEY to control the error dictionary keys.
  • Successful validation, the sequence of objects by the validated_data acquiring data attributes.

When defining serialization, a sequence of specified types and options of each parameter field, itself a behavior verification.

Create a new sub-application books

python manage.py startapp books

New books in the sub-applications in settings.py in INSTALLED_APPS

INSTALLED_APPS = [
    # ...
    'ser',
    'unser',
]

Definition of a book and the serializer model,

Book model, as follows:

from django.db import models
class Book(models.Model):
    """图书模型"""
    title = models.CharField(verbose_name='名称', max_length=20)
    pub_date = models.DateField(verbose_name='发布日期')
    read = models.IntegerField(verbose_name='阅读量',default=0)
    comment = models.IntegerField(verbose_name='评论量', null=True, blank=True)

    class Meta:
        db_table = "tb_book"
        verbose_name="图书"
        verbose_name_plural=verbose_name

    def __str__(self):
        return self.title

Perform data migration, code:

python manage.py makemigrations
python manage.py migrate

BookSerializer serialization, code:

from rest_framework import serializers
class BookSerializer(serializers.Serializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    title = serializers.CharField(label='名称', max_length=20)
    pub_date = serializers.DateField(label='发布日期', required=False)
    read = serializers.IntegerField(label='阅读量', required=False)
    comment = serializers.IntegerField(label='评论量', required=False)

By constructing a sequence of objects, and to deserialize data to the data structure parameters, and further verify

from book.serializers import BookSerializer
data = {'pub_date': 123}
serializer = BookSerializer(data=data)
serializer.is_valid()  # 返回False
serializer.errors
# {'title': [ErrorDetail(string='This field is required.', code='required')], 'pub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].', code='invalid')]}
serializer.validated_data  # {}

data = {'title': 'python'}
serializer = BookSerializer(data=data)
serializer.is_valid()  # True   验证结果返回值
serializer.errors  # {}  错误信息
serializer.validated_data  #  OrderedDict([('btitle', 'python')])

is_valid () method may further exception is thrown if the validation fails serializers.ValidationError, can pass raise_exception = True parameters open, REST framework receives this exception, it returns a response to the HTTP 400 Bad Request distal end.

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

If that was not enough, you need to add custom validation behavior, you can use the following three ways:

validate_ field name

Of the <field_name>field to verify, as

class BookSerializer(serializers.Serializer):
    """图书数据序列化器"""
    ...

    def validate_title(self, value):
        if 'django' not in value.lower():
            raise serializers.ValidationError("图书不是关于Django的")
        return value

test

from book.serializers import BookSerializer
data = {'title': 'python'}
serializer = BookSerializer(data=data)
serializer.is_valid()  # False   
serializer.errors
#  {'title': [ErrorDetail(string='图书不是关于Django的', code='invalid')]}

validate

When a plurality of fields need to be compared to verify serializer can be defined to validate authentication methods, such as

class BookSerializer(serializers.Serializer):
    """图书序列化器"""
    ...

    def validate(self, attrs):
        read = attrs['read']
        comment = attrs['comment']
        if read < comment:
            raise serializers.ValidationError('阅读量小于评论量,不可以通过')
        return attrs

test

from book.serializers import BookSerializer
data = {'title': 'about django', 'read': 10, 'comment': 20}
s = BookSerializer(data=data)
s.is_valid()  # False
s.errors
#  {'non_field_errors': [ErrorDetail(string='阅读量小于评论量', code='invalid')]}

validators

Add validators option parameters in the field, also can add validation behavior, such as

def about_django(value):
    if 'django' not in value.lower():
        raise serializers.ValidationError("图书不是关于Django的")

class BookSerializer(serializers.Serializer):
    """图书序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    title = serializers.CharField(label='名称', max_length=20, validators=[about_django])
    pub_date = serializers.DateField(label='发布日期', required=False)
    read = serializers.IntegerField(label='阅读量', required=False)
    comment = serializers.IntegerField(label='评论量', required=False)
    image = serializers.ImageField(label='图片', required=False)

test:

from book.serializers import BookSerializer
data = {'title': 'python'}
serializer = BookSerializer(data=data)
serializer.is_valid()  # False   
serializer.errors
#  {'title': [ErrorDetail(string='图书不是关于Django的', code='invalid')]}

Deserialize - save data

After the preceding data is successfully verified, we can use the data to accomplish the serializer deserialization process. This process can be converted into the data model class object.

It can be achieved create()and update()to implement two methods.

class BookSerializer(serializers.Serializer):
    """图书数据序列化器"""
    ...

    def create(self, validated_data):
        """新建"""
        return Book(**validated_data)

    def update(self, instance, validated_data):
        """更新,instance为要更新的对象实例"""
        instance.title = validated_data.get('title', instance.title)
        instance.pub_date = validated_data.get('pub_date', instance.pub_date)
        instance.read = validated_data.get('read', instance.read)
        instance.comment = validated_data.get('comment', instance.comment)
        return instance

If the time required to return the data object, save data to the database, can be modified as follows

class BookSerializer(serializers.Serializer):
    """图书数据序列化器"""
    ...

    def create(self, validated_data):
        """新建"""
        return Book.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """更新,instance为要更新的对象实例"""
        instance.title = validated_data.get('title', instance.title)
        instance.pub_date = validated_data.get('pub_date', instance.pub_date)
        instance.read = validated_data.get('read', instance.read)
        instance.comment = validated_data.get('comment', instance.comment)
        instance.save()
        return instance

After achieve the above two methods, when the deserialized data, it can save () method returns an instance of the data object

book = serializer.save()

If you create a serialized object when there is no transmission instance instance, call the save()method when, Create () is called, the contrary, if the passed instance instance, calling save()methods when update()invoked.

from .serializers import BookSerializer
data = {'title': 'python入门指南'}
serializer = BookSerializer(data=data)
serializer.is_valid()  # True
serializer.save()  # <BookInfo: python入门指南>

from .models import Book
book = Book.objects.get(id=2)
data = {'title': 'django入门指南'}
serializer = BookSerializer(book, data=data)
serializer.is_valid()  # True
serializer.save()  # <BookInfo: django入门指南>
book.title  # 'django入门指南'

Additional information

  • When the serializer for save () save, may additionally transfer data that can be acquired in the create () and update () in parameter validated_data

    # request.user 是django中记录当前登录用户的模型对象
    serializer.save(owner=request.user)
  • The default serialization must pass all required fields, otherwise it will throw an exception verification. But we can use partial parameter to allow some field update

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

Model class serializer

After the experimental front, there a doubt that we can not use the serializer corresponding model class in Django? If so, we do not need to control the number of columns of models model's design. Taking into account the cost of the majority of the time the siege lion, DRF provides us ModelSerializer model class serializer to help us quickly create a Serializer class.

ModelSerializer conventional Serializer the same, but provides:

  • Automatically generating a series based model class field
  • Serializer validators is automatically generated based on model class, such as unique_together
  • Includes a default create () and update () implementation

definition

For example, we create a BookSerializer

class BookSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = Book
        fields = '__all__'
  • Referring to specify which model-based model
  • in which specified fields generated model class field

We can see BookSerializer automatically generated in python manage.py shell in concrete realization

>>> from booktest.serializers import BookSerializer
>>> serializer = BookSerializer()
>>> serializer
BookSerializer():
    id = IntegerField(label='ID', read_only=True)
    title = CharField(label='名称', max_length=20)
    pub_date = DateField(allow_null=True, label='发布日期', required=False)
    read = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
    comment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)

The specified field

1) Use fields to clear the field, __all__table name contains all the fields, which can also indicate the specific field, such as

class BookSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = Book
        fields = "__all__"

2) Use exclude can be explicitly ruled out which fields

class BookSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""
    class Meta:
        model = Book
        exclude = ('pub_date',)

3) Display of the specified attribute, such as:

class BookSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Book
        fields = ('id', 'title', 'comment', 'read')

4) indicates a read only field

By read_only_fields field to indicate the read-only field, i.e. output only for serializing

class BookSerializer(serializers.ModelSerializer):
    """图书序列化器"""
    class Meta:
        model = Book
        fields = ('id', 'title', 'pub_date', 'read', 'comment')
        read_only_fields = ('id', 'read', 'comment')

Additional parameters

We can use extra_kwargs parameters are added to ModelSerializer or amend the option parameter

class BookSerializer(serializers.ModelSerializer):
    """图书序列化器"""
    class Meta:
        model = Book
        fields = ('id', 'title', 'pub_date', 'read', 'comment')
        extra_kwargs = {
            'read': {'min_value': 0, 'required': True},
            'comment': {'min_value': 0, 'required': True},
        }

# BookSerializer():
#    id = IntegerField(label='ID', read_only=True)
#    title = CharField(label='名称', max_length=20)
#    pub_date = DateField(allow_null=True, label='发布日期', required=False)
#    read = IntegerField(label='阅读量', max_value=2147483647, min_value=0, required=True)
#    comment = IntegerField(label='评论量', max_value=2147483647, min_value=0, required=True)

Guess you like

Origin www.cnblogs.com/jjzz1234/p/11823765.html