Django实现的登录注册功能

1 前言

在Web开发中,用户登录和注册是最基本且必不可少的功能。Django,作为一个高级的Python Web框架,为我们提供了强大的工具和库来快速实现这些功能。下面,我将详细介绍如何使用Django来实现用户登录和注册功能。

2 功能介绍

该项目是使用django+bootstrp开发的项目,包含以下功能

  • 注册: 手机获取验证码、ModelForm数据验证、验证码redis超时处理,
  • 登录:手机验证码登录、账号密码登录、生成随机图片验证码、用户信息seesion处理

项目示例

1 账号密码登录
在这里插入图片描述
2 短信验证码登录
在这里插入图片描述
3 用户的注册
在这里插入图片描述
4 用户退出
在这里插入图片描述

3 申请容联云短信服务

登录和注册都需要一个短信的验证码,但是阿里、腾讯的短信服务申请太麻烦了,所有就申请了容联云短信服务,新用户有8元的免费额度只要项目不正式上线本地测试的话申请还是没有什么问题的,

容联云,全球智能通讯云服务商 (yuntongxun.com)

3.1 创建应用

在这里插入图片描述

3.2 创建短信模板

在这里插入图片描述

3.3 填写测试号码

在这里插入图片描述

3.4 安装sdk

 pip install ronglian_sms_sdk

3.5 发送短信的python代码

import json
from ronglian_sms_sdk import SmsSDK# 容联云创建的应用中获取
accId = "应用的id"
accToken = "应用的token"
appId = "appid"def send_sms(mobile, sms_code):"""发送短信"""sdk = SmsSDK(accId, accToken, appId)tid = "1"try:resp = sdk.sendMessage(tid, mobile, (sms_code, ))res_json = json.loads(resp)if res_json.get("statusCode") == "000000":logger.info(f"向mobile[{mobile}]发送短信验证码[{sms_code}]成功")else:logger.info(f"发送短信失败:{resp}")except Exception as e:logger.error(f"发送短信失败:{e}")if __name__ == '__main__':send_sms("平台测试手机号码", "9991")

运行脚本后手机会受到短信验证码,如下图
在这里插入图片描述

4 注册

在这里插入图片描述

注册分为两个部分:

  • 点击获取验证码:前端通过ajax发送请求到后端,后端生成随机验证码随机保存到redis中,同时调用短信服务发送短信到用户手机。
  • 点击注册:用户输入用户信息和验证码之后,后端进行校验,没有问题时保存到数据库,同时跳转到登录页面。
    在这里插入图片描述
    代码实现: 直截关键代码,完整代码跳转最后下载完整代码
# setting.py  django 使用redis
# 安装
pip install django-redis
# setting
CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://192.168.1.200:6379","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient","CONNECTION_POOL_KWARGS": {"max_connections": 100, "encoding": "utf-8"}# "PASSWORD": "123",}}
}from django_redis import get_redis_connection
def test_django_redis(request):# 可以直接从连接池中拿到连接redis=get_redis_connection()age = str(conn.get('age'), encoding='utf-8')# 设置过期时间redis.set('name','xiaoming',4)  redis.set('xxx',test_redis)
# view.py
from django.shortcuts import render
from django.http.response import JsonResponse
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from django import forms
from django_redis import get_redis_connection
from users import modelsclass RegisterModelForm(forms.ModelForm):mobile_phone = forms.CharField(label="手机号",validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])password = forms.CharField(label="密码",min_length=8,max_length=64,error_messages={'min_length': "密码长度不能小于8个字符",'max_length': "密码长度不能大于64个字符"},widget=forms.PasswordInput())confirm_password = forms.CharField(label="重复密码",min_length=8,max_length=64,error_messages={'min_length': "重复密码长度不能小于8个字符",'max_length': "重复密码长度不能大于64个字符"},widget=forms.PasswordInput())code = forms.CharField(label="验证码", widget=forms.TextInput())class Meta:model = models.UserInfo# fields = "__all__"fields = ["username", "email", "password", "confirm_password", "mobile_phone", "code"]def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)for name, field in self.fields.items():field.widget.attrs['class'] = 'form-control'field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)def clean_username(self):username = self.cleaned_data['username']exists = models.UserInfo.objects.filter(username=username).exists()if exists:raise ValidationError('用户名已存在')return usernamedef clean_email(self):email = self.cleaned_data['email']exists = models.UserInfo.objects.filter(email=email).exists()if exists:raise ValidationError('邮箱已存在')return emaildef clean_confirm_password(self):pwd = self.cleaned_data.get('password')confirm_pwd = self.cleaned_data['confirm_password']if pwd != confirm_pwd:raise ValidationError('两次密码不一致')def clean_mobile_phone(self):mobile_phone = self.cleaned_data['mobile_phone']exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()if exists:raise ValidationError('手机号已注册')return mobile_phonedef clean_code(self):code = self.cleaned_data['code']# mobile_phone = self.cleaned_data['mobile_phone']mobile_phone = self.cleaned_data.get('mobile_phone')if not mobile_phone:return codeconn = get_redis_connection()redis_code = conn.get(mobile_phone)if not redis_code:raise ValidationError('验证码失效或未发送,请重新发送')redis_str_code = redis_code.decode('utf-8')if code.strip() != redis_str_code:raise ValidationError('验证码错误,请重新输入')return codedef register(request):"""用户注册视图"""if request.method == "GET":form = RegisterModelForm()return render(request, "users/register.html", {"form": form})elif request.method == "POST":form = RegisterModelForm(data=request.POST)if form.is_valid():form.save()logger.info(f"用户[{form.username}]注册成功")return JsonResponse({"status": True})logger.warning(f"用户[{form.username}]注册失败")return JsonResponse({"status": False, "error": form.errors})

主要是用Django的ModeForm对数据格式进行验证,以及注册时候的一些逻辑判断

5 短信验证码登录

在这里插入图片描述
短信验证码登录也分为两个部分

  • 点击获取验证码: 这个过程和用户的注册获取验证码类似,可以复用注册获取手机验证的代码
  • 点击登录: 输入手机号码和验证码之后,后端校验数据的有效性,将用户的信息保存在session中,跳转主页
    在这里插入图片描述
    代码实现: 直截关键代码,完整代码跳转最后下载完整代码
# view,py 中数据校验和逻辑处理
class LoginSMSForm(forms.Form):"""短信验证码登录模板"""mobile_phone = forms.CharField(label='手机号',validators=[RegexValidator(r'^(1[3|4|5|6|7|8|9])\d{9}$', '手机号格式错误'), ])code = forms.CharField(label='验证码',widget=forms.TextInput())def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)for name, field in self.fields.items():field.widget.attrs['class'] = 'form-control'field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)def clean_mobile_phone(self):mobile_phone = self.cleaned_data['mobile_phone']exists = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()if not exists:raise ValidationError('用户未注册')return mobile_phonedef clean_code(self):code = self.cleaned_data['code']mobile_phone = self.cleaned_data.get('mobile_phone')if not mobile_phone:return coderedis = get_redis_connection()redis_code = redis.get(mobile_phone)  # 根据手机号去获取验证码if not redis_code:raise ValidationError('验证码失效或未发送,请重新发送')real_code = redis_code.decode('utf-8')if code.strip() != real_code:raise ValidationError('验证码错误,请重新输入')return codedef login_sms(request):"""短信验证码登录"""if request.method == "GET":form = LoginSMSForm()return render(request, "users/login_sms.html", context={"form": form})elif request.method == "POST":form = LoginSMSForm(data=request.POST)if form.is_valid():logger.info(f"用户登录成功")return JsonResponse({"status": True})logger.warning(f"用户登录失败")return JsonResponse({"status": False, "error": form.errors})

主要是用Django的ModeForm对数据格式进行验证,以及登录时候的一些逻辑判断

6 用户密码登录

在这里插入图片描述
用户密码登录也分为两个部分

  • 生成图像验证码: 加载网页时会请求后端生成图像验证码的接口,后端会根据pillow画出一张图片返回给前端,同时将验证码保存到session中, 图像验证码具体怎么生成的看生成随机图片验证码-CSDN博客
  • 点击登录: 填好信息后点击登录,请求端口登录接口后端会对数据进行验证,成功后跳转。
    在这里插入图片描述

代码实现: 直截关键代码,完整代码跳转最后下载完整代码

class LoginForm(forms.Form):username = forms.CharField(label='用户名',min_length=4,max_length=64,error_messages={'min_length': "密码长度不能小于4个字符",'max_length': "密码长度不能大于64个字符"})password = forms.CharField(label="密码",min_length=8,max_length=64,error_messages={'min_length': "密码长度不能小于8个字符",'max_length': "密码长度不能大于64个字符"},widget=forms.PasswordInput(render_value=True))code = forms.CharField(label='图片验证码',widget=forms.TextInput())def __init__(self, request,  *args, **kwargs):super().__init__(*args, **kwargs)self.request = requestfor name, field in self.fields.items():field.widget.attrs['class'] = 'form-control'field.widget.attrs['placeholder'] = '请输入%s' % (field.label,)def clean_username(self):username = self.cleaned_data["username"]if not models.UserInfo.objects.filter(username=username).exists():logger.warning("用户未注册")raise ValidationError("用户未注册")return usernamedef clean_password(self):username = self.cleaned_data.get("username")if not username:logger.warning("用户名为空")return usernamepassword = self.cleaned_data['password']encrypt_password = md5(password)if not models.UserInfo.objects.filter(username=username, password=encrypt_password).exists():logger.warning("用户名或者密码错误")raise ValidationError("用户名或者密码错误")return encrypt_passworddef clean_code(self):code = self.cleaned_data["code"]session_code = self.request.session.get("image_code")if not session_code:logger.warning("验证码已过期, 请求重新获取")raise ValidationError("验证码已过期, 请求重新获取")if code.strip().upper() != session_code.strip().upper():logger.warning(f"验证码输入错误,{code}:{session_code}")raise ValidationError("验证码输入错误")return codedef login(request):"""用户账号密码登录"""if request.method == "GET":form = LoginForm(request)else:form = LoginForm(request, data=request.POST)if form.is_valid():username = form.cleaned_data["username"]user_obj = models.UserInfo.objects.filter(username=username).first()request.session["user_id"] = user_obj.idrequest.session.set_expiry(settings.SESSION_EXPIRY)logger.info("用户登录成功")return redirect("home")logger.warning("用户登录失败")return render(request, "users/login.html", context={"form": form})

主要是用Django的ModeForm对数据格式进行验证,以及登录时候的一些逻辑判断

6 运行项目

完整代码一下链接下载

【免费】Django+bootstrp实现用户的注册和登录功能资源-CSDN文库

# 1 下载代码解压
# 2 安装依赖
pip install -r requirement.txt
# 3 迁移数据库
python manage.py makemigrations
python manage.py migrate
# 4 登录容联云获取accId、accToken、appId替换sms.py
# 5 在setting中修改redis中的地址
# 4 启动项目
python manage.py runserver

另外安装redis的教程也可以看::Docket常见的软件部署1-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/803879.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MATLAB计算投资组合的cVaR和VaR

计算条件风险价值 (Conditional Value-at-Risk, cVaR) 是一种衡量投资组合风险的方法,它关注的是损失分布的尾部风险。 MATLAB代码如下: clc;close all;clear all;warning off;%清除变量 rand(seed, 100); randn(seed, 100); format long g;% 随机产生数据&#x…

Mac 安装 brew brew cask 遇到的问题以及解决办法

安装Homebrew和Homebrew Cask是在Mac上管理软件包的常用方法。虽然大多数情况下安装这两个工具是比较简单的,但有时候也可能遇到一些问题。下面是一些常见的问题以及解决办法: 问题1:无法安装Homebrew 解决办法: 1.确保你的Mac已连…

低代码ARM计算机在IIoT中的采集控制生产面板

工业4.0的大潮下工业物联网(IIoT)已成为推动制造业转型升级的重要动力。其中,低代码ARM嵌入式计算机凭借其出色的性能、灵活的配置以及高度集成化的特点,在工业设备远程监控、维护与诊断方面发挥着关键作用。 一、远程监控与维护 …

华为 2024 届校园招聘-硬件通⽤/单板开发——第一套(部分题目分享,完整版带答案,共十套)

华为 2024 届校园招聘-硬件通⽤/单板开发——第一套 部分题目分享,完整版带答案(有答案和解析,答案非官方,未仔细校正,仅供参考)(共十套)获取(WX:didadidadidida313,加我…

【黑马头条】-day07APP端文章搜索-ES-mongoDB

文章目录 今日内容1 搭建es环境1.1 拉取es镜像1.2 创建容器1.3 配置中文分词器ik1.4 测试 2 app文章搜索2.1 需求说明2.2 思路分析2.3 创建索引和映射2.3.1 PUT请求添加映射2.3.2 其他操作 2.4 初始化索引库数据2.4.1 导入es-init2.4.2 es-init配置2.4.3 导入数据2.4.4 查询已导…

IT行业网络安全守护者-行云管家云堡垒机

IT行业即信息技术行业,是一个涵盖广泛的行业领域,主要涉及与信息的处理、存储、传输和应用相关的技术。对于IT行业而言,保障数据安全以及网络安全至关重要,一不小心就容易造成数据泄露事件。今天我们小编就给大家介绍一下IT行业网…

设计模式系列:单例模式

作者持续关注WPS二次开发专题系列,持续为大家带来更多有价值的WPS开发技术细节,如果能够帮助到您,请帮忙来个一键三连,更多问题请联系我(WPS二次开发QQ群:250325397),摸鱼吹牛嗨起来&#xff01…

scaling laws for neural language models

关于scaling law 的正确认识 - 知乎最近scaling law 成了最大的热词。一般的理解就是,想干大模型,清洗干净数据,然后把数据tokens量堆上来,然后搭建一个海量H100的集群,干就完了。训练模型不需要啥技巧,模型…

通过本机调试远端路由器非直连路由

实验目的:如图拓扑,通过本机电脑发,telnet调试远程AR4设备。 重点1:通过ospf路由协议配置拓扑网络,知识点:ospf配置路由器协议语法格式,area区域的定义,区域内网络的配置&#xff0…

基于单片机的奶瓶温控系统设计

摘要:本设计使用STC89C51单片机为核心芯片,DS18B20 作为温度检测模块,LCD1602 显示温度值,当温度低于设定的温度时,启动加热功能;当温度高于设定的温度时,该系统中断加热,实现自动报警功能。设计简单、成本低、实用性强。 关键词:单片机;温度传感器;设计 1 概述 随…

Docker内更新Jenkins详细讲解

很多小伙伴在Docker中使用Jenkins时更新遇到困难,本次结合自己的实际经验,详细讲解。根据官网Jenkins了解以下内容: 一、Jenkins 是什么? Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建、测…

React路由快速入门:Class组件和函数式组件的使用

1. 介绍 在开始学习React路由之前,先了解一下什么是React路由。React Router是一个为React应用程序提供声明式路由的库。它可以帮助您在应用程序中管理不同的URL,并在这些URL上呈现相应的组件。 2. 安装 要在React应用程序中使用React路由,…

RabbitMQ的自动应答和手动应答,解决重试死循环

RabbitMQ的自动应答和手动应答,解决重试死循环 1.应答模式 RabbitMQ 中的消息应答模式主要包括两种:自动应答(Automatic Acknowledgement)和手动应答(Manual Acknowledgement)。 1、自动应答:…

C++string类的实现

string类 string不属于STL,早于STL出现 看文档 C非官网(建议用这个) C官网 文章目录 string类一.为什么学习string类?1.C语言中的字符串2. 两个面试题(暂不做讲解) 二.标准库中的string类1. string类(了解)2. string类的常用接口说明(注意下面我只讲解…

【spring】@Scope注解学习

Scope介绍 Scope注解是Spring框架中用于指定bean作用域的注解。在Spring中,一个bean的作用域定义了该bean的生命周期和创建bean实例的上下文。Spring提供了几种预定义的作用域,同时也支持自定义作用域。通过使用Scope注解,开发者可以更精确地…

Element UI前端页面

1.前端 如何用ElementUI快速搭建一个前端网页模板,接下来会详细讲解! 1.Container布局 这是ElementUI官网提供的能快速搭建一个网页的基本布局模式,以下是一个网页的基本架构模式,主要分为三大块: AsideHeaderMain 我…

二、显示图片、提取边缘特征并保存(C# + OpenCV)

实现功能: 1,打开照片,并显示 2,对选择的照片进行Canny边缘检测 3,保存边缘检测之后的结果 一、布局 打开在视图下打开工具箱 选择一个PictureBox,仨Button 对Button改个名字 仨Button,分别…

记录Ubuntu 20.04中被困扰半年多之久的疑难的解决

一、我的ubuntu20.04症状描述: 在编辑文字文档的过程中,会不定时的出现鼠标指针随意跳动的情形,严重干扰了做文字编辑、编写代码等工作的进行。先后排除了戴尔笔记本及配件故障、鼠标故障、ubuntu系统中文档编辑软件的故障等可能。 二、原来…

监控指标体系:交互延迟上的探索与最佳实践

FID 在互联网高速发展的时代,用户体验已成为企业竞争的关键所在。网页性能作为用户体验的重要组成部分,直接影响着用户的满意度和工作效率。First Input Delay(FID)作为衡量网页性能的重要指标,越来越受到业界关注。今天,让我们一起来深入了解FID,探讨如何优化FID以提升…

VS Code开发插件使用 pnpm 打包异常的解决姿势

前言 刚刚准备发一个插件,发现用 pnpm 打出一个本地插件包直接扑街了。 这里只聚焦错误问题的解决,不是发插件的教程。。 聊点背景信息,vscode 的插件命令行的是 vsce 这个模块提供的 cli 能力去做的 环境 pnpm : 8.x 错误截图 本地打…