[Django] DRF custom serializer, serialization and deserialization

When using Django's front-end and back-end separate development, we often need to return the processed data in a certain format (such as json), or process the data from the front-end to perform database CURD. And DRF (Django REST Framework) can help me solve this problem, namely serialization and deserialization

1. Install DRF

Install using pip

pip install djangorestframework

Configure application

INSTALLED_APPS = [
    ...
    'rest_framework',
]

2. Define Serializer

We create a new py file specifically to write serialization classes inheriting serializers.Serializer, the written fields and constraints should be within the scope of the model class

models.py

from django.db import models

class BookInfo(models.Model):
    btitle = models.CharField(max_length=20, verbose_name='名称')
    bpub_date = models.DateField(verbose_name='发布日期', null=True)
    bread = models.IntegerField(default=0, verbose_name='阅读量')
    bcomment = models.IntegerField(default=0, verbose_name='评论量')
    image = models.ImageField(upload_to='booktest', verbose_name='图片', null=True)

serializers.py

from rest_framework import serializers

class BookInfoSerializer(serializers.Serializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    btitle = serializers.CharField(label='名称', max_length=20)
    bpub_date = serializers.DateField(label='发布日期', required=False)
    bread = serializers.IntegerField(label='阅读量', required=False)
    bcomment = serializers.IntegerField(label='评论量', required=False)
    image = serializers.ImageField(label='图片', required=False)

Note: The field type of Serializer is almost the same as that of Models. If you can't remember it, just check the serializers class.
Insert picture description here

Option parameter Description
max_length The maximum length
min_lenght Minimum length
allow_blank Whether it is allowed to be empty
trim_whitespace Whether to truncate whitespace characters
max_value Max
min_value Minimum
General parameters Description
read_only Indicates that this field is only used for serialized output, the default is False
write_only Indicates that the field is only used to deserialize input, the default is False
required Indicates that the field must be entered when deserializing, the default is True
default Default value used when deserializing
allow_null Indicates whether None is allowed in the field, the default is False
validators The validator used for this field
error_messages Dictionary containing error numbers and error messages
label Used to display the field name of the API page in HTML
help_text Used for HTML display of API page, the field help prompt information displayed

3. Create the Serializer object

Serializer(instance=None, data=empty, **kwarg)

Description:

  • When serializing, instance is passed into the model class object
  • When deserializing, data is passed in the deserialized data

4. Simple serialization

Serialize a single object

from booktest.models import BookInfo  # 导入图书模型类
from booktest.serializers import BookInfoSerializer # 导入序列器类

book = BookInfo.objects.get(id=2) # 获取一个单一模型类对象
serializer = BookInfoSerializer(book) # 序列化单一模型类对象

serializer.data # 查看序列化之后的数据

Serialized query set

books = BookInfo.objects.all()
serializer = BookInfoSerializer(books, many=True) # 要指定many=True
serializer.data  # 查看结果

5. Association nested serialization (foreign key)

If there is a foreign key, the main table or the secondary table may be serialized during serialization.

models.py

class BookInfo(models.Model):
	...
    def __str__(self):
        return self.btitle

class HeroInfo(models.Model):
	...
    hbook = models.ForeignKey(BookInfo, related_name='heros',on_delete=models.CASCADE, verbose_name='图书')  # 外键
    def __str__(self):
        return self.hname

5.1 Serializing the main table

serializers.py

class HeroInfoSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    hname = serializers.CharField()
    hgender = serializers.IntegerField()
    hcomment = serializers.CharField()
    is_delete = serializers.BooleanField()

class BookInfoSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    btitle = serializers.CharField()
    bpub_date = serializers.DateField()
    bread = serializers.IntegerField()
    bcomment = serializers.IntegerField()
    is_delete = serializers.BooleanField()
    image = serializers.ImageField()

    序列化主表BookInfo的时候,它的属性heros是关联的从表的多个对象

    关联对象序列化方案一:序列化成关联对象的主键
    heros = serializers.PrimaryKeyRelatedField(
        queryset=HeroInfo.objects.all(), 
        many=True # 表示当前字段heros序列化的是多个英雄对象
    )

    关联对象序列化方案二:序列化成关联对象的__str__方法返回的结果
    heros = serializers.StringRelatedField(many=True)
    
    关联对象序列化方案三:自定义关联对象序列化
    heros = HeroInfoSerializer(many=True)
5.1 Serialization from the table

serializers.py

class BookInfoSerializer(serializers.Serializer):
    btitle = serializers.CharField()
    bpub_date = serializers.DateField()
    bread = serializers.IntegerField()
    bcomment = serializers.IntegerField()
    is_delete = serializers.BooleanField()
    image = serializers.ImageField()

class HeroInfoSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    hname = serializers.CharField()
    hgender = serializers.IntegerField()
    hcomment = serializers.CharField()
    is_delete = serializers.BooleanField()

    代表当前英雄对象(),关联的书本()单一对象
    hbook = serializers.PrimaryKeyRelatedField(
        queryset=BookInfo.objects.all()
    )
    hbook = serializers.StringRelatedField()
    
    hbook = BookInfoSerializer()

Three form description
(1), PrimaryKeyRelatedField(queryset,many)
(2), StringRelatedField()
(3), custom serializer

6. Deserialization

6.1 Operation steps

(1) Obtain valid data

book_info = {
    
    "btitle": "围城", "bpub_date": "1999-9-9"}

(2) Instantiate the serializer object

bs = BookInfoSerializer(data=book_info, partial=True)

data is the data to be verified, partial is True is partial verification, what is verified

(3) Start the calibration process

bs.is_valid()

# 通过抛ValidationError异常的方式表示失败
# bs.is_valid(raise_exception=True)

When the is_valid() method is called, the verification starts, including constraint condition verification, type verification, validators verification, validate_<field name> verification, and validate verification. If all verifications pass, it returns True, otherwise it returns False

(4) Obtain the final result

若校验成功,查看有效数据
bs.validated_data

若校验失败,查看失败信息
bs.errors

(3) Custom verification 1: validators

serializers.py

# 针对btitle字段,自定义一个校验函数
def check_btitle(value):
    if "django" not in value:
        raise serializers.ValidationError("这不是一本关于django的书")

class BookInfoSerializer(serializers.Serializer):
	# validators指定多个针对当前字段的校验函数)
    btitle = serializers.CharField(其他校验,validators=[check_btitle] 
    ...

(3) Custom verification 2: validate_<field name>

serializers.py

class BookInfoSerializer(serializers.Serializer):
	...
    btitle = serializers.CharField(label='名称',max_length=20,)

    # 重写序列化器特定名称的方法,针对特定字段单独自定义校验,函数名称:validate_<被校验字段名>
    def validate_btitle(self, value):
        if "django" not in value:
            raise serializers.ValidationError("这不是一本关于django的书")

        # 切记,一定要返回字段的有效值,如果不返回会造成当前字段数据丢失
        return value

(3) Custom verification 3: validate

serializers.py

class BookInfoSerializer(serializers.Serializer):
	...
    btitle = serializers.CharField(label='名称',max_length=20,)

    def validate(self, attrs):
    	# 提取数据
        btitle = attrs.get('btitle')
        if 'django' not in btitle:
            raise serializers.ValidationError('这不是一本关于django的书')
        # 相同方式对别的字段校验...略
        # 返回最终的有效数据,如果不返回,后果就是丢失最终的有效数据
        return attrs

The third verification method is the most commonly used because it can perform custom verification on all fields

6.2 New and update operations

The data from the front end needs to be written into the database. It may be to create a new piece of data, or it may only update some fields. The new or update operation will be performed when the save() method is called.

When instantiating the serializer object, if you only pass in data without passing the instance, it is created, and if both are passed, it is updated data .

The essence of creating and updating is to call the two methods of create() and update() that we rewrite in the serializer.

serializers.py

class BookInfoSerializer(serializers.Serializer):
	 btitle = serializers.CharField(label='名称',max_length=20)
	 ...
     def create(self, validated_data):
        instance = BookInfo.objects.create(**validated_data) # create(btitle="django精通"....)
        return instance

    def update(self, instance, validated_data):
        for field,value in validated_data.items():
            # field = "btitle"; value = "django精通新版"
            setattr(instance, field, value)
        instance.save()
        return instance

For example

book_info = {
    
    "btitle": "django精通"....}
book = BookInfo.objects.get(pk=6)
bs = BookInfoSerializer(instance=book, data=book_info)
bs.is_valid()
# 如果校验结果为True,则调用save()方法
bs.save()

7. Supplement

7.1 PrimaryKeyRelatedField acts on deserialization
  • PrimaryKeyRelatedField is used to serialize the associated object into a primary key
  • When PrimaryKeyRelatedField is used for deserialization, deserialize the primary key into an associated object
7.2 Full update and partial update
  • Full update means all fields, must be transmitted and verified (default)
  • Partial updates are part of the fields. The necessary fields can be passed or not, and the passes will be verified (such as updating part of the fields)
# 全校验
Serializer(instance=模型类对象,data=参数)

# 部分校验(如更新部分字段操作)
Serializer(instance=模型类对象,data=参数,partial=True)
7.3 The save method passes keyword parameters

Under normal circumstances, the data parameter is used to transmit the data to be verified when the serializer is instantiated, but other fields may need to be specified later. At this time, other parameters can be passed in when the save() method is called.
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_39147299/article/details/108691882