0

Django-simple-history は、ターゲット モデルの保存ごとに新しいレコードを挿入しています。docsでは、F 式の問題が説明されています。上書きされた保存方法でこれを回避しようとします。

   def save(self, *args, **kwargs):
       super().save(*args, **kwargs)
       # some other actions
       self.refresh_from_db()

しかし、これは機能していないようです。ベース モデルのシグナルは、呼び出しpost_saveの直後に呼び出されsuper().save()ますか? もしそうなら、ターゲットモデルの更新でF式を維持するこの問題を解決する方法はありますか?

更新: 保存されたインスタンスには、F 式を使用して定義された属性の 1 つがあるため、このコードは他のモジュールで呼び出されます。

   instance.some_attribute = (F('some_attribute') + 15)
   instance.save(update_fields=['some_attribute'])

これにより、履歴テーブルpost_saveに の拡張コピーを挿入しようとすると、django-simple-history のシグナルでエラーがスローされます。実際の値が読み込まれるようにinstance、オーバーライドされたsaveメソッドでインスタンスを更新して F 式を削除しようとしました。some_attributeトレースバックから、呼び出しのpost_save直後super().save()、リフレッシュの前に が呼び出されたようです。オーバーライドされた保存が機能するDjango post_saveの方法はありますか? もしそうなら、更新コードを変更せず (F 式で更新を残す)、モデルの保存で挿入された履歴を解決する方法はありますか?

4

2 に答える 2

1

django-simple-history履歴レコードが作成される前後のシグナルを提供します: https://django-simple-history.readthedocs.io/en/2.7.0/signals.html

インスタンスが履歴テーブルに保存される前に、これらを使用してインスタンスを更新することをお勧めします。このようなものが動作するはずです:

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

于 2020-06-12T17:51:49.917 に答える
0

Ross Mechanicの回答に基づいて、私は普遍的な解決策を作りました

@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))
于 2020-06-14T06:50:45.770 に答える