Python 透明地继承Django模型属性
我一直在绞尽脑汁想如何在Django 1.7上实现以下功能。我有两个Django模型。其中一个上的某些字段在另一个上重复。它们与外键相关,如下所示Python 透明地继承Django模型属性,python,django,Python,Django,我一直在绞尽脑汁想如何在Django 1.7上实现以下功能。我有两个Django模型。其中一个上的某些字段在另一个上重复。它们与外键相关,如下所示 class MyModelGroup(models.Model): name = models.CharField(max_length=128) shared_attr1 = models.NullBooleanField() shared_attr2 = models.CharField(max_length=512, n
class MyModelGroup(models.Model):
name = models.CharField(max_length=128)
shared_attr1 = models.NullBooleanField()
shared_attr2 = models.CharField(max_length=512, null=True, blank=True)
class MyModel(models.Model):
group = models.ForeignKey(MyModelGroup, null=True, blank=True)
name = models.CharField(max_length=128)
shared_attr1 = models.NullBooleanField()
shared_attr2 = models.CharField(max_length=512, null=True, blank=True)
MyModel
可能与MyModelGroup
记录相关。在MyModel
上更改shared\u attr1
或shared\u attr2
时,我希望实现以下行为:
MyModel
上即可MyModel
上MyModel
上的任一共享属性检索值时,我希望它执行以下操作:
MyModel
上的属性值MyModel
上的值与MyModelGroup
上的值不同,则返回MyModel
上的值MyModel
上的值为null,则返回MyModelGroup
上的值MyModel
从MyModelGroup
继承值,并通过在MyModel
上存储不同的值来覆盖这些值
我已经尝试在MyModel
上实现\uuuu getattr\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
我还尝试用计算字段实现它,如下所示:
@property
def shared_attr1(self):
# renamed model field to _shared_attr1
if self.group and self._shared_attr1 is None:
return self.group._shared_attr1
return self._shared_attr1
@shared_attr1.setter
def shared_attr1(self, new_value):
if self.group is None or new_value != self.group._shared_attr1:
self._shared_atttr1 = new_value
这两种方法都没有达到我预期的效果。你们中有人以前实现过类似的功能吗?在我看来,拥有此类功能的最佳方式是创建。用于在保存前调整值
然后为字段定义getter,作为setter,在值进入数据库之前使用方法转换值
看看有没有灵感。我不想太花哨。为什么不在“MyModel”上使用一个非常简单的方法来返回适当的值:
def get_shared_attr1(self):
if self.shared_attr1:
return self.shared_attr1
if self.group:
return self.group.shared_attr1
return None
并在保存
中处理正确状态的维护:
def save(self, *args, **kwargs):
if self.group and self.shared_attr1 == self.group.shared_attr1:
self.shared_attr1 = ''
super(MyModel, self).save(*args, **kwargs)
def save(self, *args, **kwargs):
self.mymodel_set.filter(shared_attr1=self.shared_attr1).update(shared_attr1='')
super(MyModelGroup, self).save(*args, **kwargs)
您必须处理组的保存中更改组属性的情况:
def save(self, *args, **kwargs):
if self.group and self.shared_attr1 == self.group.shared_attr1:
self.shared_attr1 = ''
super(MyModel, self).save(*args, **kwargs)
def save(self, *args, **kwargs):
self.mymodel_set.filter(shared_attr1=self.shared_attr1).update(shared_attr1='')
super(MyModelGroup, self).save(*args, **kwargs)
这不会导致严重的矛盾吗。假设您创建了一个模型,其中包含值'a'
和'B'
,然后您创建了一个组
(该组获取值'a'
和'B'
),但随后您为该组创建了另一个模型,并设置值'C'
和'D
)。然后该组有两个模型:一个是(A,B)
,以及带有(C,D)
。这也会导致数据重复,这通常是一种反模式。一个想法可能是,为没有组的每个模型
构建某种“虚拟”组,并在组级别对值进行编码。这将在一个点(组)存储数据,这样更新起来就不那么麻烦了。@WillemVanOnsem对我来说似乎是一个常见的用例。例如,我们对发货合作伙伴有一个默认的交货时间,但可以在他们的每个产品上覆盖它。@schwobaseggl:正确,但这里我们将“向上”对于组。在这种情况下,我认为最好使用聚合等。通常,数据重复会使程序更难调试,因为所有“事务”都需要确保数据重复保持不变。如果我们在层次结构中向下移动(从组继承的模型),然后使用派生字段之类的东西可能是个好主意,首先检查是否为对象设置了值,如果没有,则回退到组中。我可能必须这样做。问题是,我有一个现有的模型,在相当大的代码库中到处都在使用,如果我使用访问器方法来封装该行为我将不得不编辑数百个文件,因此如果可能的话,我希望维护标准接口。还有一些东西,如Django Rest Framework ModelViewSet,如果我更改当前接口,它们将被破坏。好吧,您可以将访问器设为具有先前字段名的属性。然后您必须更改fie当然,ldname会破坏现有的查询。顺便说一句,你的属性getter/setter方法到底有什么不起作用?我想要继承的属性之一是另一个模型的外键。当我更改字段的名称并为此实现getter和setter时,我的Django Rest Framework模型视图抱怨ob对象不可序列化。