我们之前已经的DRF使用案例中成功实现了序列化,通过for循环将数据库内容遍历到一个列表,然后用DRF的Response将列表返回给前端,但有个问题就是我们每次想把数据库的数据序列化返给前端,都要手动序列化,但有没有一种简洁的方式,只写一次之后就不用重复编写了,借助序列化类更快速的实现序列化。
首先依然还是需要在models.py里先用ORM命令创建个表
class Book(models.Model): # 创建了Book表
name = models.CharField(max_length=32)
price = models.IntegerField()
# 记得迁移数据库,然后随便往表里录入几条数据
urls.py路由层开放路由接口
from app01 import views
urlpatterns = [
path(‘admin/‘, admin.site.urls),
path(‘books/‘, views.BookView.as_view()),
]
在应用下可以创建一个serializer.py文件,导入serializers模块对数据库进行序列化
from rest_framework import serializers # 导入serializers模块
class BookSerializer(serializers.Serializer):
# 想序列化哪个字段就写字段和对应的类
name = serializers.CharField()
# 注意:这个CharField是DRF提供的数据类型,和Django的ORM不是一个类型!
price = serializers.IntegerField()
views.py文件写逻辑,以序列化的方式显示给前端
from rest_framework.views import APIView # 导入APIView
from app01 import models # 导入models里的表
from rest_framework.response import Response
from app01.serializer import BookSerializer # 导入serializer.py文件的序列化类
class BookView(APIView):
# get请求走下列方法
def get(self, request):
book_list = models.Book.objects.all() # 查到数据库所有数据
# instance=book_list(序列化该对象) many=True(queryset多条对象必须用many=True)
ser = BookSerializer(instance=book_list, many=True) # 将数据传入第一个参数序列化
return Response(ser.data)
就此,我们就利用serializers类实现了序列化,写好之后尝试启动服务,然后输入网址http://127.0.0.1:8000/books/就可以看见数据库里面Book表所有的书籍
我们还可以通过序列化类来控制序列化的字段了,在序列化类把某个字段注释掉,再去前端或者 postman里查看,该字段也没了
注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。
我们如何通过主键值拿到某一条数据呢,如下
# 首先路由利用转化器来实现,pk就是主键,通过网址的尾部books/1,如何根据主键拿到具体某一条数据
path(‘books/<int:pk>‘, views.BookDeteView.as_view()),
# 然后就是视图层
class BookDeteView(APIView):
def get(self,request,*args,**kwargs):
‘‘‘
不加first(),拿到的是QuerySet对象,就像这样<QuerySet [<Book: Book object (2)>]>,它还是相当于多个,就不能去掉many=True
只有加了first(),拿到的数据才是真正单个的,这样 Book object (2)
‘‘‘
book = models.Book.objects.all().filter(pk=kwargs[‘pk‘]).first()
ser = BookSerializer(instance=book) # 单条数据就不需要写many=True了
return Response(ser.data)
# 重点的:
‘‘‘
CharField 字符
IntegerField 数字
DecimalField
DateTimeField
DateField
ListField
DictField
‘‘‘
# 其他还有很多但的忽略
# 通用的(所有字段都可用)
read_only 表明该字段仅用于序列化输出,默认False(重点)
write_only 表明该字段仅用于反序列化输入,默认False(重点)
required 表明该字段在反序列化时必须输入,默认True(了解)
default 反序列化时使用的默认值(了解)
allow_null 表明该字段是否允许传入None,默认False(了解)
validators 该字段使用的验证器(写函数的列表,使用这些函数校验该字段)(了解)
error_messages 包含错误编号与错误信息的字典
# 其他的
# CharField
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
# IntegerField
max_value 最小值
min_value 最大值
class BookView(APIView):
def get(self, request): # get请求查询数据
book_list = models.Book.objects.all()
ser = BookSerializer(instance=book_list, many=True)
return Response(ser.data)
def post(self, request): # post请求增加数据
# 反序列化,通过前端操作,实现数据库的增删改
ser = BookSerializer(data=request.data)
if ser.is_valid(): # 校验字段是否合法
ser.save() # 如果是新增,就新增了
return Response({‘code‘: 100, ‘msg‘: ‘新增成功‘, ‘data‘: ser.data})
else:
return Response({‘code‘: 500, ‘msg‘: ser.errors})
class BookDeteView(APIView):
def get(self, request, *args, **kwargs): # 通过主键拿单条数据
book = models.Book.objects.all().filter(pk=kwargs[‘pk‘]).first()
ser = BookSerializer(instance=book) # 单条数据就不需要写many=True了
return Response(ser.data)
def put(self, request, pk): # put请求修改数据
book = models.Book.objects.all().filter(pk=pk).first()
# 修改数据需要进行校验,所以一定要拿到put提交的数据
ser = BookSerializer(instance=book, data=request.data)
# 然后进行校验,判断数据是否合法
if ser.is_valid():
ser.save()
# 返回的数据符合Restful规范形式
return Response({‘code‘: 100, ‘msg‘: ‘修改成功‘, ‘data‘: ser.data})
else:
return Response({‘code‘: 500, ‘msg‘: ser.errors})
def delete(self, request, pk): # delete请求删除数据
res = models.Book.objects.filter(pk=pk).delete()
if res:
return Response({‘code‘: 100, ‘msg‘: ‘删除成功‘})
else:
return Response({‘code‘: 500, ‘msg‘: ‘数据不存在‘})
增加数据、更新数据都属于反序列化的操作,需要在Serializer序列化类中 重写create和update,否则会报错
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.IntegerField()
def create(self, validated_data):
book = models.Book.objects.create(**validated_data)
return book
def update(self, instance, validated_data):
instance.name = validated_data.get(‘name‘, instance.name)
instance.price = validated_data.get(‘price‘, instance.price)
instance.save()
return instance
上面都是拿一张图书表举例的,但假如我们现在又有一张出版社表,然后图书表里增加一个出版社字段,和出版社表做外键关联,那么我们如果还按照之前的方法序列化字段,那出版社的外键字段是序列化不了给用户看的。我们需要做的是找到图书表 的出版社字段关联 的 出版社表,然后把出版社表里的出版社名字序列化给前端。
class BookSerializer(serializers.Serializer):
name = serializers.CharField()
price = serializers.IntegerField()
# publish = serializers.CharField() # 显示的是一个外键,用户看不懂!
‘‘‘显示出版社的详情的方案‘‘‘
# 方式一(在序列化类中写)
publish_name = serializers.SerializerMethodField(read_only=True) # 只能用来做序列化
def get_publish_name(self,obj):
# obj 就是当前要序列化的book对象
# return obj.publish.name # 显示出版的名字
return {‘name‘:obj.publish.name,‘addr‘:obj.publish.addr} # 显示出版社的详情
##################################################################################
# 方式二(在模型类中写方法,方法返回什么,这个字段就是什么)(在表模型中写用的多)
# 在models.py的表中写一个方法
def publish_detail(self):
return {‘name‘:self.publish.name}
# 然后去序列化类里写
publish_detail=serializers.DictField()
# 方式三(了解类型)
publish_detail = serializers.CharField(source=‘publish.name‘)
原文:https://www.cnblogs.com/poco/p/15251259.html