Sure! 首先我们需要了解 Django 如何生成验证码。 Django 提供了 django.contrib.auth.models
中的函数 make_password()
和 check_password()
来加密和验证密码,但是 Django 没有提供直接生成验证码的函数。为此,我们需要借助第三方库 Pillow
和 Captcha
。
以下是 Python 中 Django 验证码功能的实现代码的完整攻略:
1. 安装必要的依赖
Pillow
: 用于生成图片和处理图片captcha
: 用于生成验证码
可以通过以下命令安装:
$ pip install Pillow captcha
2. 在 Django 项目中集成验证码
2.1 创建一个名为 captcha 应用
在 Django 项目中创建一个名为 captcha
的应用。
$ python manage.py startapp captcha
2.2 在 captcha
应用中创建 utils.py
模块
在 captcha
应用中创建一个名为 utils.py
的模块,并添加以下代码:
from io import BytesIO
from random import randint
from captcha.image import ImageCaptcha
def generate_code():
"""
生成随机验证码并返回
"""
code = ''
for _ in range(4):
code += str(randint(0, 9))
return code
def generate_captcha_image(code):
"""
生成验证码图片并返回二进制数据
"""
image = ImageCaptcha(width=120, height=40)
data = BytesIO()
image.write(code, data)
return data.getvalue()
2.3 在 captcha
应用中创建 views.py
模块
在 captcha
应用中创建一个名为 views.py
的模块,并添加以下代码:
from django.http import HttpResponse
from .utils import generate_code, generate_captcha_image
def generate_captcha(request):
"""
生成验证码并返回二进制图片数据
"""
code = generate_code()
image_data = generate_captcha_image(code)
response = HttpResponse(image_data, content_type='image/png')
response['Content-Disposition'] = 'inline; filename=captcha.png'
request.session['captcha'] = code
return response
2.4 在 urls.py
中添加 captcha 的 URL
在项目的 urls.py
文件中添加以下 URL:
from django.urls import path
from captcha.views import generate_captcha
urlpatterns = [
path('captcha/', generate_captcha, name='captcha'),
]
3. 在模板中显示验证码图片
在需要显示验证码的模板中添加以下代码:
<img src="{% url 'captcha' %}" alt="captcha">
<input type="text" name="captcha">
其中 url
标签会根据 URL 的 name 属性解析成正确的 URL,即 '/captcha/'
。
当用户提交表单时,你可以使用以下代码验证输入的验证码是否正确:
input_captcha = request.POST['captcha']
if input_captcha.lower() != request.session.get('captcha', '').lower():
# 验证码不匹配
这里使用了 request.session.get()
来获取保存在 session 中的验证码,同时使用 lower()
将验证码转换为小写,以避免对大小写的敏感问题。
示例
示例 1:使用 Django 内置的 Form 和 Model 完成登录表单
假设我们有一个名为 user
的应用,我们的目标是实现一个登录表单页面,其中包含一个验证码字段,你可以按照以下步骤完成:
- 首先,在
user/forms.py
文件中创建一个名为AuthenticationForm
的 Form:
“`python
from django import forms
from django.contrib.auth import authenticate
class AuthenticationForm(forms.Form):
username = forms.CharField(label=’用户名’)
password = forms.CharField(label=’密码’, widget=forms.PasswordInput)
captcha = forms.CharField(label=’验证码’)
def clean(self):
cleaned_data = super().clean()
username = cleaned_data.get('username')
password = cleaned_data.get('password')
captcha = cleaned_data.get('captcha')
user = authenticate(username=username, password=password)
if user is None:
raise forms.ValidationError('用户名或密码错误')
if captcha.lower() != self.request.session.get('captcha', '').lower():
raise forms.ValidationError('验证码错误')
return cleaned_data
“`
这里我们使用 Django 内置的 Form
类作为基类,并添加了三个字段:用户名、密码以及验证码。在 clean()
方法中,我们验证了用户名和密码,并使用 self.request.session.get()
方法获取了保存在 session 中的验证码。最后,我们检验了验证码是否正确,如果验证码不正确,就会抛出一个 ValidationError
异常。
- 接下来,在
user/views.py
文件中创建一个名为LoginView
的 View:
“`python
from django.contrib.auth.views import LoginView as BaseLoginView
from user.forms import AuthenticationForm
class LoginView(BaseLoginView):
form_class = AuthenticationForm
template_name = ‘user/login.html’
success_url = ‘/’
“`
这里我们使用了 Django 内置的 LoginView
类作为基类,并指定了 form_class
为我们刚刚创建的 AuthenticationForm
Form。
- 在模板文件
user/login.html
中添加验证码部分的 HTML 代码:
“`html
“`
在这个表单中,我们使用了 Django 内置的 {{ form.as_p }}
标签来将 Form 渲染成一个 HTML 表单,并添加了一个名为 captcha
的文本框以及一个显示验证码图片的 <img>
标签。
- 最后,在
urls.py
文件中添加 URL 并指定 View:
“`python
from django.urls import path
from user.views import LoginView
urlpatterns = [
path(‘login/’, LoginView.as_view(), name=’login’),
]
“`
现在,你的登录表单页面已经完成啦!你可以通过访问 http://localhost:8000/login/
来测试。
示例 2:使用 Django REST framework 完成验证 API
假设你正在使用 Django REST framework 来创建一个 API,你想为这个 API 添加一个名为 /user/authenticate/
的 URL,用于验证用户名、密码以及验证码是否正确。你可以按照以下步骤完成:
- 首先,在项目的
settings.py
文件中添加以下配置:
“`python
INSTALLED_APPS = [
# …
‘rest_framework’,
‘rest_framework.authtoken’,
‘captcha’,
]
REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.TokenAuthentication’,
‘rest_framework.authentication.SessionAuthentication’,
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticated’,
],
}
“`
这里我们配置了 Django REST framework,使其支持 TokenAuthentication
和 SessionAuthentication
认证,并指定了默认的权限为 IsAuthenticated
。
- 接下来,在
user/views.py
文件中创建一个名为AuthenticationAPIView
的 View:
“`python
from rest_framework import status
from rest_framework.authentication import TokenAuthentication, SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from captcha.utils import generate_code
class AuthenticationAPIView(APIView):
authentication_classes = [TokenAuthentication, SessionAuthentication]
permission_classes = [IsAuthenticated]
def post(self, request):
username = request.POST.get('username')
password = request.POST.get('password')
captcha = request.POST.get('captcha')
user = authenticate(username=username, password=password)
if user is None:
return Response(data={'detail': '用户名或密码错误'}, status=status.HTTP_400_BAD_REQUEST)
if captcha.lower() != request.session.get('captcha', '').lower():
return Response(data={'detail': '验证码错误'}, status=status.HTTP_400_BAD_REQUEST)
# 生成新的验证码
request.session['captcha'] = generate_code()
return Response(data={'detail': '认证成功'})
“`
在这里我们创建了一个名为 AuthenticationAPIView
的 View,并继承了 Django REST framework 的 APIView
类。在这个 API 中,我们接收了三个参数:username
、password
和 captcha
,并分别进行了验证。如果这些信息验证不通过,我们就会返回一个 HTTP 400 BAD REQUEST
响应,表示请求无效。否则,我们将会生成一个新的验证码,并返回一个成功的响应。
- 在
urls.py
文件中添加 URL 并指定 View:
“`python
from django.urls import path
from user.views import AuthenticationAPIView
urlpatterns = [
path(‘user/authenticate/’, AuthenticationAPIView.as_view(), name=’user_authenticate’),
]
“`
现在,你的验证 API 已经完成啦!你可以通过发送一个 POST 请求到 URL /user/authenticate/
来测试。