Django:来自不同模型的模型实例的有序列表?

时间:2013-02-01 03:04:51

标签: python django sorting django-models django-queryset

用户可以在我们的网站上传三种不同类型的内容:图片,视频,音频。以下是每种类型的模型:

class ImageItem(models.Model):
    user = models.ForeignKey(User)
    upload_date = models.DateTimeField(auto_now_add=True)
    image = models.ImageField(upload_to=img_get_file_path)
    title = models.CharFiled(max_length=1000,
                             blank=True)

class VideoItem(models.Model):
    user = models.ForeignKey(User)
    upload_date = models.DateTimeField(auto_now_add=True)
    video = models.FileField(upload_to=vid_get_file_path)
    title = models.CharFiled(max_length=1000,
                             blank=True)

class AudioItem(models.Model):
    user = models.ForeignKey(User)
    upload_date = models.DateTimeField(auto_now_add=True)
    audio = models.FileField(upload_to=aud_get_file_path)
    title = models.CharFiled(max_length=1000,
                             blank=True)

我有一个名为library.html的页面,它按照从最近上传的到最早上传的顺序呈现用户上传的所有项目(显示title和每个实例的upload_date,并在左侧放置一个小图标,表示它是什么类型的项目。

假设它需要三个单独的查询,我如何合并三个查询集?如何确保它们最近上传的顺序?

3 个答案:

答案 0 :(得分:5)

作为替代方案,您可以使用multi-table inheritance并将公共属性因子分解为超类模型。然后你只需order_by在超类模型上上传日期。第三方应用django-model-utils提供了一个名为继承管理器的自定义管理器,可让您自动向下转换为查询中的子类模型。

from model_utils.managers import InheritanceManager

class MediaItem(models.Model):
    objects = InheritanceManager()

    user = models.ForeignKey(User)
    upload_date = models.DateTimeField(auto_now_add=True)
    title = models.CharFiled(max_length=1000,
                             blank=True)

class ImageItem(MediaItem):
    image = models.ImageField(upload_to=img_get_file_path)

class VideoItem(MediaItem):
    video = models.FileField(upload_to=vid_get_file_path)

class AudioItem(MediaItem):
    audio = models.FileField(upload_to=aud_get_file_path)

然后,您的查询只是:

MediaItem.objects.all().order_by('upload_date').select_subclasses()

这样,只需一个查询就可以得到你想要的东西(有3个连接)。此外,您的数据更加规范化,并且支持各种更复杂的查询以及分页非常简单。

即使您没有这样做,我仍然会使用abstract base class inheritance来概念化您的数据模型,即使您没有获得数据库端和ORM权益

答案 1 :(得分:0)

attrgetter可用于提取您可能想要按键排序的对象的属性。

from operator import attrgetter

results = []
results.extend(list(AudioItem.objects.filter(...)))
results.extend(list(VideoItem.objects.filter(...)))
results.extend(list(ImageItem.objects.filter(...))
results.sort(key=attrgetter("upload_date")

答案 2 :(得分:0)

参考问题,这是我使用的确切解决方案。受到monkut答案的影响以及Frantzdy在评论中的链接的最佳答案(谢谢你们)。

from itertools import chain
from operator import attrgetter

images = ImageItem.objects.filter(user=user)
video = VideoItem.objects.filter(user=user)
audio = AudioItem.objects.filter(user=user)
result_list = sorted(chain(images, video, audio),
                     key=attrgetter('upload_date'),
                     reverse=True)