Django教程第3章 | Web开发实战-登录

简介: 登录案例、Djiango中间件【2月更文挑战第23天】

 专栏系列:Django学习教程

前言

目标:实现用户登录和验证码功能。

知识点:表单验证、错误提示、DjangoAuth统一认证、验证码

效果图

image.gif 编辑

image.gif 编辑

 

Django cookie 与 session

Cookie 是存储在客户端计算机上的文本文件,并保留了各种跟踪信息。

识别返回用户包括三个步骤:

  • 服务器脚本向浏览器发送一组 Cookie。例如:姓名、年龄或识别号码等。
  • 浏览器将这些信息存储在本地计算机上,以备将来使用。
  • 当下一次浏览器向 Web 服务器发送任何请求时,浏览器会把这些 Cookie 信息发送到服务器,服务器将使用这些信息来识别用户。

HTTP 是一种"无状态"协议,这意味着每次客户端检索网页时,客户端打开一个单独的连接到 Web 服务器,服务器会自动不保留之前客户端请求的任何记录。

但是仍然有以下三种方式来维持 Web 客户端和 Web 服务器之间的 session 会话:

Cookies

一个 Web 服务器可以分配一个唯一的 session 会话 ID 作为每个 Web 客户端的 cookie,对于客户端的后续请求可以使用接收到的 cookie 来识别。

在Web开发中,使用 session 来完成会话跟踪,session 底层依赖 Cookie 技术。

image.gif 编辑

image.gif 编辑

代码案例

1.编写模板HTML

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户管理系统</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
    <style>
        .account {
            width: 400px;
            border: 1px solid #dddddd;
            border-radius: 5px;
            box-shadow: 5px 5px 20px #aaa;
            margin-left: auto;
            margin-right: auto;
            margin-top: 100px;
            padding: 20px 40px;
        }
        .account h2 {
            margin-top: 10px;
            text-align: center;
        }
    </style>
</head>
<body>
<div class="account">
    <h2>用户登录</h2>
    <form method="post" novalidate>
        {% csrf_token %}
        <div class="form-group">
            <label>用户名</label>
            {{ form.username }}
            <span style="color: red;">{{ form.username.errors.0 }}</span>
        </div>
        <div class="form-group">
            <label>密码</label>
            {{ form.password }}
            <span style="color: red;">{{ form.password.errors.0 }}</span>
        </div>
        <div class="form-group">
            <label for="id_code">图片验证码</label>
            <div class="row">
                <div class="col-xs-7">
                    {{ form.code }}
                    <span style="color: red;">{{ form.code.errors.0 }}</span>
                </div>
                <div class="col-xs-5">
                    <img id="image_code" src="/image/code/" onclick="changeImg(this)" style="width: 125px;" />
                </div>
            </div>
        </div>
        <input type="submit" value="登 录" class="btn btn-primary">
    </form>
</div>
</body>
<script>
    function changeImg(ths) {
        // 硬编码
        ths.src = '/image/code/?temp=' + Math.random();
    }
</script>
</html>

image.gif

2.编写模型

from django.db import models
class UserInfo(models.Model):
    username = models.CharField(verbose_name='用户名', max_length=32)
    password = models.CharField(verbose_name='密码', max_length=64)
    age = models.IntegerField(verbose_name='年龄')
    salary = models.DecimalField(verbose_name='工资', max_digits=10, decimal_places=2)
    gender_choices =(
        (1, '男'),
        (2, '女')
    )
    gender = models.SmallIntegerField(verbose_name='性别', choices=gender_choices)
    create_time = models.DateTimeField(verbose_name='创建时间')
    # dept_id = models.ForeignKey(to=Department, to_field='id', null=True, blank=True, on_delete=models.SET_NULL)
    dept = models.ForeignKey(verbose_name="部门", to='Department', to_field="id", on_delete=models.CASCADE)

image.gif

3.编写视图函数

login函数:校验验证码--》验证用户名密码是否正确--》设置用户过期时间为30分钟--》跳转到首页

image.gif 编辑

登录逻辑图

image_code函数:调用check_code(),生成验证码,设置session60过期。

logout函数:退出登录,删除服务器存储的session并跳转到登陆页面。

views.py

def login(request):
    if request.method == 'GET':
        form = LoginForm()
        return render(request, 'login.html', {'form': form})
    form = LoginForm(data=request.POST)
    if form.is_valid():
        # 验证码的校验
        user_input_code = form.cleaned_data.pop('code')
        code = request.session.get('image_code', "")
        if code.upper() != user_input_code.upper():
            form.add_error("code", "验证码错误")
            return render(request, 'login.html', {'form': form})
        # 查询数据库匹配用户名密码是否正确
        user_obj = models.UserInfo.objects.filter(**form.cleaned_data).first()
        print(user_obj)
        if not user_obj:
            form.add_error('password', '用户名或密码错误')
            return render(request, 'login.html', {'form': form})
        request.session['info'] = {'id': user_obj.id, 'username': user_obj.username}
        # 设置 session 过期时间为30分钟
        request.session.set_expiry(60 * 30)
        return redirect('/user/list/')
    return render(request, 'login.html', {'form': form})
def image_code(request):
    """ 生成图片验证码 """
    # 调用pillow函数,生成图片
    img, code_string = check_code()
    # 写入到自己的session中(以便于后续获取验证码再进行校验)
    request.session['image_code'] = code_string
    # 给Session设置60s超时
    request.session.set_expiry(60)
    stream = BytesIO()
    img.save(stream, 'png')
    return HttpResponse(stream.getvalue())
def logout(request):
    request.session.flush()
    return redirect('/login/')
class LoginForm(BootstrapForm):
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput,
        required=True
    )
    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(render_value=True),
        required=True,
    )
    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput,
        required=True
    )

image.gif

4.编写统一过滤(AuthMiddleware)

1.排除那些不需要登录就能访问的页面,例如:login请求,验证码请求

2.读取当前访问的用户的session信息,如果能读到,说明已登陆过,可以访问系统。

3.没有登陆过,也就是在访问系统在浏览器没有用户cookie或者已经失效,则跳转到登陆页面。

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect
class AuthMiddleware(MiddlewareMixin):
    def process_request(self, request):
        # 0.排除那些不需要登录就能访问的页面
        #   request.path_info 获取当前用户请求的URL /login/
        if request.path_info in ["/login/", "/image/code/"]:
            return
        # 1.读取当前访问的用户的session信息,如果能读到,说明已登陆过,就可以继续向后走。
        info_dict = request.session.get("info")
        # print(info_dict)
        if info_dict:
            return
        # 2.没有登录过,重新回到登录页面
        return redirect("/login/")

image.gif

然后在settings.py配置中间件

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'ums.middleware.auth.AuthMiddleware',    # 新增位置
]

image.gif

5.配置路由

from django.urls import path
from ums.views import auth
path('user/<int:nid>/edit_user_password/', auth.edit_user_password),
path('login/', auth.login),
path('logout/', auth.logout),
path('image/code/', auth.image_code),

image.gif

本篇中我使用的是手动绘制验证码,大家可以尝试基于下一章将手动验证码换成自动验证码或者滑动验证码。

如果本文对你有帮助,记得点赞关注,你的支持是我最大的动力!

下一章:Django教程-三种验证码实现-CSDN博客


相关文章
|
监控 NoSQL 网络协议
Django 实时通信实战:WebSocket 与 ASGI 全解析(上)
WebSocket 是一种全双工通信协议,支持实时数据传输,适用于聊天、协作、监控等场景。ASGI 是异步 Web 标准,配合 Uvicorn 服务器和 Django Channels,可实现 Django 的 WebSocket 功能,提升实时应用性能。
629 0
|
缓存 监控 中间件
Django中间件自定义开发指南:从原理到实战的深度解析
Django中间件是Web应用的“交通警察”,在请求与响应过程中进行全局处理,适用于身份验证、日志记录、性能监控等功能。本文详解中间件的工作原理、开发步骤及实战案例,帮助开发者掌握自定义中间件的构建方法,提升Django应用的可维护性与扩展性。
603 0
|
人工智能 开发工具 数据库
Django实战:Python代码规范指南
PEP 8 是 Python 官方代码风格指南,提升代码可读性与团队协作效率。本文详解命名规范、注释写法、常用工具(如 Black、flake8)、编程实践与代码优化技巧,助力写出规范、易维护的 Python 代码。
668 7
|
缓存 NoSQL 数据库
Django缓存机制详解:从配置到实战应用
本文全面解析Django缓存技术,涵盖配置方法与六大缓存后端,结合实战场景演示四种典型应用方式,帮助开发者提升Web应用性能,应对高并发挑战。
432 0
|
存储 缓存 数据库
Django模型开发全解析:字段、元数据与继承的实战指南
Django模型是业务逻辑与数据库的核心桥梁,本文详解模型开发三大核心:字段类型选择、元数据配置与继承模式应用,涵盖实战技巧与常见问题解决方案,助你构建高效可维护的数据模型。
369 0
|
缓存 NoSQL API
Django缓存机制详解:从配置到实战应用
本文介绍了 Django 缓存机制的基础知识与实战应用,涵盖缓存概念、Redis 安装配置、缓存策略及 API 使用,并通过 RBAC 权限系统演示缓存的读写与删除操作,助力提升 Web 应用性能。
370 0
|
缓存 JSON 应用服务中间件
Django实时通信实战:WebSocket与ASGI全解析(下)
本文将使用 Django Channels 构建一个多用户实时聊天室,并详细介绍如何在生产环境中部署 WebSocket 应用。
419 0
|
开发框架 前端开发 JavaScript
Python 有哪些Web框架?比如Flask、Django等知识梳理
Python 有哪些Web框架?比如Flask、Django等知识梳理
1299 1
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
【4月更文挑战第9天】本文对比了Python三大Web框架Django、Flask和Pyramid。Django功能全面,适合快速开发,但学习曲线较陡;Flask轻量灵活,易于入门,但默认配置简单,需自行添加功能;Pyramid兼顾灵活性和可扩展性,适合不同规模项目,但社区及资源相对较少。选择框架应考虑项目需求和开发者偏好。
960 0
|
前端开发 数据库 Python
使用 Python 的 Web 框架(如 Django 或 Flask)来建立后端接口,用于处理用户的请求,从数据库中查找答案并返回给前端界面
【1月更文挑战第13天】使用 Python 的 Web 框架(如 Django 或 Flask)来建立后端接口,用于处理用户的请求,从数据库中查找答案并返回给前端界面
768 7

热门文章

最新文章