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.
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.