Django多表关联序列化API报错:'Store'无'Storeimage'属性
Django序列化关联模型异常解决:'Store' object has no attribute 'Storeimage'
问题场景
调用关联Store、Storeimage、Address三个模型的REST API时抛出异常,异常信息:
'Store' object has no attribute 'Storeimage'
现有模型代码
class Store(models.Model): user = models.ForeignKey(User, default=1, null=True, on_delete=models.SET_NULL) address = models.ForeignKey(Address, null=True,on_delete=models.CASCADE) store_name = models.CharField(max_length=255) store_about = models.CharField(max_length=255,null=True) store_location = models.CharField( max_length=255) store_phoneno = models.CharField(max_length=12) class Storeimage(models.Model): store = models.ForeignKey(Store, null=True, on_delete=models.SET_NULL) picture = models.ImageField(upload_to='store_image/%Y/%m/',max_length=255,null=True) class Address(models.Model): street = models.TextField() country = models.ForeignKey(Country, default=1,null=True, on_delete=models.CASCADE) state = models.ForeignKey(State, default=1,null=True, on_delete=models.CASCADE)
现有序列化代码
class StoreGetSerialiser(serializers.ModelSerializer): address = AddressSerializer() Storeimage = StoreImage(many=True) owner = UserPublicSerializer(source='user', read_only=True) class Meta: model = Store fields = [ 'pk', 'owner', 'store_name', 'Storeimage', 'store_location', 'address', 'store_phoneno', 'store_website', ] class StoreImage(serializers.ModelSerializer): class Meta: model = Storeimage fields = '__all__'
错误原因
Django中外键的反向关联默认名称是模型名小写+_set。这里Storeimage模型关联Store,所以Store对象的反向关联属性是storeimage_set,而非序列化代码中写的Storeimage(大小写错误且不符合默认命名规则)。同时预期输出需要的字段名是store_image,需对应调整。
另外,原序列化代码中的store_website字段在Store模型中不存在,需移除,否则会引发额外错误。
修正方案
提供两种可行的修正方式:
方式1:不修改模型,通过source指定反向关联属性
修改序列化代码,将字段名改为store_image,并通过source指向正确的反向关联属性:
class StoreGetSerialiser(serializers.ModelSerializer): address = AddressSerializer() # 用source指定默认反向关联属性storeimage_set,字段名改为预期的store_image store_image = StoreImage(many=True, source='storeimage_set') owner = UserPublicSerializer(source='user', read_only=True) class Meta: model = Store fields = [ 'pk', 'owner', 'store_name', 'store_image', 'store_location', 'address', 'store_phoneno', # 移除模型中不存在的store_website字段 ] class StoreImage(serializers.ModelSerializer): class Meta: model = Storeimage fields = ['pk', 'picture'] # 只返回预期输出需要的字段
方式2:修改模型,添加related_name自定义反向关联名称
在Storeimage模型的外键中添加related_name='store_image',这样可以直接使用store_image作为序列化字段名:
# 修改Storeimage模型 class Storeimage(models.Model): store = models.ForeignKey(Store, null=True, on_delete=models.SET_NULL, related_name='store_image') picture = models.ImageField(upload_to='store_image/%Y/%m/',max_length=255,null=True)
对应的序列化代码:
class StoreGetSerialiser(serializers.ModelSerializer): address = AddressSerializer() store_image = StoreImage(many=True) owner = UserPublicSerializer(source='user', read_only=True) class Meta: model = Store fields = [ 'pk', 'owner', 'store_name', 'store_image', 'store_location', 'address', 'store_phoneno', # 移除模型中不存在的store_website字段 ] class StoreImage(serializers.ModelSerializer): class Meta: model = Storeimage fields = ['pk', 'picture']
修正后预期输出
{ "pk": 2, "owner": { "id": 1 }, "store_name": "", "store_location": "", "address": { "id": 14, "street": "1", "country": 1, "state": 1, "city": 1 }, "store_phoneno": "", "store_image": [{"pk":1,"picture":"/location/abcd"},{"pk":2,"picture":"/location/abcd"}] }
内容的提问来源于stack exchange,提问作者selvakumar
相关产品推荐
相关产品推荐

