day 73
-
ModelSerializer类;模型序列化类 - 核心类
-
单表;
-
序列化类继承ModelSerializer,所以需要在配置类Meta中进行配置
class UserModelSerializer(serializers.ModelSerializer): class Meta:
-
model配置:绑定序列化相关的model表
model = models.User
-
fields配置;采用插拔式,设置所有参与序列化与反序列化字段
fields = ('username', 'gender', 'icon', 'password', 'sex', 're_password') # 所有参与序列化与反序列化的(系统或自定义)字段都要到内部进行注册
-
extra_kwargs配置;
extra_kwargs = { 'username': { # 系统字段不设置read_only和write_only,默认都参加 'min_length': 3, # 配置简单的校验信息 'max_length': 10, 'error_messages': { # 配置不符合校验规则的返回信息 'min_length': '太短', 'max_length': '太长' } }, 'gender': { 'read_only': True, # 自定义的序列化字段默认就是read_only,且不能修改,可以省略 }, 'password': { 'write_only': True, # 配置为只写,反序列化,用于入库但不给客户端展示的字段 }, 'sex': { # 像sex有默认值的字段,为选填字段('required': True可以将其变为必填字段) 'write_only': True, # 'required': True } }
-
自定义反序列化字段
re_password = serializers.CharField(min_length=3, max_length=16, write_only=True) # 自定义反序列化字段一般不需要返回给前端,要设置 write_only = True
-
自定义序列化字段(推荐使用)
# 在model类中配置 @property # 序列化是通过反射的方法获取值 def gender(self): return self.get_sex_display()
-
局部校验钩子函数
validate_字段名(self,字段值value)
,所有字段都可以设置局部校验。规则;成功直接返回value,失败则抛出异常ValidationError('错误信息')
def validate_username(self, value): if 'g' in value.lower(): raise serializers.ValidationError('名字中不能有g') return value
-
全局校验钩子函数
validate(self, 所有字段字典attrs)
,可以在内部进行需要多字段参与的校验。规则成功直接返回attrs,失败则抛出异常ValidationError({'异常字段': '错误信息'})
def validate(self, attrs): password = attrs.get('password') re_password = attrs.pop('re_password') if password != re_password: raise serializers.ValidationError({'re_password': '两次密码不一致'}) return attrs
-
ModelSerializer内部写好了create和update方法,所以不需要重写
-
-
-
ListSerializer类;群操作序列化类 - 辅助类
- 重点;辅助完成单表多表群增群改操作
- 需要自定义辅助类继承ListSerializer
- 重写update方法,(ListSerializer没有写update方法,有create方法)
class BookListSerializer(serializers.ListSerializer): def update(self, instance_list, validated_data_list): return [ self.child.update(instance_list[index], attrs) for index, attrs in enumerate(validated_data_list) # self.child 为自定义的序列化模型类(BookModelSerializer) ]
01单表操作
class UserV3APIView(APIView):
# 单查群查
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
if pk:
# 获取数据
user_obj = models.User.objects.filter(is_delete=False, pk=pk).first()
if not user_obj:
return Response({
'status': 1,
'msg': 'pk error',
}, status=400)
# 将数据交给序列化类处理
user_ser = serializers.UserModelSerializer(user_obj, many=False)
return Response({
'status': 0,
'msg': 'ok',
'results': user_ser.data # 将序列化好的数据取出
})
else:
user_query = models.User.objects.filter(is_delete=False).all()
user_ser = serializers.UserModelSerializer(user_query, many=True)
return Response({
'status': 0,
'msg': 'ok',
'results': user_ser.data
})
# 单增
def post(self, request, *args, **kwargs):
user_ser = serializers.UserModelSerializer(data=request.data)
if user_ser.is_valid():
# 入库
user_obj = user_ser.save()
return Response({
'status': 0,
'msg': 'ok',
'results': serializers.UserModelSerializer(user_obj).data
})
else:
return Response({
'status': 1,
'msg': user_ser.errors,
})
02多表操作
-
基表;为抽象表,专门用来继承的,为表提供公有字段的,自身不会在数据库中创建
class BaseModel(models.Model): class Meta: abstract = True
-
断关联表关系
- 不会影响连表查询操作
- 会提升增删改的效率
- 易于后期数据库表的重构
- 缺点在于,数据库本身没有连表检测,容易出现脏数据,需要通过严格的逻辑避免脏数据的产生(必要时管理脏数据)
- A依赖于B,先插入A,该记录对应的B记录没有产生,在没有关联的情况下该数据可以产生,该数据就是脏数据
- 接着再将B数据添加,脏数据就得到了处理,反过来先产生B再产生A,更符合逻辑,通过逻辑将表进行关联
- 连表查询,不会有任何异常
- related_name 在外键中,设置外键反向查询的字段名,正向找字段名,反向找related_name值
- on_delete在外键中必须设置,表示级联关系,在Django 1.X 下系统默认提供值为 models.CASCADE,Django 2.X 下必须手动声明,
- CASCADE;默认值,级联
- DO_NOTHING;外键不会被级联,假设A表依赖于B表,删除B表,A表的外键字段不做任何处理
- SET_DEFAULT;假设A表依赖于B表,B记录删除,A表的外键字段设置为default属性设置的值,必须配合default使用
- SET_NULL;假设A表依赖于B表,B记录删除,A表的外键字段设置为null,所以必须配合
null = True
使用
- db_constraint在外键中控制表关联,默认为True表示关联,设施False表示断开关联(该字段只能给ForeignKey)
-
子查询
- 外键字段默认显示的是外键值(int类型)