###登陆注册功能的实现

1.数据库数据的增删改查
2.拿到http协议中请求体中的内容
3.使用哈希码加密
4.重写方法
5.使用ModelForm表单对象自动验证

####views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def login(request):
if request.method.lower() == 'get':
return render(request, 'login.html', {})
else:
# request.META类似字典,可以获得请求头,比如user_agent就是浏览器,请求行中的:method是方法,is_secure真为https
# get和post是拿消息体
username = request.POST['username']
try:
# 比较用户名是否存在,密码对不对
user = User.objects.get(username=username)
password = request.POST['password']
hasher = proto.copy()
hasher.update(password.encode('utf-8'))
if hasher.hexdigest() == user.password:
# 返回302重新请求 httpresponse是200请求成功加载网页
return redirect('index')
except User.DoesNotExist:
pass
return render(request, 'login.html', {'hint': '用户名或密码错误'})


def register(request):
form = UserForm()
if request.method.lower() == 'get':
return render(request, 'register.html', {'f': form})
else:
# 使用表单判断信息是否全,将表单直接快速生成,快速验证
form = UserForm(request.POST)
if form.is_valid():
# 其实保存的是user对象
form.save(commit=True)
# user = User()
# # 访问他的post属性,像一个字典,里面是你提交的表单数据
# user.username = request.POST['username']
# user.password = request.POST['password']
# user.email = request.POST['email']
# # 生成哈希码实例
# # hasher = sha1()
# # # 通过update方法传入对象
# # hasher.update(user.password.encode('utf-8'))
# # # 利用哈希码函数对密码进行加密,16进制加密
# # user.password = hasher.hexdigest()
# user.save()
return render(request, 'login.html', {'hint': '注册成功请登录'})
else:
return render(request, 'register.html',
{'f': form})

###models

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 带_的库是不建议使用的
# from _sha1 import sha1

from hashlib import sha1

from django.db import models
from django.db.models import PROTECT

# 生成哈希码实例
proto = sha1()


class User(models.Model):
no = models.AutoField(primary_key=True, db_column='uno', verbose_name='用户编号')
username = models.CharField(max_length=20, unique=True, verbose_name='用户名')
password = models.CharField(max_length=40, verbose_name='用户口令')
email = models.CharField(max_length=255, verbose_name='邮箱')
tcounter = models.IntegerField(default=3, db_column='counter', verbose_name='票数')

# 重写save方法
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
# 在对象基础上复制一份,比直接创建更快,内存拷贝性能更好
hasher = proto.copy()
# 通过update方法传入对象
hasher.update(self.password.encode('utf-8'))
# 利用哈希码函数对密码进行加密,16进制加密
self.password = hasher.hexdigest()
super().save(force_insert, force_update, using, update_fields)

class Meta(object):
db_table = 'tb_user'
verbose_name_plural = '用户'
verbose_name = '用户'

urls

1
2
3
path('register/', views.register),
path('login/', views.login),
path('check/', views.check_username),

login.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<h1>用户登录</h1>
<hr>
<p>{{ hint }}</p>
<form action="/login/" method="post">
{% csrf_token %}
<div>用户名:</div>
<div>
<input type="text" name="username" required>
<div>密码</div>
<input type="password" name="password" required>

<div>
<button>登录</button>
</div>
</div>
</form>
<a href="/register">Register Rightnow!</a>
</body>
</html>

register.html

使用ajax来做验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<!DOCTYPE html>
{% load staticfiles %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
<h1>用户注册</h1>
<hr>
{# {% for error in f.errors %}#}
{# <p>{{ error }}</p>#}
{# {% endfor %}#}
<form action="/register/" method="post">
{# 加上csrf_token的令牌, 防止跨站身份伪造 #}
{% csrf_token %}
{# <table>#}
{# 取出来的是行#}
{# {{ f }}#}
{# </table>#}

<div>用户名:</div>
<div>
{{ f.username }}
<span id="uhint"></span>
{% if f.errors.username %}
<span>用户名无效或已经被注册</span>
{% endif %}
</div>
<div>密码:</div>
<div>
{{ f.password }}
{% if f.errors.password %}
<span>无效的密码</span>
{% endif %}
</div>
<div>邮箱:</div>
<div>
{{ f.email }}
{% if f.errors.email %}
<span>邮箱无效或已经被注册</span>
{% endif %}
</div>
<div>
<button>注册</button>
</div>
</div>
</form>
<a href="/">返回登录</a>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>

<script>
$(function(){
$('#id_username').on('blur', function(evt){
var $input = $(evt.target);
$.ajax({
{#'url': '/check/?username=' + $input.val(),#}
'url': '/check',
'data': {'username':$input.val()},
'type':'get',
'dataType':'json',
'success':function(json){
var $img = $('<img>');
if(json.valid){
$img.attr('src', '/static/images/icon-yes.svg');
}else{
$img.attr('src', '/static/images/icon-no.svg');
}
$('#uhint').empty().append($img)
},
'error':function(){}
})
})
})
</script>


</body>
</html>

优化:使用form对象自动验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from django import forms

from hello.models import User


class UserForm(forms.ModelForm):
# 跟模型对应的表单.ModelForm/也可以写Form页面是什么样就什么样
# 自动帮我验证
username = forms.CharField(max_length=20, label='用户名')
password = forms.CharField(widget=forms.PasswordInput, max_length=20, min_length=8, label='密码')
email = forms.CharField(widget=forms.EmailInput, max_length=255, label='邮箱')

class Meta(object):
# 跟表单对应的模型是,因为写的是ModelForm,Form就不用加
model = User
# 对应的字段是
fields = ('username', 'password', 'email')