用户注册功能

数据库创建一条数据

django操作数据库模型

一、用户模型设计(用户表的设计)

  1.用户表字段分析

    用户名(账户名)

    密码

    手机

    邮箱

    邮箱是否有效

  2.用户模型设计

    开发效率极高,内置了很多功能,权限验证,

    自定义User模型

    项目app/user/models.py

    创建

class UserManager(_UserManager):
"""
自定义管理器,用来修改使用create_superuser命令创建用户必须使用email的行为
"""
def create_superuser(self, username, password, email=None, **extra_fields):
super().create_superuser(username=username, password=password,
email=email, **extra_fields)
class User(AbstractUser):
"""
自定义的User模型,添加moblie, email_active字段
"""
mobile = models.CharField('手机号', max_length=11, unique=True,
help_text='手机号', error_messages={'unique': '此手机号码已注册'})

email_active = models.BooleanField('邮箱状态', default=False)

class Meta:
db_table = 'tb_user' # 指定数据库表名
verbose_name = '用户' # 在admin站点中的显示名称
verbose_name_plural = verbose_name # 复数

def __str__(self):
return self.username

# 通过create_superuser 这个命令创建用户时,需要的字段
REQUIRED_FIELDS = ['mobile']

# user模型相当强大,还有修改必须输入email的这个行为
# 管理器执行
objects = UserManager()

操作数据库: 项目根目录输入命令:python manage.py makemigrations
      创建数据库表格:python manage.py migrate
      进入数据库:mysql -uroot -pqwe123
创建超级管理员:python manage.py createsuperuser

 
 

二、功能模型设计

1.接口设计思路

  1-1分析业务逻辑,明确在这个业务中需要涉及到几个相关业务,将每个子业务当做一个接口设计

  1-2分析接口的功能,明确接口的访问方式和返回数据

    1-2-1接口的请求方式:GET PUT POST DELTE

    1-2-2接口的URL定义

    1-2-3需要接受什么参数(路径参数、查询参数、表单,json)

    1-2-4返回的数据,及数据格式

2.注册功能分析

  1,流程

  2,功能接口

    方式一次请求,就要做一次

  3,注册页面

  4,图形验证码

  5,用户名校验是否注册

  6,手机号码校验是否注册

  7,短信验证码

  8,注册保持用户数据

 

三,注册页面

  1,接口设计

    1-1,接口说明

      条目          说明

      请求方式        GET

      url定义         '/user/regiseter'

      参数格式        无参数

    1-2返回数据

      注册页面html

    2.后端代码

  

      2-1视图

 

from django.shortcuts import render
from django.views import View

def login(requset):
return render(requset, 'user/login.html')


class RegisterView(View):
"""
注册视图
url:'/user/register'
"""
def get(self, request):
return render(request, 'user/register.html')

      2-2url

from django.urls import path
from . import views

app_name = 'user'

urlpatterns = [
path('login/', views.login, name='login'),
path('register/', views.RegisterView.as_view(), name='register'),
]

四,图像验证码

  1.接口设计

  1-1接口说明

    条目          说明

    请求方法        GET

    url定义         /iamge_code 

    参数格式        查询参数

  1.2参数说明

    参数名    类型    是否必须  描述

    rand     字符串    否    随机浮点数字支付串

   1-3返回数据

    验证码图片

 

验证码视图

import logging

from django.shortcuts import render

from utils.captcha.captcha import captcha
from . import constants
from django.http import HttpResponse

#日志器
logger =logging.getLogger('django')

def image_code_view(request):
"""
生成验证码
url:/image_code/
:param request:
:return:
"""
#1.生成一个验证码,随机生成字符串,生成图片
text, image = captcha.generate_captcha()
#2.在后端保持验证码,为了等下它来校验
#保存在session中
request.session['image_code'] = text
#给个过期时间
request.session.set_expiry(constants.IMAGE_CODE_EXPIRES)
#3.记录一个日志
logger.info('Imag code: {}'.format(text))
#4.返回验证记录
return HttpResponse(content=image, content_type='image/jpg')

五,用户名校验功能

  1.接口设计

  1-1接口说明

    条目          说明

    请求方法        GET

    url定义         /username/(?P<username>\w{5,20})/

    参数格式        url路径参数

  1.2参数说明

    参数名      类型    是否必须  描述

    username     字符串    是    输入用户名

   1-3返回数据

    返回结果:

      {

      "errno": "0",

      "errmsg": "ok",

      "data": {

        "username": "username",    #查询用户名

        "count": 1           #用户查询数量

        }

      }

六、电话号码校验
  

  1.接口设计

  1-1接口说明

    条目          说明

    请求方法        GET

    url定义         /mobile/(?P<username>\1[3-9]\d{9})/

    参数格式        url路径参数

  1.2参数说明

    参数名      类型    是否必须  描述

    mobile     字符串    是      输入的手机号码

   1-3返回数据

    返回结果:

      {

      "errno": "0",

      "errmsg": "ok",

      "data": {

        "username": "mobile",    #查询手机号

        "count": 1           #手机号查询数量

        }

      }

七,json响应数据结构设计
  目的:
    1,减少代码坈余,提高复用性,解耦
    2,分工协作

   1,结构设计

    {"errno": "0", "errmsg": "ok", "data": ""}

    字段    

 

 

 

目标utils建立文件res_code
from django.http import JsonResponse
class Code:
OK = "0"
DBERR = "4001"
NODATA = "4002"
DATAEXIST = "4003"
DATAERR = "4004"
METHERR = "4005"
SMSERROR = "4006"
SMSFAIL = "4007"

SESSIONERR = "4101"
LOGINERR = "4102"
PARAMERR = "4103"
USERERR = "4104"
ROLEERR = "4105"
PWDERR = "4106"

SERVERERR = "4500"
UNKOWNERR = "4501"


error_map = {
Code.OK: "成功",
Code.DBERR: "数据库查询错误",
Code.NODATA: "无数据",
Code.DATAEXIST: "数据已存在",
Code.DATAERR: "数据错误",
Code.METHERR: "方法错误",
Code.SMSERROR: "发送短信验证码异常",
Code.SMSFAIL: "发送短信验证码失败",

Code.SESSIONERR: "用户未登录",
Code.LOGINERR: "用户登录失败",
Code.PARAMERR: "参数错误",
Code.USERERR: "用户不存在或未激活",
Code.ROLEERR: "用户身份错误",
Code.PWDERR: "密码错误",

Code.SERVERERR: "内部错误",
Code.UNKOWNERR: "未知错误",
}
def json_response(errno=Code.OK, errmsg='', data=None, kwargs=None):

json_dict = {
'errno': errno,
'errmsg': errmsg,
'data': data
}
if kwargs and isinstance(kwargs, dict):
json_dict.update(kwargs)

return JsonResponse(json_dict)

八、获取短信验证码

  1,业务流程分析
    校验手机号吗
    校验图像验证码
    校验是否在60s内有发送记录
    生成短信验证码
    发送短信
    保存这个短信验证码(保存在哪里?)
    保存发送记录

  2,接口设计
    2.1接口说明

      条目          说明

      请求方法        POST       #get查询/获取数据、post产生新数据

      url定义         /sms_code/

      参数格式        表单

    2.2参数说明

      参数名      类型    是否必须      描述

      mobile         字符串    是      输入的手机号码

      captcha     字符串    是      用户输入的图像验证码

     2.3返回数据

      返回结果:

      {

      "errno": "0",

      "errmsg": "发送短信验证码成功",

      }

后端:
  1,校验数据用form表单
  在verification目录下新建 forms表单

verification/views.py文件代码
  
class SmsCodeView(View):
"""
发送短信验证码
url: /sms_code/
"""

def post(self, request):
"""
     生成短信验证码
     发送短信
     保存这个短信验证码(保存在哪里?)
     保存发送记录
"""
form = CheckImageForm(request.POST, request=request)
        if form.is_valid():
#获取手机号码
mobile = form.cleaned_data.get('mobile')
#生成短信验证码
sms_code = ''.join([random.choice('0123456789') for _ in range(constants.SMS_CODE_LENGTH)])
#发送短信验证码 调用接口
logger.info('发送短信验证码[正常][mobile: %s sms_code: %s ]' % (mobile, sms_code))
#保持这个验证码 保持到redis
#5分钟时效
#创建短信验证码发送记录到key
sms_flag_key = 'sms_flag_{}'.format(mobile)
#创建短信验证码内容到key
sms_text_key = 'sms_text_{}'.format(mobile)
redis_conn = get_redis_connection(alias='verify_code')
pl = redis_conn.pipeline()

try:
pl.setex(sms_flag_key, constants.SMS_CODE_INTERVAL, 1)
pl.setex(sms_text_key,constants.IMAGE_CODE_EXPIRES*60, sms_code)
#让管道通知redis执行命令
pl.execute()
return json_response(errmsg='短信验证码发送成功!')
except Exception as e:
logger.error('redis 执行异常: {}'.format(e))

return json_response(errno=Code.UNKOWNERR, errmsg=error_map[Code.UNKOWNERR])
else:
#将表单的报错信息进行拼接
err_msg_list = []
for item in form.errors.values():
err_msg_list.append(item[0])

err_msg_str = '/'.join(err_msg_list)
return json_response(errno=Code.PARAMERR, errmsg=err_msg_str)
verification/forms.py文件代码
  
from django import forms
from django.core.validators import RegexValidator
from django_redis import get_redis_connection

from user.models import User

#创建手机号码正则校验器
mobile_validator = RegexValidator(r'^1[3,9]\d{9}$', '手机号码格式不正确')


class CheckImageForm(forms.Form):
"""
校验手机号吗
校验图像验证码
校验是否在60s内有发送记录
校验图形验证码
"""
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
super().__init__(*args, **kwargs)

mobile = forms.CharField(max_length=11, min_length=11, validators=[mobile_validator], error_messages={
'max_length': '手机长度有误!',
'min_length': '手机长度有误!',
'required': '手机号码不能为空!',
})

captcha = forms.CharField(max_length=4, min_length=4, error_messages={
'max_length': '图形验证码长度有误!',
'min_length': '图形验证码长度有误!',
'required': '图形验证码不能为空!',
})

def clean(self):
clean_data = super().clean()
mobile = clean_data.get('mobile')
captcha = clean_data.get('captcha')
# 如果前面到校验失败,mobile captcha 是 none
# 如果前面到字段校验有问题,就不需要往下进行了
if mobile and captcha:
#1,校验图形验证码
#获取session中把保存到验证码,和用户填入到进行比对
image_code = self.requset.session.get('image_code')
if not image_code:
raise forms.ValidationError('图形验证码失效')
if image_code.upper() != captcha.upper():
raise forms.ValidationError('图形验证码校验失败!')

#2,是否60秒以内发送过短信
#存在redis里面
redis_conn = get_redis_connection(alias='verify_code')
if redis_conn.get('sms_flag_{}'.format(mobile)):
raise forms.ValidationError('获取短信验证码过于频繁')

#3,再次校验手机号号码是否注册
if User.objects.filter(mobile=mobile).count():
raise forms.ValidationError('手机号码已注册,请重新输入')
return clean_data

static/js/user/registe.js文件代码
  
//5.发送短信验证码
let $smsButton = $('.sms-captcha');
$smsButton.click(()=>{
// 拿到数据
// 图形验证
let sCaptcha = $('input[name="captcha_graph"]').val();
if(sCaptcha === ''){
message.showError('请输入图形验证码!');
return
}
// 判断手机号码是否准备好
if(!isMolibleReady){
fnCheckMobile();
return
}

$
.ajax({
url: '/sms_code/',
type: 'POST',
data: {
mobile: $mobile.val(),
captcha: sCaptcha
},
dataType: 'json'
})
.done((res)=>{
if(res.errno !== '0'){
message.showError(res.errmsg)
}else {
message.showSuccess(res.errmsg)
}
})
.fail(()=>{
message.showError('服务器超时,请重试!')
});
})
static/js/base/common.js文件代码
  
 function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = cookies[i].trim();
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}

function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

$.ajaxSetup({
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
}
});


templates/user/registe.html文件代码
{% block main_start %}
<main id="container">
<div class="register-contain">
<div class="top-contain">
<h4 class="please-register">请注册</h4>
<a href="javascript:void(0);" class="login">立即登录 &gt;</a>
</div>
<form action="" method="post" class="form-contain">
{% csrf_token %}  #增加这个代码
 
九、注册功能
  1.业务流程分析
    1.1对参数进行校验
      1.校验用户名
      2.校验密码
      3.校验手机号码
      4.校验短信验证码

    1.2新建数据库记录
   
  2.接口设计  
    2.1接口说明

      条目          说明

      请求方法        POST       #get查询/获取数据、post产生新数据

      url定义         /user/register/

      参数格式        表单

    注意:post请求,一定要带上csrf_token

    2.2参数说明

      参数名         类型    是否必须      描述

      username          字符串    是      用户输入到用户名

      password      字符串    是      用户输入到密码

      passwrod_repeat  字符串    是      用户输入到重复密码

      mobile       字符串    是      用户输入到电话号码

      sms_code      字符串    是      用户输入到短信验证码

     2.3返回数据

      返回结果:

      {

      "errno": "0",

      "errmsg": "恭喜您,注册成功",

      }

user/views 代码
  
class RegisterView(View):
"""
注册视图
url:'/user/register'
"""

def get(self, request):
return render(request, 'user/register.html')

def post(self, request):
# 1.校验数据
form = RegisterForm(request.POST)
if form.is_valid():
# 2.创建数据
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
mobile = form.cleaned_data.get('mobile')
User.objects.create_user(username=username,
password=password, mobile=mobile)
return json_response(errmsg='恭喜您,注册成功')
else:
# 将表单的报错信息进行拼接
err_msg_list = []
for item in form.errors.values():
err_msg_list.append(item[0])

err_msg_str = '/'.join(err_msg_list)
return json_response(errno=Code.PARAMERR, errmsg=err_msg_str)


user/forms代码
from django import forms
from django_redis import get_redis_connection

from verification import constants
from .models import User
from verification.forms import mobile_validator


class RegisterForm(forms.Form):
"""
用户注册表单
"""
username = forms.CharField(label='用户名', max_length=20, min_length=5,
error_messages={
'max_length': "用户名长度要小于20",
'min_length': "用户名长度要大于5",
'required': "用户名不能为空",
})
password = forms.CharField(label='密码', max_length=20, min_length=6,
error_messages={
'max_length': "密码长度要小于20",
'min_length': "密码长度要大于6",
'required': "密码不能为空",
})
password_repeat = forms.CharField(label='密码', max_length=20, min_length=5,
error_messages={
'max_length': "密码长度要小于20",
'min_length': "密码长度要大于5",
'required': "密码不能为空",
})
mobile = forms.CharField(label='手机号', max_length=11, min_length=11,
validators=[mobile_validator, ],
error_messages={
'max_length': "手机号码长度不正确",
'min_length': "手机号码长度不正确",
'required': "手机号不能为空",
})
sms_code = forms.CharField(label='短信验证',
max_length=constants.SMS_CODE_LENGTH,
min_length=constants.SMS_CODE_LENGTH,
error_messages={
'max_length': "短信验证码长度不正确",
'min_length': "短信验证码长度不正确",
'required': "短信验证码不能为空",
})

def clean_username(self):
"""
校验用户名
:return:
"""
username = self.cleaned_data.get('username')

if User.objects.filter(username=username).exists():
raise forms.ValidationError('用户名不存在')

return username

def clean_mobile(self):
"""
单字段校验,用clean_mobile
校验手机号码
:return:
"""
mobile = self.cleaned_data.get('mobile')

if User.objects.filter(mobile=mobile).exists():
raise forms.ValidationError('手机号已注册')

return mobile

def clean(self):
"""
联合校验
:return:
"""
clean_data = super().clean()
#校验密码是否一致
password = clean_data.get('password')
password_repeat = clean_data.get('password')

if password != password_repeat:
raise forms.ValidationError('两次密码不一致!')

#校验短信验证码
sms_code = clean_data.get('sms_code')
mobile = clean_data.get('mobile')

redis_conn = get_redis_connection(alias='verify_code')
real_code = redis_conn.get('sms_text_{}'.format(mobile))
if (not real_code) or (real_code.decode('utf-8') != sms_code):

raise forms.ValidationError('短信验证码错误!')
 


    

 

转载于:https://www.cnblogs.com/wdty/p/11305556.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaWeb用户注册功能可以通过以下步骤实现: 1. 创建注册页面:根据引用[1]中提供的示例,我们可以创建一个包含用户名密码和验证码等表单元素的注册页面。这个页面可以使用HTML和CSS编写,参考引用中提供的示例代码。 2. 创建注册处理逻辑:在后端代码中,我们可以创建一个用于处理注册请求的Servlet。当用户提交注册表单时,Servlet会接收到请求并提取出用户名密码等信息。然后,我们可以使用引用中的代码创建一个User对象,并将用户提交的数据赋值给User对象的相应属性。 3. 数据库操作:将用户注册信息保存到数据库中。可以使用MyBatis框架进行数据库操作,参考引用中提到的使用MyBatis的方法。 4. 注册成功页面:在注册成功后,可以跳转到一个注册成功页面,提示用户注册成功,并提供登录链接等操作。 总结: 以上是实现JavaWeb用户注册功能的基本步骤。通过创建注册页面、编写注册处理逻辑、进行数据库操作和创建注册成功页面等步骤,我们可以实现一个完整的用户注册功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [JavaWeb登录注册页面](https://download.csdn.net/download/weixin_59798969/86271757)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [JavaWeb实现登录注册功能[代码+详解]](https://blog.csdn.net/jiey0407/article/details/126105700)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Java-web实现用户登录、注册功能](https://blog.csdn.net/m0_52822058/article/details/128355926)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值