Django 从类继承

the*_*lco 1 python django inheritance

我在开发 Django 网站时遇到了问题。

from django.db import models

class TitlePost(models.Model):
    title_name = models.CharField(max_length=100, unique=True)
    title_body = models.TextField(max_length=30000)
    title_why = models.TextField(max_length=250, null=True)
    title_publication_date = models.DateTimeField('date')
    likes = models.IntegerField(default=0)
    dislikes = models.IntegerField(default=0)


    def __unicode__(self):
        return self.title_name


class TopTitlesPostPage(models.Model):
    title_post = models.OneToOneField(TitlePost)
    hello = models.CharField(max_length=100, unique=True)

    def __unicode__(self):
        return self.hello

class NewTitlesPostPage(models.Model):
    title_post = models.OneToOneField(TitlePost)
    hello = models.CharField(max_length=100, unique=True)

    def __unicode__(self):
        return self.hello
Run Code Online (Sandbox Code Playgroud)

TopTitlesPostPage为什么and不NewTitlesPostPage继承 的所有属性TitlePost?例如,如果我尝试likes使用 调用模板中的TopTitlesPostPage,它将不会执行,因为该likes属性不是继承的。OneToOneField和问题有关系吗?我确实读到制作TitlePost元类会有所帮助,但我需要它在我的数据库中有一个表。我实际上希望他们所有人都在我的数据库中拥有一个表。话又说回来,也许我正在以错误的方式处理这个问题,我应该使用它作为TitlePost模型来生成所有内容?

Seb*_*zny 5

您希望看到的行为称为多表继承。每个子类在内部都以您编写的相同内容结束,因此与基类具有一对一的字段TitlePost,但它由 django 在内部管理。

如果您像下面的代码一样进行多重继承,您将能够编写:

k=TopTitlesPostPage.objects.create(hello="Hello",title_name="Heh")
Run Code Online (Sandbox Code Playgroud)

这意味着这些字段将可以直接访问。

from django.db import models

class TitlePost(models.Model):
    title_name = models.CharField(max_length=100, unique=True)
    title_body = models.TextField(max_length=30000)
    title_why = models.TextField(max_length=250, null=True)
    title_publication_date = models.DateTimeField('date')
    likes = models.IntegerField(default=0)
    dislikes = models.IntegerField(default=0)


    def __unicode__(self):
        return self.title_name


class TopTitlesPostPage(TitlePost):
    hello = models.CharField(max_length=100, unique=True)

    def __unicode__(self):
        return self.hello

class NewTitlesPostPage(TitlePost):
    hello = models.CharField(max_length=100, unique=True)

    def __unicode__(self):
        return self.hello
Run Code Online (Sandbox Code Playgroud)

如果您实际上永远不会引用基类,而只会引用其子类,则将 `TitlePost抽象化TitlePost可能更合适:

  class TitlePost(models.Model):
    title_name = models.CharField(max_length=100, unique=True)
    title_body = models.TextField(max_length=30000)
    title_why = models.TextField(max_length=250, null=True)
    title_publication_date = models.DateTimeField('date')
    likes = models.IntegerField(default=0)
    dislikes = models.IntegerField(default=0)

    class Meta:
        abstract = True
    def __unicode__(self):
        return self.title_name
Run Code Online (Sandbox Code Playgroud)

进行TitlePost抽象将省略在数据库中创建表的过程TitlePost,并且子模型最终会将基类的字段单独插入到自己的表中。如果基类只是为了分解常见功能,那么这是首选方法。

对于大型查询,这也会对性能产生影响,因为 ORM 需要执行更少的JOIN操作。

无法在 Django 中安装外键来抽象模型。但是,您可以将外键安装到非抽象基类。唯一的限制是反向外键关系将返回基类实例。您可以使用django-polymorphic来规避此限制。

Django Polymorphic 允许您查询基类对象但检索子类实例:

>>> Project.objects.create(topic="Department Party")
>>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner")
>>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")

>>> Project.objects.all()
[ <Project:         id 1, topic "Department Party">,
  <ArtProject:      id 2, topic "Painting with Tim", artist "T. Turner">,
  <ResearchProject: id 3, topic "Swallow Aerodynamics", supervisor "Dr. Winter"> ]
Run Code Online (Sandbox Code Playgroud)

要使用 django 多态,您只需使用多态模型作为基类来声明您的模型:

from django.db import models
from polymorphic import PolymorphicModel

class ModelA(PolymorphicModel):
    field1 = models.CharField(max_length=10)

class ModelB(ModelA):
    field2 = models.CharField(max_length=10)

class ModelC(ModelB):
    field3 = models.CharField(max_length=10)
Run Code Online (Sandbox Code Playgroud)

外键还将返回子类实例,如果您想实现多态,这真的很酷。

# The model holding the relation may be any kind of model, polymorphic or not
class RelatingModel(models.Model):
    many2many = models.ManyToManyField('ModelA')  # ManyToMany relation to a polymorphic model

>>> o=RelatingModel.objects.create()
>>> o.many2many.add(ModelA.objects.get(id=1))
>>> o.many2many.add(ModelB.objects.get(id=2))
>>> o.many2many.add(ModelC.objects.get(id=3))

>>> o.many2many.all()
[ <ModelA: id 1, field1 (CharField)>,
  <ModelB: id 2, field1 (CharField), field2 (CharField)>,
  <ModelC: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
Run Code Online (Sandbox Code Playgroud)

请考虑到这些查询的性能会稍微降低