我知道如何更新ForeignKey的某些字段。例如,当我想每次更改Configuration或SomeOtherImportantClass时都更改last_modified字段时:
class Configuration(models.Model):
title = models.TextField()
last_modified = models.DateTimeField(auto_now=True)
class SomeOtherImportantClass(models.Model):
conf = models.ForeignKey(Configuration)
important_number = models.IntegerField()
def save(self, *args, **kwargs):
conf.last_modified = timezone.now() # I'm not sure if it is necessary
conf.save()
return super().save(*args, **kwargs)
但是在我的实际情况下,Cofiguration模型是30多个其他模型的ForeignKey。在它们中的每一个上,或者在更改另一个模型(具有ForeignKey的模型到具有ForeignKey做配置的某些模型)时,我都希望在每个模型中都更新configuration.last_modified字段。看起来像这样:
class Configuration(models.Model):
title = models.TextField()
last_modified = models.DateTimeField(auto_now=True)
class A(models.Model):
conf = models.ForeignKey(Configuration) # conf.last_modified must be updated on every change on A model object.
class B(models.Model):
conf = models.ForeignKey(Configuration) # same
...
class Z(models.Model):
conf = models.ForeignKey(Configuration) # same
class AA(models.Model):
some_field = models.TextField()
a = models.ForeignKey(A)
...
class ZZ(models.Model)
some_field = models.TextField()
z = models.ForeignKey(Z)
因此,即使AA对象字段“ some_field”已更改,我也要更新last_modified配置字段。是否有任何递归方法可以在Configuration或其他地方声明一次?
更新:像AAA和AAAA类这样的大家族也可以存在。
答案 0 :(得分:1)
按照文档中的说明使用abstract base classes。对于A-Z,这非常简单:
class ConfigurationChild(Model):
conf = ForeignKey(Configuration)
class Meta:
abstract = True
def save(self):
self.conf.last_modified = ...
self.conf.save()
super().save()
class A(ConfigurationChild):
# other fields, without conf
对于孙子孙来说,这有点复杂,因为那样的话就没有直接引用conf
了。在您填充到每个子类上的基类上设置一个属性:
class ConfigurationDescendant(Model):
conf_handle = None
class Meta:
abstract = True
def get_conf(self):
if not self.conf_handle:
return None # or raise an error
parent = getattr(self, self.conf_handle)
if isinstance(parent, ConfigurationDescendant):
return parent.get_conf() # recursion
else:
# reached `ConfigurationChild` class, might want to check this
return parent.conf if parent else None
def save(self):
conf = self.get_conf()
# you might want to handle the case that the attribute is None
if conf:
conf.last_modified = ...
conf.save()
super().save()
class AA(ConfigurationDescendant):
conf_handle = 'a'
a = ForeignKey(A)
class AAA(ConfigurationDescendant):
conf_handle = 'aa'
aa = ForeignKey(AA)
上面的代码将处理由于父母之一中缺少conf_handle
而导致链断裂的情况。在这种情况下,将返回None
而不会发生任何事情。我不是在检查手柄的设置是否错误(即未正确指向父Configuration
的方向),这将引发您可能想要的异常,以便您可以捕获错误。