Ⅰ 反序列化之校验
【一】 使用mysql 8.0
【1】django 的4版本以后,不支持mysql 5.7了,必须要8以上
必须装mysqlclient:pip3 install mysqlclient
或者使用pymysql,得写改两句话
【2】mysql 多版本共存
【二】反序列化校验
【1】字段自己的校验
name = serializers. CharField( max_length= 8 , min_length= 2 )
age = serializers. IntegerField( max_value= 100 , min_value= 1 )
使用 validators= [ 函数内存地址] - - > 了解即可
根据函数内存地址校验
name = serializers. CharField( max_length= 8 , min_length= 2 , validators= [ 函数内存地址] )
若是想将提示英文改为中文
settings.py中修改
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = False
INSTALLED_APPS = [
'django.contrib.admin' ,
'django.contrib.auth' ,
'django.contrib.contenttypes' ,
'django.contrib.sessions' ,
'django.contrib.messages' ,
'django.contrib.staticfiles' ,
"app01.apps.App01Config" ,
'rest_framework' ,
]
【2】局部钩子校验
在序列化中写 validate_字段名
如果校验通过,正常返回
如果校验失败,就抛ValidationError
需要引入 from rest_framework. exceptions import ValidationError
from rest_framework import serializers
from app01. models import Student
from rest_framework. exceptions import ValidationError
class StudentSerializer ( serializers. Serializer) :
name = serializers. CharField( max_length= 8 , min_length= 2 )
age = serializers. IntegerField( max_value= 100 , min_value= 1 )
def create ( self, validated_data) :
student = Student. objects. create( ** validated_data)
return student
def validate_name ( self, name) :
if 'sb' in name:
raise ValidationError( '名字中不能带sb' )
else :
return name
def validate_age ( self, age) :
if age == 44 :
raise ValidationError( '年龄中不能是44' )
else :
return age
【3】全局钩子
def validate ( self, attrs) :
age = attrs. get( 'age' )
name = attrs. get( 'name' )
if str ( age) == name:
raise ValidationError( '名字和年龄不能一样' )
else :
return attrs
【4】代码实现
from django. db import models
from django. db import models
class Student ( models. Model) :
name = models. CharField( max_length= 32 )
age = models. IntegerField( )
from django. shortcuts import render
from rest_framework. response import Response
from rest_framework. views import APIView
from . models import Student
from . serializer import StudentSerializer
class StudentView ( APIView) :
def post ( self, request) :
serializer = StudentSerializer( data= request. data)
serializer. is_valid( raise_exception= True )
serializer. save( )
return Response( { 'code' : 200 , 'msg' : 'ok' } )
from rest_framework import serializers
from app01. models import Student
from rest_framework. exceptions import ValidationError
class StudentSerializer ( serializers. Serializer) :
name = serializers. CharField( max_length= 8 , min_length= 2 )
age = serializers. IntegerField( max_value= 100 , min_value= 1 )
def create ( self, validated_data) :
student = Student. objects. create( ** validated_data)
return student
def validate_name ( self, name) :
if 'sb' in name:
raise ValidationError( '名字中不能带sb' )
else :
return name
def validate_age ( self, age) :
if age == 44 :
raise ValidationError( '年龄中不能是44' )
else :
return age
def validate ( self, attrs) :
age = attrs. get( 'age' )
name = attrs. get( 'name' )
if str ( age) == name:
raise ValidationError( '名字和年龄不能一样' )
else :
return attrs
Ⅱ 序列化定制返回格式
【一】 序列化定制之source(给字段重新命名)
【1】定制表中某个字段
user = serializers. CharField( max_length= 8 , min_length= 2 , source= 'name' )
重新命名的字段名 = serializers. CharField( source= '数据库中存在的需要重新命名的字段名' )
def validate_user ( self, name) :
if 'sb' in name:
raise ValidationError( '名字中不能带sb' )
else :
return name
【2】定制模型表中某个方法
from django. db import models
class Student ( models. Model) :
name = models. CharField( max_length= 32 )
age = models. IntegerField( )
@property
def new_name ( self) :
return self. name + '_NB'
(1)source='new_name'方法
序列化类中
然后返回的字段名 就变成了new_name
user = serializers. CharField( max_length= 8 , min_length= 2 , source= 'new_name' )
(2)直接放方法,原来是只放字段名 ,现在是也能直接放方法
new_name = serializers. CharField( max_length= 8 , min_length= 2 )
(3)跨表查询
publish_name = serializers. CharField( max_length= 8 , min_length= 2 , source= 'publish.name' )
【二】一对多关系定制返回格式
【1】数据准备
from django. db import models
class Publish ( models. Model) :
name = models. CharField( max_length= 32 )
addr = models. CharField( max_length= 32 )
city = models. CharField( max_length= 32 )
class Book ( models. Model) :
name = models. CharField( max_length= 32 )
price = models. IntegerField( )
publish = models. ForeignKey( to= 'Publish' , on_delete= models. SET_NULL, null= True )
authors= models. ManyToManyField( to= 'Author' )
class Author ( models. Model) :
name = models. CharField( max_length= 32 )
age = models. IntegerField( )
addr = models. CharField( max_length= 32 )
from rest_framework. response import Response
from rest_framework. views import APIView
from . models import Book
from . serializer import BookSerialzier
class BookView ( APIView) :
def get ( self, request) :
books = Book. objects. all ( )
serializer = BookSerialzier( books, many= True )
return Response( { 'code' : 100 , 'msg' : '查询成功' , 'results' : serializer. data} )
from rest_framework import serializers
class BookSerialzier ( serializers. Serializer) :
name = serializers. CharField( )
price = serializers. IntegerField( )
publish = serializers. CharField( )
authors = serializers. CharField( )
from django. contrib import admin
from django. urls import path
from . views import StudentView, BookView
urlpatterns = [
path( 'students/' , StudentView. as_view( ) ) ,
path( 'books/' , BookView. as_view( ) ) ,
]
【2】想让publish和authors显示名字
(1)最简单的就是序列化类时用source(不太用)
publish = serializers. CharField( source= 'publish.name' )
(2)在表模型中写方法
class Book ( models. Model) :
name = models. CharField( max_length= 32 )
price = models. IntegerField( )
publish = models. ForeignKey( to= 'Publish' , on_delete= models. SET_NULL, null= True )
authors= models. ManyToManyField( to= 'Author' )
def publish_detail ( self) :
return { 'name' : self. publish. name, 'addr' : self. publish. addr, 'city' : self. publish. city}
所以在serializer.py序列化类中 字段名不是publish而是publish_detail
class BookSerialzier ( serializers. Serializer) :
name = serializers. CharField( )
price = serializers. IntegerField( )
publish_detail = serializers. CharField( )
authors = serializers. CharField( )
这种是返回的单引号引起来的 字符串 所以不能像publish_detail.属性名将数据取出来
class BookSerialzier ( serializers. Serializer) :
name = serializers. CharField( )
price = serializers. IntegerField( )
publish_detail = serializers. DictField( )
authors = serializers. CharField( )
(3)在序列化类中写方法
publisher = serializers. SerializerMethodField( )
def get_publish ( self, obj) :
return { 'name' : 'xx' , 'addr' : 'yy' }
publish = serializers. SerializerMethodField( )
def get_publish ( self, obj) :
return { 'name' : obj. publish. name, 'addr' : obj. publish. addr, 'city' : obj. publish. city}
(4)使用子序列化
publish = PublishSerializer( )
class PublishSerializer ( serializers. Serializer) :
name = serializers. CharField( )
city = serializers. CharField( )
【三】多对多关系,定制返回格式
【1】表模型中写方法
def author_detail ( self) :
authors = self. authors. all ( )
author_list = [ ]
for author in authors:
author_list. append( { 'name' : author. name, 'age' : author. age} )
return author_list
author_detail = serializers. CharField( )
author_detail = serializers. ListField( )
【2】在序列化类中写方法
author_all = serializers. SerializerMethodField( )
def get_author_all ( self, obj) :
authors = obj. authors. all ( )
l = [ ]
for author in authors:
l. append( { 'name' : author. name, 'age' : author. age, 'id' : author. id } )
return l
【3】子序列化
authors = AuthorSerializer( many= True )
class AuthorSerializer ( serializers. Serializer) :
name = serializers. CharField( )
age = serializers. IntegerField( )
【四】总的代码
from django. db import models
from django. db import models
class Student ( models. Model) :
name = models. CharField( max_length= 32 )
age = models. IntegerField( )
@property
def new_name ( self) :
return self. name + '_NB'
class Publish ( models. Model) :
name = models. CharField( max_length= 32 )
addr = models. CharField( max_length= 32 )
city = models. CharField( max_length= 32 )
class Book ( models. Model) :
name = models. CharField( max_length= 32 )
price = models. IntegerField( )
publish = models. ForeignKey( to= 'Publish' , on_delete= models. SET_NULL, null= True )
authors= models. ManyToManyField( to= 'Author' )
def publish_detail ( self) :
return { 'name' : self. publish. name, 'addr' : self. publish. addr, 'city' : self. publish. city}
class Author ( models. Model) :
name = models. CharField( max_length= 32 )
age = models. IntegerField( )
addr = models. CharField( max_length= 32 )
from rest_framework import serializers
from app01. models import Student
from rest_framework. exceptions import ValidationError
class StudentSerializer ( serializers. Serializer) :
new_name = serializers. CharField( max_length= 8 , min_length= 2 )
age = serializers. IntegerField( max_value= 100 , min_value= 1 )
def create ( self, validated_data) :
student = Student. objects. create( ** validated_data)
return student
def validate_user ( self, name) :
if 'sb' in name:
raise ValidationError( '名字中不能带sb' )
else :
return name
def validate_age ( self, age) :
if age == 44 :
raise ValidationError( '年龄中不能是44' )
else :
return age
def validate ( self, attrs) :
age = attrs. get( 'age' )
name = attrs. get( 'name' )
if str ( age) == name:
raise ValidationError( '名字和年龄不能一样' )
else :
return attrs
class AuthorSerializer ( serializers. Serializer) :
name = serializers. CharField( )
age = serializers. IntegerField( )
class PublishSerializer ( serializers. Serializer) :
name = serializers. CharField( )
city = serializers. CharField( )
class BookSerialzier ( serializers. Serializer) :
name = serializers. CharField( )
price = serializers. IntegerField( )
publish = PublishSerializer( )
authors = AuthorSerializer( many= True )
Ⅲ 多表关联反序列化
【一】多表关联反序列化实现
soruce
表模型中写方法
序列化类中写方法
子序列化
新增图书
class BookSerialzier ( serializers. Serializer) :
name = serializers. CharField( )
price = serializers. IntegerField( )
publish_detail = serializers. DictField( read_only= True )
author_detail = serializers. ListField( read_only= True )
publish_id = serializers. IntegerField( write_only= True )
authors = serializers. ListField( write_only= True )
def create ( self, validated_data) :
authors = validated_data. pop( 'authors' )
book = Book. objects. create( ** validated_data)
book. authors. add( * authors)
return book
from . models import Book
from . serializer import BookSerialzier
class BookView ( APIView) :
def get ( self, request) :
books = Book. objects. all ( )
serializer = BookSerialzier( books, many= True )
return Response( { 'code' : 100 , 'msg' : '查询成功' , 'results' : serializer. data} )
def post ( self, request) :
serializer = BookSerialzier( data= request. data)
serializer. is_valid( raise_exception= True )
serializer. save( )
return Response( { 'code' : 100 , 'msg' : '新增成功' , 'results' : serializer. data} )
【二】多表关联反序列化常见问题
【1】问题一
前端传的数据:{ "name" : "三国演义" , "price" : 19 , "publish" : { "name" : "上海出版社" , "addr" : "上海" } , "authors" : [ { } ,{ } ] }
到了create中:validated_data 就是传入的
将publish和authors用pop 弹出
authors = validated_data. pop( 'authors' )
再将对应关系 对应上
book = Book. objects. create( ** validated_data)
再保存
book. authors. add( * authors)
【2】问题二
前端传的数据:{ "name" : "张三" , "age" : 19 , "author_detail" : 1 } - - > 基本不用
前端传的数据:{ "name" : "三国演义" , "age" : 19 , "addr" : 地址, "gender" : 1 } - - > 通常用它
到了create中:validated_data 就是传入的{ "name" : "三国演义" , "age" : 19 , "addr" : 地址, "gender" : 1 }
{ "name" : "三国演义" , "age" : 19 }
{ "addr" : 地址, "gender" : 1 }
分别传到两表中
【3】问题三
{ "name" : "三国演义" , "price" : 19 , "publish_id" : 1 , "authors" : [ 1 , 2 ] , "addr" : "上海" }
为什么会没有数据 因为 字段校验的时候没有这个字段 所以这个数据就不要了
Ⅳ ModelSerializer的使用
确定保存或修改到哪个表
可以不重写,特殊情况需要重写 create和update
要序列化和反序列化的字段,可以通过表映射过来,也可以不写了
【一】基于ModelSerializer编写Book的序列化和反序列化
from . serializer import BookModelSerializer
def post ( self, request) :
serializer = BookModelSerializer( data= request. data)
serializer. is_valid( raise_exception= True )
serializer. save( )
return Response( { 'code' : 100 , 'msg' : '新增成功' , 'result' : serializer. data} )
class BookModelSerializer ( serializers. ModelSerializer) :
class Meta :
model = Book
fields = '__all__'
extra_kwargs= { 'name' : { 'max_length' : 8 } , 'price' : { 'max_value' : 100 } }
def validate_name ( self, name) :
return name
数据可以新增成功,但是代码又自动进行了一次序列化 故而pubilsh和authors又被序列化
【二】既能序列化,又能反序列化---表模型中写
fields = [ 'name' , 'price' , 'publish' , 'authors' , 'publish_detail' , 'author_detail' ]
extra_kwargs = { 'name' : { 'max_length' : 8 } , 'price' : { 'max_value' : 100 } ,
'publish_detail' : { 'read_only' : True } ,
'author_detail' : { 'read_only' : True } ,
'publish' : { 'write_only' : True } ,
'authors' : { 'write_only' : True } ,
}
【三】序列化类中写方法
class BookModelSerializer ( serializers. ModelSerializer) :
class Meta :
model = Book
fields = [ 'name' , 'price' , 'publish' , 'authors' , 'publish_real' , 'author_all' ]
extra_kwargs = { 'name' : { 'max_length' : 8 } , 'price' : { 'max_value' : 100 } ,
'publish' : { 'write_only' : True } ,
'authors' : { 'write_only' : True } ,
}
publish_real = serializers. SerializerMethodField( read_only= True )
def get_publish_real ( self, obj) :
return { 'name' : obj. publish. name, 'addr' : obj. publish. name, 'city' : obj. publish. city}
author_all = serializers. SerializerMethodField( read_only= True )
def get_author_all ( self, obj) :
authors = obj. authors. all ( )
l = [ ]
for author in authors:
l. append( { 'name' : author. name, 'age' : author. age, 'id' : author. id } )
return l
【四】总代码实现
from django. shortcuts import render
from rest_framework. response import Response
from rest_framework. views import APIView
from . models import Student
from . serializer import StudentSerializer, BookModelSerializer
class StudentView ( APIView) :
def post ( self, request) :
serializer = StudentSerializer( data= request. data)
serializer. is_valid( raise_exception= True )
serializer. save( )
return Response( { 'code' : 200 , 'msg' : '创建成功' } )
def get ( self, request) :
student = Student. objects. all ( )
serializer = StudentSerializer( student, many= True )
return Response( { 'code' : 200 , 'msg' : '查询成功' , 'results' : serializer. data} )
from . models import Book
from . serializer import BookSerialzier
class BookView ( APIView) :
def get ( self, request) :
books = Book. objects. all ( )
serializer = BookSerialzier( books, many= True )
return Response( { 'code' : 100 , 'msg' : '查询成功' , 'results' : serializer. data} )
def post ( self, request) :
serializer = BookModelSerializer( data= request. data)
serializer. is_valid( raise_exception= True )
serializer. save( )
return Response( { 'code' : 100 , 'msg' : '新增成功' , 'result' : serializer. data} )
from django. db import models
from django. db import models
class Student ( models. Model) :
name = models. CharField( max_length= 32 )
age = models. IntegerField( )
@property
def new_name ( self) :
return self. name + '_NB'
class Publish ( models. Model) :
name = models. CharField( max_length= 32 )
addr = models. CharField( max_length= 32 )
city = models. CharField( max_length= 32 )
class Book ( models. Model) :
name = models. CharField( max_length= 32 )
price = models. IntegerField( )
publish = models. ForeignKey( to= 'Publish' , on_delete= models. SET_NULL, null= True )
authors= models. ManyToManyField( to= 'Author' )
def publish_detail ( self) :
return { 'name' : self. publish. name, 'addr' : self. publish. addr, 'city' : self. publish. city}
def author_detail ( self) :
authors = self. authors. all ( )
author_list = [ ]
for author in authors:
author_list. append( { 'name' : author. name, 'age' : author. age} )
return author_list
class Author ( models. Model) :
name = models. CharField( max_length= 32 )
age = models. IntegerField( )
addr = models. CharField( max_length= 32 )
from rest_framework import serializers
from app01. models import Student, Book
from rest_framework. exceptions import ValidationError
class StudentSerializer ( serializers. Serializer) :
new_name = serializers. CharField( max_length= 8 , min_length= 2 )
age = serializers. IntegerField( max_value= 100 , min_value= 1 )
def create ( self, validated_data) :
student = Student. objects. create( ** validated_data)
return student
def validate_user ( self, name) :
if 'sb' in name:
raise ValidationError( '名字中不能带sb' )
else :
return name
def validate_age ( self, age) :
if age == 44 :
raise ValidationError( '年龄中不能是44' )
else :
return age
def validate ( self, attrs) :
age = attrs. get( 'age' )
name = attrs. get( 'name' )
if str ( age) == name:
raise ValidationError( '名字和年龄不能一样' )
else :
return attrs
class AuthorSerializer ( serializers. Serializer) :
name = serializers. CharField( )
age = serializers. IntegerField( )
class PublishSerializer ( serializers. Serializer) :
name = serializers. CharField( )
city = serializers. CharField( )
class BookSerialzier ( serializers. Serializer) :
name = serializers. CharField( )
price = serializers. IntegerField( )
publish_detail = serializers. DictField( read_only= True )
author_detail = serializers. ListField( read_only= True )
publish_id = serializers. IntegerField( write_only= True )
authors = serializers. ListField( write_only= True )
def create ( self, validated_data) :
authors = validated_data. pop( 'authors' )
book = Book. objects. create( ** validated_data)
book. authors. add( * authors)
return book
class BookModelSerializer ( serializers. ModelSerializer) :
class Meta :
model = Book
fields = [ 'name' , 'price' , 'publish' , 'authors' , 'publish_real' , 'author_all' ]
extra_kwargs = { 'name' : { 'max_length' : 8 } , 'price' : { 'max_value' : 100 } ,
'publish' : { 'write_only' : True } ,
'authors' : { 'write_only' : True } ,
}
publish_real = serializers. SerializerMethodField( read_only= True )
def get_publish_real ( self, obj) :
return { 'name' : obj. publish. name, 'addr' : obj. publish. name, 'city' : obj. publish. city}
author_all = serializers. SerializerMethodField( read_only= True )
def get_author_all ( self, obj) :
authors = obj. authors. all ( )
l = [ ]
for author in authors:
l. append( { 'name' : author. name, 'age' : author. age, 'id' : author. id } )
return l
Ⅴ 补充
【一】字符长度和字节长度
字符长度- - - > len ( 字符串) - - - - > abc中国!- - - > 6 个符号
字节长度- - - > len ( 'abc中国!' . encode( 'utf-8' ) ) - - - > 字节长度 - - > abc中国!- - > 10
【二】反序列化校验—–字段类上的属性校验
def validate_name ( name) :
pass
class StudentSerializer ( serializers. Serializer) :
name = serializers. CharField( validator= [ validate_name] )
class BookModelSerializer ( serializers. ModelSerializer) :
name= serializers. CharField( max_length= 8 )
class Meta :
model = Book
fields = [ 'name' , 'price' , 'publish' , 'authors' , 'publish_real' , 'author_all' ]
class BookModelSerialzier ( serializers. ModelSerializer) :
name= serializers. CharField( max_length= 32 )
class Meta :
model = Book
fields = [ 'name' ]
【四】 depth使用
class BookView ( APIView) :
def get ( self, request) :
books = Book. objects. all ( )
serializer = BookModelSerializer( books, many= True )
return Response( { 'code' : 100 , 'msg' : '查询成功' , 'results' : serializer. data} )
class BookModelSerializer ( serializers. ModelSerializer) :
class Meta :
model = Book
fields = '__all__'
class BookModelSerializer ( serializers. ModelSerializer) :
class Meta :
model = Book
fields = '__all__'
depth = 1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY