【基于Django框架的在线教育平台开发-02】用户注册功能开发

news2024/11/8 21:24:11

用户注册功能开发

文章目录

  • 用户注册功能开发
    • 1 模型层开发
    • 2 视图层开发
    • 3 配置urls.py
    • 4 表单验证
    • 5 模板层开发
    • 6 效果展示

1 模型层开发

用户数据表如下所示:

FieldTypeExtra
idintPrime Key & Auto Increment
passwordvarchar(128)
last_logindatetime(6)Allow Null
is_superusertinyint(1)
usernamevarchar(150)
first_namevarchar(150)
last_namevarchar(150)
emailvarchar(254)
is_stafftinyint(1)
is_activetinyint(1)
date_joineddatetime(6)
nick_namevarchar(50)
birthdaydateAllow Null
gendervarchar(6)
addressvarchar(100)
mobilevarchar(11)
imagevarchar(100)

由于Django内置了用户数据表,因此并没有新建数据表,而是选择重写默认用户数据表。由于后续诸多数据表都会用到add_time数据项,所以将该数据项暂时放在一个抽象类中,其他实体类继承于该抽象类。

这里提到的相关技术请参照:
【Django】模型层开发之重写模型类
【Django】模型层开发之创建并继承抽象模型类

from datetime import datetime

from django.db import models
from django.contrib.auth.models import AbstractUser

GENDER_CHOICES = (
    ("male", "男"),
    ("famale", "女"),
)


class BaseModel(models.Model):
    """
    用于存放多个模型共用的数据列,且不生成该类的数据表
    """
    add_time = models.DateTimeField(default=datetime.now, verbose_name="数据添加时间")

    class Meta:
        # 防止父类建表
        abstract = True


class UserProfile(AbstractUser):
    """
    重写用户模型类,继承自 AbstractUser
    """
    nick_name = models.CharField(max_length=50, verbose_name="昵称", default="")
    birthday = models.DateField(verbose_name="生日", null=True, blank=True)
    gender = models.CharField(verbose_name="性别", choices=GENDER_CHOICES, max_length=6)
    address = models.CharField(max_length=100, verbose_name="地址", default="")
    # mobile = models.CharField(max_length=11, unique=True, verbose_name="电话号码")
    mobile = models.CharField(max_length=11, verbose_name="电话号码")
    image = models.ImageField(verbose_name="用户头像", upload_to="head_image/%Y%m", default="default.jpg")

    class Meta:
        """
        对当前表进行相关设置
        """
        verbose_name = "用户信息"
        verbose_name_plural = verbose_name

    def __str__(self):
        """返回一个对象的描述信息"""
        if self.nick_name:
            return self.nick_name
        else:
            return self.username

2 视图层开发

图形验证码的相关知识请看:【Django】图形验证码显示及验证
数据库操作的相关知识请看:【Django】Mysql数据库操作(增、删、改、查)

当用户以GET方式访问注册界面时,仅生成图形验证码并传到前端显示。
当用户以POST方式访问注册界面时,需要验证前端传入的邮箱、密码和图形验证码,这部分的内容都在register_post_form.is_valid()这行代码中完成,系统会自动跳转到django内置的form表单验证模块进行验证,具体请看表单验证小节。最后,将数据写入MySQL数据库中并将表单数据发往前端模板层。

class RegisterView(View):
    def get(self, request, *args, **kwargs):
        register_get_form = RegisterGetForm()
        return render(request, "register.html", {
            "register_get_form": register_get_form,
        })

    def post(self, request, *args, **kwargs):
        register_post_form = RegisterPostForm(request.POST)
        if register_post_form.is_valid():
            email = register_post_form.cleaned_data["email"]
            password = register_post_form.cleaned_data["password"]
            user = UserProfile(username=email, email=email)
            user.set_password(password)
            user.save()
            login(request, user)
            return HttpResponseRedirect(reverse("index"))
        else:
            register_get_form = RegisterGetForm()
            return render(request, "register.html", {
                "register_get_form": register_get_form,
                "register_post_form": register_post_form,
            })

3 配置urls.py

注意:配置urls时需要设置name参数,后续前端界面配置url跳转时会使用到该参数。

from apps.users.views import RegisterView
urlpatterns += [
    ······
    path('register/', RegisterView.as_view(), name="register"),
]

4 表单验证

forms表单验证主要包括两部分:对前端表单数据的约束和对前端表单数据的验证。对数据的约束已经体现在变量定义中,数据验证则使用局部钩子对邮箱进行验证,保证邮箱唯一。对图形验证码captcha的验证不需要我们进行编码,模块中已经内置。

Q:什么是form表单中的局部钩子?
A:定义一个函数,名字叫:clean_字段名字,内部,取出该字段,进行校验,如果通过,将该字段返回,如果失败,抛异常(ValidationError)
 
注意:forms组件中的变量名必须与前端输入框的<name>标签保持一致。

class RegisterGetForm(forms.Form):
    captcha = CaptchaField()


class RegisterPostForm(forms.Form):
    captcha = CaptchaField()
    email = forms.EmailField(required=True)  # 变量名必须与前端name标签保持一致
    password = forms.CharField(required=True, min_length=6)

    def clean_email(self):
        email = self.data.get("email")
        users = UserProfile.objects.filter(email=email)
        if users:
            raise forms.ValidationError("该邮箱已注册")
        return email

5 模板层开发

  • 配置form表单提交方式为POST:method="post";配置form表单向注册url提交数据:action="{% url 'register' %}",其中register是urls.py配置中所设置的name参数,对应url:http://127.0.0.1:8000/register/。
  • 根据form表单验证中的报错信息高亮标注报错数据对应的输入框:在标签的class属性中添加{% if register_post_form.errors.username %}errorput{% endif %}
  • 显示报错信息。若form表单验证出错则显示其报错信息,否则显示视图层中回传的其余报错信息。
  • 显示验证码。在需要显示验证码的地方输入代码:{{ register_get_form.captcha }}
<form id="email_register_form" method="post" action="{% url 'register' %}" autocomplete="off">
    <div class="form-group marb20 {% if register_post_form.errors.email %}errorput{% endif %}">
        <label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
        <input type="text" id="id_email" name="email" value="{{ register_post_form.email.value }}"
               placeholder="请输入您的邮箱地址"/>
    </div>
    <div class="form-group marb8 {% if register_post_form.errors.password %}errorput{% endif %}">
        <label>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</label>
        <input type="password" id="id_password" name="password"
               value="{{ register_post_form.password.value }}"
               placeholder="请输入6-20位非中文字符密码"/>
    </div>
    <div class="form-group marb8 captcha1 ">
        <label>&nbsp;&nbsp;</label>
        {{ register_get_form.captcha }}
    </div>
    <div class="error btns" id="jsEmailTips"></div>
    {% if register_post_form.errors %}
        {% for key, error in register_post_form.errors.items %}
            {{ error }}
        {% endfor %}
    {% else %}
        {{ msg }}
    {% endif %}
    <div class="auto-box marb8">
    </div>
    <input class="btn btn-green" id="jsEmailRegBtn" type="submit" value="注册并登录"/>
    {% csrf_token %}
</form>

6 效果展示

在这里插入图片描述

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

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

相关文章

缓存雪崩和缓存穿透的解决方案

缓存雪崩 缓存雪崩是指存储在缓存里面的大量数据&#xff0c;在同一时刻全部过期&#xff0c;大部分流量直接到达了数据库&#xff0c;导致数据库压力增加&#xff0c;造成数据库崩溃的情况。 缓存雪崩的解决方案如下&#xff1a; 每个缓存的key设置不同的过期时间采用多级缓…

STM32单片机(九)USART串口----第四节:USART串口实战练习(串口发送+接收)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

在 K8S 中部署一个应用 下

接着上一篇继续部署应用到 K8S中 之前简单部署的简单集群&#xff0c;三个工作节点是运行在 docker 和 kubelet 的&#xff0c;还有一个是控制节点 ReplicationController &#xff0c; pod 和 service 本次关系 之前有提到 ReplicationController &#xff0c; pod 和 服务…

设计模式之命令模式笔记

设计模式之命令模式笔记 说明Command(命令)目录命令模式示例类图订单类厨师类抽象命令类订单命令类服务员类测试类 说明 记录下学习设计模式-命令模式的写法。JDK使用版本为1.8版本。 Command(命令) 意图:将一个请求封装为一个对象&#xff0c;从而使得可以用不同的请求对客…

STM32单片机(九)USART串口----第二节:USART串口外设

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

STM32单片机(九)USART串口----第三节:USART串口实战练习(串口发送)

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其是STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

常见面试题之MySQL篇

1.MySQL中&#xff0c;如何定位慢查询? 我们当时做压测的时候有的接口非常的慢&#xff0c;接口的响应时间超过了2秒以上&#xff0c;因为我们当时的系统部署了运维的监控系统Skywalking&#xff0c;在展示的报表中可以看到是哪一个接口比较慢&#xff0c;并且可以分析这个接…

【数据库七】MySQL主从复制与读写分离

MySQL主从复制与读写分离 1.案例概述2.什么是读写分离&#xff1f;3.为什么要读写分离呢&#xff1f;4.什么时候要读写分离&#xff1f;5.主从复制与读写分离6.MySQL主从复制原理6.1 mysql的复制类型 7.主从复制的工作过程7.1 MySQL架构图7.2 口语化工作工程 8.MySQL 读写分离原…

VSCode配置C语言编译环境

一、下载C语言编译器&#xff1a; &#xff08;1&#xff09;下载地址&#xff1a;MinGW-w64 - for 32 and 64 bit Windows - Browse /mingw-w64 at SourceForge.net 下载如下的windows版本&#xff1a; &#xff08;2&#xff09;配置环境变量&#xff1a; 二、安装VSCode …

Linux学习[18]bash学习深入4----命令执行的判断依据---【; , , ||】---用于一次性输入多指令情况

文章目录 前言判断符号 &#xff1b;判断符号 &&与||总结 前言 使用指令的时候&#xff0c;使用完一个指令之后&#xff0c;我想让它接着执行另一个指令&#xff0c;而非等A指令执行完之后再输入B指令。 为了实现这个效果&#xff0c;我查阅了相关资料&#xff0c;这里…

【从零开始学习JAVA | 第十六篇】杂项知识点介绍

目录 前言&#xff1a; 包&#xff1a; final: 权限修饰符&#xff1a; 总结&#xff1a; 前言&#xff1a; 本文不隶属于正文序列&#xff0c;而是对面向对象中的一些常用词进行介绍&#xff0c;方便大家理解记忆&#xff0c;本文将会逐一介绍 什么是包&#xff0c;final…

云服务器部署企业版openGauss

openGauss 企业版安装 教程 1.下载安装包 在华为云上租一台服务器&#xff0c;操作系统选&#xff1a;openEuler 20.03 64bit (64-bit) 获取openGauss Server安装包&#xff0c;企业版&#xff1a;软件包链接 使用xshell连接服务器&#xff0c;准备软硬件安装环境(该装的依…

【软件架构模式】—微内核架构

欢迎回到软件架构模式博客系列。这是本系列的第 4 章&#xff0c;我们将讨论微内核架构模式 概述&#xff1a; 内核模式也被称为插件架构模式。将附加应用程序功能作为插件添加到核心应用程序&#xff0c;以提供可扩展性以及功能分离和隔离。 这种模式由两种类型的架构组件组…

如何搭建LNMP架构

目录 一、什么是LNMP Linux系统 Apache服务 Nginx服务 MySQL数据库 PHP服务 二、搭建LNMP 安装Nginx服务 第一步 关闭防火墙和安全机制 第二步 安装依赖环境 第三步 创建运行用户 第四步 解压服务包 第五步 编译安装 第六步 编译 第八步 添加 Nginx 系统服务 …

leetcode63. 不同路径 II(动态规划-java)

不同路径 II leetcode63. 不同路径 II题目描述暴力递归代码演示动态规划代码演示 动态规划空间压缩 动态规划专题 leetcode63. 不同路径 II 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/unique-paths-ii 题目描述 一个…

自然图像中的字符识别:Chars74K 数据集

字符识别是 研究人员从计算机早期开始工作 视觉。随着当今相机的无所不在&#xff0c;应用 的自动字符识别比以往任何时候都更广泛。为 拉丁字母&#xff0c;这在很大程度上被认为是一个已解决的问题 受限情况&#xff0c;例如扫描文档的图像 包含常用字符字体和统一 背景。但是…

7.4_3B+树

特点&#xff1a;块内无序&#xff0c;块间有序(类比于分块查找) 这个性质是为了追求平衡 3&#xff09;结点的子树个数与关键字个数相等 4&#xff09;所有叶节点包含全部关键字及指向相应记录的指针&#xff0c;叶节点中将关键字按照大小顺序排列&#xff0c; 并且相邻叶节点…

Camera之android8.0以上HIDL与C++数据类型转换(三十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

rust 集合、错误处理、泛型、Trait、生命周期、包

集合组织特性相同的数据&#xff1b;泛型可以定义任何抽象数据类型&#xff1b;生命周期限制所有权的作用域范围&#xff1b;错误处理使程序更健壮。 集合 一组特性相同的数据集合&#xff0c;除了基本数据类型的元组、数组。rust 标准库提供了一些非常有用的数据结构。 Vec…

Redis从入门到精通【进阶篇】之高可用主从详解

文章目录 0.前言1.详解1.1 主从复制概述1.2 主从复制原理1.2.1.全量复制1.2.2.增量复制1.2.3.详细描述1.3 更深入理解1.4 常见面试题 2. 总结3. Redis从入门到精通系列文章 0.前言 Redis是一个高性能的键值存储系统&#xff0c;广泛应用于Web应用、缓存、消息队列等领域。在实…