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

Django集成Google reCAPTCHA表单提交后跳转404问题解决

Django联系表单提交后跳404问题排查与解决

我使用Django构建了一个包含两个表单的联系页面。当提交带有Google reCAPTCHA验证的联系表单时,表单数据已成功提交到后端/admin面板,但页面会跳转到404页面,需要解决该问题。

相关代码

contact.html代码

{% block contactpage %}

    <!--====== PAGE TITLE  PART START ======-->
    {% for cslider in cslider %}
    <div class="page-title-area">
        <div class="section__bg" style="background-image: url('{{cslider.slider_image.url}}');"></div>
        <div class="container">
            <div class="row">
                <div class="col-lg-12">
                    <div class="page-title-content text-center">
                        <h3 class="title">Contact</h3>
                        <nav aria-label="breadcrumb">
                            <ol class="breadcrumb">
                                <li class="breadcrumb-item"><a href="#">Accueil</a></li>
                                <li class="breadcrumb-item active" aria-current="page">Contact</li>
                            </ol>
                        </nav>
                    </div>
                </div>
            </div>
        </div>
    </div>
    {% endfor %}
    <!--====== PAGE TITLE  PART ENDS ======-->

    <!--====== CONTACT US PART START ======-->
    
    <section class="contact-us-area contact-us-page">
        <div class="section__bg" style="background-image: url('{% static 'images/black-elegant-background-with-copy-space.jpg' %}');"></div>
        <div class="container">
            <!--Hidden Message Alert Area-->
                <div class="container">
                    {% for message in messages %}
                    <div class="alert alert-primary alert-dismissible fade show" role="alert">
                        <svg xmlns="http://www.w3.org/2000/svg" class="bi bi-exclamation-triangle-fill flex-shrink-0 me-2" viewBox="0 0 16 16" role="img" aria-label="Warning:">
                            <path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>
                        </svg>
                        <strong>Félicitations !! &nbsp;</strong> {{message}}
                        <button type="button" class="close" data-bs-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                    </div>
                    </div>
                    {% endfor %}
                </div>
            <div class="row justify-content-center">
                <div class="col-lg-10">
                    <div class="contact-us-box">
                        <h3 class="title">PRENDRE CONTACT</h3>
                        <p>Contactez-nous pour discuter de vos besoins.<br>
                            N'hésitez pas à nous appeler ou à nous envoyer un message.</p>
                        <form method="POST" action="{% url 'contact' %}">
                            {% csrf_token %}
                            <div class="row no-gutters">
                                <div class="col-lg-6">
                                    <div class="input-box mt-10">
                                        <input type="text" name="name" placeholder="Votre nom" required>
                                    </div>
                                </div>
                                <div class="col-lg-6">
                                    <div class="input-box mt-10">
                                        <input type="email" name="email" placeholder="Adresse e-mail" required>
                                    </div>
                                </div>
                                <div class="col-lg-6">
                                    <div class="input-box mt-10">
                                        <input type="text" name="number" placeholder="Téléphone" required>
                                    </div>
                                </div>
                                <div class="col-lg-6">
                                    <div class="input-box mt-10">
                                        <input type="text" name="location" placeholder="Localisation" required>
                                    </div>
                                </div>
                                <div class="col-lg-12">
                                    <div class="input-box mt-10">
                                        <textarea name="message" id="#" cols="30" rows="10" placeholder="écrire un message" required></textarea>
                                    </div>
                                    <div class="g-recaptcha" data-sitekey="my site key"></div>
                                    <div class="input-box">
                                        <button class="main-btn " type="submit" name="formone">Soumettre</button>
                                    </div>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </section>
    
    <!--====== CONTACT US PART ENDS ======-->

    <!--====== SUBSCRIBE PART START ======-->
    
    <div class="subscribe-area subscribe-9-area subscribe-13-area">
        <div class="container">
            <div class="row align-items-center">
                <div class="col-lg-6">
                    <div class="subscribe-item">
                        <h3 class="title">Vous souhaitez améliorer votre communication digitale ?</h3>
                        <span>Inscrivez-vous pour recevoir toutes les astuces et les ressources utiles</span>
                    </div>
                </div>
                <div class="col-lg-6">
                    <form role="form" action="{% url 'contact' %}" method="post">
                        {% csrf_token %}
                    <div class="subscribe-form subscribe-9-form subscribe-13-form">
                        <input type="email" name="emails" placeholder="Votre Email" required>
                        <button type="submit" class="main-btn" name="formtwo">Inscription</button>
                    </div>
                </form>
                </div>
            </div>
        </div>
    </div>
    
    <!--====== SUBSCRIBE PART ENDS ======-->
    {% endblock contactpage %}

views.py代码

import json
from django.shortcuts import redirect, render
from contact.models import ContactMessage, ContactSeoSnippets, ContactSlider
from django.contrib import messages
from emaillist.models import EmailSubs
from homepage.models import SiteSetting

# Create your views here.
def contact(request):
    settings = SiteSetting.objects.all()
    cslider = ContactSlider.objects.all().order_by('-id')[:1]
    c_seo = ContactSeoSnippets.objects.all().order_by('-s_id')[:1]
    context={'settings':settings, 
             'cslider':cslider,  
             'c_seo':c_seo, }
    if request.method == "GET":
        return render(request, 'contact-us.html',context)
    elif request.method=="POST":
        if 'formone' in request.POST:
            name=request.POST.get('name')
            email=request.POST.get('email')
            number=request.POST.get('number')
            location=request.POST.get('location')
            message=request.POST.get('message')
            en=ContactMessage(name=name,email=email,message=message,number=number,location=location)
            en.save()
            messages.success(request, 'Votre message a été envoyé avec succès')
            
            clientkey = request.POST['g-recaptcha-response']
            secretkey = 'secret key of mine'
            captchaData = {
                'secret': secretkey,
                'response': clientkey
            }
            r= request.post('https://www.google.com/recaptcha/api/siteverify', data=captchaData)
            response = json.loads(r)
            verify = response
            return redirect('contact') 
        if 'formtwo' in request.POST:
            emails=request.POST.get('emails')
            email=EmailSubs(emails=emails)
            email.save()
            messages.success(request, 'Merci de nous abonner')
        return render(request, 'contact-us.html',context, verify)

urls.py代码

from django.contrib import admin
from django.urls import path
from . import views

urlpatterns = [
    path('', views.contact, name="contact"),
]

问题分析与修复方案

核心问题

  1. 错误调用HTTP请求方法:代码中使用request.post()调用Google reCAPTCHA验证接口,这里的request是Django的HttpRequest对象,并没有post方法,正确的做法是使用requests库发送POST请求。
  2. 验证逻辑顺序错误:当前代码先保存表单数据,再验证reCAPTCHA,会导致即使验证不通过,数据也已经存入数据库。
  3. render函数参数错误:最后一行return render(request, 'contact-us.html',context, verify)多传入了verify参数,render函数的第三个参数是上下文字典,第四个参数是内容类型,多余参数会引发异常。
  4. 缺少reCAPTCHA验证失败的处理:没有判断验证是否通过,也没有对应的错误提示。

修复后的views.py代码

import json
import requests  # 导入requests库
from django.shortcuts import redirect, render
from contact.models import ContactMessage, ContactSeoSnippets, ContactSlider
from django.contrib import messages
from emaillist.models import EmailSubs
from homepage.models import SiteSetting

def contact(request):
    settings = SiteSetting.objects.all()
    cslider = ContactSlider.objects.all().order_by('-id')[:1]
    c_seo = ContactSeoSnippets.objects.all().order_by('-s_id')[:1]
    context={'settings':settings, 
             'cslider':cslider,  
             'c_seo':c_seo, }
    
    if request.method == "GET":
        return render(request, 'contact-us.html', context)
    
    elif request.method == "POST":
        if 'formone' in request.POST:
            # 先获取reCAPTCHA验证数据
            clientkey = request.POST.get('g-recaptcha-response')
            secretkey = 'secret key of mine'
            captcha_data = {
                'secret': secretkey,
                'response': clientkey
            }
            
            # 发送验证请求到Google
            try:
                response = requests.post('https://www.google.com/recaptcha/api/siteverify', data=captcha_data)
                response_data = json.loads(response.text)
                
                # 检查验证是否通过
                if not response_data.get('success'):
                    messages.error(request, 'reCAPTCHA验证失败,请重试')
                    return render(request, 'contact-us.html', context)
                
                # 验证通过后再保存表单数据
                name = request.POST.get('name')
                email = request.POST.get('email')
                number = request.POST.get('number')
                location = request.POST.get('location')
                message_text = request.POST.get('message')
                
                ContactMessage.objects.create(
                    name=name,
                    email=email,
                    message=message_text,
                    number=number,
                    location=location
                )
                messages.success(request, 'Votre message a été envoyé avec succès')
                return redirect('contact')
                
            except Exception as e:
                messages.error(request, '验证请求出错,请稍后重试')
                return render(request, 'contact-us.html', context)
        
        if 'formtwo' in request.POST:
            emails = request.POST.get('emails')
            EmailSubs.objects.create(emails=emails)
            messages.success(request, 'Merci de nous abonner')
            return redirect('contact')
        
        # 默认返回页面,避免参数错误
        return render(request, 'contact-us.html', context)

额外注意事项

  1. 确保已经安装requests库:执行pip install requests完成安装。
  2. 替换代码中的'secret key of mine'为你的Google reCAPTCHA密钥。
  3. 前端的reCAPTCHA站点密钥data-sitekey="my site key"也需要替换为正确的密钥。

内容的提问来源于stack exchange,提问作者Estieque Alam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 02:27:01