首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过重写save绕过django-simple-history的F表达式问题

通过重写save绕过django-simple-history的F表达式问题
EN

Stack Overflow用户
提问于 2020-06-12 19:46:05
回答 2查看 153关注 0票数 0

Django-simple-history在每次保存目标模型时插入新的记录。在docs中,描述了F表达式的问题。我试图用覆盖的save方法来绕过这个问题。

代码语言:javascript
复制
   def save(self, *args, **kwargs):
       super().save(*args, **kwargs)
       # some other actions
       self.refresh_from_db()

但看起来,这并不管用。是否在super().save()调用后直接调用基础模型的post_save信号?如果是这样的话,有没有办法解决这个问题,使目标模型中的F表达式保持更新?

更新:保存的实例有一个使用F表达式定义的属性,因此在其他模块中调用此代码:

代码语言:javascript
复制
   instance.some_attribute = (F('some_attribute') + 15)
   instance.save(update_fields=['some_attribute'])

这会在django-simple- post_save的历史信号中抛出错误,因为它试图将instance的扩展副本插入到历史表中。我尝试在重写的save方法中刷新实例,以摆脱some_attribute中的F表达式,从而加载实际的值。从回溯来看,post_save似乎是在super().save()调用之后、刷新之前调用的。这是覆盖保存的Django post_save的工作方式吗?如果是这样,有没有一种方法可以不改变更新代码(用F表达式保留更新)并解决模型保存中的历史插入问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-13 01:51:50

在创建历史记录之前和之后,django-simple-history提供信号:https://django-simple-history.readthedocs.io/en/2.7.0/signals.html

我建议在将实例保存到历史表之前使用它们来更新实例。像这样的东西应该是有效的:

代码语言:javascript
复制
from django.dispatch import receiver
from simple_history.signals import (
    pre_create_historical_record,
    post_create_historical_record
)

@receiver(pre_create_historical_record)
def pre_create_historical_record_callback(sender, **kwargs):
    instance = kwargs["instance"]
    history_instance = kwargs["history_instance"]
        if isinstance(instance, ModelYouWantToRefresh)
    instance.refresh_from_db()
    history_instance.some_attribute = instance.some_attribute
票数 1
EN

Stack Overflow用户

发布于 2020-06-14 14:50:46

基于Ross Mechanic的回答,我提出了一个通用的解决方案

代码语言:javascript
复制
@receiver(
    pre_create_historical_record,
    dispatch_uid='simple_history_refresh')
def remove_f_expressions(sender, instance, history_instance, **kwargs):
    f_fields = []
    for field in history_instance._meta.fields:
        if isinstance(getattr(history_instance, field.name), BaseExpression):
            f_fields.append(field.name)
    if f_fields:
        instance.refresh_from_db()
        for fld_name in f_fields:
            setattr(history_instance, fld_name, getattr(instance, fld_name))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62343627

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档