Django合并多模型查询结果后按不同日期字段排序报错如何解决
报错的核心原因是你判断的那样:两个模型的时间字段名称不统一,BlogPost用date存储创建时间,Comments用date_added存储,attrgetter('date')无法从Comments实例上取到对应值,因此抛出属性错误。
你可以根据自己的使用场景选以下任意一种方案解决:
方案1:自定义排序key函数(无需修改其他代码,临时使用最方便)
把sorted的key参数替换为自定义的lambda函数,根据实例类型判断取对应的时间字段,注意修复你原有代码里的两个笔误:
from itertools import chain def mypage(request): query_1 = list(BlogPost.objects.filter(user=request.user).order_by('-date')) # 修复笔误1:模型定义名为Comments,不是Comment query_2 = list(Comments.objects.filter(user=request.user).order_by('date_added')) results = sorted( chain(query_1, query_2), key=lambda x: x.date if isinstance(x, BlogPost) else x.date_added, reverse=True ) # 修复笔误2:第一个参数是request,不是reques context = {'results': results} return render(request, 'mypage.html', context)
方案2:给模型加统一的时间属性(可维护性更高,适合后续频繁调用的场景)
直接在两个模型中新增同名的只读属性,统一时间字段的调用方式,后续不管是排序还是其他逻辑都不需要再做类型判断:
# models.py 新增内容 class BlogPost(models.Model): # 原有字段不变 @property def create_time(self): return self.date class Comments(models.Model): # 原有字段不变 @property def create_time(self): return self.date_added
之后排序直接调用这个统一属性即可:
results = sorted(chain(query_1, query_2), key=attrgetter('create_time'), reverse=True)
方案3:查询时通过annotate统一字段名(不需要修改模型,也不需要在排序时写判断逻辑)
查询两个数据集时用annotate把时间字段统一命名为同一个字段,之后直接用这个统一字段排序即可,需要先导入Django的F表达式:
from django.db.models import F from itertools import chain def mypage(request): query_1 = BlogPost.objects.filter(user=request.user)\ .annotate(sort_date=F('date'))\ .order_by('-sort_date') query_2 = Comments.objects.filter(user=request.user)\ .annotate(sort_date=F('date_added'))\ .order_by('sort_date') results = sorted(chain(query_1, query_2), key=attrgetter('sort_date'), reverse=True) context = {'results': results} return render(request, 'mypage.html', context)
内容的提问来源于stack exchange,提问作者Van
相关产品推荐
相关产品推荐

