Django:如何实现django-simple-captcha验证码单独刷新功能?
问题描述
我有一个包含多个字段和验证码的注册表单,刚接触django-simple-captcha,想做一个仅单独刷新验证码的按钮。请问这个需求可行吗?应该怎么编写对应的实现函数?以下是我当前的代码:
register.html
<div><input type="text" name="studentId"></div> <div><input type="text" name="Name"></div> ... <div>{{ form.captcha }}</div> <button type="button" class="btn">Refresh</button> <!-- 刷新验证码 --> <button type="submit" class="btn btn-primary">Submit</button>
forms.py
from captcha.fields import CaptchaField class MyForm(forms.Form): captcha = CaptchaField()
views.py
from .forms import MyForm def preRegistration(request): form = MyForm(request.POST) if request.method == 'GET': return render(request, 'registration_form.html', {"form": form}) if request.method == 'POST': studentId = request.POST.get('studentId') ... if form.is_valid(): Applicant.objects.create(studentID=studentID, ...) return render(request, 'login.html') else: messages.error(request, 'Wrong Captcha!') return render(request, 'registration.html', {"form": form}) def refreshCaptcha(): ...
解决方案
这个需求完全可行,通过后端生成新的验证码实例,前端用AJAX请求替换验证码图片和隐藏字段就能实现。具体步骤如下:
1. 修正原视图的初始化错误
你当前的preRegistration视图存在初始化问题:GET请求时不能用request.POST初始化表单,改成空表单即可:
from .forms import MyForm from django.contrib import messages def preRegistration(request): if request.method == 'GET': form = MyForm() # GET请求初始化空表单 return render(request, 'registration_form.html', {"form": form}) if request.method == 'POST': form = MyForm(request.POST) studentId = request.POST.get('studentId') # 处理其他字段逻辑... if form.is_valid(): Applicant.objects.create(studentID=studentId, ...) return render(request, 'login.html') else: messages.error(request, '验证码错误!') return render(request, 'registration.html', {"form": form})
2. 编写刷新验证码的后端视图
实现refreshCaptcha视图,生成新的验证码并返回其图片URL和密钥:
from django.http import JsonResponse from captcha.models import CaptchaStore from captcha.helpers import captcha_image_url def refreshCaptcha(request): # 生成新的验证码密钥 new_key = CaptchaStore.generate_key() # 获取对应验证码图片的URL image_url = captcha_image_url(new_key) # 返回JSON格式的结果 return JsonResponse({'key': new_key, 'image_url': image_url})
记得在项目的urls.py中添加该视图的路由:
from django.urls import path from . import views urlpatterns = [ path('pre-registration/', views.preRegistration, name='pre-registration'), path('refresh-captcha/', views.refreshCaptcha, name='refresh-captcha'), ]
3. 修改前端模板并添加JS逻辑
给刷新按钮和验证码容器添加标识,方便JS定位元素,然后编写点击刷新的逻辑:
<div><input type="text" name="studentId"></div> <div><input type="text" name="Name"></div> ... <div class="captcha-box">{{ form.captcha }}</div> <button type="button" class="btn" id="refresh-captcha">刷新验证码</button> <button type="submit" class="btn btn-primary">提交</button> <script> document.getElementById('refresh-captcha').addEventListener('click', function() { // 发送请求到刷新验证码的后端接口 fetch('{% url "refresh-captcha" %}') .then(res => res.json()) .then(data => { // 获取验证码图片和隐藏的密钥输入框 const captchaImg = document.querySelector('.captcha-box img'); const captchaKeyInput = document.querySelector('.captcha-box input[type="hidden"]'); // 更新图片地址和密钥值 captchaImg.src = data.image_url; captchaKeyInput.value = data.key; }) .catch(err => console.log('刷新失败:', err)); }); </script>
逻辑说明
- 后端通过
CaptchaStore.generate_key()生成新的验证码密钥,captcha_image_url()生成对应图片的访问地址 - 前端用
fetch发起异步请求,拿到新的密钥和图片地址后,替换原有验证码的图片和隐藏字段(这个隐藏字段是django-simple-captcha自动生成的,用于存储验证码密钥) - 整个过程不会刷新页面,也不会影响表单内其他字段的已填内容
内容的提问来源于stack exchange,提问作者nana
相关产品推荐
相关产品推荐

