Wagtail ModelAdmin中Queryset过滤失效问题排查
解决Wagtail多语言资源菜单过滤失效的问题
你猜的没错!问题确实和Django的默认管理器机制有关。Wagtail的ModelAdmin默认会使用模型定义的第一个管理器,这就导致你重写的get_queryset方法没有被正确触发,所有菜单都默认加载了未过滤的完整数据集(而你看到全是英文,大概率是数据库里英文资源最多或者你测试时只注意到它)。下面给你两种可靠的解决方案:
方案一:为每种语言创建自定义管理器(推荐)
这种方式更符合Django/Wagtail的设计规范,也更稳定:
- 修改Resource模型,添加多语言管理器
# Models.py from django.db import models # 为每种语言定义专属管理器 class EnResourceManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(language='en') class FrResourceManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(language='fr') class BeFrResourceManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(language='be-fr') class BeNlResourceManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(language='be-nl') class Resource(models.Model): language = models.CharField(max_length=255, choices=constants.LANGUAGES) title = models.CharField(blank=True, max_length=255) resource_type = models.CharField( choices=constants.RESOURCE_TYPES, max_length=255 ) description = models.TextField() link = StreamField( blocks.BasicLinkBlock(max_num=1), blank=True, ) panels = [ FieldPanel('language'), FieldPanel('title'), FieldPanel('resource_type'), FieldPanel('description'), StreamFieldPanel('link'), ] # 默认管理器必须放在第一位,保证其他功能正常运行 objects = models.Manager() # 绑定各语言的专属管理器 en_objects = EnResourceManager() fr_objects = FrResourceManager() be_fr_objects = BeFrResourceManager() be_nl_objects = BeNlResourceManager()
- 修改ModelAdmin子类,指定使用对应管理器
# WagtailHooks.py class EnResourceAdmin(ResourceAdmin): menu_label = 'English Resources' # 指定使用英文资源管理器 manager_name = 'en_objects' class FrResourceAdmin(ResourceAdmin): menu_label = 'French Resources' manager_name = 'fr_objects' class BeResourceAdmin(ResourceAdmin): menu_label = 'Belgium Resources' manager_name = 'be_fr_objects' class NlResourceAdmin(ResourceAdmin): menu_label = 'Nederlands Resources' manager_name = 'be_nl_objects'
方案二:修复get_queryset方法的实现
如果你不想添加自定义管理器,可以直接修改get_queryset的逻辑,绕开父类的可能干扰:
# WagtailHooks.py class EnResourceAdmin(ResourceAdmin): menu_label = 'English Resources' def get_queryset(self, request): # 直接从模型默认管理器获取数据集,再做过滤 qs = self.model.objects.all() # 保留排序逻辑(和父类行为一致) ordering = self.get_ordering(request) if ordering: qs = qs.order_by(*ordering) return qs.filter(language='en') # 其他语言的ModelAdmin子类同理修改get_queryset方法
额外小修复
注意到你的ResourceAdmin里search_fields包含了business_email,但你的Resource模型并没有这个字段,这会导致后台搜索功能报错,建议修改为模型存在的字段:
class ResourceAdmin(ModelAdmin): # ... 其他配置 ... search_fields = ( 'title', 'description', # 替换成实际存在的字段 )
内容的提问来源于stack exchange,提问作者JaredOzzy
相关产品推荐
相关产品推荐

