【web开发】8、Django(3)

news2024/12/23 19:00:03

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、管理员
    • 1.表结构
    • 2.layout.html文件下添加管理员账号的导航
    • 3.urls.py文件(POST请求传递nid)
    • 4.form.py文件(密码加密,确认密码,重置密码与原密码要求不一致)
    • 5.admin.py文件
  • 二、中间件(实现登录校验)
    • 1.中间件的作用
    • 2.定义中间件
    • 3.应用中间件
    • 4.在中间件的process_request方法
  • 三、图片验证码及登录界面
    • 1.图片验证码
    • 2.登录界面
  • 四、注销用户(退出登录)


前言

提示:这里可以添加本文要记录的大概内容:

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、管理员

1.表结构

首先在models.py文件下定义Admin这个类,同时用djando命令生成数据库表(python manage.py makemigrations;python manage.py migrate)数据库下才有app01_admin这个数据表。

#models.py
class Admin(models.Model):
    """管理员"""
    username = models.CharField(verbose_name="用户名",max_length=32)
    password = models.CharField(verbose_name="密码",max_length=64)

    def __str__(self):
        return self.username      #连接表中所显示的内容

2.layout.html文件下添加管理员账号的导航

<li><a href="/admin/list/">管理员账户</a></li>

3.urls.py文件(POST请求传递nid)

     path('admin/list/', admin.admin_list),
     path('admin/add/', admin.admin_add),
     path('admin/<int:nid>/edit/', admin.admin_edit),
     path('admin/<int:nid>/delete/', admin.admin_delete),
     path('admin/<int:nid>/reset/', admin.admin_reset),

4.form.py文件(密码加密,确认密码,重置密码与原密码要求不一致)

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

from app01 import models
from app01.utils.encrypt import md5
from app01.utils.bootstrap import BootstrapModelForm

class AdminModelForm(BootstrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput(render_value=True))

    class Meta:
        model = models.Admin
        fields = ["username", 'password', 'confirm_password']
        widgets = {
            "password": forms.PasswordInput(render_value=True)
            #render_value=True密码错误也不会置空
        }

    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        return md5(pwd)

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get("password")
        confirm = md5(self.cleaned_data.get("confirm_password"))
        if confirm != pwd:
            raise ValidationError("密码不一致")
        # 返回的数值保存在数据库中
        return confirm

class AdminEditModelForm(BootstrapModelForm):
    class Meta:
        model = models.Admin
        fields = ['username']  # 只允许编辑用户名,其他信息不能编辑

class AdminResetModelForm(BootstrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput(render_value=True))

    class Meta:
        model = models.Admin
        fields = ["password", "confirm_password"]
        widgets = {
            "password": forms.PasswordInput(render_value=True)
        }

    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        md5_pwd = md5(pwd)

        # 去数据库校验当前密码和输入密码是否一致
        exists = models.Admin.objects.filter(id=self.instance.pk, password=md5_pwd).exists()
        if exists:
            raise ValidationError("与之前密码一致")
        return md5_pwd

    def clean_confirm_password(self):
        pwd = self.cleaned_data.get("password")
        confirm = md5(self.cleaned_data.get("confirm_password"))
        if confirm != pwd:
            raise ValidationError("密码不一致")
        # 返回的数值保存在数据库中
        return confirm

5.admin.py文件

(用户是否存在/登录、搜索、分页、编辑前确认所编辑对象存在于数据库中、编辑时显示编辑前字段的信息、添加页面相同时写入模板文件传递标题)

from django.shortcuts import render, redirect

from app01 import models
from app01.utils.pagination import Pagination
from app01.utils.form import AdminModelForm,AdminEditModelForm,AdminResetModelForm


def admin_list(request):
    """管理员列表"""
    
    """检查用户是否登录,已登录继续走下去,未登录,跳转到登录页面
    用户发来请求,获取cookie随机字符串,拿着随机字符串看session中有没有"""
   #是否登录
    info = request.session["info"]
    if not info:
        return redirect("/login/")
    # 搜索
    data_dict = {}
    search_data = request.GET.get('q', "")
    if search_data:
        data_dict["username__contains"] = search_data
    # 根据搜索条件去数据库获取
    queryset = models.Admin.objects.filter(**data_dict)
    # 分页
    page_object = Pagination(request, queryset, page_size=3)
    context = {
        'queryset': page_object.page_queryset,
        'page_string': page_object.html(),
        'search_data': search_data,
    }
    return render(request, "admin_list.html", context)

def admin_add(request):
    """添加管理员"""
    title = "新建管理员"
    if request.method == "GET":
        form = AdminModelForm()
        #change.html为添加模板
        return render(request, 'change.html', {"form": form, "title": title})
    form = AdminModelForm(data=request.POST)
    if form.is_valid():
        form.save()
        return redirect('/admin/list')
    return render(request, 'change.html', {"form": form, "title": title})

def admin_edit(request, nid):
    """编辑管理员"""
    row_object = models.Admin.objects.filter(id=nid).first()
    if not row_object:
        return render(request, "error.html", {"msg": "数据不存在"})
    title = "编辑管理员"

    if request.method == "GET":
        form = AdminEditModelForm(instance=row_object)  # 输入框内显示的默认值
        return render(request, 'change.html', {"form": form, "title": title})
    form = AdminEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect("/admin/list")
    return render(request, 'change.html', {"form": form, "title": title})

def admin_delete(request, nid):
    models.Admin.objects.filter(id=nid).delete()
    return redirect('/admin/list/')

def admin_reset(request, nid):
    """重置密码"""
    row_object = models.Admin.objects.filter(id=nid).first()
    if not row_object:
        return redirect('/admin/list/')
    title = "重置密码-{}".format(row_object.username)
    if request.method == "GET":
        form = AdminResetModelForm()
        return render(request, 'change.html', {"form": form, "title": title})
    form = AdminResetModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect("/admin/list/")
    return render(request, 'change.html', {"form": form, "title": title})

二、中间件(实现登录校验)

#info用于验证用户是否登录过,以便能否访问其他页面
在其他需要登录才能访问的页面中,都要加入:

#是否登录
    info = request.session["info"]
    if not info:
        return redirect("/login/")

1.中间件的作用

可以在请求到达视图函数之前执行操作。这使得你可以在请求处理之前进行身份验证权限检查、日志记录等操作。

在appo01目录下创建middleware目录,并创建auth.py文件
在这里插入图片描述

2.定义中间件

#auth.py
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect

class AuthMiddleware(MiddlewareMixin):
    """中间件"""
    def process_request(selfself,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/")

3.应用中间件

并在settings.py文件下的MIDDLEWARE中添加中间件auth.py的路径
在这里插入图片描述

4.在中间件的process_request方法

#如果方法中没有返回值(返回None),继续向后走
#如果有返回值HttpResponse\render\redirect,则不再继续向后执行

三、图片验证码及登录界面

1.图片验证码

pip install pillow
def image_code(request):
    """生成图片验证码"""
    # 调用pillow函数,生成图片
    img, code_string = check_code()
    print(code_string)
    # 写入到自己的session中,以便后续获取验证码再进行校验
    request.session['imge_code'] = code_string
    # 给session设置60*60*24*7秒超时
    request.session.set_expiry(60 * 60 * 24 * 7)
    #内存文件BytesIO
    stream = BytesIO()
    img.save(stream, 'png')
    return HttpResponse(stream.getvalue())

2.登录界面

POST提交需要添加: {% csrf_token %}
消除浏览器自带提示:在form内添加 novalidate

#html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .account {
            width: 450px;
            border: 1px solid gray;
            height: 400px;
            margin-left: auto;
            margin-right: auto;
            margin-top: 150px;
            padding: 40px 20px 40px 20px;
            border-radius: 5px;
            box-shadow: 5px 5px 5px #aaa;
        }

        .account h1 {
            text-align: center;
            margin-top: 5px;
        }
    </style>
</head>
<body>
<div class="account">
    <h1>用户登录</h1>
    {#    <form method="post" action = "{% url 'admin' %}">#}
    <form method="post" novalidate>
        {% csrf_token %}
        <div >
            <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"><!---->
                <div>
                    <label>图片验证码</label>
                </div>
                <div class="col-lg-7">
                    {{ form.code }}
            <span style="color: red;">{{ form.code.errors.0 }}</span>
                </div>
                <img data-v-66879da5="" alt="验证码"
                     src="/image/code/"
                     class="img-logo" style="margin-left: 20px">
            </div>
        <div>
            <button type="submit" class="btn btn-primary" style="margin-top: 18px;">登 录</button>
        </div>
    </form>

</div>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
class LoginForm(BootstrapForm):
#Form组件需要手动写字段
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput(),
        # widget=forms.TextInput(attrs={"class":"form-group"}),
        required=True  # 必填,不能为空

    )
    password = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(render_value=True),
        required=True  # 必填,不能为空
    )
    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput,
        required=True  # 必填,不能为空
    )
    class Meta:
        model = models.Admin
        fields = ['username', 'password']
    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        return md5(pwd)


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():
        print(form.cleaned_data)#验证成功,获取用户名和密码
        user_input_code = form.cleaned_data.pop('code')
        code = request.session.get('imge_code')
        if code.upper() != user_input_code.upper():
            form.add_error("code", "验证码错误")  # 主动在password下添加错误提示
            return render(request, 'login.html', {"form": form})
        # 去数据库校验用户名和密码是否正确,获取用户对象
        admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error("password", "用户名或密码错误")  # 主动在password下添加错误提示
            return render(request, 'login.html', {"form": form})
        # 用户名和密码正确
        # 网站生成随机字符串,写到用户浏览器的cookie中,在写入到session中
        request.session["info"] = {"id": admin_object.id, "name": admin_object.username}
        #info用于验证用户是否登录过,以便能否访问其他页面
        return redirect("/admin/list/")
    return render(request, 'login.html', {"form": form})

四、注销用户(退出登录)

def logout(request):
    """注销"""
    request.session.clear()
    return redirect('/login/')
登录完成,则{{ request.session.info.name }}一定存在,可以直接传到html中

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

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

相关文章

辉瑞与吉利德科学:制药巨头的新冠病毒之战

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 总结&#xff1a; &#xff08;1&#xff09;猛兽财经认为&#xff0c;华尔街低估了辉瑞&#xff08;PFE&#xff09;和吉利德科学&#xff08;GILD&#xff09;的前景&#xff0c;因为它们在开发新冠病毒疫苗和药物方面都…

安达发|APS软件系统的发展进化史

从古至今&#xff0c;生产计划一直是制造业的核心。无论是古代的手工作坊&#xff0c;还是现代的自动化工厂&#xff0c;都需要一种有效的方法来安排和调度生产活动。这就是我们今天要谈论的主题——高级排产软件&#xff08;APS&#xff09;的起源和发展。 1. 初识APS&#xf…

碳化硅夹阻整流器(PBR)

标题&#xff1a;Silicon Carbide Pinched Barrier Rectifier (PBR) 摘要 本文首次提出一种碳化硅&#xff08;SiC&#xff09;中的新型整流器结构。所提出的结构既不涉及肖特基接触也不涉及通过P-N结的少数载流子注入。当相邻的P区域放置得足够近时&#xff0c;形成了用于整流…

C语言练习题解析:挑战与突破,开启编程新篇章!(4)

&#x1f493;博客主页&#xff1a;江池俊的博客⏩收录专栏&#xff1a;C语言刷题专栏&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐ 文…

药店销售系统设计与实现

目 录 摘要 Ⅰ Abstract Ⅱ 第1章 绪论 1 1.1选题意义 1 1.1.1选题背景 1 1.1.2选题意义 1 1.2系统方案 1 1.3可行性分析 1 1.3.1技术可行性分析 1 1.3.2经济可行性分析 1 第2章 系统主要功能及界面设计 3 2.1系统功能分析 3 2.1.1系统功能分析 3 2.1.2 数据库结构设计 4 2.2界…

Centos7 禁止ping的几种方式

参考链接 https://cloud.tencent.com/developer/article/1448499 1. #禁ping echo 1 > /proc/sys/net/ipv4/icmp_echo_ignore_all #启用ping echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_all#编辑配置 vim /etc/sysctl.conf #设置禁ping&#xff08;如果有此配置就无…

GDB之常见缩写命令(十九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

基于安卓Java试题库在线考试系统uniapp 微信小程序

本文首先分析了题库app应用程序的需求&#xff0c;从系统开发环境、系统目标、设计流程、功能设计等几个方面对系统进行了系统设计。开发出本题库app&#xff0c;主要实现了学生、教师、测试卷、试题、考试等。总体设计主要包括系统功能设计、该系统里充分综合应用Mysql数据库、…

5.4双积分ADC工作原理

文章目录 1、高中几个知识点exp(n)log(n)lgx、lnx电容充放电公式 2、双积分型ADC工作原理3、SAR和∑-Δ型模数转换器(ADC) 1、高中几个知识点 exp(n) exp函数即指数函数&#xff1a;e的n次方的函数&#xff0c;自然常数e2.718281828459045 举例&#xff1a; exp(0) e 0 e^{…

MQ 异步削峰解耦 交换机与队列

MQ全称 Message Queue&#xff08;消息队列&#xff09;&#xff0c;是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信&#xff0c;解耦 作用&#xff08;这是个面试题&#xff09; 1、异步处理 场景说明&#xff1a;用户注册后&#xff0c;需要发注册邮件…

高压放大器在mems传感器中的应用有哪些

高压放大器在MEMS传感器中具有广泛的应用。MEMS传感器是一种能够将微小机械运动转化为电信号的微型传感器&#xff0c;其应用涵盖了多个领域&#xff0c;包括汽车、医疗、消费电子等。而高压放大器则是用于增强MEMS传感器输出信号的设备&#xff0c;可以提供更高的增益和更低的…

二、链表(linked-list)

文章目录 一、定义二、经典例题&#xff08;一&#xff09;[21.合并两个有序链表](https://leetcode.cn/problems/merge-two-sorted-lists/description/)1.思路2.复杂度分析3.注意4.代码 &#xff08;二&#xff09;[86.分割链表](https://leetcode.cn/problems/partition-list…

批量BMP图片转为PNG透明图片,去掉BMP黑色背景,压缩导出png图片V1.1

前段时间上传了一款bmp转png并去黑底的demo软件&#xff0c;非常受欢迎&#xff0c; 旧版软件介绍文章&#xff1a;批量BMP图片转为PNG透明图片&#xff0c;去掉BMP黑色背景 应广大爱好者的要求&#xff0c;完善了一下软件的功能&#xff0c;增加了导出png图片压缩功能&#x…

本地部署CodeLlama +GTX1080显卡 对接open-interpreter对接wxbot(一)

1.效果展示 开源项目GitHub - oobabooga/text-generation-webui: A Gradio web UI for Large Language Models. Supports transformers, GPTQ, llama.cpp (GGUF), Llama models. "Code Llama" 是一个大型代码语言模型的系列,基于 "Llama 2" 构建,为编程…

【LeetCode-简单题】剑指 Offer 05. 替换空格

文章目录 题目方法一&#xff1a;常规做法&#xff1a;方法二&#xff1a;双指针做法 题目 方法一&#xff1a;常规做法&#xff1a; class Solution {public String replaceSpace(String s) {int len s.length() ;StringBuffer str new StringBuffer();for(int i 0 ; i &l…

JColorChooser 和JFileChooser

语雀笔记&#xff1a;https://www.yuque.com/huangzhanqi/rhwoir/paaoghdyv0tgksk1https://www.yuque.com/huangzhanqi/rhwoir/paaoghdyv0tgksk1Java图形化界面: Java图形化界面学习demo与资料 (gitee.com)https://gitee.com/zhanqi214/java-graphical-interface Swing提供了J…

Linux Day14 :线程的创建与同步

一、简单认知 进程&#xff1a;一个正在运行的程序 线程&#xff1a;进程内部的一个执行路径 头文件&#xff1a;#include<pthread.h> 二、进程与线程的区别 ◼ 进程是资源分配的最小单位&#xff0c;线程是 CPU 调度的最小单位 ◼ 进程有自己的独立地址空间&…

笔记(四)传统图机器学习的特征工程-连接

1、引言 工作&#xff1a;通过已知连接&#xff0c;补全未知连接 思想&#xff1a; 直接提取link特征&#xff0c;把link变成D维向量把link两端节点的D维向量拼接在一起&#xff08;不好&#xff0c;丢失了link本身的连接结构信息&#xff09; 2、连接分类 客观静态图&…

刻字机尖角补偿

1 刻字机尖角补偿原理 刀具切割直线段过渡方法在文章旋转偏心裁切刀切向跟踪及半径补偿 已经有过说明。刻字机由于刀具半径的影响&#xff0c;切割直角时会不直会比较圆滑&#xff0c;而且在闭合曲线的下刀点会容易不闭合。使用尖角补偿可以克服这些问题。 如上图所示&#xf…

大数据Flink(七十七):SQL窗口的Over Windows

文章目录 SQL窗口的Over Windows 一、​​​​​​​时间区间聚合