【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)

目录

    • 1. model编写数据表
    • 2. 管理员列表
      • 2.1 admin.py视图文件
      • 2.2 admin_list.html
      • 2.3 url.py
      • 2.4 最终效果
    • 3. 管理员添加
      • 3.0 md5包的书写
      • 3.1 form.py表单组件
      • 3.2 admin.py视图文件
      • 3.3 引入公共的添加数据html
      • 3.4 url.py
      • 3.5 最终效果
    • 4. 管理员编辑
      • 4.0 form表单组件
      • 4.1 admin.py视图文件
      • 4.2 admin_list.html
      • 4.3 url.py
      • 4.4 最终效果
    • 5. 管理员删除
      • 5.1 admin.py视图文件
      • 5.2 admin_list.html
      • 5.3 url.py
    • 6. 管理员密码重置
      • 6.1 form表单组件
      • 6.2 admin.py视图文件
      • 6.3 url.py
      • 6.4 admin_list.html
      • 6.5 最终效果
    • 总结


欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中

1. model编写数据表

  • model.py
class Admin(models.Model):
    """ 管理员 """
    username = models.CharField(verbose_name="用户名", max_length=32)
    password = models.CharField(verbose_name="密码", max_length=64)
  • cmd命令写入数据库
makemigrations
migrate

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第1张图片

  • 添加几条数据
    【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第2张图片
  • layot.html新增一个管理员管理模块
<li><a href="/admin/list/">管理员管理a>li>
{% 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>
        .navbar {
            border-radius: 0;
        {#去掉圆角#}
        }
    </style>
    {% block css %}{% endblock %}
</head>
<body>
<nav class="navbar navbar-default">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/depart/list/"> XX公司用户管理系统 </a>
        </div>
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li><a href="/admin/list/">管理员管理</a></li>
                <li><a href="/depart/list/">部门管理</a></li>
                <li><a href="/user/list/">用户管理</a></li>
                <li><a href="/pretty/list/">靓号管理</a></li>
                <li><a href="#">Link</a></li>


            </ul>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">登录</a></li>

                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">mzh <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">个人资料</a></li>
                        <li><a href="#">我的信息</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">注销</a></li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
</nav>

<div>
    {% block content %}{% endblock %}
</div>

{#导入jquery和bootstrap,注意要先导入js再导入jquery,顺序的问题#}
<script src="{% static 'js/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'plugins/bootstrap-3.4.1/js/bootstrap.min.js' %}"></script>
{% block js %}{% endblock %}
</body>
</html>


2. 管理员列表

2.1 admin.py视图文件

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第3张图片
同时也调用了分页插件,也实现了搜索功能。

from django.shortcuts import render
from app01 import models
from app01.utils.pagination import Pagination


def admin_list(request):
    """ 管理员列表 """

    # 构造搜索
    data_dict = {}
    search_data = request.GET.get('q', "")
    if search_data:
        data_dict["username__contains"] = search_data

    # 根据搜索条件去数据库获取
    queryset = models.Admin.objects.filter(**data_dict)

    print(queryset)
    # 分页
    page_object = Pagination(request, queryset)
    context = {
        'queryset': page_object.page_queryset,
        'page_string': page_object.html(),
    }
    return render(request, 'admin_list.html', context)

2.2 admin_list.html

复制黏贴我们的靓号表,只保留管理员名和密码字段,删掉多余字段,用户名替换为管理员名,注意把超链接的内容改成admin的。

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
    <div style="margin-bottom: 10px" class="clearfix">
        <a class="btn btn-success" href="/admin/add/">
            <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
            新建管理员
        </a>
        <div style="float: right;width: 300px;">
            <form method="get">
                <div class="input-group">
                    <input type="text" name="q" class="form-control" placeholder="Search for..."
                           value="{{ search_data }}">
                    <span class="input-group-btn">
                        <button class="btn btn-default" type="submit">
                            <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
                        </button>
                      </span>
                </div>
            </form>
        </div>

    </div>
    <div class="panel panel-default">
        <!-- Default panel contents -->
        <div class="panel-heading">
            <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
            管理员列表
        </div>

        <!-- Table -->
        <table class="table table-bordered">
            <thead>
            <tr>
                <th>ID</th>
                <th>管理员名</th>
                <th>密码</th>
            </tr>
            </thead>
            <tbody>
            {% for obj in queryset %}
                <tr>
                    <th>{{ obj.id }}</th>
                    <td>{{ obj.username }}</td>
                    <td>******</td>
                    <td>
                        <a class="btn btn-primary btn-xs" href="/admin/{{ obj.id }}/edit/">编辑</a>
                        <a class="btn btn-danger btn-xs" href="/admin/{{ obj.id }}/delete/">删除</a>
                    </td>
                </tr>
            {% endfor %}

            </tbody>

        </table>


    </div>
    <div class="clearfix">
        <ul class="pagination">
            {{ page_string }}
        </ul>
    </div>
    </div>


{% endblock %}

2.3 url.py

注意要先导包 from app01.views import admin

path('admin/list/', admin.admin_list),

2.4 最终效果

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第4张图片


3. 管理员添加

3.0 md5包的书写

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第5张图片

后面密码存储会使用到

from django.conf import settings
import hashlib


def md5(data_string):
    obj = hashlib.md5(settings.SECRET_KEY.encode('utf-8'))
    obj.update(data_string.encode('utf-8'))
    return obj.hexdigest()

3.1 form.py表单组件

render_value=True 表示错误后 保留原来的密码而不是直接清空

from app01.utils.encrypt import md5
class AdminModelForm(BootStrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        widget=forms.PasswordInput(render_value=True)#render_value=True 表示错误后 保留原来的密码而不是直接清空
    )

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

    # 得到 首次输入密码的md5
    def clean_password(self):
        pwd = self.cleaned_data.get("password")
        return md5(pwd)

    # 判断两次输入的密码是否相等,返回保存进数据库的是md5后的格式
    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']

3.2 admin.py视图文件

def admin_add(request):
    """ 添加管理员 """
    title = "新建管理员"
    if request.method == "GET":
        form = AdminModelForm()
        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})

3.3 引入公共的添加数据html

我们观察发现使用了moudleForm之后其实所有的添加数据页面只有title标题不同,其他内容完全相同,没有必要复制新建几个差不多的html,用一个公共的chang.html来替代所有add.html,只需要在使用时传入不同的标题名即可。

return render(request, 'change.html', {'form': form, "title": title})

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第6张图片

{% extends 'layout.html' %}


{% block content %}

    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">
                <h3 class="panel-title"> {{ title }} h3>
            div>
            <div class="panel-body">
                <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>
        div>
    div>

{% endblock %}

3.4 url.py

注意要先导包 from app01.views import admin

path('admin/add/', admin.admin_add),

3.5 最终效果

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第7张图片


4. 管理员编辑

4.0 form表单组件


class AdminEditModelForm(BootStrapModelForm):
    class Meta:
        model = models.Admin
        fields = ['username']

4.1 admin.py视图文件

class AdminEditModelForm(BootStrapModelForm):
    class Meta:
        model = models.Admin
        fields = ['username']

4.2 admin_list.html

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
    <div style="margin-bottom: 10px" class="clearfix">
        <a class="btn btn-success" href="/admin/add/">
            <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
            新建管理员
        </a>
        <div style="float: right;width: 300px;">
            <form method="get">
                <div class="input-group">
                    <input type="text" name="q" class="form-control" placeholder="Search for..."
                           value="{{ search_data }}">
                    <span class="input-group-btn">
                        <button class="btn btn-default" type="submit">
                            <span class="glyphicon glyphicon-search" aria-hidden="true"></span>
                        </button>
                      </span>
                </div>
            </form>
        </div>

    </div>
    <div class="panel panel-default">
        <!-- Default panel contents -->
        <div class="panel-heading">
            <span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>
            管理员列表
        </div>

        <!-- Table -->
        <table class="table table-bordered">
            <thead>
            <tr>
                <th>ID</th>
                <th>管理员名</th>
                <th>密码</th>
            </tr>
            </thead>
            <tbody>
            {% for obj in queryset %}
                <tr>
                    <th>{{ obj.id }}</th>
                    <td>{{ obj.username }}</td>
                    <td>******</td>
                    <td>
                        <a class="btn btn-primary btn-xs" href="/admin/{{ obj.id }}/edit/">编辑</a>
                        <a class="btn btn-danger btn-xs" href="/admin/{{ obj.id }}/delete/">删除</a>
                    </td>
                </tr>
            {% endfor %}

            </tbody>

        </table>


    </div>
    <div class="clearfix">
        <ul class="pagination">
            {{ page_string }}
        </ul>
    </div>
    </div>


{% endblock %}

  • 这里也可以定义一个错误页面,当找不到指定id的记录时显示
    【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第8张图片
{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <div class="alert alert-danger" role="alert">{{ msg }}div>
    div>
{% endblock %}

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第9张图片

4.3 url.py

注意要先导包 from app01.views import admin

path('admin//edit/', admin.admin_edit),

4.4 最终效果

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第10张图片


5. 管理员删除

5.1 admin.py视图文件

def admin_delete(request, nid):
    """ 删除管理员 """
    models.Admin.objects.filter(id=nid).delete()
    return redirect('/admin/list/')

5.2 admin_list.html

不变

5.3 url.py

    path('admin//delete/', admin.admin_delete),

6. 管理员密码重置

6.1 form表单组件

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

6.2 admin.py视图文件

def admin_reset(request, nid):
    """ 重置密码 """
    # 对象 / None
    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})

6.3 url.py

    path('admin//reset/', admin.admin_reset),

6.4 admin_list.html

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px" class="clearfix">
            <a class="btn btn-success" href="/admin/add/">
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true">span>
                新建管理员
            a>
            <div style="float: right;width: 300px;">
                <form method="get">
                    <div class="input-group">
                        <input type="text" name="q" class="form-control" placeholder="Search for..."
                               value="{{ search_data }}">
                        <span class="input-group-btn">
                        <button class="btn btn-default" type="submit">
                            <span class="glyphicon glyphicon-search" aria-hidden="true">span>
                        button>
                      span>
                    div>
                form>
            div>

        div>
        <div class="panel panel-default">
            
            <div class="panel-heading">
                <span class="glyphicon glyphicon-th-list" aria-hidden="true">span>
                管理员列表
            div>

            
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>IDth>
                    <th>管理员名th>
                    <th>密码th>
                tr>
                thead>
                <tbody>
                {% for obj in queryset %}
                    <tr>
                        <th>{{ obj.id }}th>
                        <td>{{ obj.username }}td>
                        <td>******td>
                        <td>
                            <a href="/admin/{{ obj.id }}/reset/">重置密码a>
                        td>
                        <td>
                            <a class="btn btn-primary btn-xs" href="/admin/{{ obj.id }}/edit/">编辑a>
                            <a class="btn btn-danger btn-xs" href="/admin/{{ obj.id }}/delete/">删除a>
                        td>
                    tr>
                {% endfor %}

                tbody>

            table>


        div>
        <div class="clearfix">
            <ul class="pagination">
                {{ page_string }}
            ul>
        div>
    div>


{% endblock %}

6.5 最终效果

【Django 网页Web开发】15. 实战项目:管理员增删改查,md5密码和密码重置(08)(保姆级图文)_第11张图片


总结

大家喜欢的话,给个,点个关注!给大家分享更多有趣好玩的Python 网页Web开发知识!

版权声明:

发现你走远了@mzh原创作品,转载必须标注原文链接

Copyright 2023 mzh

Crated:2023-3-1

欢迎关注 『Django 网页Web开发』 系列,持续更新中
欢迎关注 『Django 网页Web开发』 系列,持续更新中
『01. 安装配置Django』
『02. 创建并运行一个Django项目』
『03. 初识Django』
『04. 请求和响应,网页跳转重定向,实战简易表单模拟登陆』
『05. 数据库操作,实战用户管理』
『06. 报错:You have 26 unapplied migration(s). Your project may not work properly until you apply the migra』
『07. 模板语法』
『08. 实战项目:部门和员工管理系统(01)』
『09. 实战项目:员工编辑删除功能与靓号管理(02)』
『10. 实战项目:靓号搜索功能(03)』
『11. 实战项目:分页与页码跳转功能(04)』
『12. 实战项目:分页组件的封装 面向接口编程(05)』
『13. 实战项目:添加用户时的时间选择组件(06)』
『14. 实战项目:一些面向对象的代码结构优化(07)』
『15. 实战项目:管理员增删改查,md5密码和密码重置(08)』
『16. 实战项目:BootStrap类的进一步优化(09)』
『17. 实战项目:login业务涉及cookie、session、中间件(10)』
『18. 实战项目:登录时的验证码(11)』
『19. 实战项目:初识Ajax请求(12)』
『20. 实战项目:Ajax实战之订单管理与弹出对话框(13)』
『21. 实战项目:echart数据图表(14)』
『22. 实战项目:简单的文件上传(15)』
『23. 实战项目:Excel和form和moudleForm的文件上传(16)』
【更多内容敬请期待】


你可能感兴趣的:(#,Django网页Web开发,python,django,前端,python)