文章目录
1、序列化器的使用
1、序列化:格式转换--把python中的对象转换成json格式字符串
2、反序列化:反转--json格式的字符串转成python格式的对象
3、drf序列化组件(序列化器)
Response可以转换很多、用Response不用JsonResponse了
1.1 models表
class Staff(models.Model):
name = models.CharField(max_length=64,verbose_name='姓名')
age = models.IntegerField(verbose_name='年龄')
department = models.ForeignKey(to='Department',on_delete=models.CASCADE,
verbose_name='部门')
projects = models.ManyToManyField(to='Project')
class Meta:
verbose_name_plural = '员工表'
def __str__(self):
return self.name
class Department(models.Model):
name = models.CharField(max_length=64,verbose_name='部门名称')
contact = models.IntegerField(verbose_name='部门电话')
email = models.IntegerField(verbose_name='部门邮箱')
class Meta:
verbose_name_plural = '部门表'
def __str__(self):
return self.name
class Project(models.Model):
name = models.CharField(max_length=128,verbose_name='项目名称')
price = models.IntegerField(verbose_name='启动资金',default=0)
def __str__(self):
return self.name
class Meta:
verbose_name_plural='项目表'
####1.2 建serializer.py书写类
settings-----app注册
INSTALLED_APPS = [
'rest_framework'
]
1、写一个序列化的类继承 Serializer
2 在类中写要序列化的字段
3 在视图类中使用(实例化)
4 得到序列化后的数据,返回
5 字段参数,source,指定要序列化表中的哪个字段
from rest_framework import serializers
class StaffSerializer(serializers.Serializer):
# 在这里写要序列化的字段
# 序列化字段类(有很多,常用的就几个,等同于models中的字段类)
# 字段类,有很多字段参数()
name = serializers.CharField()
age = serializers.IntegerField()
department = serializers.CharField() #拿到对象、"Department object (1)
models中字段下书写---就会拿到 department的name
def __str__(self)
return self.name
'source指定字段参数 指定要序列化的字段 ' source不能和赋值变量名冲突
department = serializers.CharField(source='department.email')
' 跨表查使用较多' (要么是列表,要么是字典)
department = serializers.SerializerMethodField()
def get_department(self, obj):
return {'name':obj.department.name,'city':obj.department.contact}
1.3 views
from rest_framework.response import Responsefrom app01
import modelsfrom rest_framework.views
import APIViewfrom app01.serializer
import StaffSerializer
#查所有path('text/',views.StaffView.as_view()),
class StaffView(APIView):
def get(self, request):
staff_list = models.Staff.objects.all()
# instance=None, 要序列化的数据
# data=empty ,要反序列化的数据(目前data先不用)
# many=True 如果序列化多条,一定要写many=True
staff_ser = StaffSerializer(instance=staff_list, many=True)
# book_ser.data就是序列化后的数据
return Response(staff_ser.data) #查单个path('text/<int:id>/',views.StaffViewId.as_view()),
class StaffViewId(APIView): def get(self,request,id):
staff = models.Staff.objects.all().filter(pk=id).first()
staff_ser = StaffSerializer(instance=staff)
return Response(staff_ser.data)
1.4 模型表中写方法
# 表模型中写的
def publish_name(self):
return {'name':self.publish.name,'city':self.publish.city}
@property
def author_list(self):
return [{'name':author.name,'age':author.age,'id':author.nid} for author in self.authors.all()]
#序列化类中
# publish = serializers.CharField(source='publish_name')
publish_name = serializers.DictField()
author_list=serializers.ListField()
2、反序列化、钩子
2.1 serializer视图
*继承Serializer类 必须重写create、update方法
class StaffSerializer(serializers.Serializer):
name = serializers.CharField()
age = serializers.IntegerField()
# department = serializers.CharField() #拿到对象、"Department object (1)
# def __str__(self)
# return self.name #拿到 department的name
department = serializers.CharField(source='department.name')
#拿到字典、
# department = serializers.SerializerMethodField()
# def get_department(self, obj):
# return {'name':obj.department.name,'city':obj.department.contact}
def create(self, validated_data):
#需要取到外键字段id、添加外键字段
department_id = validated_data.get('department').get('name')
del validated_data['department']
return models.Staff.objects.create(department_id=department_id,
**validated_data)
#局部钩子校验
def validate_name(self,data):
#data当前字段的值
if data.startswith('sb'):
raise ValidationError('不能以<sb>开头')
else:
return data
#全局钩子
def validate(self,attrs):
if attrs.get('name') == attrs.get('age'):
raise ValidationError('名字和年龄不能一样')
else:
return attrs
2.2增加数据需要进行反序列化、并且对数据进行校验’–views视图
员工表--外键department--多对多peoject
class StaffView(APIView):
def post(self, request): 是drf的request
data = request.data **取到数据
staff_ser = StaffSerializer(data=data) *对数据进行序列化成json格式的字符串
if staff_ser.is_valid(raise_exception=True): *对数据进行校验
#可以在API中全局复写校验错误响应的格式
staff_ser.save() *校验通过保存
return Response(staff_ser.data) *返回结果
else:
return Response(staff_ser.errors) *错误信息、返回应该还带着状态码
2.3序列化类 常用和非常用字段
参考博客--
http://www.liuqingzheng.top/python/Django-rest-framework%E6%A1%86%E6%9E%B6/2-drf-%E5%BA%8F%E5%88%97%E5%8C%96%E7%BB%84%E4%BB%B6/
2.4 字段参数
# 针对charfield
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
# 针对interfield
max_value 最小值
min_value 最大值
# 通用的,大家都有
#这两个最重要
read_only 表明该字段仅用于序列化输出,默认False(序列化)
write_only 表明该字段仅用于反序列化输入,默认False(反序列化)
required 表明该字段在反序列化时必须输入,默认True
default 反序列化时使用的默认值
allow_null 表明该字段是否允许传入None,默认False
error_messages 包含错误编号与错误信息的字典
validators 该字段使用的验证器(了解)
3、模型序列化器–重要
序列化类 --ModelSerializer模型序列化器
-ModelSerializer是对Serializers进一步的封装、
继承了ModelSerializer无需重写create、update方法
'from rest_framework.serializers import ModelSerializer'
class DepartmentSerializer(serializers.Serializer):
nid = serializers.IntegerField(required=False)
name= serializers.CharField(max_length=3, error_messages={'max_length': '太长了小伙子'})
contact = serializers.IntegerField(read_only=True)
email = serializers.EmailField(write_only=True)
class StaffModelSerializer(ModelSerializer):
class Meta:
model = models.Staff
#1、取全部字段
fields = '__all__'
#2、自定义包含字段
fields = ['name','age']
#3、排除某个字段
exclude=['name',] 2和3只能用一个、3一般不用
extra_kwargs = {
#write_only:True和read_only:True不能同时用
'department':{'required':True,'write_only':True},
'project':{'required':True,'write_only':True},
}
department_detail = DepartmentSerializer(source='department',read_only=True)
project_list = serializers.ListField(read_only=True)
views
class StaffView(APIView):
#查所有
def get(self, request):
staff_list = models.Staff.objects.all()
staff_ser = StaffModelSerializer(instance=staff_list, many=True)
# book_ser.data就是序列化后的数据
return Response(staff_ser.data)
#增加
def post(self, request):
data = request.data
staff_ser = StaffModelSerializer(data=data)
if staff_ser.is_valid(raise_exception=True):
staff_ser.save()
return Response(staff_ser.data)
else:
return Response(staff_ser.errors)
class StaffViewId(APIView):
# 查单个
def get(self, request, id):
staff = models.Staff.objects.all().filter(pk=id).first()
staff_ser = StaffModelSerializer(instance=staff)
return Response(staff_ser.data)
#改单个
def put(self, request, id):
staff = models.Staff.objects.filter(pk=id).first()
staff_ser = serializer.StaffModelSerializer(instance=staff, data=request.data)
if staff_ser.is_valid():
staff_ser.save()
return Response(staff_ser.data)
else:
return Response(staff_ser)
#删单个
def delete(self, request, id):
res = models.Staff.objects.filter(pk=id).delete()
if res[0] > 0: res--影响行数 res--元组、需要取出[0]
return Response('')
else:
return Response('要删的不存在')
models
from django.db import models
class Staff(models.Model):
name = models.CharField(max_length=64,verbose_name='姓名')
age = models.IntegerField(verbose_name='年龄')
department = models.ForeignKey(to='Department',on_delete=models.CASCADE,
verbose_name='部门')
projects = models.ManyToManyField(to='Project')
class Meta:
verbose_name_plural = '员工表'
def __str__(self):
return self.name
def department_name(self):
return {'name':self.department.name,'contact':self.department.contact}
@property
def project_list(self):
return [{'name':project.name,'price':project.price} for project in self.projects.all()]
路由
path('books/',views.StaffView.as_view()),
path('books/<int:id>/',views.StaffViewIda.as_view()),