主要在views函数里进行判断,然后使用messages在模板中将相关信息显示出来。
from django.shortcuts import render, get_object_or_404, reverse from django.http import HttpResponseRedirect, HttpResponse from django.contrib.auth import authenticate, login from django.contrib.auth.models import User from .models import ExUser from .forms import UserLoginForm, UserRegForm from django.contrib import messages def user_login(request): if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] login_user = authenticate(request, username=username, password=password) if login_user is not None: login(request, login_user) return HttpResponseRedirect(reverse('simplesite:login_ok', kwargs={'username': username})) else: messages.error(request, '登录失败,请检查用户名和密码;如果尚未注册,请先注册!') form = UserLoginForm context = {'form': form} return render(request, 'login.html', context)
在登录函数里,通过authenticate,直接去匹配一个用户-密码对象,如果为not None,表示当前用户-密码能对应一个对象,即存在!
之后,还必须调用login()函数,将request和login_user传入,最终才实现登录!如果你在之前曾经在/admin里登录了其他帐号,此时会被踢掉。
否则,通过messages.error()增加一个提示反馈,然后仍然返回到当前页面。
注意:messages不需要放入上下文,但是需要在模板里对messages进行处理:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> {% for message in messages %} <p>{{message}}</p> {% endfor %} <form action="{% url 'account:login' %}" method="post"> {% csrf_token %} {{form.as_p}} <span><input type="submit" value="login" /><a href="{% url 'account:register' %}">register</a></span> </form> </body> </html>
具体的message,通过for——in——取出来。
在注册部分:
def user_register(request): form = UserRegForm context = {'form': form} if request.method != 'POST': return render(request, 'reg.html', context) else: form = UserRegForm(request.POST) if form.is_valid(): username = form.cleaned_data['username'] password = form.cleaned_data['password'] email = form.cleaned_data['email'] confirm_password = form.cleaned_data['confirm_password'] im_qq = form.cleaned_data['im_qq'] if password == confirm_password: already_user = User.objects.filter(username=username) if already_user: messages.error(request, '该用户已存在!') return render(request, 'reg.html', context) else: new_user = User.objects.create_user(username=username, password=password, email=email) new_exuser = ExUser(user=new_user) new_exuser.confirm_password = confirm_password new_exuser.im_qq = im_qq new_exuser.save() # 注册完成后,同时进行登录 login(request, new_user) return HttpResponseRedirect(reverse('simplesite:login_ok')) else: messages.error(request, '两次密码输入不一致,请重新填写注册信息!') return render(request, 'reg.html', context) else: messages.error(request, '发生异常错误,未收到注册信息,请尝试重新填写或刷新页面!') return render(request, 'reg.html', context)
判断比较多,非常复杂,可能应该有更好的方式!
非POST传值的部分就不用看了,主要看第一个else之后的内容:
- 首先用一个form保存post传来的值,如果获取不到,反馈第一个提示:messages.error(request, '发生异常错误,未收到注册信息,请尝试重新填写或刷新页面!')
- 接着检查两次密码是否输入一致,否则会提示密码输入错误:messages.error(request, '两次密码输入不一致,请重新填写注册信息!')
- 如果密码输入一致,此时这个帐号的信息基本满足注册,但是还需要判断当前用户名是否已经存在,如果存在则仍然不能进行注册:messages.error(request, '该用户已存在!')
- 以上所有判断全部检查完毕后,方可进行相关的保存动作,完成注册,并且用这个刚刚注册的帐号去登录。
【问题】
- 有很多重复的return render代码,这里应该可以优化;
- 在界面中弹出对话框可能比较好。
--------------------------------------------------------------
代码的第一部分优化
--------------------------------------------------------------
''' def login(request): form = UserLoginForm context = {'form': form} if request.method != 'POST': return render(request, 'login.html', context) else: username = request.POST['username'] password = request.POST['password'] login_user = authenticate(request, username=username, password=password) if login_user is not None: return HttpResponseRedirect(reverse('simplesite:login_ok')) else: messages.error(request, '登录失败,请检查用户名和密码;如果尚未注册,请先注册!') return render(request, 'login.html', context) ''' def login(request): if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] login_user = authenticate(request, username=username, password=password) if login_user is not None: return HttpResponseRedirect(reverse('simplesite:login_ok')) else: messages.error(request, '登录失败,请检查用户名和密码;如果尚未注册,请先注册!') form = UserLoginForm context = {'form': form} return render(request, 'login.html', context)
这样修改之后,两个分支最终都通过最后一行的return render(request, 'login.html', context)来实现页面,其中一个分支运行到这里时还会添加messages内容。
理论上,第二个if完成后,仍然会持续后续内容,但是这里的if比较特殊,他通过url的跳转,会执行其他的views函数。