Wagtail多站点Django表单关联子站点专属训练日期需求问询
嘿,我来帮你搞定Wagtail多站点表单显示专属训练日期的需求!以下是一步步的实操方案:
Wagtail多站点表单添加子站点专属训练日期解决方案
1. 先构建专属训练日期模型
首先我们需要一个模型来存储不同群体的训练日期,并且和Wagtail站点关联起来,方便后续匹配:
# models.py from django.db import models from wagtail.models import Site class TrainingDate(models.Model): # 对应三个子站点的目标群体 GROUP_CHOICES = ( ('child', '儿童训练'), ('teen', '青少年训练'), ('adult', '成人训练'), ) group = models.CharField(max_length=10, choices=GROUP_CHOICES, unique=True) # 存储未来三个训练日期 date_1 = models.DateTimeField(verbose_name="训练日期1") date_2 = models.DateTimeField(verbose_name="训练日期2") date_3 = models.DateTimeField(verbose_name="训练日期3") # 可选:直接绑定到对应Wagtail站点,更精准匹配 site = models.ForeignKey(Site, on_delete=models.CASCADE, null=True, blank=True) def __str__(self): return f"{self.get_group_display()} 训练日程"
你可以在Django后台直接给每个群体录入对应的未来训练日期,也可以绑定到具体的子站点。
2. 在表单中动态匹配当前子站点的日期
接下来要让表单能识别当前访问的子站点,自动拉取对应群体的训练日期。假设你的表单是普通Django Form:
# forms.py from django import forms from .models import TrainingDate from wagtail.models import Site class TrainingSignupForm(forms.Form): # 你的基础表单字段 name = forms.CharField(label="姓名") contact = forms.CharField(label="联系方式") def __init__(self, *args, **kwargs): # 从参数中取出当前站点对象 self.current_site = kwargs.pop('site', None) super().__init__(*args, **kwargs) # 根据站点匹配对应训练日期 if self.current_site: # 这里可以通过站点域名/名称来匹配群体,比如子站点域名为child.yourdomain.com site_prefix = self.current_site.hostname.split('.')[0] if site_prefix in ['child', 'teen', 'adult']: try: training_data = TrainingDate.objects.get(group=site_prefix) # 把日期转为友好格式,添加为只读字段展示给用户 date_text = ( f"1. {training_data.date_1.strftime('%Y-%m-%d %H:%M')}\n" f"2. {training_data.date_2.strftime('%Y-%m-%d %H:%M')}\n" f"3. {training_data.date_3.strftime('%Y-%m-%d %H:%M')}" ) self.fields['available_dates'] = forms.CharField( label="可选训练日期", initial=date_text, widget=forms.Textarea(attrs={'readonly': 'readonly', 'rows':3}) ) except TrainingDate.DoesNotExist: # 没有找到对应日期时的提示 self.fields['available_dates'] = forms.CharField( label="训练日期", initial="当前暂无可用训练日期,请稍后再试", widget=forms.Textarea(attrs={'readonly': 'readonly'}) )
3. 模板中渲染表单时传递站点信息
在子站点的页脚模板里渲染表单时,要把当前请求的站点对象传给表单:
<!-- templates/includes/footer_form.html --> {% load wagtailcore_tags %} <form method="post" class="footer-form"> {% csrf_token %} {% with form=TrainingSignupForm(site=request.site) %} {{ form.as_p }} {% endwith %} <button type="submit" class="btn-submit">提交报名</button> </form>
如果是通过视图处理表单提交,记得在实例化表单时传入site=request.site:
# views.py from django.shortcuts import render from .forms import TrainingSignupForm def handle_footer_form(request): if request.method == 'POST': form = TrainingSignupForm(request.POST, site=request.site) if form.is_valid(): # 处理表单提交逻辑,比如保存数据、发送通知邮件等 # 可通过form.cleaned_data获取字段值 pass else: form = TrainingSignupForm(site=request.site) return render(request, 'includes/footer_form.html', {'form': form})
4. 进阶:用Wagtail Snippets管理日期
如果想在Wagtail后台更友好地管理训练日期,可以把TrainingDate注册为Snippet:
# wagtail_hooks.py from wagtail.snippets.models import register_snippet from .models import TrainingDate register_snippet(TrainingDate)
这样就能在Wagtail后台的「Snippets」菜单里直接编辑各个群体的训练日期,不用跳转到Django原生后台。
小提示
- 可以根据子站点的
site_name来匹配群体,比如站点名称是「儿童训练站点」,直接匹配group='child',比域名匹配更灵活; - 如果训练日期是固定周期(比如每周六),可以在模型里写逻辑自动生成未来三个日期,不用手动录入;
- 若不需要用户看到日期,可把日期设为隐藏字段,仅在后台处理提交数据时使用。
内容的提问来源于stack exchange,提问作者Ronnie Stevens
相关产品推荐
相关产品推荐

