Django - 如何以子类形式而不是父类形式返回 QuerySet 中的所有对象?



我有一个类Set,与Item具有多对多关系。我有很多"设置"对象,都包含很多"项目"。

但是,Item类已被子类化以创建ArticlePodcastVideoEpisode。基本上,数据库上的所有内容最初都是一个项目。如果my_set是一个包含ItemsSet实例 - 如何创建一个以子类形式返回这些对象的查询集?也就是说,我得到的不是满是项实例的查询集,而是ArticleEpisodeVideoPodcast实例的查询集。

如何让"my_set.objects.all().as_subclass()"工作?

class Item(models.Model, AdminVideoMixin):
base_attributes = 'foo'
def as_episode(self):
return Episode.objects.get(slug=self.slug)
class Video(Item): 
class specific fields
class Article(Item):
class specific fields
class Podcast(Item):
class specific fields
class Episode(Item):
class specific fields
class Set(Item):
front_page = models.BooleanField(max_length=300, blank=False, default=False, null=False)
items = models.ManyToManyField(Item, related_name='in_sets', through='SetMeta', max_length=5000,)
def get_absolute_url(self):
return reverse('foo')
def ordered(self):
return self.items.all().order_by('-itemOrder__order')
def episodes(self):
episode_list = []
for each_item in self.items.all():
episode_list.append(each_item.as_episode())
return episode_list

def __str__(self):
return self.title

如您所见,我尝试了两种方法 - 在 Item() 上编写一个模型方法,该方法将自身返回为 Episode - 但这仅适用于单个实例而不是 Queryset。因此,我在 Set 上编写了一个方法,它可以对自身中的所有项目执行该方法,但这不会生成 Queryset,而只是一个列表,感觉很混乱?

更新:刚刚再次浏览了 django 多态文档,它似乎正是您想要的。所以我的其余答案可能不是很有用,除非你被禁止从 django 包中取出代码。

我不认为 Django 提供了一种表达返回多个模型类型的对象的查询集的方法。查询集应该映射 inro SQL 查询,我认为 SQL 不能从多个混合表中返回行。(我不是SQL专家,所以我可能是错的)。但是,如果你不想要列表,Python 提供了一种获取查询集并将转换应用于它返回的每个Item实例的方法:生成器函数。 因此,例如,您可以编写代码

def items_as_subclasses(qs):
for instance in qs:
try:
yield instance.video
continue
except Video.DoesNotExist:
pass
try:
yield instance.article
continue
except Article.DoesNotExist:
pass
try: ...
raise ProbableCodingError(
f"Item instance id={instance.id} does not have a known subclass"
)

然后写

for item_subclass_instance in items_as_subclasses(queryset):
# whatever

或者确实将"items":items_as_subclasses( queryset)传递到模板渲染中 上下文。

如果存在一长串可能的子类,则最好在基类中有一个subclass_type字段,并使用该字段直接转到唯一有效的子类字段。

从基类到其特定子类有一个可为空的 OneToOne 链接,因此您可以编写查询子类的查询集。

或者你可以研究一下django-polymorphic,我曾经略过,我依稀记得它是针对这种用法的。

最新更新