Django加Vue电商项目实战18 实现用户注册登录和注销

前言

学无止境,无止境学。大家好,我是张大鹏,之前在抖音有5万多粉丝,不过现在不拍视频,专心写公众号了。笔者目前是高级Python工程师,之前是全栈工程师,主要擅长Golang和Python开发,对于JavaVue,React也有一些研究。工作之余,喜欢学习和分享,希望能够通过此公众号”张大鹏520″,将自己学到的东西分享给大家,和大家一起交流,一起成长,一起进步。

今天要给大家分享的是《Django加Vue电商项目实战18 实现用户注册登录和注销》,这是一个系列的教程,从零基础到项目实战。在本教程中,我会给大家介绍实现用户注册,登录和注销。比如注册页面的实现,登录页面的实现,注册和登录表单,视图函数实现等。还会配套相关的练习,大家学完以后可以自行通过练习题巩固和加深对知识点的理解。

如果大家需要本教程的PDF电子书或者完整的源码,可以在文末找到获取方式哈。

效果预览

注册页面

展示注册页面:

Django加Vue电商项目实战18 实现用户注册登录和注销


注册信息校验,会回显错误信息:

Django加Vue电商项目实战18 实现用户注册登录和注销


登录页面

展示登录页面:

Django加Vue电商项目实战18 实现用户注册登录和注销


登录信息校验,会回显错误信息:

Django加Vue电商项目实战18 实现用户注册登录和注销


登录成功以后跳转到首页:

Django加Vue电商项目实战18 实现用户注册登录和注销


注销功能

Django加Vue电商项目实战18 实现用户注册登录和注销


点击注销以后清空用户session,跳转到登录页面。

页面实现

注册页面

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>大鹏商城后台管理系统</title>
    <link rel="stylesheet" href="{% static 'css/style.css' %}">
    <link rel="shortcut icon" href="{% static 'images/favicon.ico' %}"/>
    <style>
        .form-group label {
            color: red;
            margin-top5px;
        }
    
</style>
</head>
<body>
<div class="container-scroller">
    <div class="container-fluid page-body-wrapper full-page-wrapper">
        <div class="content-wrapper d-flex align-items-center auth">
            <div class="row flex-grow">
                <div class="col-lg-4 mx-auto">
                    <div class="auth-form-light text-left p-5">
                        <div class="brand-logo">
                            <img src="{% static 'images/logo.svg' %}">
                        </div>
                        <h4>注册新用户</h4>
                        <h6 class="font-weight-light">只需要非常简单的步骤,就能够快速注册一个新的账号</h6>
                        <form class="pt-3" method="post" action="{% url 'user:register' %}" novalidate>
                            {% csrf_token %}
                            <div class="form-group">
                                {{ register_form.username }}
                                {% if register_form.errors.username %}
                                    <label>{{ register_form.errors.username.0 }}</label>
                                {% endif %}
                            </div>
                            <div class="form-group">
                                {{ register_form.password }}
                                {% if register_form.errors.password %}
                                    <label>{{ register_form.errors.password.0 }}</label>
                                {% endif %}
                            </div>
                            <div class="form-group">
                                {{ register_form.re_password }}
                                {% if register_form.errors.re_password %}
                                    <label>{{ register_form.errors.re_password.0 }}</label>
                                {% endif %}
                            </div>
                            <div class="mt-3">
                                <button class="btn btn-block btn-gradient-primary btn-lg font-weight-medium auth-form-btn"
                                        type="submit">

                                    立即注册
                                </button>
                            </div>
                            <div class="text-center mt-4 font-weight-light"> 已经拥有账号? <a
                                    href="{% url 'user:login' %}" class="text-primary">
立即登录</a>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

登录页面

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>大鹏商城后台管理系统</title>
    <link rel="stylesheet" href="{% static 'css/style.css' %}">
    <link rel="shortcut icon" href="{% static 'images/favicon.ico' %}"/>
    <style>
        .form-group label {
            color: red;
            margin-top5px;
        }
    
</style>
</head>
<body>
<div class="container-scroller">
    <div class="container-fluid page-body-wrapper full-page-wrapper">
        <div class="content-wrapper d-flex align-items-center auth">
            <div class="row flex-grow">
                <div class="col-lg-4 mx-auto">
                    <div class="auth-form-light text-left p-5">
                        <div class="brand-logo">
                            <img src="{% static 'images/logo.svg' %}">
                        </div>
                        <h4>欢迎使用大鹏商城后台管理系统</h4>
                        <h6 class="font-weight-light">请登录您的账号</h6>
                        <form class="pt-3" method="post" action="{% url 'user:login' %}" novalidate>
                            {% csrf_token %}
                            <div class="form-group">
                                {{ login_form.username }}
                                {% if login_form.errors.username %}
                                    <label>{{ login_form.errors.username.0 }}</label>
                                {% endif %}
                            </div>
                            <div class="form-group">
                                {{ login_form.password }}
                                {% if login_form.errors.password %}
                                    <label>{{ login_form.errors.password.0 }}</label>
                                {% endif %}
                                {% if info %}
                                    <label>{{ info }}</label>
                                {% endif %}
                            </div>
                            <div class="mt-3">
                                <button class="btn btn-block btn-gradient-primary btn-lg font-weight-medium auth-form-btn"
                                        type="submit">

                                    立即登录
                                </button>
                            </div>
                            <div class="text-center mt-4 font-weight-light"> 没有账号? <a
                                    href="{% url 'user:register' %}" class="text-primary">
立即注册</a>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

公共顶部实现注销

{% load static %}
{#顶部导航开始#}
<nav class="navbar default-layout-navbar col-lg-12 col-12 p-0 fixed-top d-flex flex-row">
    {#logo#}
    <div class="text-center navbar-brand-wrapper d-flex align-items-center justify-content-center">
        <a class="navbar-brand brand-logo" href="{% url 'index:index' %}">
            <img src="{% static 'images/logo.svg' %}" alt="logo"/>
        </a>
        <a class="navbar-brand brand-logo-mini" href="{% url 'index:index' %}">
            <img src="{% static 'images/logo-mini.svg' %}" alt="logo"/>
        </a>
    </div>

    {#导航菜单#}
    <div class="navbar-menu-wrapper d-flex align-items-stretch">
        <button class="navbar-toggler navbar-toggler align-self-center" type="button" data-toggle="minimize">
            <span class="mdi mdi-menu"></span>
        </button>
        {#搜索#}
        <div class="search-field d-none d-md-block">
            <form class="d-flex align-items-center h-100" action="#">
                <div class="input-group">
                    <div class="input-group-prepend bg-transparent">
                        <i class="input-group-text border-0 mdi mdi-magnify"></i>
                    </div>
                    <input type="text" class="form-control bg-transparent border-0" placeholder="请输入...">
                </div>
            </form>
        </div>

        {#右侧菜单#}
        <ul class="navbar-nav navbar-nav-right">
            {#头像#}
            <li class="nav-item nav-profile dropdown">
                <a class="nav-link dropdown-toggle" id="profileDropdown" href="#" data-bs-toggle="dropdown"
                   aria-expanded="false">

                    <div class="nav-profile-img">
                        <img src="{% static 'images/faces/face1.jpg' %}" alt="image">
                        <span class="availability-status online"></span>
                    </div>
                    <div class="nav-profile-text">
                        <p class="mb-1 text-black">{{ request.user.username }}</p>
                    </div>
                </a>
                <div class="dropdown-menu navbar-dropdown" aria-labelledby="profileDropdown">
                    <a class="dropdown-item" href="#">
                        <i class="mdi mdi-cached me-2 text-success"></i> 用户日志
                    </a>
                    <div class="dropdown-divider"></div>
                    {#注销#}
                    <a class="dropdown-item" href="{% url 'user:logout' %}">
                        <i class="mdi mdi-logout me-2 text-primary"></i> 注销
                    </a>
                </div>
            </li>

            {#全屏#}
            <li class="nav-item d-none d-lg-block full-screen-link">
                <a class="nav-link">
                    <i class="mdi mdi-fullscreen" id="fullscreen-button"></i>
                </a>
            </li>

            {#消息#}
            <li class="nav-item dropdown">
                <a class="nav-link count-indicator dropdown-toggle" id="messageDropdown" href="#"
                   data-bs-toggle="dropdown" aria-expanded="false">

                    <i class="mdi mdi-email-outline"></i>
                    <span class="count-symbol bg-warning"></span>
                </a>
                <div class="dropdown-menu dropdown-menu-right navbar-dropdown preview-list"
                     aria-labelledby="messageDropdown">

                    <h6 class="p-3 mb-0">消息列表</h6>
                    <div class="dropdown-divider"></div>
                    <a class="dropdown-item preview-item">
                        <div class="preview-thumbnail">
                            <img src="{% static 'images/faces/face4.jpg' %}" alt="image" class="profile-pic">
                        </div>
                        <div class="preview-item-content d-flex align-items-start flex-column justify-content-center">
                            <h6 class="preview-subject ellipsis mb-1 font-weight-normal">标记并发送你的消息</h6>
                            <p class="text-gray mb-0"> 1 分钟以前 </p>
                        </div>
                    </a>
                    <div class="dropdown-divider"></div>
                    <a class="dropdown-item preview-item">
                        <div class="preview-thumbnail">
                            <img src="{% static 'images/faces/face2.jpg' %}" alt="image" class="profile-pic">
                        </div>
                        <div class="preview-item-content d-flex align-items-start flex-column justify-content-center">
                            <h6 class="preview-subject ellipsis mb-1 font-weight-normal">标记并发送你的消息</h6>
                            <p class="text-gray mb-0"> 15 分钟以前 </p>
                        </div>
                    </a>
                    <div class="dropdown-divider"></div>
                    <a class="dropdown-item preview-item">
                        <div class="preview-thumbnail">
                            <img src="{% static 'images/faces/face3.jpg' %}" alt="image" class="profile-pic">
                        </div>
                        <div class="preview-item-content d-flex align-items-start flex-column justify-content-center">
                            <h6 class="preview-subject ellipsis mb-1 font-weight-normal">更新你的头像</h6>
                            <p class="text-gray mb-0"> 18 分钟以前 </p>
                        </div>
                    </a>
                    <div class="dropdown-divider"></div>
                    <h6 class="p-3 mb-0 text-center">4 条新消息</h6>
                </div>
            </li>

            {#通知#}
            <li class="nav-item dropdown">
                <a class="nav-link count-indicator dropdown-toggle" id="notificationDropdown" href="#"
                   data-bs-toggle="dropdown">

                    <i class="mdi mdi-bell-outline"></i>
                    <span class="count-symbol bg-danger"></span>
                </a>
                <div class="dropdown-menu dropdown-menu-right navbar-dropdown preview-list"
                     aria-labelledby="notificationDropdown">

                    <h6 class="p-3 mb-0">通知列表</h6>
                    <div class="dropdown-divider"></div>
                    <a class="dropdown-item preview-item">
                        <div class="preview-thumbnail">
                            <div class="preview-icon bg-success">
                                <i class="mdi mdi-calendar"></i>
                            </div>
                        </div>
                        <div class="preview-item-content d-flex align-items-start flex-column justify-content-center">
                            <h6 class="preview-subject font-weight-normal mb-1">今日提现</h6>
                            <p class="text-gray ellipsis mb-0"> 记得学习Django哦 </p>
                        </div>
                    </a>
                    <div class="dropdown-divider"></div>
                    <a class="dropdown-item preview-item">
                        <div class="preview-thumbnail">
                            <div class="preview-icon bg-warning">
                                <i class="mdi mdi-settings"></i>
                            </div>
                        </div>
                        <div class="preview-item-content d-flex align-items-start flex-column justify-content-center">
                            <h6 class="preview-subject font-weight-normal mb-1">设置</h6>
                            <p class="text-gray ellipsis mb-0"> 更新面板 </p>
                        </div>
                    </a>
                    <div class="dropdown-divider"></div>
                    <a class="dropdown-item preview-item">
                        <div class="preview-thumbnail">
                            <div class="preview-icon bg-info">
                                <i class="mdi mdi-link-variant"></i>
                            </div>
                        </div>
                        <div class="preview-item-content d-flex align-items-start flex-column justify-content-center">
                            <h6 class="preview-subject font-weight-normal mb-1">启动后台</h6>
                            <p class="text-gray ellipsis mb-0"> 新的后台管理系统 </p>
                        </div>
                    </a>
                    <div class="dropdown-divider"></div>
                    <h6 class="p-3 mb-0 text-center">查看所有通知</h6>
                </div>
            </li>

            {#图标#}
            <li class="nav-item nav-logout d-none d-lg-block">
                <a class="nav-link" href="#">
                    <i class="mdi mdi-power"></i>
                </a>
            </li>

            {#图标#}
            <li class="nav-item nav-settings d-none d-lg-block">
                <a class="nav-link" href="#">
                    <i class="mdi mdi-format-line-spacing"></i>
                </a>
            </li>
        </ul>
        <button class="navbar-toggler navbar-toggler-right d-lg-none align-self-center" type="button"
                data-toggle="offcanvas">

            <span class="mdi mdi-menu"></span>
        </button>
    </div>
</nav>
{#顶部导航结束#}

功能实现

路由实现

from django.urls import path

from . import views

app_name = 'user'

urlpatterns = [
    # 用户注册
    path('register/', views.register, name='register'),
    # 用户登录
    path('login/', views.login_view, name='login'),
    # 用户注销
    path('logout/', views.logout_view, name='logout'),
]

表单实现

import re

from django import forms
from django.core.exceptions import ValidationError


def mobile_validate(value):
    """手机号校验器"""
    mobile_re = re.compile(
        r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')


class LoginForm(forms.Form):
    username = forms.CharField(label="用户名", min_length=6,
                               widget=forms.widgets.TextInput(
                                   # 其中class样式为form-control,这是bootstrap的样式
                                   attrs={'class''form-control form-control-lg''placeholder'"请输入用户名"}),
                               error_messages={
                                   'required''用户姓名不能为空',
                                   'min_length''长度最少6位',
                               })
    password = forms.CharField(label="密码", min_length=6, max_length=72,
                               widget=forms.widgets.PasswordInput(
                                   # render_value=True,页面校验不通过后,页面上该值还存在
                                   attrs={"class""form-control form-control-lg"'placeholder'"请输入密码"},
                                   render_value=True),
                               error_messages={
                                   'max_length''密码最长72位',
                                   'required''密码不能为空',
                                   'min_length''密码最少6位'
                               })


class RegisterForm(LoginForm):
    re_password = forms.CharField(label="确认密码", min_length=6, max_length=72,
                                  widget=forms.widgets.PasswordInput(
                                      # render_value=True,页面校验不通过后,页面上该值还存在
                                      attrs={"class""form-control form-control-lg"'placeholder'"请确认密码"},
                                      render_value=True),
                                  error_messages={
                                      'max_length''密码最长72位',
                                      'required''密码不能为空',
                                      'min_length''密码最少6位'
                                  })

    def clean(self):
        """当表单校验的时候,自动触发"""
        # 获取密码和确认密码
        password = self.cleaned_data.get("password")
        re_password = self.cleaned_data.get("re_password")

        # 判断两个密码是否一致
        if password != re_password:
            self.add_error("re_password", ValidationError("二次密码输入不一致"))


class UserRegForm1(forms.Form):
    username = forms.CharField(label="用户名", min_length=6,
                               widget=forms.widgets.TextInput(
                                   # 其中class样式为form-control,这是bootstrap的样式
                                   attrs={'class''form-control''placeholder'"请输入用户名"}),
                               error_messages={
                                   'required''用户姓名不能为空',
                                   'min_length''长度最少6位',
                               })
    password = forms.CharField(label="密码", min_length=6, max_length=72,
                               widget=forms.widgets.PasswordInput(
                                   # render_value=True,页面校验不通过后,页面上该值还存在
                                   attrs={"class""form-control"}, render_value=True),
                               error_messages={
                                   'max_length''密码最长72位',
                                   'required''密码不能为空',
                                   'min_length''密码最少6位'
                               })
    re_password = forms.CharField(label="确认密码", min_length=6, max_length=72,
                                  widget=forms.widgets.PasswordInput(
                                      # render_value=True,页面校验不通过后,页面上该值还存在
                                      attrs={"class""form-control"}, render_value=True),
                                  error_messages={
                                      'max_length''密码最长72位',
                                      'required''密码不能为空',
                                      'min_length''密码最少6位'
                                  })
    nickname = forms.CharField(label="昵称", max_length=20, required=False,
                               widget=forms.widgets.TextInput(
                                   # 其中class样式为form-control,这是bootstrap的样式
                                   attrs={'class''form-control''placeholder'"请输入用户昵称"}),
                               error_messages={
                                   'required''用户昵称不能为空',
                                   'max_length''昵称长度不能超过20位',
                               })
    email = forms.EmailField(label="邮箱",
                             widget=forms.widgets.EmailInput(
                                 attrs={'class''form-control', }),
                             error_messages={
                                 'required''邮箱不能为空',
                                 'invalid''邮箱格式不对',
                             })
    mobile = forms.CharField(label="手机号码", validators=[mobile_validate],
                             widget=forms.widgets.TextInput(
                                 attrs={'class''form-control', }),
                             error_messages={
                                 'required''手机号码不能为空',
                             })
    user_img = forms.ImageField(label="用户头像", required=False, widget=forms.widgets.FileInput(
        attrs={'class''form-control'}))

    def clean(self):
        """当表单校验的时候,自动触发"""
        # 获取密码和确认密码
        password = self.cleaned_data.get("password")
        re_password = self.cleaned_data.get("re_password")

        # 判断两个密码是否一致
        if password != re_password:
            self.add_error("re_password", ValidationError("二次密码输入不一致"))

视图函数

from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render, redirect
from django.urls import reverse

from users.models import User
from .forms import LoginForm, RegisterForm


def register(request):
    """用户注册"""
    # 渲染注册页面
    if request.method == "GET":
        return render(request, 'apps/users/register.html', {"register_form": RegisterForm()})

    # 执行注册功能
    if request.method == "POST":
        # 获取用户名和密码
        register_form = RegisterForm(request.POST)
        if register_form.is_valid():
            # 判断是否已存在
            username = request.POST.get("username"'')
            users = User.objects.filter(username=username)
            if users:
                return render(request, 'apps/users/register.html',
                              {"register_form": RegisterForm(), "msg""该用户已存在"})

            # 注册用户
            # 移除重复密码
            register_form.cleaned_data.pop("re_password")
            # 添加数据
            # 是否登录后台
            register_form.cleaned_data["is_staff"] = 0
            # 是否为超级管理员
            register_form.cleaned_data["is_superuser"] = 0
            # 是否激活
            register_form.cleaned_data["is_active"] = 1
            # 新增
            User.objects.create_user(**register_form.cleaned_data)

            # 跳转到登陆页面
            return redirect(reverse("user:login"))

        # 返回错误信息
        return render(request, 'apps/users/register.html',
                      {"register_form": register_form})


def login_view(request):
    """用户登录"""
    # 渲染登录页面
    if request.method == "GET":
        return render(request, 'apps/users/login.html', {"login_form": LoginForm})

    # 执行登录功能
    if request.method == "POST":

        # 校验登录
        login_form = LoginForm(request.POST)
        info = ""
        if login_form.is_valid():
            # 获取用户名和密码
            username = request.POST.get("username"'')
            password = request.POST.get("password"'')
            if User.objects.filter(username=username):  # 判断用户是否存在
                # 如果存在,进行验证
                user = authenticate(username=username, password=password)
                if user:  # 如果验证通过
                    if user.is_active:  # 如果用户状态为激活
                        login(request, user)  # 进行登陆操作,完成session的设置
                        return redirect(reverse("index:index"))
                    else:
                        info = "用户还未激活"
                else:
                    info = "账号密码不对,请重新输入"
            else:
                info = '用户账号不存在,请查询'
        return render(request, 'apps/users/login.html', {"info": info, "login_form": login_form})


def logout_view(request):
    """用户注销"""
    logout(request)
    return redirect(reverse("user:login"))

权限中间件

import re

from django.shortcuts import redirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin


class PermissionMiddleWare(MiddlewareMixin):
    """权限校验中间件"""

    def process_request(self, request):
        """处理请求的方法"""

        # 获取当前路径
        curr_path = request.path

        # 白名单处理
        white_list = [reverse("user:login"), reverse("user:register")]
        for w in white_list:
            if re.search(w, curr_path):
                return None  # 通过

        # 验证是否登陆
        if not request.user.is_authenticated:
            return redirect(reverse("user:login"))

结语

关注我不迷路,欢迎关注我的微信公众号”张大鹏520″,如果您对此文章感兴趣,欢迎点赞收藏,留言评论。

文中所有代码,只需要打赏20元,然后留言评论“已打赏”,即可获取哦。

本文的PDF电子书版,只需要打赏3元,然后留言评论“已打赏”,即可获取哦。

写文章不容易,不喜勿喷哈,如果有想要学编程,学项目,或者在工作中有项目难以单独完成需要提供帮助的同学,欢迎私信我哈。生活不易,想要利用学到的编程知识,业余赚点零花钱。

接项目:网站开发,APP开发,各种管理系统开发。

带徒弟:Python编程教学,Golang编程教学,前端编程教学。

谢谢您!!!


原文始发于微信公众号(张大鹏520):Django加Vue电商项目实战18 实现用户注册登录和注销

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/48561.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!