在Django中如何从两个模型创建对象列表并按日期排序?
在Django中如何从两个模型创建对象列表并按日期排序?
嘿,这个需求我做项目时也碰到过,给你几个实用的方案,你根据自己的数据量和使用场景来选就行:
方法一:用itertools.chain合并后Python层面排序(简单直接,适合小数据量)
这种方法上手最快,先把两个模型的查询集合并,再在Python里按日期排序:
- 先导入需要的工具
- 获取两个模型的对象集合
- 合并后用
sorted函数指定排序字段
代码示例:
from itertools import chain from django.utils import timezone # 获取两个模型的查询集(也可以加filter过滤你需要的数据) small_news = SmallNews.objects.all() big_news = BigNews.objects.all() # 合并两个查询集为一个可迭代对象 combined_news = chain(small_news, big_news) # 按日期排序,reverse=True表示最新的在前,反之则去掉 # 如果你有日期为null的情况,可以加个默认值,比如lambda x: x.date_news or timezone.datetime.min sorted_news = sorted(combined_news, key=lambda x: x.date_news, reverse=True)
优点:操作简单,返回的是完整的模型实例,能直接调用模型的方法和属性;
缺点:排序是在Python内存中完成的,如果数据量很大(比如上万条),性能会比较差。
方法二:数据库层面合并排序(性能更好,适合大数据量)
如果你的数据量比较大,推荐在数据库层面完成合并和排序,这就要求两个查询集返回的字段结构一致:
# 让两个查询集返回相同的字段集合,还可以加个标记区分来源 small_news_data = SmallNews.objects.all().values( 'id', 'date_news', 'title' # 选你需要的字段 ).annotate(news_type='small') big_news_data = BigNews.objects.all().values( 'id', 'date_news', 'title' ).annotate(news_type='big') # 用union合并,然后直接在数据库层面按日期排序 sorted_news_data = small_news_data.union(big_news_data).order_by('-date_news')
优点:合并和排序都在数据库中完成,性能更优,适合大数据场景;
缺点:返回的是字典类型的数据,不是模型实例,没法直接调用模型的方法,适合只需要展示数据的场景。
额外提示
如果你的两个模型字段结构非常相似,其实可以考虑重构一下,用抽象基类来定义共同的字段,比如:
class BaseNews(models.Model): date_news = models.DateField() title = models.CharField(max_length=200) class Meta: abstract = True class SmallNews(BaseNews): # 小新闻独有的字段 small_content = models.TextField() class BigNews(BaseNews): # 大新闻独有的字段 big_content = models.TextField()
这样后续要合并查询、排序或者做其他操作都会更方便,也符合DRY原则~
备注:内容来源于stack exchange,提问作者plurim
相关产品推荐
相关产品推荐

