如何使超类查询集返回子类对象?或者将超类查询集向下转换为子类列表?

时间:2014-10-23 22:38:25

标签: python django web

我在django项目中工作,我需要在按日期排序的同一视图中列出两个不同的模型。为了实现这一点,我使用继承来将它们全部放入通用查询集中。我的模特是:

class Publication(models.model):
    title = models.CharField(max_lengh = 200)
    pub_date = models.DateTimeField(default = datetime.now)
    headline = models.TextField()

    class Meta:
        abstract = True

    @abc.abstractmethod
    def say_hello(self):
        return

class New(Publication):
    author = models.ForeignKey(Author)
    source = models.CharField(max_length = 200)
    categories = models.ManyToManyField(Category)
    url = '/news/'

    def say_hello(self):
        return "Hello New!!!"

class Opinion(Publication):
    writer = models.ForeignKey(Writer)
    style = .models.CharField(max_length=3, choices=(('txt', 'Text'), ('glr', 'Galery')))
    url = '/opinions/'

    def say_hello(self):
        return "Hello Opinion!!!"

我正在尝试调用子类方法,同时迭代发布QuerySet,如下所示:

publications = Publications.objects.all().order_by('-pub_date')
for pub in publications:
    pub.say_hello()
    url = pub.url

问题是我的QuerySet正在返回Publication对象,所以我无法访问子属性和方法,显然我正在处理Publication对象。我不应该将Publication设置为抽象类,避免处理Publication对象的可能性。它们不应该被阻止被实例化吗?是否有任何选项可以在Publication类中执行QuerySet并返回包含子对象的列表?

如果没有。你们怎么会绕过这种情况?我真的可以使用一些技巧。

3 个答案:

答案 0 :(得分:1)

听起来使用多表继承和django多态可能是合适的:

多表继承:https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance

Django polymorphic:http://django-polymorphic.readthedocs.org/en/latest/

django中的多表继承允许您拥有一个具有基本字段的基本模型/表。然后,您的子类定义扩展字段,这些字段放在它们自己的表中。当您从任何子类获取带有查询集的记录时,您将从基本模型/表和子类模型/表中获取每条记录的信息。

为了使用基本模型的查询集获取记录,并为每个结果获取相应子类的实例,一个选项是django polymorphic。我以前用过它,效果很好。它肯定有其局限性,但我会试一试。

答案 1 :(得分:0)

每个发布实例都应该有一个' new'属性或意见'属性分别指向两个子类中的一个。请注意,每个实例只有一个属性,所以尝试更好...除了访问它们。

答案 2 :(得分:0)

好吧,我将把我的解决方案的代码放在这里,这要归功于@David的答案。

正如大卫所建议的,我使用了django-polymorphic,这非常简单。但事实上,我已经有一个人口密集的数据库,使事情有点复杂。没什么好修的。

我做的第一件事就是使用south迁移数据库,以便将新字段(polymorphic_ctype)添加到我的父模型中(​​没有字段添加到子类中)。

然后,我在终端上的django shell模式下使用了以下代码。 (python manage.py shell

from jornal.models import Publication, New, Opinion
from django.contrib.contenttypes.models import ContentType

ctype_opinion = ContentType.objects.get(model = 'opinion', app_label = 'jornal')
ctype_new = ContentType.objects.get(model = 'new', app_label = 'jornal')
opinions = Opinion.objects.non_polymorphic().all()
news = New.objects.non_polymorphic().all()

for new in news:
    new.polymorphic_ctype = ctype_new
    new.save()

for opinion in opinions:
    opinion.polymorphic_ctype = ctype_opinion
    opinion.save()