【问题标题】:Django: Ordered list of model instances from different models?Django:来自不同模型的模型实例的有序列表?
【发布时间】:2013-02-01 03:04:50
【问题描述】:

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

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每个实例的名称,并在左侧放置一个小图标,表示它是什么类型的项目)。

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

【问题讨论】:

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


【解决方案1】:

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

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 的好处。

【讨论】:

  • 这绝对是这样做的方法。如果您将来需要更多媒体类型,维护起来会容易得多。它还具有良好的面向对象编程的重用特性。
  • 感谢 Nasmon 发现了一个错字。看来他的编辑尝试被第三方模组拒绝了,但我想在应得的地方给予赞扬,因为我不知道如何覆盖和接受编辑。
【解决方案2】:

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")

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-15
      • 1970-01-01
      • 2022-01-19
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 2019-08-11
      • 2020-09-06
      相关资源
      最近更新 更多