序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
成都创新互联公司专注于企业全网营销推广、网站重做改版、资阳网站定制设计、自适应品牌网站建设、H5建站、电子商务商城网站建设、集团公司官网建设、成都外贸网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为资阳等各大城市提供网站开发制作服务。
反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
反序列化时同时会完成数据校验功能
1.在setting.py中的app配置里注册一下drf
2.在django的模型层创建一个表
from django.db import models
# Create your models here.
class Book(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
author = models.CharField(max_length=32)
3.在表中添加一些数据
4.编写序列化组件(类似forms组件),可以在应用下单独创一个文件夹,里面放序列化组件.py
from rest_framework import serializers# 导入drf中的序列化类
# 创建一个类继承Serializer序列化类
class BookSerializer(serializers.Serializer):
# 定义需要序列化的字段,想要哪个字段就添加该字段,不需要就注释掉
nid = serializers.CharField()
name = serializers.CharField()
price = serializers.CharField()
5.在url.py中开设路径获取序列化之后的数据
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'^book/(?P\d+)/$',views.BooksView.as_view()) #CBV格式的url
]
6.在视图函数中序列化需要的模型对象,返回给前端页面字典格式的数据
from rest_framework.views import APIView # 导入drf模块的apiview,使得cbv格式的视图函数继承它
from app01 import models
from .ser import BookSerializer # 导入自己写好的序列化组件
from rest_framework.response import Response # 导入drf模块的响应类
class BooksView(APIView):
# get请求的视图函数
def get(self,request,pk):
# 得到需要查询的模型对象
book = models.Book.objects.filter(pk=pk).first()
# 将模型对象交给自己写好的序列化器,生成一个序列化对象
book_ser = BookSerializer(book)
# book_ser.data 序列化对象.data就是序列化后的字典
return Response(book_ser.data) # 利用drf中的Response类返回给前端,Response会帮您把这个字典序列化成json格式!
# 使用JsonResponse返回上述字典,在浏览器就没有Response漂亮的格式而已,也是返回json数据格式
return JsonResponse(book_ser.data,json_dumps_params={'ensure_ascii':False})
# views.py
class BooksView(APIView):
def get(self,request):
response_msg = {'status': 100, 'msg': '成功'}
books=Book.objects.all()
book_ser=BookSerializer(books,many=True) #序列化多条,如果序列化一条,不需要写
response_msg['data']=book_ser.data
return Response(response_msg)
#urls.py
path('books/', views.BooksView.as_view()),
1.在cbv格式的视图函数中添加put函数
def put(self,request,pk):
back_dic = {'code':1000,'msg':'成功'}
# 1.得到需要查询的模型对象
book = models.Book.objects.filter(pk=pk).first()
# 2. 将模型对象交给自己写好的序列化器,生成一个序列化对象,除了传模型对象,还需要传入用户修改的数据
book_ser = BookSerializer(instance=book,data=request.data)
# 3.进行数据校验,类似forms组件的校验
is_right = book_ser.is_valid()
if is_right:
# 4.校验通过操作序列化对象保存修改数据
book_ser.save() # 注意这里需要在序列化组件中重写update()方法,否则报错
# 5.将正确的数据在返回给前端
back_dic['data'] = book_ser.data
else:
back_dic['code'] = 1001
back_dic['msg'] = '数据格式不正确'
back_dic['data'] = book_ser.errors
return Response(back_dic)
2.在自定义的序列化组件类中添加update()方法
def update(self, instance, validated_data):
# instance参数就是book这个对象,validated_data就是用户修改提交上来的字典格式数据
# 1.修改这个对象的字段值
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
# 2.操作数据库保存修改数据
instance.save() # 相当于book.save() 是django orm提供的方法
# 最后需要把这个book对象在返回出去
return instance
# views.py
class BooksView(APIView):
# 新增
def post(self,request):
response_msg = {'status': 100, 'msg': '成功'}
#修改才有instance,新增没有instance,只有data
book_ser = BookSerializer(data=request.data)
# book_ser = BookSerializer(request.data) # 这个按位置传request.data会给instance,就报错了
# 校验字段
if book_ser.is_valid():
book_ser.save()
response_msg['data']=book_ser.data
else:
response_msg['status']=102
response_msg['msg']='数据校验失败'
response_msg['data']=book_ser.errors
return Response(response_msg)
#ser.py 序列化类重写create方法
def create(self, validated_data):
instance=Book.objects.create(**validated_data)
return instance
# urls.py
path('books/', views.BooksView.as_view()),
# views.py
class BookView(APIView):
def delete(self,request,pk):
ret=Book.objects.filter(pk=pk).delete()
return Response({'status':100,'msg':'删除成功'})
# urls.py
re_path('books/(?P\d+)', views.BookView.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-fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee0fb31a" 3)'int' - 如: "" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-fb31a"
# 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)
需要记住的字段类型
CharField
BooleanField
IntegerField
DecimalField
ListField
DictField
常用的字段参数
1 给CharField字段类使用的参数
max_length 最长长度
min_length 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字段
2 给IntegerField字段类使用的参数
max_value 最小值
min_value 最大值
3 通用参数,放在哪个字段类上都可以
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
validators 该字段使用的验证器
error_messages 包含错误编码与错误信息的字典
label 用于HTML展示API页面时,显示的字段名称
help_text 用于Html展示API页面时,显示的字段帮助提示信息
4 重点
read_only 表明该字段仅用于序列化输出,默认False,如果设置成True,postman中可以看到该字段,修改时,不需要传该字段
write_only 表明该字段仅用于反序列化输入,默认False,如果设置成True,postman中看不到该字段,修改时,该字段需要传
局部钩子:
# 序列化组件中的钩子函数
# 局部钩子函数validate_字段名的形式,需要传入一个data参数,data就是price
def validate_price(self, data):
print(type(data)) #格式为
print(data) # 34.00
# 进行校验,当价格大于30报错
if float(data) < 30:
return data
else:
# 校验不通过,抛出异常 rest_framework异常在 from rest_framework.exceptions import ValidationError里
raise ValidationError('价格太高')
全局钩子:
def validate(self,validated_data): # validated_data校验之后的数据
name = validated_data.get('name')
price = validated_data.get('price')
if name == 'zhang' and price == '25':
raise ValidationError('不正确')
return validated_data
第三种validators校验:
# 定义一个函数
def check_name(data):
if data.startswith('sb'):
raise ValidationError('名字不能是sb开头')
else:
return data
# 在指定字段内添加validators
name = serializers.CharField(validators=[check_name]) #validators=[]列表中写函数的内存地址
总结:主要用局部钩子和全局钩子!!
# 模型化序列器,继承ModelSerializer,并且不需要自己书写updata和create方法了
class BookSerializer2(serializers.ModelSerializer):
# 1.定义一个Meta类
class Meta:
# 2.model后面等于需要序列化的表
model = models.Book
# 3.表示序列化该表中所有的字段
# fields = '__all__'
# 4.序列化表中的指定字段
# fields = ('name','price') # 注意fields里可以放model.py里book表对应的字段,也可以放book表类里定义的方法(详解下图)
# 5.序列化除以下字段
exclude = ('name',) # ()里是一个元组,注意需要加个逗号
# 6.read_only和write_only这些原本需要在字段括号内书写的参数都放在extra_kwargs里书写
extra_kwargs = {
'price':{'write_only':True},
}
在book表类里加的publish_name方法,fields里放该方法,会返回该方法的返回值!
视图函数部分:
class BooksView2(APIView):
def get(self,request):
books = models.Book.objects.all()
book_ser = BookSerializer2(books,many=True) # 这里改成了BookSerializer2模型化序列器
return Response(book_ser.data)
class MyResponse(): # 这里复杂一点可以继承rest_framework的Response类
def __init__(self): # 定义一个初始化方法,该方法有默认属性status和msg(任何由该类产生的对象都有这两个属性)
self.status=100
self.msg = '成功'
@property # 将这个方法伪装成属性
def get_dict(self):
return self.__dict__ # 返回一个字典