django实现登录和登录的鉴权

1、创建数据库的管理员表

在models.py 中定义admin表,为了简单,表里只有用户名和密码还有默认加的id 三个字段

python 复制代码
from django.db import models

# Create your models here.

class Admin(models.Model):
    username = models.CharField(verbose_name="用户名",max_length=16)
    passwd = models.CharField(verbose_name="密码",max_length=64)

执行创建表的语句

python 复制代码
py -3 manage.py makemigrations
py -3 manage.py migrate

然后自己手动插入一些用户

2、登录界面和登录视图

在urls.py中加入路径

python 复制代码
from django.urls import path
from app01.views import user,depart,pretty,admin,account

urlpatterns = [
    #path('admin/', admin.site.urls),
    path('depart/list/', depart.depart_list),
    path('depart/add/', depart.depart_add),
    path('depart/delete/', depart.depart_delete),
    #http://127.0.0.1:8000/depart/2/edit/
    path('depart/<int:nid>/edit/', depart.depart_edit),

    path('user/list/', user.user_list),
    path('user/add/', user.user_add),
    path('user/<int:nid>/edit/', user.user_edit),
    path('user/<int:nid>/delete/', user.user_delete),

    path('pretty/list/', pretty.pretty_list),
    path('pretty/add/', pretty.pretty_add),
    path('pretty/<int:nid>/edit/', pretty.pretty_edit),
    path('pretty/<int:nid>/delete/', pretty.pretty_delete),

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

    path('login/account/',account.login),      #这个是登录的
]

在写登录的视图函数account.py

我把不同模块的视图函数拆分了,不同功能模块的一个py文件,在app01目录下创建目录views, 在views目录下分类写视图函数,主要要把原始的views.py文件删除

登录使用的Form组件

获取到用户输入的数据后要对数据进行校验,根数据库里面的值

再有如果验证通过要request.session 通过这个生成session, django会自动处理,生成一个session保存到数据库,并把这个session返回给浏览器。

python 复制代码
from django.shortcuts import render,redirect
from django import forms
from app01.utils.encrypt import md5
from app01 import models


class LoginForm(forms.Form):
    username = forms.CharField(
        label="用户名",
        widget=forms.TextInput,
        required=True,
    )
    passwd = forms.CharField(
        label="密码",
        widget=forms.PasswordInput(render_value=True),
        required=True
    )
    # 这个init方式是给自己加样式的
    def __init__(self, *args,**kwargs):
        super().__init__(*args,**kwargs)

        for name ,field in self.fields.items():
            #字段中有属性,保留原来的属性,没有属性,才增加
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs["placeholder"] = field.label
            else:
                field.widget.attrs = {"class":"form-control"}


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)   #获取到的值是一个字典{'username': 'root', 'passwd': '1234'}
        #校验数据库的用户名和密码
        admin_object = models.Admin.objects.filter(**form.cleaned_data).first()
        if not admin_object:
            form.add_error('passwd','用户名或密码错误')
            return render(request,'login.html',{'form':form})
        #用户名和密码正确
        #网站生成随机字符串; 写到用户浏览器的cookie中,再写入到session中
        request.session['info'] = {'id':admin_object.id,'name':admin_object.username}
        return redirect('/admin/list/')
    return render(request,'login.html',{'form':form})

login.html 的内容

html 复制代码
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="{% static 'plugins/bootstrap-3.4.1/css/bootstrap.min.css' %}">
    <style>
        .account {
            width: 400px;
            border-radius: 5px;
            border: 1px solid #dddddd;
            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 %}
                    {% for field in form %}
                      <div class="form-group">
                        <label >{{ field.label }}</label>
                        {{ field }}
                      <span style="color:red">{{ field.errors.0 }}</span>
                      </div>
          {% endfor %}
          <button type="submit" class="btn btn-primary">提交</button>
      </form>

</div>

<script src="{% static 'js/jquery-3.7.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
</body>
</html>

3、中间件实现登录鉴权

在开始我们写了一个功能后,把django项目运行起来,直接方法url就能访问到了,正常来说是只有登录后的用户才能访问到,django中给我们提供了中间件,可以通过中间件来实现鉴权

在django 中可以定义多个中间件,中间件就是一个类,类里面定义有两个函数一个是process_request进入的,穿过所有的中间件到达视图函数,视图函数返回结果通过process_response函数返回给浏览器

  • 定义中间件
python 复制代码
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect

class AuthMiddleWare(MiddlewareMixin):
    """中间件判断是否登录"""

    def process_request(self,request):
        # 1、排除那些不需要登录就能访问的页面
        # request.path_info  获取当前用户请求的URL  ru /login/account/
        if request.path_info == '/login/account/':
            return
        # 2、读取当前访问的用户的session信息,如果能读到,说明以登录过,就可以继续向后走
        info_dict = request.session.get("info")
        if info_dict:
            return
        # 3、没有登录过,重新回到登录页面
        return redirect('/login/account/')
  • 使用中间件,在settings.py中注册中间件
    会按这个顺序执行,中间件定义好后,会自动调佣
python 复制代码
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',
    'app01.middleware.auth.AuthMiddleWare',
]

中间件添加好后,你再没有登录的情况下去访问http://127.0.0.1:8000/user/list/ 这些页面会自动跳转到登录界面。

相关推荐
ClouGence7 小时前
Oracle 数据同步为什么会出现数据不一致?长事务是常被忽略的原因
数据库·后端·oracle
飞将9 小时前
从零实现数据库(2)——HashIndex + IndexManager
数据库
兵慌码乱20 小时前
面向桌面端的资产管理系统分层架构设计与核心模块实现
python·系统架构·sqlite·pyqt5·数据库设计·桌面应用开发·mvc架构
呱呱复呱呱1 天前
Django CBV 源码解读:一个请求是怎么找到你的 get() 方法的
python·django
Nturmoils1 天前
订单列表慢查询,先看 WHERE、ORDER BY 和 LIMIT
数据库
渣波1 天前
拒绝 SQL 焦虑!手把手带你用 NestJS + Prisma + DTO 写出“防弹”级后端代码
javascript·数据库·后端
兵慌码乱2 天前
基于Python+PyQt5+SQLite的药房管理系统实现:事务一致性与界面解耦全流程解析
python·sqlite·信号与槽·pyqt5·数据库设计·桌面应用开发·事务处理
倔强的石头_2 天前
KingbaseES 新版MySQL 兼容版体验:旧版迁移 + 功能实测
数据库
倔强的石头_5 天前
《Kingbase护城河》——数据库存储空间全景探测与精细化瘦身实战
数据库
冬奇Lab6 天前
每日一个开源项目(第134篇):Zvec - 阿里开源的嵌入式向量数据库,向量搜索界的 SQLite
数据库·人工智能·llm