Wagtail多语言站点中ModelAdmin城市页面分站点管理方案问询
实现Wagtail多语言站点下的City页面独立管理
我来帮你一步步实现这个需求,结合Wagtail的ModelAdmin和多语言站点特性,让你能通过独立菜单先选站点再管理对应语言的城市页面:
1. 先搞定ModelAdmin的基础配置
首先得确保你的项目里装了wagtail-modeladmin这个包——毕竟ModelAdmin功能是它提供的,如果还没装,先跑这个命令:
pip install wagtail-modeladmin
然后在项目的settings.py里把它加到INSTALLED_APPS中:
INSTALLED_APPS = [ # ... 你已有的其他应用 'wagtail_modeladmin', ]
2. 创建自定义的PageModelAdmin类
因为你的City是Page的子类,我们得用PageModelAdmin来适配页面模型的管理,同时加上多语言站点的过滤逻辑。在你的app目录下新建或修改admin.py:
from wagtail_modeladmin.options import PageModelAdmin, modeladmin_register from wagtail_modeladmin.views import IndexView from django.shortcuts import redirect from django.urls import reverse from .models import City # 注意这里别和cities.models的City重名,必要时调整导入路径 from wagtail.core.models import Site from django.views.generic import TemplateView # 自定义索引视图:先让用户选站点,再显示对应站点的City页面 class CityIndexView(IndexView): def dispatch(self, request, *args, **kwargs): # 如果没传site_id参数,直接跳转到站点选择页 if 'site_id' not in request.GET: return redirect(reverse('city-site-select')) return super().dispatch(request, *args, **kwargs) def get_queryset(self, request): # 根据选中的站点过滤City页面 site_id = request.GET.get('site_id') qs = super().get_queryset(request) if site_id: # Page模型本身有site字段,直接关联过滤 qs = qs.filter(site_id=site_id) return qs # 自定义站点选择页面的视图 class CitySiteSelectView(TemplateView): template_name = 'city_site_select.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 把所有多语言站点传给模板 context['sites'] = Site.objects.all() return context # 定义City页面的ModelAdmin配置 class CityPageModelAdmin(PageModelAdmin): model = City menu_label = 'Cities' # 后台菜单显示的名称 menu_icon = 'site' # 用Wagtail内置的站点图标,也可以换其他的 menu_order = 200 # 调整菜单在左侧的位置,数字越小越靠前 index_view_class = CityIndexView # 用上我们自定义的索引视图 list_display = ('title', 'cityobject', 'site') # 列表页显示的字段 search_fields = ('title', 'cityobject__name') # 支持搜索的字段 # 注册这个ModelAdmin modeladmin_register(CityPageModelAdmin)
3. 添加站点选择的模板和URL
先在你的app的templates目录下创建city_site_select.html模板:
{% extends "wagtailadmin/base.html" %} {% load wagtailadmin_tags %} {% block content %} {% trans "Select a Site to manage Cities" as title_str %} {% include "wagtailadmin/shared/header.html" with title=title_str %} <div class="nice-padding"> <ul class="listing"> {% for site in sites %} <li class="row row-flush"> <a href="{% url 'city-modeladmin-index' %}?site_id={{ site.id }}" class="col6"> <h3>{{ site.name }} ({{ site.hostname }})</h3> </a> </li> {% endfor %} </ul> </div> {% endblock %}
这里的city-modeladmin-index是ModelAdmin自动生成的URL名称,格式是[你的app名]-[模型名小写]-index,如果不确定可以用reverse_lazy调试一下,或者自定义URL名称。
然后在项目的urls.py中添加站点选择的URL:
from django.urls import path from .admin import CitySiteSelectView # 对应你刚才写的视图 urlpatterns = [ # ... 你已有的其他URL配置 path('admin/cities/select-site/', CitySiteSelectView.as_view(), name='city-site-select'), ]
4. 优化页面创建的站点关联逻辑
为了让用户创建新City页面时,自动关联到之前选中的站点,我们可以给City模型加个自定义表单:
# 回到你的models.py文件 from wagtail.admin.forms import WagtailAdminPageForm # 自定义City页面的表单 class CityPageForm(WagtailAdminPageForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 从session里取之前选中的site_id,默认设置到表单里 site_id = self.request.session.get('selected_city_site_id') if site_id and 'site' in self.fields: self.fields['site'].initial = site_id # 修改你的City模型,关联这个表单 class City(Page): cityobject = models.ForeignKey(City, on_delete=models.SET_NULL, null=True, blank=True) streamfield = StreamField(BasicStreamBlock, null=True, blank=True) base_form_class = CityPageForm # 加上这行 content_panels = Page.content_panels + [ FieldPanel('cityobject', classname="full"), StreamFieldPanel('streamfield'), ]
同时,还要在ModelAdmin里把选中的site_id存到session中,修改CityPageModelAdmin:
class CityPageModelAdmin(PageModelAdmin): # ... 之前的配置 def create_view(self, request, form_url='', *args, **kwargs): # 把选中的site_id存到session里,方便表单调用 site_id = request.GET.get('site_id') if site_id: request.session['selected_city_site_id'] = site_id return super().create_view(request, form_url, *args, **kwargs)
5. 验证效果
现在登录Wagtail后台,左侧菜单会出现「Cities」按钮:
- 点击后会跳转到站点选择页面,显示你配置的所有多语言站点(比如EN、DE)
- 选择某个站点后,就会进入该站点专属的City页面列表,支持增、改、删操作
- 创建新页面时,站点字段会自动填充为你之前选中的站点,确保页面属于正确的语言站点
这样就完美实现了你想要的功能啦!
内容的提问来源于stack exchange,提问作者Philipp S.
相关产品推荐
相关产品推荐

