-
序列化器-Serializer
# 序列化器的作用
1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能
-
序列化器的基本使用
序列化器的使用分两个阶段:
1.在客户端请求时,使用序列化器可以完成对数据的反序列化。
2.在服务器响应时,使用序列化器可以完成对数据的序列化。
-
视图层views.py
from django.shortcuts import render
from app01 import models
# 导入APIView模块
from rest_framework.views import APIView
# 导入自定义序列化类
from app01.MySerializer import BookSerializer
# 导入Response
from rest_framework.response import Response
class Bookser(APIView):
# 查询全部数据
def get(self, request, *args, **kwargs):
# 1.查询所有图书对象
book_list = models.Book.objects.all()
# 2.序列化 引入自定义序列化类 instance 要序列化的对象 可以单个对象,可以多个, 多个要加many=True
bs = BookSerializer(instance=book_list, many=True)
# 3.传给前段 统一用Response 里面有一个data参数
return Response(data=bs.data)
def post(self,request,*args,**kwargs):
#1.反序列化接受的参数 前端传入的数据,在request.data中,是个字典
ser=BookSerializer(data=request.data)
print(ser)
#2.数据校验:如果是True,表示校验通过,直接保存
if ser.is_valid():
ser.save()# 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
return Response(ser.data)
else:
return Response(ser.errors)
class BookDetailSer(APIView):
# 查询单个字段
def get(self, request, pk):
# 1.查询pk对应的数据对象
book_obj = models.Book.objects.filter(pk=pk).first()
# 2.序列化
bs = BookSerializer(instance=book_obj)
# 3.发送给前端
return Response(data=bs.data)
def put(self,request, pk):
#1.查找数据对象
book_obj=models.Book.objects.filter(pk=pk).first()
#2.序列化数据对象 前端传入的数据,在request.data中,是个字典
ser=BookSerializer(instance=book_obj,data=request.data)
#3.数据校验 记得重写uppdate方法
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
#删除后返回一个空的
def delete(self,request,pk):
models.Book.objects.filter(pk=pk).delete()
return Response()
-
序列化器文件serializer.py
#引入Serializer模块
from rest_framework import serializers
#导入models
from app01 import models
from rest_framework.exceptions import ValidationError
# 一定要继承一个序列化的基类
class BookSerializer(serializers.Serializer):
# 你想序列化哪个字段,就写哪个
title = serializers.CharField(max_length=8,min_length=3,)
price = serializers.IntegerField()
publish = serializers.CharField(max_length=8,min_length=3)
# 重写create,使它能够支持新增保存 (派生)
def create(self, validated_data): #validated_data校验过后的数据
book=models.Book.objects.create(**validated_data)
return book # 一定不要忘了return 对象,否则在视图类中用ser.data 就报错了
def update(self, instance, validated_data):
instance.title=validated_data.get('title')
instance.price=validated_data.get('price')
instance.publish=validated_data.get('publish')
instance.save()
return
# validate_字段名局部钩子 先走字段自己的,再走局部钩子
def validate_title(self,item):
print(item)
#检验规则 需要导入ValidationError
if item.startswith('lv'):
raise ValidationError('不能以lv开头')
return item
#先走局部再走全局
def validate(self, attrs):
print(attrs)
#验证 title和出版社不能相同
if attrs.get('title')==attrs.get('publish'):
raise ValidationError('书名和出版社不能相同')
return attrs
-
表模型层 models.py
from django.db import models
# Create your models here.
class Book(models.Model):
title = models.CharField(max_length=16, default='好书')
price = models.IntegerField(default=0)
publish = models.CharField(max_length=32, default='奥特出版社')
-
路由层 urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('books/',views.Bookser.as_view()),
path('books/<int:pk>/', views.BookDetailSer.as_view()), #记得加/
]
-
常用字段
字段 |
字段构造方式 |
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页面时,显示的字段帮助提示信息 |
-
序列化器的反序列化
#post和put都是反序列化前端发过来的数据
def post(self,request,*args,**kwargs):
#1.反序列化接受的参数 前端传入的数据,在request.data中,是个字典
ser=BookSerializer(data=request.data)
#2.数据校验:如果是True,表示校验通过,直接保存
if ser.is_valid():
ser.save()# 调用保存,但是有问题,保存不了,一定要在序列化类中重写某个方法
return Response(ser.data)
else:
return Response(ser.errors)
def put(self,request, pk):
#1.查找数据对象
book_obj=models.Book.objects.filter(pk=pk).first()
#2.序列化数据对象 前端传入的数据,在request.data中,是个字典
ser=BookSerializer(instance=book_obj,data=request.data)
#3.数据校验 记得重写uppdate方法
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
-
模型类序列化器(重要)ModelSerializer
相对于Serializer 不需要重写create和update #因为内部封装了这两个方法
序列化,不需要每个字段都写
class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model=models.Book #跟那个表建立关系
# fields=['title','price'] #要序列化哪些字段
fields='__all__' #要序列化哪些字段 全部
#了解
# exclude=['title'] # 除了某个字段除外显示其他
# depth = 1 # 表关联 查询关联的表的信息 还是只显示id
#校验规则 写在meta类里 额外给某些字段传参数
# extra_kwargs = {'title': {'max_length': 8, 'min_length': 3},
# 'price': {'min_value': 100}}
#read_only 只读 只序列化 title 这个字段只序列化
#详细解释 :post请求 传参数时候title这个key传不传值都一样 不会用来写 给用户看 往外走
extra_kwargs = {'title': {'read_only':True},
'price': {'write_only': True}}
#write_only 只写 只反序列化price 这个字段只写 不做序列化 往数据库写 往里走
#校验规则 重写某个字段 写在外面
# title=serializers.CharField(max_length=8,min_length=3)
#
# #钩子
# def validate_price(self,price):
# if price>300:
# raise ValidationError('价格不能大于100')
# return price
-
习题
# 通过模型类序列化器,写出book单表的5个接口 上面的都是# 扩展:(book和publish 一对多关系) -通过模型类序列化器 -实现 book和publish的分别5个接口 class Books(models.Model): book = models.ForeignKey(Author,on_delete=models.CASCADE)CASCADE:删除作者信息一并删除作者名下的所有书的信息;PROTECT:删除作者的信息时,采取保护机制,抛出错误:即不删除Books的内容;SET_NULL:只有当null=True才将关联的内容置空;SET_DEFAULT:设置为默认值;SET( ):括号里可以是函数,设置为自己定义的东西;DO_NOTHING:字面的意思,啥也不干,你删除你的干我毛线关系