管理员管理

创建数据库表

models.py

class Admin(models.Model):
    """管理员表"""
    username = models.CharField(verbose_name="用户名", max_length=32)
    password = models.CharField(verbose_name="密码", max_length=64)
在数据库生成
Tools->run manage.py task
执行命令
makemigrations
migrate

  

 数据库中插入一条数据

 insert into  app01_admin(username,password) values("coco", "123");

  

 

增加管理员菜单

修改/app01/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="/prettynum/list/">靓号管理</a></li>
</ul>

  

 在views文件夹下新建admin.py,用于存放管理账户管理的视图函数

修改urls.py

#导入admin
from app01.views import depart, pretty, user, admin
#添加url
urlpatterns = [
    #管理员账户管理
    path('admin/list/', admin.admin_list),
]

 

 admin.py

from django.shortcuts import render
from app01 import models

def admin_list(request):
"""管理员列表"""
queryset = models.Admin.objects.all()

context = {
'queryset' : queryset
}
return render(request, 'admin_list.html', context)

 在templates文件夹创建admin_list.html

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px" class="clearfix">
            <a class="btn btn-success" href="#">
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
                新建管理员
            </a>
            <div style="float: right; width: 300px;">
                <form>
                    <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><!-- /input-group -->
                </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>
                    <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="#">编辑</a>
                            <a class="btn btn-danger btn-xs" href="#">删除</a>
                        </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
{% endblock %}

  管理员列表就可以在前端展示出来了

 管理员列表添加分页

admin.py

from django.shortcuts import render

from app01 import models
from app01.utils.pagination import Pagination

def admin_list(request):
    """管理员列表"""
    queryset = models.Admin.objects.all()

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

  

 admin_list.html

{% extends 'layout.html' %}

{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px" class="clearfix">
            <a class="btn btn-success" href="#">
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
                新建管理员
            </a>
            <div style="float: right; width: 300px;">
                <form>
                    <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><!-- /input-group -->
                </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>
                    <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="#">编辑</a>
                            <a class="btn btn-danger btn-xs" href="#">删除</a>
                        </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
        <ul class="pagination">
            {{ page_string }}
        </ul>
    </div>
{% endblock %}

 完成

 添加搜索功能

admin.py

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)

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

  

 

 admin_list.html

 新建管理员

admin_list.html

            <a class="btn btn-success" href="/admin/add/">
                <span class="glyphicon glyphicon-plus-sign" aria-hidden="true"></span>
                新建管理员
            </a>

 

 urls.py

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

  修改/app01/views/admin.py

from django import forms
from app01.utils.bootstrap import BootStrapModelForm

class AdminModelForm(BootStrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现
        widget=forms.PasswordInput
    )

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

def admin_add(request):
    """添加管理员"""
    form = AdminModelForm()
    return render(request, 'change.html', {'form': form, "title": "新建管理员"})

  

 

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

新建zpp01/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">
                {#   novalidate去除浏览器的错误提示  #}
                <form method="post" novalidate>
                    {% csrf_token %}

                    {% for field in form %}
                        <div class="form-group">
                            <label>{{ field.label }}</label>
                            {{ field }}
                            {#  {{ field.errors }}错误信息是一个列表[错误1,错误2,错误3...], {{ field.errors.0 }}只取第一个错误1  #}
                            <span style="color: red;">{{ field.errors.0 }}</span>
                            {#   <input type="text" class="form-control" placeholder="姓名" name="user">  #}
                        </div>
                    {% endfor %}

                    <button type="submit" class="btn btn-primary">提 交</button>
                </form>
            </div>
        </div>
    </div>
{% endblock %}

  浏览器测试

 新建管理员页面点击提交,将数据保存到数据库

admin.py

from django import forms
from app01.utils.bootstrap import BootStrapModelForm

class AdminModelForm(BootStrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现
        widget=forms.PasswordInput
    )

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

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

 

 

 

 存在问题:

密码跟确认密码输入不一致也能提交成功,需要添加校验,使密码、确认密码输入一致

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

#包的导入要按照内置包、第三方包、自己写的这种顺序导入,短的在前面
from django import forms
#导入异常包 from django.core.exceptions import ValidationError from app01.utils.bootstrap import BootStrapModelForm class AdminModelForm(BootStrapModelForm): confirm_password = forms.CharField( label="确认密码", #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现 widget=forms.PasswordInput ) class Meta: model = models.Admin fields = ["username", "password", "confirm_password"] widgets = { "password": forms.PasswordInput } #钩子函数 def clean_confirm_password(self): password = self.cleaned_data.get("password") confirm = self.cleaned_data.get("confirm_password") if confirm != password: raise ValidationError("密码不一致,请重新输入。")
      #返回什么,此字段以后保存到数据库就是什么
  
      return confirm

  

 

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

render_value=True

  

 浏览器测试,这样密码就不会清空了

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

密码采用md5加密

新建app01/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()

  修改app01/views/admin.py

from django import forms
from django.core.exceptions import ValidationError
from app01.utils.bootstrap import BootStrapModelForm
from  app01.utils.encrypt import md5

class AdminModelForm(BootStrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现
        widget=forms.PasswordInput(render_value=True)
    )

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

    # 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 = md5(self.cleaned_data.get("confirm_password"))
        if confirm != pwd:
            raise ValidationError("密码不一致,请重新输入。")

        #返回什么,此字段以后保存到数据库就是什么
        return confirm

  

 看看效果吧

 

添加管理员编辑页面

修改app01/templates/admin_list.html

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

  

 修改myproject/myproject/urls.py

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

 添加一个公共的错误信息提示页面

在myprojrct/app01/templates/  新建 error.html

error.html

{% extends 'layout.html' %}

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

  编写视图函数

修改myproject/app01/views/admin.py

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

def admin_edit(request,nid):
    """编辑管理员"""

    #如果数据存在返回一个对象,如果数据不存在,返回none
    row_object = models.Admin.objects.filter(id=nid).first()
    #判断nid是否存在
    if not row_object:
        return render(request,'error.html', {"msg": "数据不存在"})
    title = "编辑管理员"

    if request.method == "GET":
        # instance = row_object显示编辑框的默认值
        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})

 

 浏览器访问,修改cocococo1

 点击提交

 添加管理员删除

修改app01/templates/admin_list.html

 <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>/delete/', admin.admin_delete),

修改myproject/app01/views/admin.py

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

  删除coco1

 完成

 

管理员重置密码

修改app01/templates/admin_list.html

<table class="table table-bordered">
    <thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</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 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>

 修改myproject/myproject/urls.py

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

修改myproject/app01/views/admin.py

 

class AdminResetModelForm(BootStrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现
        widget=forms.PasswordInput(render_value=True)
    )
    class Meta:
        model = models.Admin
        fields = ["password", "confirm_password"]
        widgets = {
            "password": forms.PasswordInput(render_value=True)
        }
    # 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 = md5(self.cleaned_data.get("confirm_password"))
        if confirm != pwd:
            raise ValidationError("密码不一致,请重新输入。")

        #返回什么,此字段以后保存到数据库就是什么
        return confirm

def admin_reset(request,nid):
    """重置密码"""
    row_object = models.Admin.objects.filter(id=nid).first()
    if not row_object:
        return render('/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})

 添加功能:重置密码时不允许跟之前设置的密码一致 

修改myproject/app01/views/admin.py

class AdminResetModelForm(BootStrapModelForm):
    confirm_password = forms.CharField(
        label="确认密码",
        #默认生成的input框为text框,想要密码不显示需要使用passwordInput框,定义widget插件实现
        widget=forms.PasswordInput(render_value=True)
    )
    class Meta:
        model = models.Admin
        fields = ["password", "confirm_password"]
        widgets = {
            "password": forms.PasswordInput(render_value=True)
        }
    # clean_字段名
    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什么.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

 

 完成

 

 

 

  

  

  

 

 

 

 

 



posted @ 2023-10-19 11:41  可可eleven  阅读(65)  评论(0)    收藏  举报