展示用户注册页面
1. 准备用户注册模板文件
加载页面静态文件
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>美多商城-注册</title>
<link rel="stylesheet" type="text/css" href="{{ static('css/reset.css') }}">
<link rel="stylesheet" type="text/css" href="{{ static('css/main.css') }}">
</head>
2. 定义用户注册视图
class RegisterView(View):
"""用户注册"""
def get(self, request):
"""
提供注册界面
:param request: 请求对象
:return: 注册界面
"""
return render(request, 'register.html')
3. 定义用户注册路由
1.总路由
urlpatterns = [
# users
url(r'^', include('users.urls', namespace='users')),
]
2.子路由
urlpatterns = [
# 注册
url(r'^register/$', views.RegisterView.as_view(), name='register'),
]
定义用户模型类
1. Django默认用户认证系统
- Django自带用户认证系统
- 它处理用户账号、组、权限以及基于cookie的用户会话。
- Django认证系统位置
django.contrib.auth
包含认证框架的核心和默认的模型。django.contrib.contenttypes
是Django内容类型系统,它允许权限与你创建的模型关联。
- Django认证系统同时处理认证和授权
- 认证:验证一个用户是否它声称的那个人,可用于账号登录。
- 授权:授权决定一个通过了认证的用户被允许做什么。
- Django认证系统包含的内容
- 用户:用户模型类、用户认证。
- 权限:标识一个用户是否可以做一个特定的任务,MIS系统常用到。
- 组:对多个具有相同权限的用户进行统一管理,MIS系统常用到。
- 密码:一个可配置的密码哈希系统,设置密码、密码校验。
2. Django默认用户模型类
- Django认证系统中提供了用户模型类User保存用户的数据。
- User对象是认证系统的核心。
-
Django认证系统用户模型类位置
-
django.contrib.auth.models.User
-
-
父类AbstractUser介绍
- User对象基本属性
- 创建用户(注册用户)必选:
username、password
- 创建用户(注册用户)可选:
email、first_name、last_name、last_login、date_joined、is_active 、is_staff、is_superuse
- 判断用户是否通过认证(是否登录):
is_authenticated
- 创建用户(注册用户)必选:
- 创建用户(注册用户)的方法
user = User.objects.create_user(username, email, password, **extra_fields)
- 用户认证(用户登录)的方法
from django.contrib.auth import authenticate user = authenticate(username=username, password=password, **kwargs)
- 处理密码的方法
- 设置密码:
set_password(raw_password)
- 校验密码:
check_password(raw_password)
- 设置密码:
- User对象基本属性
3. 自定义用户模型类
思考:为什么要自定义用户模型类?
- 观察注册界面会发现,美多商城
注册数据
中必选用户mobile信息
。- 但是Django默认用户模型类中没有mobile字段,所以要自定义用户模型类。
如何自定义用户模型类?
- 继承自AbstractUser(可通过阅读Django默认用户模型类的源码得知) 。
- 新增
mobile
字段。
from django.db import models from django.contrib.auth.models import AbstractUser # Create your models here. class User(AbstractUser): """自定义用户模型类""" mobile = models.CharField(max_length=11, unique=True, verbose_name='手机号') class Meta: db_table = 'tb_users' verbose_name = '用户' verbose_name_plural = verbose_name def __str__(self): return self.username
迁移用户模型类
1. 指定用户模型类
思考:为什么Django默认用户模型类是User?
- 阅读源代码:'django.conf.global_settings'
AUTH_USER_MODEL = 'auth.User'
结论:
- Django用户模型类是通过全局配置项 AUTH_USER_MODEL 决定的
配置规则:
AUTH_USER_MODEL = '应用名.模型类名'
# 指定本项目用户模型类
AUTH_USER_MODEL = 'users.User'
2. 迁移用户模型类
1.创建迁移文件
python manage.py makemigrations
2.执行迁移文件
python manage.py migrate
- 用户认证系统中的用户模型类,是通过全局配置项 AUTH_USER_MODEL 决定的。
- 如果迁移自定义用户模型类,必须先配置 AUTH_USER_MODEL 。
用户注册接口定义
1.注册视图
class RegisterView(View): """用户注册""" def get(self, request): """ 提供注册界面 :param request: 请求对象 :return: 注册界面 """ return render(request, 'register.html') def post(self, request): """ 实现用户注册 :param request: 请求对象 :return: 注册结果 """ pass
2.总路由
urlpatterns = [ # users url(r'^', include('users.urls', namespace='users')), ]
3.子路由
urlpatterns = [ # 注册 url(r'^register/$', views.RegisterView.as_view(), name='register'), ]
用户注册后端逻辑
1. 接收参数
提示:用户注册数据是从注册表单发送过来的,所以使用
request.POST
来提取。
username = request.POST.get('username') password = request.POST.get('password') password2 = request.POST.get('password2') mobile = request.POST.get('mobile') allow = request.POST.get('allow')
2. 校验参数
前端校验过的后端也要校验,后端的校验和前端的校验是一致的
# 判断参数是否齐全 # 判断用户名是否是5-20个字符 # 判断密码是否是8-20个数字 # 判断两次密码是否一致 # 判断手机号是否合法 # 判断是否勾选用户协议
# 判断参数是否齐全 if not all([username, password, password2, mobile, allow]): return http.HttpResponseForbidden('缺少必传参数') # 判断用户名是否是5-20个字符 if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username): return http.HttpResponseForbidden('请输入5-20个字符的用户名') # 判断密码是否是8-20个数字 if not re.match(r'^[0-9A-Za-z]{8,20}$', password): return http.HttpResponseForbidden('请输入8-20位的密码') # 判断两次密码是否一致 if password != password2: return http.HttpResponseForbidden('两次输入的密码不一致') # 判断手机号是否合法 if not re.match(r'^1[3-9]\d{9}$', mobile): return http.HttpResponseForbidden('请输入正确的手机号码') # 判断是否勾选用户协议 if allow != 'on': return http.HttpResponseForbidden('请勾选用户协议')
提示:这里校验的参数,前端已经校验过,如果此时参数还是出错,说明该请求是非正常渠道发送的,所以直接禁止本次请求。
3. 保存注册数据
- 这里使用Django认证系统用户模型类提供的 create_user() 方法创建新的用户。
- 这里 create_user() 方法中封装了 set_password() 方法加密密码。
# 保存注册数据 try: User.objects.create_user(username=username, password=password, mobile=mobile) except DatabaseError: return render(request, 'register.html', {'register_errmsg': '注册失败'}) # 响应注册结果 return http.HttpResponse('注册成功,重定向到首页')
如果注册失败,我们需要在页面上渲染出注册失败的提示信息。
{% if register_errmsg %} <span class="error_tip2">{{ register_errmsg }}</span> {% endif %}
4. 响应注册结果
- 重要提示:注册成功,重定向到首页
1.创建首页广告应用:contents
$ cd ~/projects/meiduo_project/meiduo_mall/meiduo_mall/apps $ python ../../manage.py startapp contents
2.定义首页广告视图:IndexView
class IndexView(View): """首页广告""" def get(self, request): """提供首页广告界面""" return render(request, 'index.html')
3.配置首页广告路由:绑定命名空间
# contents url(r'^', include('contents.urls', namespace='contents')),
# 首页广告 url(r'^$', views.IndexView.as_view(), name='index'),
4.测试首页广告是否可以正常访问
http://127.0.0.1:8000/
5.响应注册结果:重定向到首页
# 响应注册结果 return redirect(reverse('contents:index'))
状态保持
说明:
- 如果需求是注册成功后即表示用户登入成功,那么此时可以在注册成功后实现状态保持
- 如果需求是注册成功后不表示用户登入成功,那么此时不用在注册成功后实现状态保持
美多商城的需求是:注册成功后即表示用户登入成功
1. login()方法介绍
- 用户登入本质:
- 状态保持
- 将通过认证的用户的唯一标识信息(比如:用户ID)写入到当前浏览器的 cookie 和服务端的 session 中。
- login()方法:
- Django用户认证系统提供了
login()
方法。 - 封装了写入session的操作,帮助我们快速登入一个用户,并实现状态保持。
- Django用户认证系统提供了
-
login()位置:
-
django.contrib.auth.__init__.py文件中。 login(request, user, backend=None)
-
- 状态保持 session 数据存储的位置:Redis数据库的1号库
SESSION_ENGINE = "django.contrib.sessions.backends.cache" SESSION_CACHE_ALIAS = "session"
2. login()方法登入用户
# 保存注册数据 try: user = User.objects.create_user(username=username, password=password, mobile=mobile) except DatabaseError: return render(request, 'register.html', {'register_errmsg': '注册失败'}) # 登入用户,实现状态保持 login(request, user) # 响应注册结果 return redirect(reverse('contents:index'))
用户名重复注册
用户名重复注册后端逻辑
class UsernameCountView(View): """判断用户名是否重复注册""" def get(self, request, username): """ :param request: 请求对象 :param username: 用户名 :return: JSON """ count = User.objects.filter(username=username).count() return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})
用户名重复注册前端逻辑
if (this.error_name == false) { let url = '/usernames/' + this.username + '/count/'; axios.get(url,{ responseType: 'json' }) .then(response => { if (response.data.count == 1) { this.error_name_message = '用户名已存在'; this.error_name = true; } else { this.error_name = false; } }) .catch(error => { console.log(error.response); }) }
手机号重复注册后端逻辑
class MobileCountView(View): """判断手机号是否重复注册""" def get(self, request, mobile): """ :param request: 请求对象 :param mobile: 手机号 :return: JSON """ count = User.objects.filter(mobile=mobile).count() return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})
4. 手机号重复注册前端逻辑
if (this.error_mobile == false) { let url = '/mobiles/'+ this.mobile + '/count/'; axios.get(url, { responseType: 'json' }) .then(response => { if (response.data.count == 1) { this.error_mobile_message = '手机号已存在'; this.error_mobile = true; } else { this.error_mobile = false; } }) .catch(error => { console.log(error.response); }) }
- 判断用户名和手机号重复注册的核心思想:
- 使用用户名查询该用户名或者手机号对应的记录是否存在,如果存在,表示重复注册了,反之,没有重复注册。
- axios发送异步请求套路:
- 处理用户交互
- 收集请求参数
- 准备请求地址
- 发送异步请求
- 得到服务器响应
- 控制界面展示效果