给定(简化)模型,在Django Admin应用程序中使用:
models.py
class Appointment(models.Model):
customer = models.ForeignKey(
Customer, blank=False, null=True, on_delete=models.CASCADE
)
pianos = models.ManyToManyField(Piano, blank=True)
def save(self, *args, **kwargs):
# Is it a new Appointment, not an existing one being re-saved?
newAppointment = self.id is None
try:
super().save(*args, **kwargs) # Call the "real" save() method.
if newAppointment:
# Returns empty queryset
for piano in self.pianos.all():
print(piano)
except:
pass
字符串
我想访问“钢琴”。如果是新创建的约会,则返回self.pianos
<django.db.models.fields.related_descriptors.create_forward_many_to_many_manager..ManyRelatedManager object at 0x7f6f875209a0>
而self.pianos.all()
返回一个空的queryset,即使钢琴显示在提交以启动保存的模板表单中。
然而,如果它是对现有Appointment
的更新,'pianos'将按预期返回数据。
显然,当save()
被调用时,ManyToMany
字段不会立即保存到数据库中。那么我如何才能访问如下所示的数据呢?请注意,“钢琴”在这里没有示例化,它们已经存在于数据库中,并且只需要Appointment指向其m2m字段中的一个或多个钢琴,就像从admin.py
中定义的horizontal_filter
定向的那样。
我还尝试了使用post_save
信号的替代方法,结果完全相同:
@receiver(signals.post_save, sender=Appointment)
def createServiceHistory(sender, instance, created, **kwargs):
if created:
for piano in instance.pianos.all(): #empty queryset
print(piano)
型
更新:修改为捕获m2m_changed
而不是post_保存:
@receiver(signals.m2m_changed, sender=Appointment)
def createServiceHistory(sender, instance, action, **kwargs):
print(action)
型
但是这个信号没有被接收到。
文档说ManyToMany
字段是使用add()
而不是save()
保存的,但我不知道在这种情况下如何应用。
1条答案
按热度按时间4bbkushb1#
在两个示例都保存之前不能创建
ManyToMany
关联,这就是为什么当您在Appointment.save() method
中时还没有创建它的原因。Form.save()
方法(或Save
按钮,如果您使用Django管理界面)保存Appointment
,然后使用.add()
将其与Piano
示例关联。在这种情况下,您可以使用@IainShelvington建议的m2m_changed
信号:当模型示例上的
ManyToManyField
发生更改时发送。严格来说,这不是模型信号,因为它是由ManyToManyField
发送的,但由于它在跟踪模型更改时补充了pre_save
/post_save
和pre_delete
/post_delete
,因此包含在这里。请注意,此信号的
sender
将不再是Appointment
。您应该使用文档中提到的Appointment.pianos.through
:与此信号一起发送的参数:
sender
个描述
ManyToManyField
的中间模型类。这个类在定义多对多字段时自动创建;您可以使用多对多字段上的through
属性访问它。一个简单的例子是:
字符串
OP的其他评论:
为了方便以后的读者,我们先将action设置为
pre_add
,然后第二个信号到达,action设置为post_add
。只有在这个时候,本例中的数据才可以通过Appointment.pianos.all()
获得。