4

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

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到最早上传的顺序呈现用户上传的所有项目(它显示每个实例的和,并在左侧放置一个小图标,表示它是什么类型的项目)。titleupload_date

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

4

3 回答 3

5

作为替代方案,您可以使用多表继承并将公共属性分解到超类模型中。然后你只需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 个连接)获得所需的内容。另外,您的数据被更好地标准化,并且支持各种更复杂的查询以及分页相当简单。

即使您不这样做,我仍然会使用抽象基类继承在概念上规范化您的数据模型,即使您没有获得数据库端和 ORM 的好处。

于 2013-02-01T07:24:04.263 回答
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")
于 2013-02-01T07:06:41.853 回答
0

参考这个问题,这是我使用的确切解决方案。受蒙库特的回答和 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)
于 2013-02-02T03:21:41.123 回答