【发布时间】:2020-01-02 21:39:22
【问题描述】:
使用 Django,我遇到了多对多字段的已知问题。在 post_save_event 信号/挂钩中,多对多字段的 Event 实例中的值:类别不会使用管理表单上提交的最新值进行更新。它始终显示旧值。
这是我的保存挂钩,其中我有一个父“事件”,每个事件都有一个用于 0 或多个类别的字段。但是,instance.categories 值不会更新为最新值。
@receiver(post_save, sender=Event)
def post_save_event(sender, instance, **kwargs):
success = events_api.create_or_update_event(instance)
我知道为什么会发生这种情况。基本上,多对多字段需要在父模型之后保存,因为多对多表需要有事件的主键。
我做了我在下面网上找到的修复。这是多对多表事务提交后发送的信号。
这种方法可以作为一种解决方法,但显然这意味着如果事件的类别发生变化,则 api 会被多次调用,更糟糕的是 m2m_changed 信号在发生时似乎会触发两次。所以我最终为一次更新调用了 3 次 api。
在成功保存表单而不是 post_save 事件之后,我可以使用任何解决方法/挂钩来执行此操作?
def category_has_changed(sender, **kwargs):
logger.error("Inside: Inside category has changed")
instance = kwargs.pop('instance')
success = events_api.create_or_update_event(instance)
m2m_changed.connect(category_has_changed, sender=Event.categories.through)
events_api的相关部分:
def _create_or_update_event(event, mode):
response = None
try:
headers = get_api_headers(event.cms_event_id)
categories = []
for cat in event.categories.all():
categories.append(cat.id)
# ISSUE: event.categories.all() does not contain the most recent updated array of categories
# Basic event details.
body = {
'cms_event_id': str(event.cms_event_id),
'categories': categories,
}
requests.post(ENDPOINT_CREATE_EVENT, json=body, headers=headers)
型号:
class Category(models.Model):
name_en = models.CharField(
_('Category name (English)'),
blank=True, null=True, max_length=200,
help_text=_('''
Helpful details (for English language customers) about where the workshop is taking
place, such as the location inside the store (ex. 2nd floor cafeteria).
'''))
name_fr = models.CharField(
_('Category name (French)'),
blank=True, null=True, max_length=200,
help_text=_('''
Helpful details (for English language customers) about where the workshop is taking
place, such as the location inside the store (ex. 2nd floor cafeteria).
'''))
def __str__(self):
return self.name_en
class Meta:
ordering = ('name_en',)
verbose_name_plural = _('Categories')
class Event(Page):
formfield_overrides = {
models.ManyToManyField: {'widget': CheckboxSelectMultiple},
}
super_manager = models.Manager()
...
categories = models.ManyToManyField(blank=True, null=True, to='Category')
【问题讨论】:
-
您能否展示您的 Event 和 Category 模型以及您的 events_api(创建或更新方法),以便我们了解您想要做什么?您已经向我们介绍了您认为可能的解决方案,但并没有真正解释您想要做什么。
-
@dirkgroten 我更新了模型和类别 api 部分的问题。 api 调用本身不是问题,问题在于调用 api 发送具有过时类别的实例的信号。我添加了更新类别多对多表时的信号,并使用更新的类别再次调用 api,但是每当外键更改时必须调用 api 两次,这很愚蠢。我只是想知道是否有更好的钩子或信号。
-
现在清楚了,谢谢,好问题!在将类别添加到事件时,您可能会循环访问它们,而不是调用
set()立即更新它们。这就是为什么您会多次调用 m2m_changed。但是,是的,无论如何我都不会将它与 m2m_changed 信号挂钩,如果稍后删除一个类别会发生什么?这将为所有事件调用 m2m_changed,是否应该在您的 api 上再次创建事件? -
我想我找到了一种从表单传递值的方法。我会更新解决方案
标签: django django-models