一 序列化器-Serializer
作用:
序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
反序列化,完成数据校验功能
1.1 定义序列化器
Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。
首先我们要有数据库模型类Publish:
from django.db import models
# Create your models here.
class Publish(models.Model):
nid = models.AutoField(primary_key=True,verbose_name='编号')
name = models.CharField(max_length=32,verbose_name='名称')
city = models.CharField(max_length=32,verbose_name='所在城市')
email = models.EmailField(verbose_name='邮箱')
def __str__(self):
return self.name
我们想为这个模型类提供一个序列化器,可以定义如下:
在serializer.py中定义继承Serilizer类的PublishSerializer类。
from rest_framework import serializers
class PublishSerializer(serializers.Serializer):
nid = serializers.IntegerField(required=False)
name = serializers.CharField(max_length=32,error_messages={
'max_length':'太长了,小伙子'
})
city = serializers.CharField()
email = serializers.EmailField()
注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。
常用字段类型:
字段 | 字段构造方式 |
---|---|
BooleanField | BooleanField() |
NullBooleanField | NullBooleanField() |
CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+ |
URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
UUIDField | UUIDField(format=’hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" |
IPAddressField | IPAddressField(protocol=’both’, unpack_ipv4=False, **options) |
IntegerField | IntegerField(max_value=None, min_value=None) |
FloatField | FloatField(max_value=None, min_value=None) |
DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
DurationField | DurationField() |
ChoiceField | ChoiceField(choices) choices与Django的用法相同 |
MultipleChoiceField | MultipleChoiceField(choices) |
FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ListField | ListField(child=, min_length=None, max_length=None) |
DictField | DictField(child=) |
选项参数:
参数名称 | 作用 |
---|---|
max_length | 最大长度 |
min_lenght | 最小长度 |
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页面时,显示的字段帮助提示信息 |
1.2 创建Serializer对象
定义好PublishSerializer类后,就可以创建PublishSerializer对象了。
PublishSerializer的构造方法为:
|
说明:
1)用于序列化时,将模型类对象传入instance参数
2)用于反序列化时,将要被反序列化的数据传入data参数
3)除了instance和data参数外,在构造PublishSerializer对象时,还可通过context参数额外添加数据,如
|
通过context参数附加的数据,可以通过PublishSerializer对象的context属性获取。
- 使用序列化器的时候一定要注意,序列化器声明了以后,不会自动执行,需要我们在视图中进行调用才可以。
- 序列化器无法直接接收数据,需要我们在视图中创建序列化器对象时把使用的数据传递过来。
- 序列化器的字段声明类似于我们前面使用过的表单系统。
- 开发restful api时,序列化器会帮我们把模型数据转换成字典.
- drf提供的视图会帮我们把字典转换成json,或者把客户端发送过来的数据转换字典.
1.3 序列化器的使用
序列化器的使用分两个阶段:
- 在客户端请求时,使用序列化器可以完成对数据的反序列化。
- 在服务器响应时,使用序列化器可以完成对数据的序列化。
1.3.1 序列化
1.3.1.1 基本使用
1) 先查询出一个出版社对象
|
2) 构造序列化器对象
|
3)获取序列化数据
from rest_framework.views import APIView
from rest_framework.response import Response
from app01 import models
# Create your views here.
from app01 import serializer
class PublishDetailView(APIView):
"""使用序列化器序列化转换单个模型数据"""
def get(self,request,id):
# 获取数据
publish = models.Publish.objects.filter(pk=id).first()
# 数据转换[序列化过程]
publish_ser = serializer.PublishSerializer(instance=publish)
print(publish_ser.instance)
# 响应数据
return Response(publish_ser.data)
通过data属性可以获取序列化后的数据
|
完整视图代码:
4)如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明
class PublishView(APIView):
"""使用序列化器序列化转换多个模型数据"""
def get(self,request):
# 获取数据
publish_qs = models.Publish.objects.all()
# 响应数据给客户端
# 返回的json数据,如果是列表,则需要声明safe=False
publish_ser = serializer.PublishSerializer(instance=publish_qs,many=True)
return Response(publish_ser.data,safe=False)
1.3.2 通过Serializer序列化写关于出版社增删改查的接口实例。
第一步:在models.py中建好数据库模型类Publish,使用makegrations和migrate迁移命令
from django.db import models
# Create your models here.
class Publish(models.Model):
nid = models.AutoField(primary_key=True,verbose_name='编号')
name = models.CharField(max_length=32,verbose_name='名称')
city = models.CharField(max_length=32,verbose_name='所在城市')
email = models.EmailField(verbose_name='邮箱')
def __str__(self):
return self.name
第二步:在serializer.py中创建序列化类PublishSerializer继承Serializer
class PublishSerializer(serializers.Serializer):
nid = serializers.IntegerField(required=False)
name = serializers.CharField(max_length=32,error_messages={
'max_length':'太长了,小伙子'
})
city = serializers.CharField()
email = serializers.EmailField()
第三步:在views.py中创建继承APIView的视图类PublishView类和PublishDetailView类
from rest_framework.views import APIView
from rest_framework.response import Response
from app01 import models
# Create your views here.
from app01 import serializer
class PublishView(APIView):
# get请求所有出版社信息
def get(self,request):
publish_qs = models.Publish.objects.all()
# 对所有信息进行序列化,这里many设置True
publish_ser = serializer.PublishSerializer(instance=publish_qs,many=True)
return Response(publish_ser.data)
# post请求添加一条出版社数据
def post(self,request):
publish_ser = serializer.PublishSerializer(data=request.data)
if publish_ser.is_valid():
publish_ser.save()
return Response(publish_ser.data)
else:
print(publish_ser.errors)
return Response(publish_ser.errors)
class PublishDetailView(APIView):
# get请求单条出版社信息
def get(self,request,id):
publish = models.Publish.objects.filter(pk=id).first()
publish_ser = serializer.PublishSerializer(instance=publish)
print(publish_ser.instance)
return Response(publish_ser.data)
# put请求修改一条出版社信息
def put(self,request,id):
print(request.data)
publish = models.Publish.objects.filter(pk=id).first()
publish_ser = serializer.PublishSerializer(instance=publish,data=request.data)
if publish_ser.is_valid():
publish_ser.save()
return Response(publish_ser.data)
else:
return Response('数据校验有误')
# delete请求删除一条出版社信息
def delete(self,request,id):
res = models.Publish.objects.filter(pk=id).first()
print(res)
if res[0]>0:
return Response('')
else:
return Response('要删的不存在')
第四步:在使用post请求和put请求时,数据库的数据发生了改变,所以我们需要保存序列化的数据。所以在serialzier.py的PublishSerializer类中我们需要重写create()和update()方法:
def create(self, validated_data):
res = models.Publish.objects.create(**validated_data)
return res
def update(self, instance, validated_data):
name = validated_data.get('name')
city = validated_data.get('city')
email = validated_data.get('email')
instance.name = name
instance.city = city
instance.email = email
instance.save()
return instance
第五步:在urls.py中为PublishView类和PublishDetailView类添加路由,记得在settings.py中的apps中注册rest_framework应用。
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('publish/',views.PublishView.as_view()),
path('publish/<int:id>',views.PublishDetailView.as_view())
]
第六步:启动django项目,在postman中输入接口地址操作数据。