繁体   English   中英

Python和Django中的继承和工厂函数

[英]Inheritance and factory functions in Python and Django

我正在创建一个在它的模型中使用一些继承的Django应用程序,主要是因为我需要为UUID和引用分配所有内容,所以我知道它是什么类。 这是基类的简化版本:

class BaseElement(models.Model):
    uuid = models.CharField(max_length=64, editable=False, blank=True, default=lambda:unicode(uuid4()))
    objmodule = models.CharField(max_length=255, editable=False, blank=False)
    objclass = models.CharField(max_length=255, editable=False, blank=False)

class ChildElement(BaseElement):
    somefield = models.CharField(max_length=255)

我想确保自动设置objmodule,objclass和uuid。 我从这篇文章中了解到,通过编写自己的构造函数来做这件事是个坏主意,而且我最好写一个工厂函数。 所以现在我的BaseElement和ChildElement看起来像这样:

class BaseElement(models.Model):
    uuid = models.CharField(max_length=64, editable=False, blank=True, default=lambda:unicode(uuid4()))
    objmodule = models.CharField(max_length=255, editable=False, blank=False)
    objclass = models.CharField(max_length=255, editable=False, blank=False)

    def set_defaults(self):
        self.objmodule = unicode(self.__class__.__module__)
        self.objclass = unicode(self.__class__.__name__)
        self.uuid = unicode(uuid4())

class ChildElement(BaseElement):
    somefield = models.CharField(max_length=255)

    @staticmethod
    def create(*args, **kwargs):
        ce = ChildElement(*args, **kwargs)
        ce.set_defaults()
        return ce

这有效。 我可以调用ChildElement.create(somefield="foo") ,我将获得一个适当的对象,其中uuidobjmoduleobjclass字段设置正确。 但是,当我经历并创建更多类如ChildElement2ChildElement3 ,我发现我正在插入完全相同的静态工厂函数。 这对我来说很重要,因为代码重复很糟糕。

使用普通方法我只是在BaseElement插入create工厂函数,但是,我不能在这里做,因为我没有自己的句柄(因为它尚未创建)来获取有关该类的信息调用该方法的对象。

有没有办法可以将这个工厂迁移到BaseElement类中,所以我不必在任何地方复制这个代码并且仍然拥有它所以它会自动设置uuidobjmoduleobjclass

如果你使create()成为@classmethod而不是@staticmethod ,你将可以访问类对象,你可以使用它而不是通过名称引用它:

@classmethod
def create(cls, *args, **kwargs):
    obj = cls(*args, **kwargs)
    obj.set_defaults()
    return obj

现在这是通用的,可以在基类而不是每个子类上进行。

我认为你可能更好地覆盖你的BaseElement中的保存。 然后在保存时,您可以设置这些字段。 它是这样的:

class MyBase(models.Model):
    uuid = models.CharField(max_length=64, editable=False, blank=True,
        default=lambda:unicode(uuid4()))
    objmodule = models.CharField(max_length=255, editable=False, blank=False)
    objclass = models.CharField(max_length=255, editable=False, blank=False)

    def save(self):
        if not self.id:
            self.objmodule = unicode(self.__class__.__module__)
            self.objclass = unicode(self.__class__.__name__)
            self.uuid = unicode(uuid4())
        super(self.__class__.__base__, self).save()

class InheritedFromBase(MyBase):
    new_field = models.CharField(max_length=100)

我测试了它,它似乎做你想要的。 我能够创建一个“InheritedFromBase”对象,它具有您需要的字段,而不需要大量的代码重复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM