Skip to main content
 首页 » 编程设计

python之Django 模型之继承成本

2024年08月30日29leader

我们有django项目,发现有些模型变大了。

class BigModel(models.Model): 
    """ 
    Large set of fields 
    """ 
    field1 = models.IntegerField() 
    field2 = models.IntegerField() 
    field3 = models.IntegerField() 
    ... 
    fieldN = models.IntegerField() 
    """ 
    Large set of methods 
    """ 
    def method1(self): pass 
    def method2(self): pass 
    def method3(self): pass 
    ... 
    def methodN(self): pass 

我想用方法列表将 BigModel 类分成更小的类。但在整个项目中,我们引用了 BigModel 类。

所以我的想法是循序渐进:

  1. 将BigModel类分为BigFields和BigMethods。继承 BigMethods 来自 BigFields。从 BigMethods 继承 BigModel。
  2. 通过创建代理模型并在代码中用它们替换对 BigModel 的引用 - 减少 BigMethods 类的大小。

所以,在重构的时候我们的代码会是这样的:

class BigFields(models.Model): 
    class Meta: 
        abstract = True 
    """ 
    Large set of fields 
    """ 
    field1 = models.IntegerField() 
    field2 = models.IntegerField() 
    field3 = models.IntegerField() 
    ... 
    fieldN = models.IntegerField() 
 
class BigMethods(BigFields): 
    class Meta: 
        abstract = True 
    """ 
    Large set of methods 
    """ 
    def method1(self): pass 
    def method2(self): pass 
    def method3(self): pass 
    ... 
    def methodN(self): pass 
 
class BigModel(BigMethods): 
    pass 
  • 它将如何影响性能?
  • python 中一级继承的成本是多少?
  • 元类会影响继承成本吗?

请您参考如下方法:

如果您的模型中有这样的顺序字段,解决方案不是继承,而是将这些字段分解为单独的模型并创建一对多关系。很难用您的示例模型来说明这一点,所以我将使用我正在从事的项目中的一个。

原始模型看起来像这样:

class Page(models.Model): 
    title = models.CharField(max_length=256) 
    section_1_title = models.CharField(max_length=256) 
    section_1_content = models.TextField() 
    section_2_title = models.CharField(max_length=256) 
    section_2_content = models.TextField() 
    section_3_title = models.CharField(max_length=256) 
    section_3_content = models.TextField() 
    ... 

显然这是维护的噩梦,所以我将其更改为以下内容:

class Page(models.Model): 
    title = models.CharField(max_length=256) 
 
class Section(models.Model): 
    page = models.ForeignKey(Page, related_name='sections') 
    title = models.CharField(max_length=256) 
    content = models.TextField() 
    order = models.PositiveIntegerField() 
 
    class Meta: 
        ordering = ['order'] 
        order_with_respect_to = 'page'