我在开发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
为什么TopTitlesPostPage
和NewTitlesPostPage
不继承TitlePost
的所有属性?例如,如果我尝试使用likes
在模板中调用TopTitlesPostPage
,则不会执行,因为likes
属性未被继承。 OneToOneField
是否与问题有关?我确实读到让TitlePost
元类有用,但我需要它在我的数据库中有一个表。我实际上希望他们所有人都在我的数据库中有一个表。然后,也许我正在以错误的方式接近这个,我应该只使用TitlePost
作为模型来生成所有内容?
答案 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)
您需要TopTitlesPostPage
和NewTitlesPostPage
扩展TitlePost
的基类,如此...
class TopTitlesPostPage(models.Model)
如果您继承自基类,则不需要OneToOneField
,因为TitlePost
的属性将在子类中可用。如果你想使TitlePost
抽象(你不能声明该类的实例,只能从它继承),你必须将它添加到元类
class TitlePost(models.Model):
class Meta:
abstract = True
以下是documentation的链接。