很多-到-很多字段更改-太多的api调用

时间:2019-08-29 15:09:16

标签: django django-models

使用Django,我遇到了“多对多”字段的已知问题。在post_save_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')


1 个答案:

答案 0 :(得分:0)

我能够像这样

在我的modelAdmin中修改save_model
class EventAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
    obj.new_categories = form.cleaned_data.get('categories')
    obj.save()

    super().save_model(request, obj, form, change)

然后在signals.py中将它作为实例的一部分:

instance.new_category