用户注册模块创建用户(头条项目-04)

打印 上一主题 下一主题

主题 917|帖子 917|积分 2751

1 创建⽤户模块⼦应⽤

1.1 在项⽬包⽬录下 创建apps的python包



1.2 在apps包下 创建应⽤userapp

  1. $ cd 项⽬包⽬录/apps
  2. $ python ../../manage.py startapp userapp
复制代码
1.3 设置导包路径 默认情况下导包路径指向项⽬根⽬录

  1. # 通过下⾯语句可以打印当前导包路径
  2. print(sys.path)
  3. # 在dev.py⽂件中配置导包路径
  4. sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
复制代码
1.4 注册⼦应⽤

  1. INSTALLED_APPS = [
  2.     'django.contrib.admin',
  3.     'django.contrib.auth',
  4.     'django.contrib.contenttypes',
  5.     'django.contrib.sessions',
  6.     'django.contrib.messages',
  7.     'django.contrib.staticfiles',
  8.     'userapp',
  9. ]
复制代码
2. 实现展示⽤户注册⻚⾯功能

2.1 在项⽬包⽬录 /templates下 创建基础模板⽂件


2.2 在项⽬包⽬录/templates下 创建userapp⽂件夹


2.3 将 register.html 存放⾄ 项⽬包⽬录/templates/userapp⽬录 

register: 注册
2.4 创建注册视图

  1. class Register(View):
  2.     def get(self,request):
  3.         return render(request,'userapp/register.html')
复制代码
2.5 定义 ⽤户注册路由

  1. # 项⽬根路由
  2. from django.contrib import admin
  3. from django.urls import path, re_path, include
  4. urlpatterns = [
  5.     path('admin/', admin.site.urls),
  6.     re_path('^', include(('userapp.urls', 'userapp',), namespace='userapp'
  7.                          )),
  8. ]
  9. # ⽤户模块⼦路由
  10. from django.urls import re_path
  11. from . import views
  12. urlpatterns = [
  13.     re_path('^register/$', views.Register.as_view(), name='register'),
  14. ]
复制代码

3 Django默认⽤户认证系统



  • Django⾃带⽤户认证系统

    • 它处理 ⽤户账号、组、权限以及基于cookie的⽤户会话

  • Django认证系统位置

    • django.contrib.auth包罗 认证框架的核⼼和默认的模型
    • django.contrib.contenttypes是 Django内容类型系统,它允许权限与你创建的模型关联

  • Django认证系统同时处理 认证和授权

    • 认证:验证⼀个⽤户是否它声称的那个⼈,可⽤于账号登录。
    • 授权:授权决定⼀个通过了认证的⽤户被允许做什么。

  • Django认证系统包罗的内容

    • ⽤户⽤户模型类、⽤户认证
    • 权限标识⼀个⽤户是否可以做⼀个特定的任务,MIS系统常⽤到
    • :对多个具有雷同权限的⽤户进⾏统⼀管理,MIS系统常⽤到。
    • 密码:⼀个可设置的密码哈希系统,设置密码、密码校验。

3.1 Django默认⽤户模型类



  • Django认证系统中提供了⽤户模型类,User保存⽤户的数据

    • User对象是认证系统的核⼼。

  • Django认证系统⽤户模型类位置

    • django.contrib.auth.models.User

  1. class User(AbstractUser):
  2.     """
  3.     Users within the Django authentication system are represented
  4.     by this
  5.     model.
  6.     Username and password are required. Other fields are optional.
  7.     """
  8.     class Meta(AbstractUser.Meta):
  9.         swappable = 'AUTH_USER_MODEL'
复制代码


  • ⽗类AbstractUser先容
  • User对象根本属性

    • 创建⽤户(注册⽤户)必选: username、password
    • 创建⽤户(注册⽤户)可选:email、first_name、last_name、last_login、 date_joined、is_active 、is_staff、is_superuse
    • 判定⽤户是否通过认证(是否登录):is_authenticated

  • 创建⽤户(注册⽤户)的⽅法
  1. user = User.objects.create_user(username, email, password, **extra_fields)
复制代码
  1. # 源码
  2. def _create_user(self, username, email, password, **extra_fields):
  3.     """
  4.      Create and save a user with the given username, email, and
  5.     password.
  6.      """
  7.     if not username:
  8.         raise ValueError('The given username must be set')
  9.     email = self.normalize_email(email)
  10.     username = self.model.normalize_username(username)
  11.     user = self.model(username=username, email=email, **extra_fields)
  12.     user.set_password(password)
  13.     user.save(using=self._db)
  14.     return user
  15. def create_user(self, username, email=None, password=None, **extra_fields):
  16.     extra_fields.setdefault('is_staff', False)
  17.     extra_fields.setdefault('is_superuser', False)
  18.     return self._create_user(username, email, password,
  19.                              **extra_fields)
复制代码


  • ⽤户认证 (⽤户登录)的⽅法
  1. from django.contrib.auth import authenticate
  2. user = authenticate(username=username, password=password, **kwargs)
复制代码


  • 处理密码的⽅法 设置密码:

    • set_password(raw_password)
    • 校验密码:check_password(raw_password)

3.2 ⾃定义⽤户模型类

Django⾃带AbstractUser⽤户模型类中 没有⼿机号字段
  1. class Users(AbstractUser):
  2.     phone = models.CharField(max_length=11, unique=True,
  3.                              verbose_name='⼿机号')
  4.     class Meta:
  5.         db_table = 't_user'
  6.         verbose_name = '⽤户表'
  7.         verbose_name_plural = verbose_name
  8.     def __str__(self):
  9.         return self.username
复制代码
3.3 设置Django⽤户模型类

  1. # Django⽤户认证系统中的⽤户模型类
  2. # django.conf下的global_settings.py⽂件中
  3. AUTH_USER_MODEL = 'auth.User'
  4. # 配置规则:
  5. # AUTH_USER_MODEL = '应⽤名.模型类名'
  6. # 指定芒果头条项⽬⽤户模型类
  7. AUTH_USER_MODEL = 'userapp.Users'
复制代码
3.4 迁移⽤户模型类

注意:假如迁移⾃定义⽤户模型类,必须先设置 AUTH_USER_MODEL
  1. # 1.创建迁移⽂件
  2. $ python manage.py makemigrations userapp
  3. # 2.执⾏迁移⽂件
  4. $ python manage.py migrate
复制代码

4 用户注册功能接口设计

4.1 ⽤户注册业务逻辑分析


4.2 ⽤户注册接⼝设计和定义



  • 对于接⼝的设计,我们要根据详细的业务逻辑,设计出适合业务逻辑的接⼝。
  • 设计接⼝的思路:

    • 分析要实现的业务逻辑:

      • 明确在这个业务中涉及到⼏个相干⼦业务
      • 将每个⼦业务当做⼀个接⼝来设计

    • 分析接⼝的功能任务,明确接⼝的访问⽅式与返回数据:

      • 请求⽅法(如GET、POST、PUT、DELETE等)。
      • 请求地址
      • 请求参数(如路径参数、查询字符串、表单、JSON等 )。
      • 相应数据(如HTML、JSON等)。


   GET接口
  

  • 用于获取数据,比如从服务器拿信息。
  • 参数在URL里,能被缓存,但不适合传敏感信息,长度有限制。
  POST接口
  

  • 用于创建新资源,比如提交表单,向服务器添加数据
  • 参数在请求体里,不会袒露在URL中,适合传大量数据和敏感信息。
  PUT接口
  

  • 用于更新资源,一般是 替换整个资源
  • 参数在请求体里,和POST雷同,但语义上强调更新已有资源。
  DELETE接口
  

  • 用于删除资源,告诉服务器删除某个数据。
  • 通常不需要参数,或者参数很少,直接通过URL指定要删除的资源。
  
4.3 ⽤户注册接⼝设计



  • 请求⽅式

    • 请求⽅法:POST
    • 请求地址:/register/

  • 请求参数(表单参数)



  • 相应结果 :

    • html register.html


4.4 ⽤户注册接⼝定义



  • 创建⽤户注册视图
  1. class RegisterView(View):
  2.     """⽤户注册"""
  3.     def get(self, request):
  4.         """
  5.          提供注册界⾯
  6.          :param request: 请求对象
  7.          :return: 注册界⾯
  8.          """
  9.         return render(request, 'register.html')
  10.     def post(self, request):
  11.         """
  12.          实现⽤户注册
  13.          :param request: 请求对象
  14.          :return: 注册结果
  15.          """
  16.         pass
复制代码


  • 设置路由
  1. # 项⽬根路由
  2. from django.contrib import admin
  3. from django.urls import path, re_path, include
  4. urlpatterns = [
  5.     path('admin/', admin.site.urls),
  6.     re_path('^', include(('userapp.urls', 'userapp',), namespace='userapp')),
  7. ]
  8. # 应⽤⼦路由
  9. # userapp/urls.py
  10. from django.urls import re_path
  11. from . import views
  12. urlpatterns = [
  13.     re_path('^register/$', views.Register.as_view(), name='register'),
  14. ]
复制代码
5 用户注册前端逻辑

使⽤Vue.js的双向绑定实现⽤户的交互和⻚⾯局部刷新效果
5.1 ⽤户注册⻚⾯绑定Vue数据

5.1.1 准备div盒⼦标签

  1. <div id="register" v-cloak class="col-lg-6 col-md-6 col-sm-12">
  2. ......
  3. </div>
复制代码
5.1.2. register.html 【注册html】

  1. <div id="register" v-cloak class="col-lg-6 col-md-6 col-sm-12">
  2.     <div class="login-item">
  3.         <h5 class="title-login">⽤户注册
  4.             {% if register_error %}
  5.             <span class="error-tip">{{ register_error }}</span>
  6.             {% endif %}
  7.         </h5>
  8.         <form class="register" method="post" @submit="reg_sub">
  9.             {{ csrf_input }}
  10.             <p class="form-row form-row-wide">
  11.                 <input placeholder="⽤户名" v-model='username'
  12.                        @blur="check_uname" name="username" type="text" class="input-text">
  13.                 <span class="error-tip" v-show="error_username">${error_username_msg}</span>
  14.             </p>
  15.             <p class="form-row form-row-wide">
  16.                 <input placeholder="⼿机号" v-model='phone'
  17.                        @blur="check_phone" name="phone" type="text" class="input-text">
  18.                 <span class="error-tip" v-show="error_phone">${error_phone_msg}</span>
  19.             </p>
  20.             <p class="form-row form-row-wide">
  21.                 <input style="width: 250px;" placeholder="短信验证码" v-model='smscode' @blur="check_smscode"
  22.                        name="msgcode" type="text" class="input-text" id="reg_mescode">
  23.                 <span class="error-tip" v-show="error_code">${error_msgcode_msg}</span>
  24.                 <button style="font-size: 16px;text-align: center;font-weight:
  25.                 normal;float: right" id="reg_mescode_btn" able="able"
  26.                         @click="send_code($event)">${smscode_tip}
  27.                 </button>
  28.             </p>
  29.             <p class="form-row form-row-wide">
  30.                 <input style="width: 250px;" placeholder="图⽚验证码" v-model='imgcode' @blur="check_imgcode"
  31.                        name="imgcode" type="text"
  32.                        class="input-text">
  33.                 <img style="height: 40px;float: right;" :src="img_url"
  34.                      @click="generate_img_code">
  35.                 <span class="error-tip" v-show="error_imgcode">${error_imgcode_msg}</span>
  36.             </p>
  37.             <p class="form-row form-row-wide">
  38.                 <input placeholder="设置密码" v-model='password'
  39.                        @blur="check_pwd" name="password" type="password" class="input-text">
  40.                 <span class="error-tip" v-show="error_password">${error_password_msg}</span>
  41.             </p>
  42.             <p class="form-row">
  43.                 <span class="inline">
  44.                     点击 “注册” 即表示您同意并愿意遵守芒果头条 <a href="#">⽤户协议</a>
  45.                     和 <a href="#">隐私政策</a> 。
  46.                 </span>
  47.             </p>
  48.             <p class="">
  49.                 <input type="submit" class="button-submit" style="font-size:
  50.                 16px;font-weight: normal;" value="注册">
  51.             </p>
  52.         </form>
  53.     </div>
  54. </div>
复制代码
5.2 ⽤户注册JS⽂件实现⽤户交互

5.2.1 导⼊Vue.js库和ajax请求的库

  1. <script src="{{static('js/vue.js')}}"></script>
  2. <script src="{{static('js/axios.min.js')}}"></script>
复制代码
5.2.2  准备register.js⽂件

  1. <script type="text/javascript" src="{{ static('js/register.js')}}"></script>
复制代码
register.js详细内容
  1. //注册⻚⾯js内容
  2. let vue = new Vue({
  3.     el: '#register',
  4.     delimiters: ['${', '}'],
  5.     data: {
  6.         // v-model
  7.         username: '',
  8.         password: '',
  9.         smscode: '',
  10.         imgcode: '',
  11.         phone: '',
  12.         // v-show
  13.         error_username: false,
  14.         error_password: false,
  15.         error_phone: false,
  16.         error_smscode: false,
  17.         error_imgcode: false,
  18.         // v-message
  19.         error_username_msg: '请输⼊⻓度4-16的⽤户名!',
  20.         error_password_msg: '密码不能为空!',
  21.         error_phone_msg: '⼿机号输⼊有误!',
  22.         error_smscode_msg: '验证码输⼊有误!',
  23.         error_imgcode_msg: '验证码错误!',
  24.     },
  25.     methods: {
  26.         // 校验⽤户名
  27.         check_uname: function () {
  28.             
  29.         },
  30.         // 校验密码
  31.         check_pwd: function () {
  32.         },
  33.         // 校验⼿机号
  34.         check_phone: function () {
  35.         },
  36.         // 监听表单提交事件
  37.         reg_sub: function () {
  38.         }
  39.     }
  40. });
复制代码
5.2.3 ⽤户交互事件实现 

  1. //注册⻚⾯js内容
  2. let vue = new Vue({
  3.     el: '#register',
  4.     delimiters: ['${', '}'],
  5.     data: {
  6.         // v-model
  7.         username: '',
  8.         password: '',
  9.         smscode: '',
  10.         imgcode: '',
  11.         phone: '',
  12.         // v-show
  13.         error_username: false,
  14.         error_password: false,
  15.         error_phone: false,
  16.         error_smscode: false,
  17.         error_imgcode: false,
  18.         // v-message
  19.         error_username_msg: '请输⼊⻓度4-16的⽤户名!',
  20.         error_password_msg: '密码不能为空!',
  21.         error_phone_msg: '⼿机号输⼊有误!',
  22.         error_smscode_msg: '验证码输⼊有误!',
  23.         error_imgcode_msg: '验证码错误!',
  24.     },
  25.     methods: {
  26.         // 校验⽤户名
  27.         check_uname: function () {
  28.             //获取⽤户名⻓度
  29.             let reg = /^[a-zA-Z][a-zA-Z0-9_-]{4,7}$/;
  30.             //校验规则
  31.             if (!reg.test(this.username)) {
  32.                 this.error_username = true;
  33.             } else {
  34.                 this.error_username = false;
  35.             }
  36.             //校验⽤户名是否唯⼀
  37.             if (this.error_username == false) {
  38.                 let url = '/usernames/' + this.username + '/count/';
  39.                 axios.get(url, {
  40.                     responseType: 'json'
  41.                 })
  42.                     .then(response => {
  43.                         if (response.data.count == 1) {
  44.                             this.error_username_msg = '⽤户名已存在';
  45.                             this.error_username = true;
  46.                         } else {
  47.                             this.error_username = false;
  48.                         }
  49.                     })
  50.                     .catch(error => {
  51.                         console.log(error.response);
  52.                     })
  53.             }
  54.         },
  55.         // 校验密码
  56.         check_pwd: function () {
  57.             //定义正则
  58.             let reg = /^[0-9A-Za-z]{6,8}$/;
  59.             //校验规则
  60.             if (!reg.test(this.password)) {
  61.                 this.error_password = true;
  62.             } else {
  63.                 this.error_password_msg = '';
  64.                 this.error_password = false;
  65.             }
  66.         },
  67.         // 校验⼿机号
  68.         check_phone: function () {
  69.             let reg = /^1[3-9]\d{9}$/;
  70.             if (!reg.test(this.phone)) {
  71.                 this.error_phone = true;
  72.             } else {
  73.                 this.error_phone = false;
  74.             }
  75.             if (this.error_phone == false) {
  76.                 let url = '/phones/' + this.phone + '/count/';
  77.                 axios.get(url, {
  78.                     responseType: 'json'
  79.                 })
  80.                     .then(response => {
  81.                         if (response.data.count == 1) {
  82.                             this.error_phone_msg = '⼿机号已存在';
  83.                             this.error_phone = true;
  84.                         } else {
  85.                             this.error_phone = false;
  86.                         }
  87.                     })
  88.                     .catch(error => {
  89.                         console.log(error.response);
  90.                     })
  91.             }
  92.         },
  93.         // 监听表单提交事件
  94.         reg_sub: function () {
  95.             this.check_uname();
  96.             this.check_phone();
  97.             this.check_smscode();
  98.             this.check_pwd();
  99.             this.check_imgcode();
  100.             if (this.error_username || this.error_password ||
  101.                 this.error_phone || this.error_smscode || this.error_imgcode) {
  102.                 // 阻⽌表单提交
  103.                 window.event.returnValue = false;
  104.             }
  105.         }
  106.     }
  107. });
复制代码
5.3 重点回顾

1 Vue绑定⻚⾯的套路


  • 导⼊Vue.js库和ajax请求的库
  • 准备div盒⼦标签
  • 准备js⽂件
  • html⻚⾯绑定变量、事件
  • js⽂件定义变量、事件等 
2 错误提示


  • 假如错误提示信息是固定的,可以把错误提示信息写死,再通过v-show控 制是否展示
  • 假如错误提示信息不是固定的,可以 使⽤绑定的变量动态的展- 示错误提 示信息,再通过v-show控制是否展示
3 修改Vue变量的读取语法,制止和Django模板语法冲突


  • delimiters: ['[[', ']]'] 
4 后续的⻚⾯中假如有雷同的交互和刷新效果,也可按照此套路实现。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小小小幸运

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表