序列化:从Django数据库—Django的模型—JSON/XML等文本格式
例如:我们在django的ORM中获取到的数据默认是模型对象,但是模型对象数据无法直接提供给前端或别的平台使用,所以我们需要把数据进行序列化,变成字符串或者json数据,提供给别人。
反序列化:上面过程的反方向
例如:前端js提供过来的json数据,对于python而言就是字符串,我们需要进行反序列化换成模型类对象,这样我们才能把数据保存到数据库中。
注意:Serializer的使用不需要依赖于模型。ModelSerializer的使用需要依赖于已有model模型,常用来编写api
# models.py
from django.db import models
# Create your models here.
class Book(models.Model):
id = models.IntegerField(primary_key=True)
title = models.CharField(max_length=255)
desc = models.CharField(max_length=255)
is_deleted = models.IntegerField(choices=[(1, "删除"), (0, "未删除")])
author = models.CharField(max_length=255)
# serializer.py
from rest_framework.serializers import Serializer
from rest_framework import serializers
class BookSerializer(Serializer):
id = serializers.IntegerField()
title = serializers.CharField()
desc = serializers.CharField()
is_deleted = serializers.ChoiceField(choices=[(1, "删除"), (0, "未删除")], source="get_is_deleted_display")
author = serializers.CharField()
# views.py
from app01.models import Book
from app01.serializer import BookSerializer
from django.http import HttpResponse, JsonResponse
# Create your views here.
def get_books(request):
books = Book.objects.all()
se = BookSerializer(books, many=True)
return JsonResponse(se.data, safe=False)
结果返回:[{“id”: 1, “title”: “活着”, “desc”: “讲述一代人的人生”, “is_deleted”: “未删除”, “author”: “余华”}]
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
ModelSerializer并没有任何魔法,它只是一个创建序列化类的快捷方式:
在写法上model和serializer的写法非常相近,但内在逻辑model是与数据库表的关系映射,serializer是对对象的序列化和反序列化。
序列化: 模型对象 -> 字典
1、序列化器的创建
Serializer(instance=None, data=empty, **kwarg)
# instance: 用于序列化时,传入要序列化的模型类对象。
# data: 用于反序列化时,传入字典数据
2、序列化操作
from users.models import *
from users.serializers import *
dep = Department.objects.get(id=1)
serializer = DepartmentSerializer(dep)
serializer.data
# {'create_date': '2009-01-01', 'name': '研发部',
# 'is_delete': False, 'id': 1}
3、序列化操作: many=True参数
如果要序列化的是包含多条数据的QuerySet,则需要指定many=True,否则报错。模型类的实例转换成了Python原生的数据类型
serializer = DepartmentSerializer(query_set, many=True)
serializer.data
# [OrderedDict([('id', 1), ('name', '研发部'), ('create_date', '2009-01-01'), ('is_delete', False)]),
# OrderedDict([('id', 2), ('name', '人事部'), ('create_date', '2009-03-01'), ('is_delete', False)])]
将数据渲染成json:
content = JSONRenderer().render(serializer.data)
content
# '{"id": 2, "title": "", "code": "print \\"hello, world\\"\\n", "linenos": false, "language": "python", "style": "friendly"}'
4.反序列化
字节流解析成Python原生的数据类型:
from django.utils.six import BytesIO
stream = BytesIO(content)
data = JSONParser().parse(stream)
将这些原生数据类型存储成模型类的实例:
serializer = SnippetSerializer(data=data)
serializer.is_valid()
# True
serializer.validated_data
# OrderedDict([('title', ''), ('code', 'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])
serializer.save()
#
参数名称 | 作用 |
max_length | 最大长度 |
min_length | 最小长度 |
allow_blank | 是否允许为空 |
trim_whitespace | 是否截断空白字符 |
max_value | 最大数值 |
min_value | 最小数值 |
通用参数:
read_only | 表明该字段仅用于序列化输出,默认False |
write_only | 表明该字段仅用于反序列化输入,默认False |
required | 表明该字段在反序列化时必须输入,默认True |
default | 反序列化时使用的默认值 |
allow_null | 表明该字段是否允许传入None,默认False |
validators | 该字段使用的验证器 |
error_messages | 包含错误编号与错误信息的字典 |
label | 用于HTML展示API页面时,显示的字段名称 |
help_text | 用于HTML展示API页面时,显示的字段帮助提示信息 |
serializer = CommentSerializer(data={'email': 'foobar', 'content': 'baz'})
serializer.is_valid()
# False
serializer.errors
# {'email': ['Enter a valid e-mail address.'], 'created': ['This field is required.']}
serializer.validated_data就可以获取校验过后的数据字典
有三种方式:
1.在字段的validators属性, 其中传入一个校验方法列表如:validators=(my_validator, )其中my_validator中定义校验规则。
示例:
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])
2.定义一个validate_field_name(self, value)的函数(其中field_name指的是字段名),函数内是具体的逻辑。
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
3.定义一个validate(self, data)其中data是所有字段的键值对,所以这个校验方法是对象级别的校验。
from rest_framework import serializers
class EventSerializer(serializers.Serializer):
description = serializers.CharField(max_length=100)
start = serializers.DateTimeField()
finish = serializers.DateTimeField()
def validate(self, data):
"""
Check that start is before finish.
"""
if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start")
return data
在我们定义的序列化类中, 可以添加create和update方法,当我们有需求是根据反序列化后的数据在数据库表中创建记录或者更新某条数据,这时我们就可以在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.objects.create(**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)
instance.save()
return instance
调用serializer.save()命令便可创建一条纪录或者更新一条记录,其中判断save时什么时候是创建什么时候是更新呢?关键在于serializer的实例化。
# .save() will create a new instance.
serializer = CommentSerializer(data=data)
serializer.save()
# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)
serializer.save()
其中当Serializer类实例化没有传入model对象时会调用create方法创建一条记录, 如果Serializer类实例化时传入了model对象就会调用update方法更新一条记录。