透明地继承Django模型属性

2024-09-26 22:13:03 发布

您现在位置:Python中文网/ 问答频道 /正文

关于如何在django1.7上实现以下功能,我一直在绞尽脑汁。我有两个Django模型。其中一个上的某些字段在另一个上重复。它们与外键相关,就像这样。你知道吗

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记录有关。当shared_attr1shared_attr2MyModel上更改时,我希望实现以下行为:

  1. 如果外键为空,只需将值保存在MyModel

  2. 如果外键不为null,并且该值与与与该外键链接的记录上共享的值不同,请将该值保存在MyModel

  3. 否则,将该值留空。

然后,当我从MyModel上的任一共享属性检索值时,我希望它执行以下操作:

  1. 如果外键为null,则返回MyModel上属性的值。

  2. 如果外键不为null,MyModel上的值与MyModelGroup上的值不同,则返回MyModel上的值。

  3. 如果外键不为null,MyModel上的值为null,则返回MyModelGroup上的值。

其目的是允许一堆MyModelMyModelGroup继承值,并且可以通过在MyModel上存储不同的值来重写这些值。你知道吗

我已经尝试在MyModel上实现__getattr____setattr__,以透明地检查外键是否存在,并在适当的情况下获取和设置值,但是Django正在做很多让这变得困难的神奇的事情。你知道吗

我还尝试用计算字段实现它,如下所示:

@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

这两种方法都没有达到我的预期效果。你们中有人以前实现过这样的东西吗?你知道吗


Tags: selftruemodelsgroupnulllengthmax外键
2条回答

我不想太花哨。为什么不在“MyModel”上使用一个非常简单的方法来返回适当的值:

def get_shared_attr1(self):
    if self.shared_attr1:
        return self.shared_attr1
    if self.group:
        return self.group.shared_attr1
    return None

并处理save中正确状态的保持:

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)

您必须处理组的save中组的属性发生更改的情况:

def save(self, *args, **kwargs):
    self.mymodel_set.filter(shared_attr1=self.shared_attr1).update(shared_attr1='')        
    super(MyModelGroup, self).save(*args, **kwargs)

从我的角度来看,拥有这种功能的最佳方法是创建Custom Django Field。保存前使用pre_save调整值。你知道吗

然后为字段定义getter,作为setter,在值进入数据库之前使用pre_save方法转换值。你知道吗

灵感请参见You can see django.db.fields。你知道吗

相关问题 更多 >

    热门问题