我有以下型号:
class SrdRevisionWording(ModelDiff):
srd_revision = models.ForeignKey(SrdRevision, on_delete=models.CASCADE)
word = models.CharField(max_length=50, null=False)
designation = models.CharField(max_length=200, null=False)
is_list = models.BooleanField(null=False, default=False)
parent_element = models.IntegerField(null=True) # ID of the Wording element in the previous SRD Revision
__original_instance = None
with_signal = True
def get_revision_history_message(self, created=False, deleted=False, updated_field=None, check_history=False):
if created:
return 'Word "{}" added'.format(self.word)
if deleted:
return 'Word "{}" deleted'.format(self.word)
match updated_field:
case 'word':
return 'Word {} changed to {}'.format(self.__original_instance.word, self.word)
case 'designation' | 'is_list':
return 'Word {} modified'.format(self.word)
属性
__original_instance
是自定义模型字段(不在数据库中)。
该属性在 pre_save
信号期间实例化:
@receiver(pre_save, sender=SrdRevisionDocument)
@receiver(pre_save, sender=SrdRevisionWording)
def model_pre_save_handler(sender, instance, **kwargs):
print('pre_save')
if instance.srd_revision.revision != 'A':
try:
previous_srd_revision_state = sender.objects.get(pk=instance.parent_element)
except sender.DoesNotExist:
instance.__original_instance = None
else:
instance.__original_instance = previous_srd_revision_state
print(instance.__original_instance)
print(instance.__original_instance)
很好地向我展示了物体SrdRevisionWording object (21)
。
我还可以在 post_save
信号中打印对象:
@receiver(post_save, sender=SrdRevisionDocument)
@receiver(post_save, sender=SrdRevisionWording)
def handle_revision_history_element_changed(sender, instance, **kwargs):
print('signal')
print(instance.__original_instance)
if instance.with_signal is not False:
message = instance.get_revision_history_message(created=True, check_history=True)
调用
instance.get_revision_history_message()
时,问题出现在最后一行。
我在 models.py 文件中收到以下错误:
return 'Word {} changed to {}'.format(self.__original_instance.word, self.word)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'word'
我认为这更多是我自己对OOP的误解。但是有人可以解释一下为什么 __original_instance 似乎无法在这里为 Model 方法实例化/访问吗?
因为在 post_save 信号处理程序中调用 get_revision_history_message 时,__original_instance 属性为 None。发生这种情况是因为 post_save 信号不保留 pre_save 信号中设置的 __original_instance 的状态。要解决这个问题,您可以使用 Django 的 instance._state.adding 属性来确定是否正在创建实例并相应地处理逻辑。
例如:你可以这样通勤......
class SrdRevisionWording(ModelDiff):
srd_revision = models.ForeignKey(SrdRevision, on_delete=models.CASCADE)
word = models.CharField(max_length=50, null=False)
designation = models.CharField(max_length=200, null=False)
is_list = models.BooleanField(null=False, default=False)
parent_element = models.IntegerField(null=True) # ID of the Wording element in the previous SRD Revision
__original_instance = None
with_signal = True
def set_original_instance(self):
if self.srd_revision.revision != 'A':
try:
self.__original_instance = SrdRevisionWording.objects.get(pk=self.parent_element)
except SrdRevisionWording.DoesNotExist:
self.__original_instance = None
这种方法将有助于维持状态。