使用Django创建一个系统(下)

本文详细介绍了如何使用Django构建一个包含图形验证码、邮箱注册及邮件验证功能的用户注册系统。从表单创建、视图逻辑优化到前端模板的调整,再到密码加密存储和邮箱确认流程,一步步展示了完整的实现过程。此外,还涉及了如何发送邮件、处理邮件确认请求以及注册规则的修改。
摘要由CSDN通过智能技术生成

可重用用户注册系统

8、图片验证码

为了防止机器人频繁登录网站或者破坏分子恶意登录,很多用户登录和注册系统都提供了图形验证码功能。
在Django中实现图片验证码功能非常简单,有现成的第三方库可以使用,我们不必自己开发(不必重复造轮子)。这个库叫做django-simple-captcha。
具体安装教程 :戳我

Django表单
  • 创建表单类型
# /login/forms.py(新建的文件)
from captcha.fields import CaptchaField
from django import forms

class LoginForm(forms.Form):
    username = forms.CharField(label='用户名', required=True, min_length=4, max_length=128)
    password = forms.CharField(label='密码', required=True, min_length=4, max_length=10)
    captcha = CaptchaField(label='验证码')
  • 视图逻辑优化
# login/views.py
def login(request):
    #请求方法为POST提交
    if request.method == "POST":
        # 修改1、实例化表单对象
        login_form = LoginForm(request.POST)
        # 修改2、验证表单数据是否符合表单定义的语法
        if login_form.is_valid():
            # 修改3、获取表单填写的数据并进行数据清洗
            username = login_form.cleaned_data.get('username')
            password = login_form.cleaned_data.get('password')
            user = SiteUser.objects.filter(name=username, password=password).first()
            if user:
                request.session['is_login'] = True
                request.session['user_id'] = user.id
                request.session['username'] = user.name
                # return redirect('/index/')
                return render(request, 'login/index.html')
            else:
                message = "用户名或密码错误"
                # 修改4、locals()以字典方式返回当前所有的变量到用户(前端)
                # eg: {'message':"xxxx",'login_form':"xxxx"}
                return render(request, 'login/login.html', locals())
        else:
            message = "填写的信息不正确或是不合法!"
            return render(request, 'login/login.html', locals())
    #请求方法为GET请求
    login_form = LoginForm()
    return render(request, 'login/login.html', locals())
Templatest页面优化
# login/login.html(部分修改)
# 修改1、不同的报错显示不同的信息
<h3 style="text-align: center">用户登录</h3>
            {% if login_form.captcha.errors %}
            <div class="alert alert-warning" role="alert">
                <strong>登陆失败!</strong>  验证码不正确!
            </div>
            {% elif message %}
            <div class="alert alert-warning" role="alert">
                <strong>登录失败!</strong> {{ message }}
            </div>
            {% endif %}


 {% csrf_token %}
                <div class="form-group">
                    <label>{{ login_form.username.label }}</label>
                    <input type="text" class="form-control" name="username">
                </div>


                <div class="form-group">
                    <label>{{ login_form.password.label }}</label>
                    <input type="password" class="form-control" name="password">
                    <small class="form-text text-muted">密码必须是由字母、数字或是特殊符号组成</small>
                </div>

                <div class="form-group">
                    <label>{{ login_form.captcha.label }}</label>
                    {{ login_form.captcha }}
                </div>
验证是否正确

localhost:8000/login
在这里插入图片描述

9、邮箱注册

发送邮件功能测试
  • 配置邮件信息
# loginRegister/settings.py
# mail configure(添加信息如下)
EMAIL_HOST = 'smtp.163.com'
EMAIL_PORT = 25
EMAIL_HOST_USER = 'binghh1314@163.com'
EMAIL_HOST_PASSWORD = 'ZJPCYZRDKCUKIQNS' # 是邮箱的授权码,不是登录密码
EMAIL_USER_SSL = False #不开启SSL模式
  • 如何获取授权码

163邮箱:设置–>SMTP设置–>开启SMTP的所有服务并复制授权码
在这里插入图片描述
确保SMTP开启才能发送使用该邮箱发送邮件
在这里插入图片描述
需要的话可以再次新增授权码
在这里插入图片描述

  • 交互环境中测试发送邮件是否成功
python manage.py shell

# 引进settings中的EMAIL_HOST_USER
In [2]: from loginRegister.settings import EMAIL_HOST_USER
# 引进django中的mail模块
In [3]: from django.core.mail import send_mail
# 编辑测试发送的邮件信息
In [4]: send_mail("test","content",EMAIL_HOST_USER,['binghh1314@163.c
   ...: om'])
# 输出为1表示发送邮件成功
Out[4]: 1

在163邮箱端查看是否能够接收到邮件
在这里插入图片描述

基本的注册功能实现
  • 注册表单
# login/forms.py
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='验证码')
  • 实现注册视图
  1. 如果用户已经登录,则不能跳转到注册界面
  2. 如果是GET请求,返回用户注册的HTML页面
  3. 如果是POST请求,先验证提交的数据是否通过,清洗数据。接下来判断用户名的邮箱是否已经被注册,将注册信息储存到数据库并跳转到登录界面
  4. 额外功能:为了数据的安全性注册时,密码存储到数据不铭文存储,二十先加密再存储
loginRegister/views.py

def login(request):
    # 请求方法为POST提交
    if request.method == "POST":
        # 修改1、实例化表单对象
        login_form = LoginForm(request.POST)
        # 修改2、验证表单数据是否符合表单定义的语法
        if login_form.is_valid():
            # 修改3、获取表单填写的数据并进行数据清洗
            username = login_form.cleaned_data.get('username')
            password = login_form.cleaned_data.get('password')
            user = SiteUser.objects.filter(name=username, password=password).first()
            if user:
                request.session['is_login'] = True
                request.session['user_id'] = user.id
                request.session['username'] = user.name
                # return redirect('/index/')
                return render(request, 'login/index.html')
            else:
                message = "用户名或密码错误"
                # 修改4、locals()以字典方式返回当前所有的变量到用户(前端)
                # eg: {'message':"xxxx",'login_form':"xxxx"}
                return render(request, 'login/login.html', locals())
        else:
            message = "填写的信息不正确或是不合法!"
            return render(request, 'login/login.html', locals())
    # 请求方法为GET请求
    login_form = LoginForm()
    return render(request, 'login/login.html', locals())
  • Templates模板的更改
templates/login/register.html
			{% if register_form.captcha.errors %}
                <div class="alert alert-warning" role="alert">
                    <strong>注册失败!</strong> 验证码不正确!
                </div>

            {% elif message %}
                <div class="alert alert-warning" role="alert">
                    <strong>注册失败!</strong> {{ message }}
                </div>

            {% endif %}

            <form action="/register/" method="post">
                {% csrf_token %}
                
                <div class="form-group">
                    <label>{{ register_form.username.label }}</label>
                    <input type="text" class="form-control" name="username">
                    <small id="emailHelp" class="form-text text-muted"></small>
                </div>

                <div class="form-group">
                    <label>{{ register_form.email.label}}</label>
                    <input type="email" class="form-control" name="email">
                </div>

                <div class="form-group">
                    <label>{{ register_form.password1.label }}</label>
                    <input type="password" class="form-control" name="password1">
                    <small>密码必须由字母数字特殊字符组成</small>
                </div>

                <div class="form-group">
                    <label>{{ register_form.password2.label }}</label>
                    <input type="password" class="form-control" name="password2">
                </div>

                <div class="form-group">
                    <label>{{ register_form.captcha.label }}</label>
                    {{ register_form.captcha }}
                </div>
  • 测试

进入浏览器进行注册
在这里插入图片描述

注册添加密码加密功能

对于如何加密密码,有很多不同的途径,其安全程度也高低不等。这里我们使用Python内置的hashlib库,使用哈希值的方式加密密码,可能安全等级不够高,但足够简单,方便使用。

loginRegister/utils.py

import hashlib
def hash_code(s, salt='mysite'):
    h = hashlib.sha256()
    s += salt
    h.updates(s.encode())
    return h.hexdigest()
loginRegister/views.py

def login(request):
	# 修改1
    user = SiteUser.objects.filter(name=username, password=hash_code(password)).first()

def register(request):
	# 修改2
    new_user = SiteUser(name=username, password=hash_code(password1), email=email)
  • 测试查看加密后的密码在数据库中的形态
    在这里插入图片描述
邮箱注册确认

很自然地,我们会想到如果能用邮件确认的方式对新注册用户进行审查,既安全又正式,也是目前很多站点的做法。

  • 创建模型

既然要区分通过和未通过邮件确认的用户,那么必须给用户添加一个是否进行过邮件确认的属性
另外,我们要创建一张新表,用于保存用户的确认码以及注册提交的时间。

#login/models.py

class SiteUser(models.Model):
	# 新增的行
	has_confirmed = models.BooleanField(default=False)

# 新添加的类模型
class ConfirmString(models.Model):
    code = models.CharField(max_length=256)
    user = models.OneToOneField('SiteUser', on_delete=models.CASCADE)
    create_time = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.user.name + ":   " + self.code

    class Meta:
        ordering = ["-create_time"]
        verbose_name = "确认码"
        verbose_name_plural = "确认码"

数据库模型更改一定要注意进行数据库的迁移和写入数据库

同时应当修改admin.py,方便在后台进行修改和观察数据

# login/admin.py
admin.site.register(ConfirmString)
  • 修改视图
# login/views.py

 # 将注册信息储存到数据库并跳转到登录界面
     new_user = SiteUser(name=username, password=hash_code(password1), email=email)
     new_user.save()

 # 生成确认码并发送确认邮件
     code = make_confirm_string(new_user)
            send_email(email, code)
    # 这两个类需要在新的文件urls.py中编辑,编辑后注意引进到该文件中
  • 新添加的文件中写入新的类
#login/utils.py #新添加的函数

import datetime

# make_confirm_string是创建确认码对象的方法
def make_confirm_string(user):
    # 获取当前时间
    print('确认码生成中.......')
    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


# send_mail(email,code)函数接收两个参数,分别是注册使用的邮箱和前面生成的哈希值
def send_email(email, code):
    print('邮件发送中......')
    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:8000', code, settings.CONFIRM_DAYS)# 需要在settings文件中添加设置

    send_mail(subject, text_content,
              settings.EMAIL_HOST_USER, email, html_message=html_content)
  • 有效期天数设置
# loginRegister/settings.py(添加的内容)

 # 确认邮件失效的时间
CONFIRM_DAYS = 3
  • 再次修改视图
# login/views.py
def register(request):
			........
			
            if same_name_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)
                print('code:', code)
                send_email(email, code)
                message = '邮件已发送!请前往邮箱确认!'
            except Exception:
                return render(request, 'login/register.html', locals())
            else:
                return render(request, 'login/login.html', locals())

    # 如果是GET请求,返回用户注册的HTML页面
    register_form = RegisterForm()
    # 额外功能:为了数据的安全性注册时,密码存储到数据不明文存储,先加密再存储
    return render(request, 'login/register.html', locals())
  • 测试邮件能否发送成功
    注册一个新用户,测试能否收到邮件
    在这里插入图片描述
    在这里插入图片描述
  • 处理邮件请求
# login/urls.py添加一条新的url
	path('confirm/', views.user_confrim),

在视图中添加user_confirm类

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

  • 修改登录规则
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值