You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django CMS邮件发送联系表单插件功能失效求助

解决Django CMS插件中联系表单无法触发视图逻辑的问题

核心原因

Django CMS页面由自身视图处理,嵌入的插件表单默认提交到CMS页面URL,而非你自定义的utilities/views.py处理视图,导致表单逻辑不执行。

解决方案

1. 为表单指定正确的提交目标

确保表单的action属性指向你的表单处理视图URL:

  • 在项目主urls.py中添加表单处理路由:
    path('contact/submit/', utilities.views.contact_form_submit, name='contact_form_submit')
    
  • 在插件的表单模板中,设置action为该URL:
    <form method="post" action="{% url 'contact_form_submit' %}">
        {% csrf_token %}
        <!-- 表单字段 -->
        <button type="submit">提交</button>
    </form>
    

2. 改用AJAX无刷新提交(推荐)

CMS页面刷新会丢失插件状态,AJAX既能触发视图逻辑,又能保留Bootstrap提示效果:

  • 修改视图返回JSON响应:
    from django.http import JsonResponse
    from .forms import ContactForm
    
    def contact_form_submit(request):
        if request.method != 'POST':
            return JsonResponse({'status': 'error', 'message': '无效请求'}, status=400)
        
        form = ContactForm(request.POST)
        if form.is_valid():
            # 执行邮件发送逻辑
            form.send_email()
            return JsonResponse({'status': 'success', 'message': '邮件发送成功!'})
        
        # 返回表单错误
        errors = {field: messages[0] for field, messages in form.errors.items()}
        return JsonResponse({'status': 'error', 'errors': errors}, status=400)
    
  • 添加前端JS处理提交(原生JS,兼容Bootstrap 5):
    document.addEventListener('DOMContentLoaded', function() {
        const contactForm = document.getElementById('contact-form');
        if (!contactForm) return;
    
        contactForm.addEventListener('submit', function(e) {
            e.preventDefault();
            const formData = new FormData(this);
            const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
    
            fetch(this.action, {
                method: 'POST',
                headers: {
                    'X-CSRFToken': csrfToken,
                    'Accept': 'application/json'
                },
                body: formData
            })
            .then(res => res.json())
            .then(data => {
                // 移除已有提示
                const existingAlert = contactForm.parentNode.querySelector('.alert');
                if (existingAlert) existingAlert.remove();
    
                // 创建新提示
                const alert = document.createElement('div');
                alert.className = data.status === 'success' 
                    ? 'alert alert-success alert-dismissible fade show' 
                    : 'alert alert-danger alert-dismissible fade show';
                
                let alertContent = '';
                if (data.status === 'success') {
                    alertContent = data.message;
                    contactForm.reset();
                } else {
                    alertContent = Object.values(data.errors).join('<br>');
                }
                alert.innerHTML = `${alertContent}<button type="button" class="btn-close" data-bs-dismiss="alert"></button>`;
                
                contactForm.parentNode.insertBefore(alert, contactForm);
                setTimeout(() => alert.remove(), 5000);
            })
            .catch(err => {
                console.error(err);
                const alert = document.createElement('div');
                alert.className = 'alert alert-danger alert-dismissible fade show';
                alert.innerHTML = '提交失败,请稍后重试<button type="button" class="btn-close" data-bs-dismiss="alert"></button>';
                contactForm.parentNode.insertBefore(alert, contactForm);
                setTimeout(() => alert.remove(), 5000);
            });
        });
    });
    
  • 给表单添加id属性:
    <form id="contact-form" method="post" action="{% url 'contact_form_submit' %}">
        {% csrf_token %}
        <!-- 表单字段 -->
    </form>
    

3. 排除CMS缓存影响

如果CMS页面启用了缓存,需确保表单插件不被缓存:

  • 在CMS插件类中添加cache = False:
    from cms.plugin_base import CMSPluginBase
    from cms.plugin_pool import plugin_pool
    from .models import ContactFormPlugin
    
    @plugin_pool.register_plugin
    class ContactFormPlugin(CMSPluginBase):
        model = ContactFormPlugin
        name = "联系表单"
        render_template = "utilities/contact_form_plugin.html"
        cache = False  # 禁用插件缓存
    

4. 验证CSRF令牌配置

确保表单中包含{% csrf_token %},AJAX请求头正确携带CSRF令牌(上述JS已处理),同时确认项目settings.py中CSRF_COOKIE_SECURE等配置符合当前环境。


内容的提问来源于stack exchange,提问作者Simon Powell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 20:55:36