我有一个Wagtail网站,我正在为几种不同的页面类型/内容类型制作一个列表页面。我首先按摘要字段进行过滤:
def highlights_list(category='Highlight'):
tag = ContentCategory.objects.get(name=category)
highlights = Page.objects.filter(
Q(event__categories=tag)|
Q(newspage__categories=tag)|
Q(contentpage__categories=tag)).live()
return highlights.order_by('-last_published_at')
在Wagtail中,所有内容类型都继承自基础Page
类,这使使用我想要的所有内容类型创建查询集变得非常容易。但是我无法弄清楚如何排序。
按last_published_at
排序适用于NewsPage
和ContentPage
,但不适用于Event
,因为我想根据事件的DateTimeField
进行排序。
[我曾考虑在所有名为@property
的模型上制作一个sort_date
,该模型使用特定于我要排序的每个模型的datetime字段,但这是行不通的。
非常欢迎提出任何建议!
我可以想到两个解决方案,但是似乎只有一个更容易实现。我将上面的功能更改为此:
def highlights_list(category='Highlight'):
tag = ContentCategory.objects.get(name=category)
highlights = Page.objects.filter(
Q(event__categories=tag)|
Q(newspage__categories=tag)|
Q(contentpage__categories=tag)
).live().specific()
return sorted(
highlights,
key=lambda p: getattr(p, 'date') or getattr(p, 'last_published_at'),
reverse=True
)
这是从highlights
中获取所有页面,并根据date
或last_published_at
中的值对其进行排序,就好像它们是同一字段一样。因为只有Event
页面具有date
字段,所以last_published_at
用作后备,因此所有活动页面都具有该字段。如果像问题一样在查询集中遗漏specific()
,则会抛出AttributeError
并说'Page' object has no attribute 'date'
。
另外,由于排序部分是在Python中完成的,因此它不使用任何数据库查询。请注意,这会返回基于原始QuerySet
的列表。
第二种解决方案涉及数据库事务和Wagtail钩子,并且具有更多代码,但这是我不想共享的东西,因为我还没有想到如何写出来。