Django可重用注册系统项目----(4)(登陆+登出+邮箱验证+验证码)函数实现及登陆注册页表单、密码加密、生成确认码、邮件发送


1. 路由配置


1.1 主路由


loginRegister/urls.py

from django.contrib import admin
from django.urls import path,include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('login.urls'))
    path('captcha/', include('captcha.urls')), # 验证码
]

1.2 子路由


login/urls

from django.urls import path
from login import views
urlpatterns = [
    path('index/', views.index, name='index'), #首页
    path('login/', views.login, name='login'), # 登录页
    path('register/', views.register, name='register'), # 注册页面
    path('logout/', views.logout, name='logout'), # 登出页面
    path('confirm/', views.user_confirm, name='confirm'), # 邮件确认请求页
]

2. 登陆及注册页面表单


2.1 Django表单简介


Django表单官方

我们前面都是手工在HTML文件中编写表单form元素,然后在views.py的视图函数中接收表单中的用户数据,再编写验证代码进行验证,最后使用ORM进行数据库的增删改查。这样费时费力,整个过程比较复杂,而且有可能写得不太恰当,数据验证也比较麻烦。设想一下,如果我们的表单拥有几十上百个数据字段,有不同的数据特点,如果也使用手工的方式,其效率和正确性都将无法得到保障。有鉴于此,Django在内部集成了一个表单功能,以面向对象的方式,直接使用Python代码生成HTML表单代码,专门帮助我们快速处理表单相关的内容。

Django的表单给我们提供了下面三个主要功能:

  • 准备和重构数据用于页面渲染;
  • 为数据创建HTML表单元素;
  • 接收和处理用户从表单发送过来的数据。

编写Django的form表单,非常类似我们在模型系统里编写一个模型。在模型中,一个字段代表数据表的一列,而form表单中的一个字段代表 <form> 中的一个 <input> 元素。

2.2 创建表单


login/forms.py

from captcha.fields import CaptchaField
from django import forms
# 登陆页表单
class LoginForm(forms.Form):
    username = forms.CharField(label='用户名', required=True, max_length=128)
    password = forms.CharField(label='密码', required=True, max_length=10)
    captcha = CaptchaField(label='验证码', required=True)
# 注册页表单
class RegisterForm(forms.Form):
    username = forms.CharField(label="用户名", required=True, max_length=128)
    password1 = forms.CharField(label="密码", required=True, max_length=256)
    password2 = forms.CharField(label="确认密码", required=True, max_length=256)
    email = forms.EmailField(label="邮箱地址")
    captcha = CaptchaField(label="验证码")

3. 其他功能实现


文件: login/utils.py

引入包:

import hashlib
import datetime
from django.core.mail import send_mail
from login.models import ConfirmString
from loginRegister import settings

3.1 密码加密


def hash_code(s, salt='mysite'):# 加点盐
    h = hashlib.sha256()
    s += salt
    h.update(s.encode()) # update方法只接收bytes类型
    return h.hexdigest()

3.2 生成确认码


# 创建确认码对象
def make_confirm_string(user):
    # 获取当前时间
    now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    code = hash_code(user.name, now)
    ConfirmString.objects.create(code=code, user=user)
    return code

3.3 发送邮件


send_email(email, code) 方法接收两个参数,分别是注册的邮箱和前面生成的哈希值,

def send_email(email, code):
	# 邮件内容
    subject = '注册确认邮件'
    text_content = '''感谢注册,这里是登录注册系统网站!\
                    如果你看到这条消息,说明你的邮箱服务器不提供HTML链接功能,请联系管理员!'''
    html_content = '''
    <p>感谢注册<a href="http://{}/confirm/?code={}" target=blank>点击验证</a>,\
    这里是登录注册系统网站!</p>
    <p>请点击站点链接完成注册确认!</p>
    <p>此链接有效期为{}天!</p>
    '''.format('127.0.0.1:9999', code, settings.CONFIRM_DAYS)
    # 发送
    send_mail(subject, text_content, settings.EMAIL_HOST_USER, [email, ], html_message=html_content)

4. 视图函数


视图函数: login/views.py

4.1 引入包


from datetime import datetime, timedelta
from django.shortcuts import render, redirect

from login.models import SiteUser, ConfirmString
from login.forms import LoginForm, RegisterForm
from login.utils import hash_code, make_confirm_string, send_email
from loginRegister import settings

4.2 首页函数


def index(request):
    if request.session.get('is_login'):
        return render(request, 'login/index.html')
    return redirect('/login/')

4.3 登陆函数


登陆条件:

  • 用户存在
  • 密码正确
  • 注册后点击邮件确认请求
  • 验证码正确

def login(request):
    if request.method == 'POST':
        login_form = LoginForm(request.POST)
        if login_form.is_valid():
            username = login_form.cleaned_data.get('username')
            password = login_form.cleaned_data.get('password')
            user = SiteUser.objects.filter(name=username).first()
            if not user:
                message = "用户不存在!"
                return render(request, 'login/login.html', locals())
            if hash_code(password) != user.password:
                message = "密码输入错误!"
                return render(request, 'login/login.html', locals())
            else:
                if not user.has_confirmed:
                    message = '该用户还未经过邮件确认!'
                    return render(request, 'login/login.html', locals())
                request.session['is_login'] = True
                request.session['user_id'] = user.id
                request.session['username'] = user.name
                return redirect('/index/')
        else:
            message = "请输入合法信息!"
            return render(request, 'login/login.html', locals())
    login_form = LoginForm()
    return render(request, 'login/login.html', locals())

4.4 邮箱注册函数


注册条件:

  • 邮箱填写正确
  • 其他内容合法
  • 用户名未被注册
  • 邮箱未被注册

def register(request):
    # 如果用户已经登录,则不能注册跳转到首页。
    if request.session.get('is_login', None):
        return redirect('/index/')
    # 如果是POST请求
    if request.method == 'POST':
        # print(request.POST)
        register_form = RegisterForm(request.POST)
        message = "请检查填写的内容!"
        # 先验证提交的数据是否通过
        if register_form.is_valid():
            # 清洗数据
            username = register_form.cleaned_data.get('username')
            password1 = register_form.cleaned_data.get('password1')
            password2 = register_form.cleaned_data.get('password2')
            email = register_form.cleaned_data.get('email')
            # 接下来判断用户名和邮箱是否已经被注册
            same_name_user = SiteUser.objects.filter(name=username)
            if same_name_user:
                message = '用户名已经存在'
                return render(request, 'login/register.html', locals())
            same_email_user = SiteUser.objects.filter(email=email)
            if same_email_user:
                message = '该邮箱已经被注册了!'
                return render(request, 'login/register.html', locals())
            try:
                # 将注册的信息存储到数据库,跳转到登录界面
                new_user = SiteUser(name=username, password=hash_code(password1), email=email)
                new_user.save()
                # 生成确认码并发送确认邮件
                code = make_confirm_string(new_user)
                send_email(email, code)
                message = "请前往邮箱进行确认!"
            except Exception:
                new_user.delete()
                message = "发送邮件失败!"
                return render(request, 'login/register.html', locals())
            else:
                return redirect('/login/')
    # 如果是GET请求,返回用户注册的html页面。
    register_form = RegisterForm()
    return render(request, 'login/register.html', locals())

4.5 登出函数


def logout(request):
    if request.session.get('is_login'):
        request.session.flush()  # 清空session信息
    return redirect('/login/')

4.6 确认注册请求函数


  • 获取确认码信息
  • 数据库中是否有该确认码,如果没有, 返回说是无效的请求
  • 数据库中是否有该确认码,如果有, 判断是否过期? 如果过期,删除用户信息,否则更新用户信息。

def user_confirm(request):
    code = request.GET.get('code', None)
    message = ''
    try:
        confirm = ConfirmString.objects.get(code=code)
    except:
        message = '无效的确认请求!'
        return render(request, 'login/confirm.html', locals())
    create_time = confirm.create_time
    now = datetime.now()
    if now > create_time + timedelta(settings.CONFIRM_DAYS):
        confirm.user.delete()
        message = '您的邮箱已经过期!请重新注册!'
    else:
        confirm.user.has_confirmed = True
        confirm.user.save()
        confirm.delete()
        message = '感谢确认,请使用账户登录!'
    return render(request, 'login/confirm.html', locals())

猜你喜欢

转载自blog.csdn.net/weixin_46069582/article/details/114593557