Django web 开发(四) - Django项目实践(六)-管理员管理

管理员管理

创建数据库表

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

执行命令

python3 manage.py makemigrations
python3 manage.py migrate

在这里插入图片描述
像素数据库表中插入一条数据

mysql> use my_project;

mysql> insert into employee_management_admin(username, password) values("张三", "123456");
Query OK, 1 row affected (0.00 sec)

mysql> insert into employee_management_admin(username, password) values("李四", "456789");
Query OK, 1 row affected (0.00 sec)

mysql> insert into employee_management_admin(username, password) values("楚云飞", "qwe123");
Query OK, 1 row affected (0.01 sec)

mysql> insert into employee_management_admin(username, password) values("小日子", "123456");
Query OK, 1 row affected (0.00 sec)

mysql> insert into employee_management_admin(username, password) values("小瘪三", "123456");
Query OK, 1 row affected (0.00 sec)

mysql> insert into employee_management_admin(username, password) values("大狗", "123456");
Query OK, 1 row affected (0.00 sec)

mysql> insert into employee_management_admin(username, password) values("孙悟空", "123456");
Query OK, 1 row affected (0.00 sec)

增加管理员菜单

修改/root/python/myproject/employee_management/templates/layout.html

<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>
</ul>

在这里插入图片描述

管理员列表

新建myproject/employee_management/templates/admin_list.html

{% extends 'layout.html' %}

{% block content %}
<div class="container">

    <div>
        <div style="margin-bottom: 10px; ">
            <a class="btn btn-primary" href="/pretty/add/" target="_blank">新建管理员</a>

            <div style="float: right; width: 300px;">
                <form method="get">
                    <div class="input-group">
                        <input type="text" name="query" 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>

    <div>
        <div class="panel panel-default">
            <!-- Default panel contents -->
            <div class="panel-heading">
                <span class="glyphicon glyphicon-th-list" aria-hidden="true" style="margin-right: 5px;"></span>
                <span>管理员列表</span>
            </div>

            <!-- Table -->
            <table class="table table-bordered">
                <thead>
                    <tr>
                        <th>ID</th>
                        <th>姓名</th>
                        <th>密码</th>
                        <th>操作</th>
                    </tr>
                </thead>
                <tbody>
                    {% for obj in page_queryset %}
                    <tr>
                        <th>{
   
   { obj.id }}</th>
                        <td>{
   
   { obj.username }}</td>
                        <td>{
   
   { obj.password }}</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>

    <ul class="pagination">
        {
   
   { page_string }}
    </ul>
    <br>

    <form method="get">
        <div style="display:inline-block; width: 150px;">
            <div class="input-group">
                <span> <input type="text" class="form-control" placeholder="请输入页码" name="page"></span>
                <span class="input-group-btn">
                    <button class="btn btn-primary" type="submit">跳转</button>
                </span>
            </div>
        </div>
    </form>
</div>

{% endblock %}

新建myproject/employee_management/views/admin.py

from django.shortcuts import render
from employee_management.models import Admin
from employee_management.utils.pagination import Pagination


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

    data_dict = {
    
    }
    # 不加后面的 "", 首次访问浏览器,搜索框中不会显示前端页面中的 placeholder="Search for..." 属性
    search_data = request.GET.get('query', "")
    if search_data:
        data_dict["username__contains"] = search_data 
    
    queryset = Admin.objects.filter(**data_dict).order_by("id")

    # queryset = Admin.objects.all()
    page_object = Pagination(request, queryset, page_size=2)
    page_queryset = page_object.page_queryset
    page_object.html()
    page_string = page_object.page_string

    context = {
    
    
        "page_queryset": page_queryset,
        "page_string": page_string,
        "search_data": search_data,
    }

修改/root/python/myproject/myproject/urls.py

from django.contrib import admin
from django.urls import path
from employee_management.views import depart,user,pretty,admin

urlpatterns = [

    # path('admin/', admin.site.urls),

    # 部门管理
    path('depart/list/', depart.depart_list),
    path('depart/add/', depart.depart_add),
    path('depart/delete/', depart.depart_delete),
    path('depart/<int:nid>/edit/', depart.depart_edit),

    # 用户管理
    path('user/list/', user.user_list),
    path('user/model/form/add/', user.user_model_form_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/list/', admin.admin_list),
]

在这里插入图片描述

管理员添加

修改myproject/employee_management/views/admin.py

from employee_management.utils.modelform import BootStrapModelForm
from django import forms


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

    class Meta:
        model = Admin
        fields = ["username", "password", "confirm_password"]
        widgets = {
    
    
            "password": forms.PasswordInput
        }

def admin_add(request):
    """添加管理员"""

    form = AdminModelForm

    context = {
    
    
        "form": form,
        "title": "新建管理员",
    }

    return render(request, "change.html", context)

按照之前的套路,我应该会新建一个名为admin_add.html的HTML文件来展示添加界面
这次我们优化一下
不管是pretty_add.html或者user_add.html,除了标题不一样,其他的都是一样的
没有必要在创建一个单独的HTML页面,我们只需要在一个公共的HTML页面中传入各自的标题即可

新建myproject/employee_management/templates/change.html

{% 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 %}
</body>

</html>

修改myproject/myproject/urls.py

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

浏览器访问
在这里插入图片描述

将数据保存到数据库

修改myproject/employee_management/views/admin.py

def admin_add(request):
    """添加管理员"""

    title = "新建管理员"

    if request.method == "GET":
        form = AdminModelForm()
        return render(request, "change.html", {
    
    "form": form, "title": title})

    # 如果是POST请求
    form = AdminModelForm(data=request.POST)

    context = {
    
    
        "form": form,
        "title": title,
    }
    
    if form.is_valid():
        form.save()
        return redirect("/admin/list")


    return render(request, "change.html", context)

在这里插入图片描述
在这里插入图片描述

但是现在还有一个问题,如果两次输入的密码不一致呢?

修改myproject/employee_management/views/admin.py,增加钩子函数clean_confirm_password

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

    class Meta:
        model = Admin
        fields = ["username", "password", "confirm_password"]
        widgets = {
    
    
            "password": forms.PasswordInput
        }

    # 钩子函数
    def clean_confirm_password(self):
        pwd = self.cleaned_data.get("password")
        confirm = self.cleaned_data.get("confirm_password")
        if confirm != pwd:
            raise ValidationError("密码不一致!")
        return confirm

浏览器测试
在这里插入图片描述
可以发现,数据校验成功了
但是还有个问题,当我们点击保存后,密码和密码确认框中的数据清空了
这样不是太友好,因此我们需要添加一个属性

修改myproject/employee_management/views/admin.py

render_value=True

在这里插入图片描述
然后测试,就不会出现自动清空的情况了

现在又出现一个问题
密码这样存储进数据库,很不安全
我们最好对其进行加密后,再进行保存

这里我们使用md5方式进行加密
新建/root/python/myproject/employee_management/utils/encrypt.py文件

import hashlib
from django.conf import settings

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

修改myproject/employee_management/views/admin.py

# clean_字段名
def clean_password(self):
    pwd = self.cleaned_data.get("password")
    # return什么.password字段保存什么
    return md5(pwd)

# 钩子函数
def clean_confirm_password(self):
    pwd = self.cleaned_data.get("password")
    confirm = self.cleaned_data.get("confirm_password")
    if md5(confirm) != pwd:
        raise ValidationError("密码不一致!")
    
    # return返回什么,字段 confirm_password 保存至数据库的值就是什么
    return md5(confirm)

在这里插入图片描述
浏览器添加新用户测试
在这里插入图片描述

管理员编辑

修改myproject/employee_management/templates/admin_list.html

<a class="btn btn-primary btn-xs" href="/admin/{
     
     { obj.id }}/edit/">编辑</a>

在这里插入图片描述
修改myproject/myproject/urls.py

path('admin/<int:nid>/edit/', admin.admin_edit),

修改myproject/employee_management/views/admin.py

# 如果不想让用户修改密码,只能修改用户名,那么使用下面这个AdminEditModelForm 
# 如果都可以修改,直接用上面的AdminModelForm即可
class AdminEditModelForm(BootStrapModelForm):
    class Meta:
        model = Admin
        fields = ["username"]

def admin_edit(request, nid):

    # 判断 nid 是否存在
    row_object = 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})

浏览器访问,修改张三张三啊
在这里插入图片描述
点击"保存"
在这里插入图片描述

管理员删除

修改myproject/employee_management/templates/admin_list.html

<a class="btn btn-danger btn-xs" href="/admin/{
     
     { obj.id }}/delete/">删除</a>

修改myproject/myproject/urls.py

path('admin/<int:nid>/delete/', admin.admin_delete),

修改myproject/employee_management/views/admin.py

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

管理员重置密码

修改myproject/employee_management/templates/admin_list.html

<th>重置密码</th>

...

<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>

在这里插入图片描述
修改myproject/myproject/urls.py

path('admin/<int:nid>/reset/', admin.admin_reset),

修改myproject/employee_management/views/admin.py

class AdminResetModelForm(BootStrapModelForm):

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

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

    # clean_字段名
    def clean_password(self):
        pwd = self.cleaned_data.get("password")

        # 校验当前数据库中的密码与用户输入的新密码是否一致
        exists = Admin.objects.filter(id=self.instance.pk, password=md5(pwd))
        if exists:
            raise ValidationError("密码不能与当前密码一致!")

        # return什么.password字段保存什么
        return md5(pwd)

    # 钩子函数
    def clean_confirm_password(self):
        pwd = self.cleaned_data.get("password")
        confirm = self.cleaned_data.get("confirm_password")
        if md5(confirm) != pwd:
            raise ValidationError("密码不一致!")
        
        # return返回什么,字段 confirm_password 保存至数据库的值就是什么
        return md5(confirm)

def admin_reset(request, nid):
    """重置管理员密码"""

    # 判断 nid 是否存在
    row_object = Admin.objects.filter(id=nid).first()
    if not row_object:
        return render(request, "error.html", {
    
    "msg": "数据不存在!"})

    title = "重置密码 - {}".format(row_object.username)

    if request.method == "GET":
        form = AdminResetModelForm(instance=row_object)
        
        return render(request, "change.html", {
    
    "title": title, "form": form})

    form = AdminResetModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect("/admin/list/")

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

在这里插入图片描述

不知道为什么下面的"密码不一致错误也出来了",后面待解决

猜你喜欢

转载自blog.csdn.net/qq_43139145/article/details/128716268