Django继承自类

时间:2015-05-27 21:22:49

标签: 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

为什么TopTitlesPostPageNewTitlesPostPage不继承TitlePost的所有属性?例如,如果我尝试使用likes在模板中调用TopTitlesPostPage,则不会执行,因为likes属性未被继承。 OneToOneField是否与问题有关?我确实读到让TitlePost元类有用,但我需要它在我的数据库中有一个表。我实际上希望他们所有人都在我的数据库中有一个表。然后,也许我正在以错误的方式接近这个,我应该只使用TitlePost作为模型来生成所有内容?

3 个答案:

答案 0 :(得分:4)

您希望看到的行为称为multi table inheritance。每个子类内部都会以您编写的相同内容结束,因此对于基类TitlePost使用一对一字段,但它由django内部管理。

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

k=TopTitlesPostPage.objects.create(hello="Hello",title_name="Heh")

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

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

如果您实际上从未实际引用基类TitlePost,但只有它的子项可能更适合制作`TitlePost abstract

  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

使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"> ]

要使用django polymorphic,您只需要将多态模型声明为基类:

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)

外键也会返回子类实例,如果您尝试多态,这真的很酷。

# 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)> ]

考虑到这些查询将是slightly less performant

答案 1 :(得分:1)

你需要扩展类如下:

class TopTitlesPostPage(TitlePost):

只需提及所有以逗号分隔的模型,你就可以添加更多并继承多个模型!模型中的所有字段也将在子类中创建

编辑:

我这样做的方法是创建一个Abstract类,其中包含所有常用字段并将其扩展到TitlePost,TopTitlesPostPagea和NewTitlesPostPage

答案 2 :(得分:0)

您需要TopTitlesPostPageNewTitlesPostPage扩展TitlePost的基类,如此...

class TopTitlesPostPage(models.Model)

如果您继承自基类,则不需要OneToOneField,因为TitlePost的属性将在子类中可用。如果你想使TitlePost抽象(你不能声明该类的实例,只能从它继承),你必须将它添加到元类

class TitlePost(models.Model):
    class Meta:
        abstract = True

以下是documentation的链接。