gpt4 book ai didi

python - DRF 在序列化器 update() 调用中更新 ManyToMany

转载 作者:行者123 更新时间:2023-11-28 19:19:51 25 4
gpt4 key购买 nike

模型:

class Dvd(models.Model):
movie = models.ForeignKey(Movie)
price = models.DecimalField(...)
sold_copies = models.IntegerField(...)
final_value = models.DecimalField(...)

class Licence(models.Model):
distribution = models.ForeignKey(Dvd, related_name="licence_dvd")
percent = models.DecimalField(...)
computed_value = models.DecimalField(...)

序列化器:

class LicenceSerializer(serializers.ModelSerializer):
class Meta:
model = Licence

class DvdSerializer(serializers.ModelSerializer):
movie = MovieSerializer()
licence_dvd = LicenceSerializer(many=True)

class Meta:
model = Dvd
fields = ('id', 'price', 'sold_copies', 'final_value', 'movie', 'licence_dvd')

def update(self, instance, validated_data):
instance.price = validated_data.get('price', instance.price)
instance.sold_copies = validated_data.get('sold_copies', instance.sold_copies)
instance.final_value = instance.price * instance.sold_copies # is this ok?

# TODO recalculate the licence values

instance.save()
return instance

故事:

此序列化程序的目标是每次 Dvd 更改时更新 Licence.computed_value。每年年底,会计师都会查看当年售出的所有电影,并计算每部电影的总值(value) (final_value)。 许可证是电影制作人和公司之间的契约(Contract)。每卖出一张 dvd,公司就有 xx% 的钱。公司很多,会计要根据相关dvdfinal_value计算xx%(通常在5%左右)并保存它到那个特定的 licence.computed_value
(清楚了吗?如果需要,我可以举个例子)
基本公式为:

Dvd.final_value = Dvd.price * Dvd.sold_copies
Dvd.licence_dvd.computed_value = Dvd.final_value * Dvd.licence_dvd.percent

第一个有效,但第二个……棘手。
如果每个 dvd 只有一个 licence,那将很容易(validated_data.pop,保存 licence,保存 dvd)。问题是我在数据库中每个 dvd 有多个 licences,所以 licence_dvd 返回多个对象。
遍历 validated_data['licence_dvd'] 给我:

OrderedDict([('percent', Decimal('0.5')), ('computed_value', Decimal('1234'))])

每个许可(这只是一个例子)。

问题:

  • 我这样做对吗?如果某些值是通过公式重新计算的,那么定义和计算应该放在哪里?在 API/序列化器/前端级别?
  • update函数中的instance和validated_data有什么区别?我了解 validated_data 是经过验证的传入数据,但我应该何时以及如何访问/修改其(或实例的)变量?
  • 如何修改 DvdSerializer.update 函数中的 licence_dvd 数据?

非常感谢您提供任何有用的信息!

最佳答案

首先,我在您的示例中找不到 ManyToMany 关系,因此问题标题似乎具有误导性(它本质上是一对多,许多许可证可以引用一张 DVD)。对于问题:

  • 我绝对确定序列化程序不是定义业务逻辑的正确位置(更新计数器正是其中的一部分)。我建议将它放在 View 中。序列化程序只能用于序列化/反序列化您的数据(例如,将其从 JSON 转换为对象并返回);
  • instance 和 validated_data 之间的区别在于 instance 是您将要更改的数据库中现有行的表示,而 validated_data 是您用于更新的数据(并且在更新请求中序列化到达);
  • 正如我在上面提到的,序列化程序不适合这样做。否则,您必须考虑到 dvd.license_dvd 本质上是一个集合,而不是单个值(实际上,在您的逻辑中,每个 dvd 可以有多个许可证).因此,为了更新许可证,您必须遍历它们:

dvd.license_dvd 中的许可证:
在这里为每个许可证进行更新
如果您真的每张 DVD 只有一个许可证,请考虑使用 OneToOneField,因为它更合适。

关于python - DRF 在序列化器 update() 调用中更新 ManyToMany,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28049768/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com