Django关联用户扩展模型ImageField时ImageFileDescriptor不可迭代错误求解
问题根因
报错是因为UserSerializer中avatar字段的source参数使用方式错误。DRF的source参数要求传入字符串格式的属性访问路径,你直接传入了UserExtended.avatar这个模型类属性对象,DRF内部判断source中是否包含.时,将ImageFileDescriptor类型的对象当作字符串处理,触发了类型不匹配的异常。
修复方案
- 基础修复:直接修正序列化器的source配置
你定义的User和UserExtended是一对一关联,未指定related_name的情况下,Django默认给User模型生成的反向关联属性名为小写的关联模型名userextended,把source改为字符串格式的关联路径即可:
class UserSerializer(serializers.ModelSerializer): name = serializers.SerializerMethodField(read_only=True) isAdmin = serializers.SerializerMethodField(read_only=True) # 修正source为字符串格式的关联属性路径 avatar = serializers.ImageField(source='userextended.avatar', read_only=True) class Meta: model = User fields = ['id', 'username', 'email', 'name', 'avatar', 'isAdmin'] def get_name(self, obj): name = obj.first_name if name == '': name = obj.email return name def get_isAdmin(self, obj): return obj.is_staff
如果当初定义UserExtended的user字段时设置了related_name,比如user = models.OneToOneField(User, on_delete=models.CASCADE, null=False, related_name='profile'),则把source改为'profile.avatar'即可。
- 兼容优化:处理无关联扩展记录的场景
如果存在部分用户未创建对应的UserExtended扩展记录,直接访问会抛出属性不存在的异常,可以改用SerializerMethodField做兼容处理:
class UserSerializer(serializers.ModelSerializer): name = serializers.SerializerMethodField(read_only=True) isAdmin = serializers.SerializerMethodField(read_only=True) avatar = serializers.SerializerMethodField(read_only=True) class Meta: model = User fields = ['id', 'username', 'email', 'name', 'avatar', 'isAdmin'] def get_name(self, obj): name = obj.first_name if name == '': name = obj.email return name def get_isAdmin(self, obj): return obj.is_staff def get_avatar(self, obj): if hasattr(obj, 'userextended') and obj.userextended.avatar: return obj.userextended.avatar.url # 可自定义默认头像地址,无则返回None return None
内容的提问来源于stack exchange,提问作者techedifice
相关产品推荐
相关产品推荐

