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

Pri*_*ett 5 python django inheritance

我正在创建一个在它的模型中使用一些继承的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)
Run Code Online (Sandbox Code Playgroud)

我想确保自动设置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
Run Code Online (Sandbox Code Playgroud)

这有效.我可以叫ChildElement.create(somefield="foo")我一定要得到一个合适的对象有uuid,objmoduleobjclass字段中设置正确.但是,当我经历并创建更多像ChildElement2和的类时ChildElement3,我发现我正在插入完全相同的静态工厂函数.这对我来说很重要,因为代码重复很糟糕.

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

有没有我可以在这个工厂迁移到一个方法BaseElement类,所以我没有到处复制该代码,仍然有它,所以它会自动设置的值uuid,objmoduleobjclass

Car*_*yer 7

如果你把create()一个@classmethod不是@staticmethod,你将有机会对类对象,你可以使用,而不是由名称引用它:

@classmethod
def create(cls, *args, **kwargs):
    obj = cls(*args, **kwargs)
    obj.set_defaults()
    return obj
Run Code Online (Sandbox Code Playgroud)

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