125 lines
4.1 KiB
Python
125 lines
4.1 KiB
Python
|
"""
|
|||
|
用户登录视图
|
|||
|
"""
|
|||
|
from django.shortcuts import render, HttpResponse, redirect
|
|||
|
from django import forms
|
|||
|
from app import models
|
|||
|
from app.utils.bootstrap import BootstrapForm, BootstrapModelForm
|
|||
|
from app.utils.code import check_code # 验证码
|
|||
|
from app.utils.encrypt import md5
|
|||
|
from io import BytesIO # 用于在内存中生成文件,验证码用
|
|||
|
|
|||
|
"""
|
|||
|
两种实现方式
|
|||
|
1.LoginForm 是用Form实现,字段需要自己写
|
|||
|
2.LoginModelForm 是用ModelForm实现,字段可以从数据库(models)中获取
|
|||
|
"""
|
|||
|
|
|||
|
"""登录窗体"""
|
|||
|
|
|||
|
|
|||
|
class LoginForm(BootstrapForm):
|
|||
|
username = forms.CharField(
|
|||
|
label='用户名',
|
|||
|
widget=forms.TextInput,
|
|||
|
required=True, # 必填
|
|||
|
)
|
|||
|
password = forms.CharField(
|
|||
|
label='密码',
|
|||
|
widget=forms.PasswordInput(render_value=True), # render_value 不清空密码
|
|||
|
required=True, # 必填
|
|||
|
)
|
|||
|
img_code = forms.CharField(
|
|||
|
label='验证码',
|
|||
|
widget=forms.TextInput,
|
|||
|
required=True, # 必填
|
|||
|
)
|
|||
|
|
|||
|
# 钩子方法,猎取密码的md5值
|
|||
|
def clean_password(self):
|
|||
|
pwd = self.cleaned_data.get('password')
|
|||
|
return md5(pwd)
|
|||
|
|
|||
|
|
|||
|
# 这个类没有用到,因为登录界面就两个输入框 ,简单,所以用Form实现
|
|||
|
class LoginModelForm(BootstrapModelForm):
|
|||
|
class Meta:
|
|||
|
models = models.Admin
|
|||
|
fields = ['username', 'password']
|
|||
|
|
|||
|
|
|||
|
""" 用户登录 """
|
|||
|
|
|||
|
|
|||
|
def login(request):
|
|||
|
if request.method == 'GET':
|
|||
|
form = LoginForm()
|
|||
|
return render(request, 'login.html', {'form': form})
|
|||
|
|
|||
|
form = LoginForm(data=request.POST)
|
|||
|
if form.is_valid():
|
|||
|
# 验证成功,获取到用户名和密码
|
|||
|
# form.cleaned_data本身是一个字典
|
|||
|
print(form.cleaned_data)
|
|||
|
|
|||
|
# 验证码校验
|
|||
|
# 取出用户输入的验证码,并且从cleaned_data字典中删除,确保在数据库验证中不携带验证码
|
|||
|
user_input_imgcode = form.cleaned_data.pop('img_code')
|
|||
|
code = request.session.get('img_code', '')
|
|||
|
if code.upper() != user_input_imgcode.upper():
|
|||
|
form.add_error('img_code', '验证码错误')
|
|||
|
return render(request, 'login.html', {'form': form})
|
|||
|
|
|||
|
# 查询数据库中的用户名,没查到返回None
|
|||
|
# models.Admin.objects.filter(username=form.cleaned_data['username'],password=form.cleaned_data['password']).first()
|
|||
|
admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
|
|||
|
print(admin_object) # 验证通过后,所有数据都在form.cleaned_data
|
|||
|
if not admin_object:
|
|||
|
# 主动在password下展示错误信息
|
|||
|
form.add_error('password', '用户名或密码错误')
|
|||
|
return render(request, 'login.html', {'form': form})
|
|||
|
# 正确输入
|
|||
|
# 这里就要用到cookie和session的知识了,
|
|||
|
# 1.先生成一个随机字符 2.写入到本地浏览器的cookie中 3.再写入到服务器(网站)的session中
|
|||
|
# 但django帮我们简化成了
|
|||
|
# request.session['info'] = admin_object.username # 可以存入一个值
|
|||
|
request.session['info'] = {'id': admin_object.id, 'username': admin_object.username}
|
|||
|
# 如果登录成功,session会保存7天,免登录
|
|||
|
request.session.set_expiry(60 * 60 * 24 * 7)
|
|||
|
return redirect('/admin/list')
|
|||
|
# return HttpResponse('提交成功')
|
|||
|
|
|||
|
return render(request, 'login.html', {'form': form})
|
|||
|
|
|||
|
|
|||
|
""" 生成图片验证码 """
|
|||
|
|
|||
|
|
|||
|
def image_code(request):
|
|||
|
# 生成图片验证码图像和字符串
|
|||
|
img, code_str = check_code()
|
|||
|
|
|||
|
# 把验证码写入到session中
|
|||
|
request.session['img_code'] = code_str
|
|||
|
request.session.set_expiry(60) # 设置session变量的60s超时
|
|||
|
|
|||
|
# 写入内存
|
|||
|
stream = BytesIO() # 在内存中生成文件
|
|||
|
img.save(stream, 'png') # 把生成的img验证码写入到内存文件中
|
|||
|
|
|||
|
return HttpResponse(stream.getvalue())
|
|||
|
|
|||
|
# 4. 写入内存(Python2)
|
|||
|
# import StringIO
|
|||
|
# stream = StringIO.StringIO()
|
|||
|
# img.save(stream, 'png')
|
|||
|
# stream.getvalue()
|
|||
|
|
|||
|
|
|||
|
""" 注销用户 """
|
|||
|
|
|||
|
|
|||
|
def loginout(request):
|
|||
|
request.session.clear()
|
|||
|
return redirect('/login/')
|