Django 2.x中给非ModelSerializer添加模型字段的问题
解决Django Serializer中validate赋值后的TypeError问题
这个问题我之前也碰到过,本质是你在validate()方法里的操作和字段定义冲突了——咱们来拆解下:
你定义的database字段是IntegerField,序列化器在处理这个字段时,默认会期望它的值是整数类型。但你在validate()里把attrs['database']替换成了Database模型实例,后续序列化器在做数据处理(比如保存、返回序列化结果)时,会尝试把这个实例转换成整数,自然就触发了TypeError: int() argument must be a string, a bytes-like object or a number, not 'Database'。
下面给你两个最实用的解决办法,推荐第一个,更符合DRF的设计思路:
方法一:用PrimaryKeyRelatedField替代IntegerField(推荐)
DRF专门提供了PrimaryKeyRelatedField来处理“传入模型ID,自动转换成模型实例”的场景,还能自动帮你做存在性和权限验证,完全不用自己写validate()方法:
from rest_framework import serializers from .models import Database class ExecuteSerializer(serializers.Serializer): database = serializers.PrimaryKeyRelatedField( queryset=Database.objects.none(), # 先设为空,后续动态过滤 required=True ) query = serializers.CharField(required=True) user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 动态过滤queryset,只保留当前用户有权限的数据库 user = self.context['request'].user self.fields['database'].queryset = Database.objects.filter(collection__user=user)
这样做的好处:
- 自动验证传入的ID是否存在于当前用户的权限范围内,不存在会直接抛出验证错误
- 验证通过后,
attrs['database']直接就是Database实例,不用手动转换 - 完全符合DRF的字段设计逻辑,避免自定义validate带来的冲突
方法二:不覆盖原字段,新增键存储实例(兼容原有写法)
如果你坚持要用IntegerField,可以把转换后的实例存到一个新的键里,不要覆盖原来的database字段:
from rest_framework import serializers from rest_framework.exceptions import ValidationError from .models import Database class ExecuteSerializer(serializers.Serializer): database = serializers.IntegerField(required=True) query = serializers.CharField(required=True) user = serializers.HiddenField( default=serializers.CurrentUserDefault() ) def validate(self, attrs): user = attrs.get('user') try: # 新增键存储实例,不修改原database字段 database_instance = Database.objects.get(pk=attrs['database'], collection__user=user) except Database.DoesNotExist: raise ValidationError({'database': ['Does not exist']}) attrs['database_instance'] = database_instance return attrs
之后你在视图中使用时,直接取validated_data['database_instance']即可,原来的database还是整数类型,不会触发类型转换错误。
内容的提问来源于stack exchange,提问作者Anuj TBE
相关产品推荐
相关产品推荐

