serializer.is_valid() 适用于整数字段,但 serializer.save() 要求模型实例



我在ma数据库中有一个多对多关系(PK是整数)。我从数据库自动生成了 django 模型,并实现了最简单的序列化程序。

当我给序列化程序一个带有整数的字典时,serializer.is_valid() 返回 True,但 serializer.save() 说字段应该是模型实例。

但是当我给出一个带有模型实例的字典时,serializer.is_valid() 返回 False。

data = {'tag_id': 9, 'spending_id': 17}
serializer = TagspendingSerializer(data= data)
serializer.is_valid()
True
serializer.save()

=> 值错误:无法分配"9":"Tagspending.tag_id"必须是"标记"实例。

data = {'tag_id': Tag.objects.get(tag_id= 9), 'spending_id': Spending.objects.get(spending_id= 17)}
serializer = TagspendingSerializer(data= data)
serializer.is_valid()

=> 假

这是我的模型:

class Tagspending(models.Model):
tag_id = models.ForeignKey(Tag, models.DO_NOTHING, db_column='tag_ID', primary_key=True)
spending_id = models.ForeignKey(Spending, models.DO_NOTHING, db_column='spending_ID')
class Meta:
managed = True
db_table = 'TagSpending'
unique_together = (('tag_id', 'spending_id'),)

这是我的序列化程序:

class TagspendingSerializer(serializers.ModelSerializer):
class Meta:
model = Tagspending
fields = ('tag_id', 'spending_id')

我认为有一些事情可以让你更清楚一点

Django 这样做:

外键定义一个额外的属性,并将_id附加到字段名称

模型中有以下字段:

tag_id = models.ForeignKey(Tag, models.DO_NOTHING, db_column='tag_ID', primary_key=True)

但是您实际上并不需要指定 db 列或主键并执行此操作:

tag = models.ForeignKey(Tag, models.DO_NOTHING)

在 db 中,此字段的 db 列将具有名称 tag_id(如您所愿),类型将为整数。 这就是验证通过的原因。

现在,您可以访问 idinstance.tag_idinstance.tag.id(但是这两个调用之间存在差异 - 如果尚未检索,则一个命中数据库)。

但是,在您的情况下,"tag_id"是外键,需要"标签"实例。

您有两种可能的方法来解决此问题(假设您使用我建议的更改来重命名字段)

1)您可以在帖子请求中使用tag_id(现在,字段名称更改为tag)

2) 在序列化程序中,可以指定以下内容:

tag = serializers.PrimaryKeyRelatedField(queryset=Tag.objects.all())

你可以做发布请求

{"tag" : 1 } 

这会将您的 ID 解析为 Tag 实例(如果有效)

由于您使用tag_id作为主键,Django Rest Framework似乎存在错误。 您应该更改模型,这是最佳实践,方法是更改与Tag的关系作为OneToOneField(因为它是主键,因此此关系是唯一的,因此OneToOneField更合适)。然后,您的序列化程序应该可以工作。

您还应考虑重命名模型字段。无需引入"_id"后缀。

最新更新