我正在尝试使用Django Rest Framework序列化程序为前端创建API,以创建/更新和删除商店中的商品。这些文章可以有多个价格(取决于时间)。因此,从商品(一)到价格(多)存在一对多的关系。我已经在models.py
中定义了这一点:
class Article(models.Model):
article_id = models.AutoField(primary_key=True, verbose_name="Article ID")
article_name = models.CharField(max_length=250, verbose_name="Name")
article_order = models.IntegerField(verbose_name="Order")
class Price(models.Model):
price_id = models.AutoField(primary_key=True, verbose_name="Price ID")
article_id = models.ForeignKey(Article, on_delete=models.CASCADE, verbose_name="Article ID", related_name="Prices")
price_price = models.DecimalField(max_digits=6, decimal_places=2, verbose_name="Price")
我的serializers.py文件如下:
from rest_framework import serializers
from .models import *
class PriceSerializer(serializers.ModelSerializer):
class Meta:
model = Price
fields = ('price_price',)
class ArticleSerializer(serializers.ModelSerializer):
Prices = PriceSerializer(many=True)
def create(self, validated_data):
prices_data = validated_data.pop('Prices')
article = Article.objects.create(**validated_data)
for price_data in prices_data:
Price.objects.create(article_id=article, **price_data)
return article
def update(self, instance, validated_data):
prices_data = validated_data.pop('Prices')
Article.objects.filter(article_id=instance.article_id).update(**validated_data)
for price_data in prices_data:
Price.objects.get_or_create(article_id=instance, **price_data)
return instance
class Meta:
model = Article
fields = '__all__'
这很好用,我可以使用以下数据创建新的商品价格衡量指标:({article_order
将在以后用于订购列表)
{"Prices":[{"price_price":"1"}],"article_name":"Article A","article_order":"1"}
到目前为止,一切都按预期进行。但是,当我尝试更新价格时,Price.objects.get_or_create()
语句无法识别现有价格。例如:如果第一个价格为€10,然后为€20,然后再次为€10,则不会插入最后一个价格,因为get_or_create
语句无法将其识别为price
的新实例。模型。这可能是有道理的,因为PriceSerializer
不会序列化price_id
。但是当我将序列化器更改为:
class PriceSerializer(serializers.ModelSerializer):
class Meta:
model = Price
fields = '__all__
,我无法再创建实例,因为ArticleSerializer
实例需要article_id
的实例(但尚不存在)。
有人知道如何解决此问题吗? DRF文档仅包含此类型的嵌套序列化程序的create语句。
https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers
答案 0 :(得分:1)
您没有正确使用get_or_create
方法。
它接受用于查找对象的kwargs
,如果对象不存在,则创建它们,并从defaults
添加其他字段值。
这意味着,如果您传递新值以更新为kwargs
,则将找不到该对象,因为当前这些字段的值不同。
相反,您应该传递在kwargs
中保持不变的字段,在defaults
中传递其余字段。
这就是你应该做的
def update(self, instance, validated_data):
prices_data = validated_data.pop('Prices')
Article.objects.filter(article_id=instance.article_id).update(**validated_data)
for price_data in prices_data:
Price.objects.get_or_create(article_id=instance, defaults=price_data)
return instance
但是请注意,由于文章根据您的数据库体系结构可能有多种价格,因此您可能会遇到MutipleObjectsReturned
错误。如果不打算按每条商品多价,则可能需要将article_id
更改为OneToOneField
以防止这种情况。
您可以在Django docs
中详细了解get_or_create
请注意,在id
的OOP体系结构Article
中已经隐含了文章ID,因此在字段名前面加上article
是一个非常多余且不明智的做法。再说一次,您可能想使用Django自动生成的id字段而不是重新定义它,除非您想以某种方式自定义它(当前在您的代码中并不明显)
答案 1 :(得分:0)
您可以看到django rest框架文档:https://www.django-rest-framework.org/api-guide/serializers/
def update(self, instance, validated_data):
instance.email = validated_data.get('email', instance.email)
instance.content = validated_data.get('content', instance.content)
instance.created = validated_data.get('created', instance.created)
return instance
希望能对您有所帮助