如何为Wagtail的PageChooserBlock设置自定义排序?
自定义PageChooserBlock相关列表排序的两种方案
你的场景里,排序问题可以从两个维度解决——后台选择器里的可选页面排序,以及前端展示已选页面的排序,具体方法如下:
一、后台选择器中让可选Article页面按自定义规则排序
默认的PageChooserBlock是按页面ID排序的,看起来随机。要改这个,你可以自定义一个PageChooserBlock子类,重写它的queryset来指定排序规则:
from wagtail.blocks import PageChooserBlock from articles.models import Article class SortedArticleChooserBlock(PageChooserBlock): def get_queryset(self, request): # 这里按发布日期倒序排序,你可以换成title、创建时间等字段 return Article.objects.all().order_by('-first_published_at') # 然后在StreamField里使用这个自定义块 class ActualSection(models.Model): content = StreamField( [ ("article", SortedArticleChooserBlock(page_type="articles.Article")), ], min_num=1, )
这样后台选择器里的Article列表就会按你指定的规则排序,方便用户选择。
二、前端渲染已选Article时按自定义规则排序
如果是已经选好的Article在前端展示时需要重新排序(不管用户添加的顺序),可以在模板里对StreamField的条目进行排序处理:
比如在模板中:
{% for block in page.content %} {% if block.block_type == 'article' %} {% with article=block.value %} {# 先把所有文章收集到列表里 #} {% if not articles_list %} {% set articles_list = [] %} {% endif %} {% set articles_list = articles_list|concat:article %} {% endwith %} {% endif %} {% endfor %} {# 对列表按发布日期倒序排序,再遍历输出 #} {% for article in articles_list|dictsortreversed:"first_published_at" %} <div class="article-item"> <h3><a href="{{ article.url }}">{{ article.title }}</a></h3> <p>{{ article.first_published_at|date:"Y-m-d" }}</p> </div> {% endfor %}
如果用的是Django的模板,需要确保concat和set这些过滤器可用(Wagtail默认模板环境通常已支持),或者你也可以在视图层先处理好排序逻辑,再将有序列表传给模板渲染。
另外补充:StreamField本身支持拖拽排序——在后台编辑页面时,每个条目左侧有拖拽手柄,直接拖动就能调整已选Article的顺序,前端渲染时会按这个手动调整的顺序输出。
内容的提问来源于stack exchange,提问作者Headmaster
相关产品推荐
相关产品推荐

