2

我想使用继承来实现模型,我找到了这个包django-polymorphic。但是我正在阅读有关 django 模型中的继承的内容,并且几乎在我发现他们推荐abstract = True在父模型中使用的每一页上。这将复制子类的字段,从而使查询更快。

我做了一些测试,发现这个库没有使用抽象变量:

class Parent(PolymorphicModel):
    parent_field = models.TextField()

class Child(Parent):
    child_field = models.TextField()

This results in:

父表:

| app_parent| CREATE TABLE `app_parent` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_field` longtext NOT NULL,
  `polymorphic_ctype_id` int(11),
  PRIMARY KEY (`id`),
  KEY `app_polymorphic_ctype_id_a7b8d4c7_fk_django_content_type_id` (`polymorphic_ctype_id`),
  CONSTRAINT `app_polymorphic_ctype_id_a7b8d4c7_fk_django_content_type_id` FOREIGN KEY (`polymorphic_ctype_id`) REFERENCES `django_content_type` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |

Child table:

| app_child | CREATE TABLE `app_child` (
  `parent_ptr_id` int(11) NOT NULL,
  `child_field` varchar(20) NOT NULL,
  PRIMARY KEY (`parent_ptr_id`),
  CONSTRAINT `no_parent_ptr_id_079ccc0e_fk_app_parent_id` FOREIGN KEY (`parent_ptr_id`) REFERENCES `app_arent` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |

我应该使用我自己的使用抽象字段的类还是应该坚持这个?

4

1 回答 1

1

您是否需要能够查询父表?

Parent.objects.all()

如果是,那么您很可能需要将多表继承与abstract=False.

使用模型继承abstract=False可以获得更复杂的数据库模式,以及更多的数据库关系。创建子实例将需要 2 次插入而不是 1 次(父表和子表)。查询子数据需要表连接。所以这种方法肯定有它的缺点。但是当你想查询公共列数据时,django 是最好的支持方式。

Django 多态建立在标准 django 模型继承之上,通过添加额外的列polymorphic_ctype来允许识别只有父对象的子类。

您可以通过多种方式使用abstract=True. 但通常它会导致更复杂的查询代码。

如果使用abstract=True波纹管是 2 个示例,您如何查询所有孩子的公共数据。

  • 链接多个查询

    def query_all_childs(**kwargs):
        return chain(
            Child1.objects.filter(**kwargs)
            Child2.objects.filter(**kwargs)
        )
    
  • 使用数据库视图

    手动创建一个组合多个表的数据库视图(这可以通过将 sql 代码附加到迁移后信号来完成):

    create database view myapp_commonchild
    select 'child1' as type, a, b from child1
    union all
    select 'child2' as type, a, b from child2
    

    使用 .创建一个具体父模型managed=False。该标志告诉 django 在数据库迁移中忽略该表(因为我们已经为此手动创建了数据库视图)。

    class Parent(models.Model):
        a = CharField()
        b = CharField()
    
    class CommonChild(Parent):
        type = models.CharField()
        class Meta:
            managed = False
    
    class Child1(Parent):
        pass
    
    class Child2(Parent):
        pass
    

    现在您可以查询CommonChild.objects.all()和访问子类的公共字段。

说到性能,我不知道你的表有多大或读/写有多大,但很可能使用abstract=False不会以明显的方式影响你的性能。

于 2017-07-14T14:23:16.183 回答