Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 透明地继承Django模型属性_Python_Django - Fatal编程技术网

Python 透明地继承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

我一直在绞尽脑汁想如何在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, 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
    上即可

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

  • 否则,将该值留空

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

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

  • 如果外键不为空,并且
    MyModel
    上的值与
    MyModelGroup
    上的值不同,则返回
    MyModel
    上的值

  • 如果外键不为null,并且
    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对象不可序列化。