【web开发】8、Django(3)

2023-09-15 12:14:44

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


前言

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

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


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

一、管理员

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中
更多推荐

Python编程指南:利用HTTP和HTTPS适配器实现智能路由

嗨,爬虫大佬们!今天我要为大家分享一篇关于如何利用HTTP和HTTPS适配器来实现智能路由的Python编程指南。在现代互联网应用中,路由功能起着至关重要的作用,而利用Python编程语言实现智能路由则可以为我们的应用带来更高的灵活性和性能优化。接下来,让我们一起深入了解这个令人激动的主题吧!1、了解HTTP和HTTP

简单易上手,亚马逊云科技Amazon CodeWhisperer个性化辅助功能成为开发者好帮手

AmazonCodeWhisperer介绍AmazonCodeWhisperer是亚马逊云科技出品的一款基于机器学习的通用代码生成器,可实时提供代码建议。类似Cursor和GithubCopilot编码工具。在编写代码时,它会自动根据您现有的代码和注释生成建议。从单行代码建议到完整的函数,它可为您提供各种大小和范围的个

关于React Hooks的面试题及其答案

请解释一下ReactHooks是什么,以及它的优点和缺点是什么?Hooks是React16.8版本引入的一种新特性,它允许你在不写class的情况下操作state和其他React特性。Hooks是一种特殊的函数,可以让你“钩入”React的特性。它的优点是让编写组件更简单方便,同时可以自定义hook把公共的逻辑提取出来

面试中的技术趋势:如何展示你跟进最新技术的能力

🌷🍁博主猫头虎(🐅🐾)带您GotoNewWorld✨🍁🦄博客首页——🐅🐾猫头虎的博客🎐🐳《面试题大全专栏》🦕文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺🌊《IDEA开发秘籍专栏》🐾学会IDEA常用操作,工作效率翻倍~💐🌊《100天精通Golang(基础入门篇)》🐅学会Gol

小程序测试基础知识分享,获取专业测试报告就找卓码软件测评

近年来,随着互联网的快速发展,小程序测试成为了一个重要的环节。而小程序测试的内容以及注意事项则会直接影响到产品的质量和用户体验。卓码软件测评作为专业的软件测试公司,在软件测试方面有着丰富的经验。下面将从多个角度来详细描述小程序测试的内容和注意事项,并分析测试对产品的作用。一、小程序测试的内容1、功能测试:各项功能的稳定

如何查看mysql的存储引擎

要查看MySQL中的存储引擎,可以使用以下两种方法:1.使用SQL查询:您可以使用SQL查询来查看MySQL中的存储引擎。打开MySQL客户端,并连接到您的MySQL服务器,然后运行以下SQL查询:SHOWTABLESTATUS;这将列出所有数据库中的表以及与每个表相关的信息,包括存储引擎。在结果中,可以查看"Engi

腾讯云16核服务器配置大全_CVM和轻量服务器汇总

腾讯云16核CPU服务器有哪些配置可以选择?可以选择标准型S6、标准型SA3、计算型C6或标准型S5等,目前标准型S5云服务器有优惠活动,性价比高,计算型C6云服务器16核性能更高,轻量16核32G28M带宽优惠价3468元15个月,腾讯云百科分享腾讯云16核CPU服务器可以选择的云服务器CVM规格列表:目录腾讯云16

二蛋赠书三期:《C#入门经典(第9版)》

文章目录前言活动规则参与方式本期赠送书籍介绍作者介绍内容简介读者对象获奖名单结语前言大家好!我是二蛋,一个热爱技术、乐于分享的工程师。在过去的几年里,我一直通过各种渠道与大家分享技术知识和经验。我深知,每一位技术人员都对自己的技能提升和职业发展有着热切的期待。因此,我非常感激大家一直以来对我的关注和支持。为了回馈大家的

[DB]数据库--lowdb

[DB]数据库--lowdblowdb基本应用获取数据数据变更写入文件lodash的使用获取数据lodash方法使用数据变更写入文件lowdblowdb,是一个基于文件存储的非关系型数据库基于loadsh的轻量级数据库可用于在json中存储数据,大小一般为0~200M的json文件方便简单的数据存储,快速的实现数据的增

Keepalived 高可用(附带配置实例,联动Nginx和LVS)

Keepalived一、Keepalived相关知识点概述1.1单服务的风险(单点故障问题)1.2一个合格的集群应该具备的特性1.3VRRP虚拟路由冗余协议1.4健康检查1.5”脑裂“现象二、Keepalived2.1Keepalived是什么?2.2Keepalived体系主要模块及其作用2.3Keepalived工

Git --- 基础介绍

Git---基础介绍git是什么git---工作区,暂存区,资源库git---文件状态git---branch和HEADgit---一次正常的git提交流程git是什么Git是一款分布式源代码管理工具(版本控制工具)Git和其他传统版本控制系统比较:传统的版本控制系统(例如SVN)是基于差异的版本控制,它们存储的是一组

热文推荐