注册和登录是两个流程。
因为主要利用了预设的user类,登录比较简单,只要有用户名和密码即可;而注册会比较麻烦一点,你的网站的用户信息通常会大于django默认设置的user类,因此需要对user类进行拓展:
一种方式是自己创建一个user类(比如MyUser),继承默认的User,然后设置这个MyUser,最后用MyUser替代官方默认的User;
另一种方式是建立一个和User是1v1对应关系的新类,增添一些属性。
先看登录流程:
【1】由于直接使用预设的user类,所以不需要模型,而直接在表单类中指明其承载user类即可。
from django import forms from django.contrib.auth.models import User from .models import ExUser # 仅作测试用,非正常情况 class UserLoginForm(forms.ModelForm): class Meta: model = User fields = ['username', 'password'] labels = {'username': '用户名称', 'password': '用户密码'}
【2】在视图中,直接使用了authenticate方法,他获得一组username-password,然后去和数据库里进行匹配,并返回一个user(或空),然后根据返回,即可判断登录是否成功!
注意:这里不能忘记了对user的引用:from django.contrib.auth.models import User,在pycharm中,引用后这行代码是灰色的,但是其实不可或缺。
如果没有引用,username=username等式的左侧就不知道是什么了!
from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect, HttpResponse from django.contrib.auth import authenticate from django.contrib.auth.models import User from .models import ExUser from .forms import UserLoginForm, UserRegForm def login(request): if request.method != 'POST': form = UserLoginForm context = {'form': form} 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 HttpResponse('login ok!') else: return HttpResponse('login wrong!')
【3】模板非常简单,没啥可说的!
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="{% url 'account:login' %}" method="post"> {% csrf_token %} {{form.as_p}} <input type="submit" value="login" /> </form> </body> </html>
再看注册流程:
【1】按前面所说,注册时需要拓展user类,这里使用一个最常见也最必须的拓展:密码确认。
这个类只有一个属性confirm_password,并使用OneToOneField和预设的user类绑定1对1关系。
from django.db import models from django.contrib.auth.models import User # Create your models here. class ExUser(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) confirm_password = models.CharField(max_length=256)
【2】由于完成注册涉及到2个模型,因此使用ModelForm来创建表单已经不可能,只能完全自定义一个表单。
使用PasswordInput会在输入时,用圆点代替字符,不过这仅仅只是前端表现,此时并没有真正加密。
from django import forms from django.contrib.auth.models import User from .models import ExUser # 不依赖于ModelForm,完全自定义的一个form类 class UserRegForm(forms.Form): username = forms.CharField(max_length=128, label='用户名称') password = forms.CharField(max_length=256, label='用户密码', widget=forms.PasswordInput) confirm_password = forms.CharField(max_length=256, label='确认密码', widget=forms.PasswordInput) email = forms.EmailField(label='电子邮箱')
【3】视图里对注册的处理略微复杂,我们关注else部分即可:
在使用form接收表单传来的数据之后,如果验证有效,可使用form.cleaned_data[ ]的方法,将一些值取出来。使用x=form.save(commit=False),然后通过x去取值也许也可以,但不确定?
最重要的一步是:User.objects.create_user(),通过这个方法可以用传来的值创建一个用户,并且自动完成保存。
当这个user对象保存之后,接下来就是用关联关系,让exuser对应起来,并且存储他自己的属性。虽然这里保存一个confirm_password看起来没有多大意义,不过如果保存的手机号,地址,QQ等,就会很有意义。
from django.shortcuts import render, get_object_or_404 from django.http import HttpResponseRedirect, HttpResponse from django.contrib.auth import authenticate from django.contrib.auth.models import User from .models import ExUser from .forms import UserLoginForm, UserRegForm def register(request): if request.method != 'POST': form = UserRegForm context = {'form': form} return render(request, 'reg.html', context) else: form = UserRegForm(request.POST) if form.is_valid(): # return HttpResponse('ok!') username = form.cleaned_data['username'] password = form.cleaned_data['password'] email = form.cleaned_data['email'] confirm_password = form.cleaned_data['confirm_password'] if password == confirm_password: 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.save() return HttpResponse('ok!') else: pass else: pass
【4】最后就是模板部分,同样很简单,没啥可说的!
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>register</title> </head> <body> <form action="{% url 'account:register' %}" method="post"> {% csrf_token %} {{form.as_p}} <input type="submit" value="register" /> </form> </body> </html>