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 !! </strong> {{message}} <button type="button" class="close" data-bs-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</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"), ]
问题分析与修复方案
核心问题
- 错误调用HTTP请求方法:代码中使用
request.post()调用Google reCAPTCHA验证接口,这里的request是Django的HttpRequest对象,并没有post方法,正确的做法是使用requests库发送POST请求。 - 验证逻辑顺序错误:当前代码先保存表单数据,再验证reCAPTCHA,会导致即使验证不通过,数据也已经存入数据库。
- render函数参数错误:最后一行
return render(request, 'contact-us.html',context, verify)多传入了verify参数,render函数的第三个参数是上下文字典,第四个参数是内容类型,多余参数会引发异常。 - 缺少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)
额外注意事项
- 确保已经安装
requests库:执行pip install requests完成安装。 - 替换代码中的
'secret key of mine'为你的Google reCAPTCHA密钥。 - 前端的reCAPTCHA站点密钥
data-sitekey="my site key"也需要替换为正确的密钥。
内容的提问来源于stack exchange,提问作者Estieque Alam
相关产品推荐
相关产品推荐

