我在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_id
或instance.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"后缀。