Wagtail中如何在ServicePage上通过TariffPagePrices属性筛选ServiceCategoryPage?
问题描述
现有页面层级结构:ServiceCategoryPage → ServicePage → TariffPage,同时存在如下模型代码:
TariffPagePrices(Orderable): page = ParentalKey(TariffPage, on_delete=models.CASCADE, related_name='tariff_prices') # 示例筛选属性:比如价格、状态等 ....
需要在ServicePage页面中,根据TariffPagePrices的属性筛选ServiceCategoryPage的结果。
解决方案
要实现这个需求,你可以借助Django/Wagtail的ORM多层关联查询能力,通过反向关联链筛选目标分类页面,以下是具体实现方式:
1. 明确关联逻辑
页面与模型的关联链为:ServiceCategoryPage → 子页面ServicePage → 子页面TariffPage → 关联模型TariffPagePrices(通过tariff_prices反向关联)
2. 在ServicePage中编写筛选逻辑
假设你要筛选**旗下存在至少一个TariffPage关联的TariffPagePrices满足price < 100**的ServiceCategoryPage,可以在ServicePage模型中重写get_context方法:
from wagtail.models import Page from django.db.models import Exists, OuterRef class ServicePage(Page): # 你的页面字段定义... def get_context(self, request, *args, **kwargs): context = super().get_context(request, *args, **kwargs) # 子查询:匹配满足TariffPagePrices条件的TariffPage tariff_subquery = TariffPage.objects.filter( parent=OuterRef('pk'), tariff_prices__price__lt=100 # 替换为你的实际筛选条件 ) # 筛选包含符合条件ServicePage的ServiceCategoryPage filtered_categories = ServiceCategoryPage.objects.filter( service_pages__in=ServicePage.objects.filter(Exists(tariff_subquery)) ).distinct() context['filtered_categories'] = filtered_categories return context
3. 优化反向关联(可选)
如果页面模型没有默认的清晰反向关联名称,可以给页面添加ParentalKey并指定related_name,让查询更直观:
class ServicePage(Page): parent_page_types = ['your_app.ServiceCategoryPage'] subpage_types = ['your_app.TariffPage'] # 添加到分类页面的反向关联 category = ParentalKey('your_app.ServiceCategoryPage', on_delete=models.CASCADE, related_name='service_pages') class TariffPage(Page): parent_page_types = ['your_app.ServicePage'] subpage_types = [] # 添加到服务页面的反向关联 service = ParentalKey('your_app.ServicePage', on_delete=models.CASCADE, related_name='tariff_pages')
此时可以简化筛选代码,直接通过多层反向关联查询:
filtered_categories = ServiceCategoryPage.objects.filter( service_pages__tariff_pages__tariff_prices__price__lt=100 ).distinct()
注意:使用多层关联查询时必须加
.distinct(),避免返回重复的分类页面结果。
4. 模板中使用筛选结果
在ServicePage的模板里,直接遍历filtered_categories即可:
{% for category in filtered_categories %} <div class="category-item"> <h3><a href="{{ category.url }}">{{ category.title }}</a></h3> </div> {% endfor %}
内容的提问来源于stack exchange,提问作者IvanSCM
相关产品推荐
相关产品推荐

