gpt4 book ai didi

django - 如何在模型的保存方法中访问 ManyToManyField?

转载 作者:行者123 更新时间:2023-12-01 19:56:48 26 4
gpt4 key购买 nike

我知道我不可能是第一个问这个问题的人,但我找不到答案,所以请不要吃掉我。

如果我有一个模型,其字段ManyToManyField;我知道我可以在保存之前获取所选对象,但如果所选对象已更改,则这没有帮助。

models.py:

class AddOn(models.Model):
name = models.CharField(max_length=100)


class Invoice(models.Model):
additional_options = models.ManyToManyField(AddOn)

def save(self, *args, **kwargs):
super().save()
# this prints the objects that were selected prior to the save.
# this isn't helpful if the selected objects have changed.
print(self.additional_options.all())

最佳答案

根据您提出问题的方式,我认为您对 ManyToManyField 幕后实际发生的情况感到困惑(我将其称为 M2M从现在开始),所以我将尝试用以下模型来解释它:

class Topping(models.Model):
name = models.CharField(max_length=30)

class Pizza(models.Model):
name = models.CharField(max_length=50)
toppings = models.ManyToManyField(Topping)

当我们声明一个 M2M 字段时,Django 在幕后创建一个通过模型,在本例中如下所示:

class ThroughModel(models.Model):
topping = models.ForeignKey(Topping)
pizza models.ForeignKey(Pizza)

这用于将模型链接在一起,并且不会存储在数据库中,除非您在 M2M 字段中使用 through 关键字来创建自己的模型。

在您实际链接 M2M 中的 PizzaTopping 模型之前,您必须已保存实例:

>>> t1 = Topping(name='pepperoni')
>>> t2 = Topping(name='sausage')
>>> t3 = Topping(name='ham')
>>> Topping.objects.bulk_create([
>>> t1, t2, t3
>>> ])
>>>
>>> pizza = Pizza(name='meat lovers')

现在,我们如何向 M2M 字段添加数据?像这样:

>>> pizza.toppings.add(t1, t2, t3)

但按原样,这会引发:

ValueError: 'Pizza' instance needs to have a primary key value before a many-to-many relationship can be used.

因为 pizza 实例未保存

>>> pizza.save()
>>> pizza.toppings.add(t1, t2, t3)
>>>
>>> print('no error thrown now!')

您还可以通过传入主键而不是实例来添加toppings:

>>> pk = Toppings.objects.first().pk
>>> pk
1
>>> pizza = Pizza.objects.create(name='pepperoni pizza')
>>> pizza.toppings.add(pk)

最后,从给定的披萨实例中获取配料:

>>> pizza.toppings.all()
<QuerySet [<Toppings: Toppings object (1)>, <Toppings: Toppings object (2)>, <Toppings: Toppings object (3)>]>

需要注意的是,从 M2M 获取值需要 2 次数据库查询,而且确实没有办法解决这个问题。

最后,要真正回答您的问题,您可以执行以下操作来访问 save 内的 M2M 字段:

class Pizza(models.Model):
name = models.CharField(max_length=50)
toppings = models.ManyToManyField(Topping)

def save(self, *args): # args will be M2M data
super().save() # now that the instance is saved, we can access toppings
if args:
self.toppings.add(*args)

print(self.toppings.all())

使用示例:

>>> pizza = Pizza(name='sausage and ham')
>>> pizza.save(2, 3)
<QuerySet [<Toppings: Toppings object (2)>, <Toppings: Toppings object (3)>]>
# this is from the print inside of save

我的示例模型来自 prefetch_related文档部分,但我建议阅读 this如果您想了解有关 ManyToManyFields 的更多信息,请参阅部分。

关于django - 如何在模型的保存方法中访问 ManyToManyField?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58254104/

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