从Django代理模型的基类创建实例

2024-05-01 08:47:28 发布

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

我有一系列的模型是这样的:

class Analysis(models.Model):
    analysis_type = models.CharField(max_length=255)

    def important_method(self):
        ...do stuff...


class SpecialAnalysis(Analysis):
    class Meta:
        proxy = True

    def important_method(self):
        ...something different...

这都很标准。但是,我想做的是根据analysis_type字段的值自动将Analysis模型转换为代理模型。例如,我希望能够编写如下代码:

^{pr2}$

这有可能吗?有人问了一个类似的问题here,这实际上为迭代示例提供了一些代码,但它仍然留给我一个问题,即如何从其父类获取或创建代理类的实例。我想我可以重写一堆manager方法,但我觉得必须有一种更优雅的方法来实现它。在


Tags: 方法代码模型self代理modelmodelsdef
2条回答

这是一个很好的方法,我并不特别认为这是一个欺骗。这里是对__init__函数的一些增强,这样当您添加更多的类时,它就不必更改了。

def __init__(self, *args, **kwargs):
    super(Analysis, self).__init__(*args, **kwargs)
    if not self.__type and type(self) == Analysis:
        raise Exception("We should never create a base Analysis object. Please create a child proxy class instead.")

    for _class in Analysis.__subclasses__():
        if self.check_type == _class.__name__:
            self.__class__ = _class
            break

def save(self, **kwargs):
    self.check_type = self.__class__.__name__
    super(Analysis, self).save(**kwargs)

希望这有帮助!

我还没有找到一个“干净”或“优雅”的方法来做到这一点。当我遇到这个问题时,我通过欺骗Python解决了这个问题。

class Check(models.Model):
    check_type = models.CharField(max_length=10, editable=False)
    type = models.CharField(max_length=10, null=True, choices=TYPES)
    method = models.CharField(max_length=25, choices=METHODS)
    'More fields.'

    def __init__(self, *args, **kwargs):
        super(Check, self).__init__(*args, **kwargs)
        if self.check_type:
            map = {'TypeA': Check_A,
                'TypeB': Check_B,
                'TypeC': Check_C}
            self.__class__ = map.get(self.check_type, Check)

    def run(self):
        'Do the normal stuff'
        pass


class Check_A(Check):
    class Meta:
        proxy = True

    def run(self):
        'Do something different'
        pass

class Check_B(Check):
    class Meta:
        proxy = True

    def run(self):
        'Do something different'
        pass


class Check_C(Check):
    class Meta:
        proxy = True

    def run(self):
        'Do something different'
        pass

它不是真的干净,但它是最容易找到的黑客解决了我的问题。

也许这对你有帮助,也许没有

我也希望其他人能有一个更像Python的解决办法来解决这个问题,因为我一直在数着直到这个方法失败并回来困扰我的日子。。

相关问题 更多 >