美文网首页点滴技术
Django之用户管理系统CBV-全新升级(5)

Django之用户管理系统CBV-全新升级(5)

作者: 点滴技术 | 来源:发表于2021-08-15 15:59 被阅读0次

    时间过的真快,又接近4个月没更新文章了,不是我闲着,家里事情是真多,时间都给了溜娃还是溜娃,剩余点时间就学习Django的知识,为了打磨好这一篇文章,可费了九牛二虎之力,完成该篇文章。

    为了各位读者有较好的UI视觉、有动力去学习和摸索,前端可投入不少时间。毕竟作为一名网工,去搞前端,那还真不是一件容易的事情,你想,Django这个后端知识体系已经够学一阵一阵子的了。

    前端有啥学习?HTML、javascrip、jQuery、ajAX、Vue...

    后端有啥学习?Django就够了...

    前方高能,请看如下效果图...


    1.0 效果展示

    说明:提前贴出这些图,希望各位看了有动力去学习。虽然django有自带一套用户系统,但是人的审美总是要有的哈,又可以提升下自己的代码水平.

    • 用户列表展示

      user_list.gif
    • 新增用户


    • 更新用户


    • 删除用户

    1.1 基础配置

    说明:有一些共性的东西,我就提前在这个章节写出来。

    • settings.py 配置
      文件路径:mysite/settings.py

      static文件夹路径:用于存放前端的一些cssjsicon等文件。

      AUTH_USER_MODEL:重写内置的用户管理。

      DATABASES:使用的是mysql数据库,一直用的这个。

      INSTALLED_APPS:新建和注册app,就不多讲了,请看之前的文章。

    # mysite/settings.py
    
    INSTALLED_APPS = [
      # 新建的app,注册一下
        'users',  
    ]
    
    # 定义存放js/cs/img的文件路径
    STATIC_URL = '/static/'
    STATICFILES_DIRS = (
        (BASE_DIR / 'static'),
    )
    # 全局声明,使用UserProfile
    # 默认是: AUTH_USER_MODEL = 'auth.User'
    AUTH_USER_MODEL = 'users.UserProfile'
    
    # 数据库mysql参数配置, 内置有sqlite。
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'django_db',
            'HOST': '192.168.8.130',
            'USER': '<数据库用户名>',
            'PASSWORD': '<数据库密码>,
            'PORT': 3306,
        }
    }
    
    • 母版配置
      文件路径:mysite/templates/base1.html

      templates目录下新建base1.html文件,作为母版,代码如下所示。

      说明: 母版存放基本cssjs样式, 这样子页面就不用单独加载这些了,切记不要把所有的js或css放在一个html内,避免导致页面加载慢,按需页面加载即可。

    <!-- mysite/templates/base1.html -->
    
    <!DOCTYPE html>
    {% load  static %}
    <html lang="en">
        
    <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <meta name="description" content="">
            <meta name="author" content="">
            <!-- 页面标签 -->
            <title>
                {% block title %}自动化运维平台{% endblock %}
            </title>
    
            <!-- 加载CSS样式 -->
            <!-- Bootstrap core CSS -->
            <link href="{% static "css/bootstrap.min.css" %}" rel="stylesheet">
            <link href="{% static "css/bootstrap-reset.css" %}" rel="stylesheet">
    
            <!--Animation css-->
            <link href="{% static "css/animate.css" %}" rel="stylesheet">
    
            <!--Icon-fonts css-->
            <link href="{% static "assets/font-awesome/css/font-awesome.css" %}" rel="stylesheet" />
            <link href="{% static "assets/ionicon/css/ionicons.min.css" %}" rel="stylesheet" />
    
            <!--Morris Chart CSS -->
            <link rel="stylesheet" href="{% static "assets/morris/morris.css" %}">
    
            <!-- Custom styles for this template -->
            <link href="{% static "css/style.css"  %}" rel="stylesheet">
            <link href="{% static "css/helper.css" %}" rel="stylesheet">
    
            <!-- Plugin Css-->
            <link rel="stylesheet" href="{% static "assets/magnific-popup/magnific-popup.css"%}" />
            <link rel="stylesheet" href="{% static "assets/jquery-datatables-editable/datatables.css"%}" />
    
            <!-- Custom styles for this template -->
            <link rel="stylesheet" href="{% static "css/style.css" %}">
            <link rel="stylesheet" href="{% static "css/helper.css" %}">
    
            {% block css %}{% endblock %}
    </head>
    
        <body>
            <!-- Aside Start-->
            <aside class="left-panel">
                <!-- brand -->
                <div class="logo">
                    <a href="{% url 'index' %}" class="logo-expanded">
                        <i class="ion-social-buffer"></i>
                        <span class="nav-label">自动化运维平台</span>
                    </a>
                </div><!-- / brand -->
    
                <!-- Navbar Start 导航栏 -->
                <nav class="navigation">
                    <ul class="list-unstyled">
                        <li class="active"><a href="#"><i class="ion-home"></i> <span class="nav-label">仪表盘</span></a></li>
                        <li class="has-submenu"><a href="#"><i class="ion-android-social-user"></i> <span class="nav-label">用户权限管理</span></a>
                    <ul class="list-unstyled">
                        <li class="users"><a href="{% url 'users:userlist' %}">用户管理</a></li>
                        <li class="roles"><a href="#">角色管理</a></li>
                        <li class="permissions"><a href="#">权限管理</a></li>
                    </ul>
                        </li>
                    </ul>
                </nav><!-- Navbar Ends -->
            </aside><!-- Aside Ends-->
    
            <!--Main Content Start -->
            <section class="content">
                
                <!-- Header -->
                <header class="top-head container-fluid">
                    <!-- 左上角收缩 导航栏 -->
                    <button type="button" class="navbar-toggle pull-left">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
    
                    <nav class=" navbar-default" role="navigation">
                        <!-- Right navbar -->
                        <ul class="nav navbar-nav navbar-right top-menu top-right-menu">
                            <!-- user login dropdown start-->
                            <li class="dropdown text-center">
                                <a data-toggle="dropdown" class="dropdown-toggle" href="#">
                                    <img alt="" src="{% static "img/avatar-2.jpg" %}" class="img-circle profile-img thumb-sm">
                                    <span class="username"> admin </span> <span class="caret"></span>
                                </a>
                                <ul class="dropdown-menu pro-menu fadeInUp animated" tabindex="5003" style="overflow: hidden; outline: none;">
                                    <li><a href="#"><i class="fa fa-edit"></i> 修改密码</a></li>
                                    <li><a href="#"><i class="fa fa-sign-out"></i> 退出 </a></li>
                                </ul>
                            </li>
                            <!-- user login dropdown end -->       
                        </ul>
                        <!-- End right navbar -->
                    </nav>
                    
                </header>
                <!-- Header Ends -->
                <!-- 以上就是每一个页面共用的部分,即母版 -->
    
                <!-- Page Content Start -->
                <!-- ================== -->
                <!-- 以下就是每一个页面自定义内容的部分 -->
                <div class="wraper container-fluid">
                    <div class="page-title"> 
                        <h3 class="title"> {% block page-title %} {% endblock %} </h3>
                    </div>
    
                    {% block page-content %} {% endblock %}
    
                </div>
                <!-- Page Content Ends -->
                <!-- ================== -->
    
                <!-- 页脚 Footer Start -->
                <footer class="footer">
                  2021©自动化运维平台
                </footer>
                <!-- 页脚 Footer Ends -->
    
            </section>
            <!-- Main Content Ends -->
            <script src="{% static 'js/jquery.js' %}"></script>
            <script src="{% static 'js/bootstrap.min.js' %}"></script>
            <script src="{% static 'js/wow.min.js' %}"></script>
            <script src="{% static 'js/pace.min.js' %}"></script>
            <!--控制菜单栏点击显示子菜单-->
            <script src="{% static 'js/jquery.app.js' %}"></script>
            <!--子菜单点击时,不收缩-->
            <script src="{% static 'js/jquery.nicescroll.js' %}" ></script>
    
            {% block js %}{% endblock %}
    
        </body>
    </html>
    
    • model配置
      文件路径: mysite/users/models.py

      继承内置用户系统AbstractUser, 内置有usernamepasswordemailis_active等字段,我在此基础上增加了cn_namephonesex, 3个字段属性。

      # mysite/users/models.py
      #!/usr/bin/env python3
      #-*- coding:UTF-8 -*-
      
      from django.db import models
      from django.contrib.auth.models import AbstractUser
      
      class Userprofile(AbstractUser):
          SEX_CHOICE = (
              (0, '男'),
              (1, '女'),
          )
          cn_name = models.CharField('中文名', max_length=128)
          phone = models.CharField('手机', max_length=11, null=True, blank=True)
          sex = models.IntegerField(choices=SEX_CHOICE, null=True, blank=True)
      
          class Meta:
              verbose_name = '用户信息'
      
          def __str__(self):
              return self.username
      

      温馨提示:model编写好后,各位记得python manage.py makemigrations userspython manage.py migrate users

    • 路由url配置
      文件路径:mysite/urls.py

      主路由urls:

      # mysite/urls.py
      
      from django.contrib import admin
      from django.urls import path, include
      
      urlpatterns = [
          path('admin/', admin.site.urls),
          path('user/', include('users.urls'))  # 新建
      ]
      

      子路由urls(app为users):

      # mysite/users/urls.py
      
      from django.urls import path, re_path
      from .views import *
      
      app_name = 'users'
      urlpatterns = [
        # 用户查看
          path('userlist/', UserListView.as_view(), name='userlist'),
        # 用户增加
          path('useradd/', UserAddView.as_view(), name='useradd'),
        # 用户编辑
          re_path('useredit/(?P<pk>[0-9]+)?/', UserEditView.as_view(), name='useredit'),
        # 用户删除
          re_path('userdel/(?P<pk>[0-9]+)?/', UserDelView.as_view(), name='userdel'),
          ]
      
    • 分页
      文件路径:mysite/templates/_paginator.html

      效果是这样子的:


      templates目录下创建_paginator.html,写入如下代码:
      说明:这个分页文件会在userlist.html被调用,这个模板是别人写好的,拿来用即可.
      # mysite/templates/_paginator.html
      
      <ul class="pagination m-b-5" style="float: right">
          {% if page_obj.has_previous %}
              <li><a href="?page=1">首页</a></li>
              <li><a href="?{{ page_obj.previous_page_number.querystring }}" aria-label="上一页">上一页</a></li>
          {% else %}
              <li><a class="disabled" href="?page=1">首页</a></li>
              <li><a class="disabled">上一页</a></li>
          {% endif %}
          {% for page in page_obj.pages %}
               {% if page %}
                  {% ifequal page page_obj.number %}
                      <li class="active"><a class="">{{ page }}</a></li>
                  {% else %}
                      <li><a class="" href="?{{ page.querystring }}">{{ page }}</a></li>
                  {% endifequal %}
              {% else %}
                   <li><a class="" href="javascript:void(0)">...</a></li>
              {% endif %}
          {% endfor %}
          {% if page_obj.has_next %}
              <li><a class="" href="?{{ page_obj.next_page_number.querystring }}">下一页</a></li>
              <li><a class="" href="?page={{ page_obj.paginator.num_pages }}">尾页</a></li>
          {% else %}
              <li><a class="disabled">下一页</a></li>
              <li><a class="disabled">尾页</a></li>
          {% endif %}
      </ul>
      

    1.2 用户添加

    说明:用户添加的表单使用forms的ModelForm,可以依赖model, 视图则使用generic(通用视图)的CreateView.

    • 创建form.py文件

      #!/usr/bin/env python3
      #-*- coding:UTF-8 -*-
      
      from django import forms
      from django.contrib.auth import get_user_model
      import re
      
      class UserModelForm(forms.ModelForm):
          # 新增确认密码字段,用于两次密码作比较
          # 该字段不用写入数据库
          confirm_password = forms.CharField(required=True)
      
          class Meta:
              # 与model建立了依赖关系,即按照model中的字段类型验证
              model = User
              # 根据model定义的类型,验证列的属性
              fields = ('username', 'cn_name', 'password', 'sex', 'phone')
      
          def clean_phone(self):
              # clean_字段名,该方法用于验证字段,自定义条件
              phone = self.cleaned_data['phone']
              if phone:
                  phone_re = re.match("^1[35789][0-9]{9}$", phone)
                  # print(phone_re)
                  if phone_re:
                      return phone
                  else:
                      raise forms.ValidationError("手机号码非法")
              else:
                  # ValidationError自定义表单错误
                  raise forms.ValidationError("这个字段是必填项")
      
          def clean_confirm_password(self):
              """
              用于比较两次输入的密码
              """
              password = self.cleaned_data.get('password')
              confirm_password = self.cleaned_data.get('confirm_password')
              if password != confirm_password:
                  raise forms.ValidationError('两次密码不一致!')
              # return confirm_password
      

      说明:设计成表单,需要单独创建一个form.py,名字自定义,def clean_字段名用于判断表单的字段是否符合设定的要求。

    • 视图配置
      文件路径:mysite/users/views.py

      # mysite/users/views.py
      
      from django.views.generic import CreateView
      from django.contrib.messages.views import SuccessMessageMixin
      from django.contrib.auth import get_user_model
      from .form import UserModelForm
      
      User = get_user_model()
      
      class UserAddView(SuccessMessageMixin, CreateView):
          """
          新增用户
          """
          template_name = 'users/form.html'
          model = User
          form_class = UserModelForm
          success_message = '%(username)s 用户添加成功!'
      
          def get_success_url(self):
              # print(self.request.POST)
              if "_addanother" in self.request.POST:
                  return reverse('users:useradd')
              return reverse('users:userlist')
      
          def form_valid(self, form):
              """
              form.cleaned_data:获取表单所有数据
              from.instance:一个用户对象(是一个类)
              """
              password = form.cleaned_data['password']
              form.instance.password = make_password(password)
              # print(form.cleaned_data)
              # print(make_password(password))
              # print(form.instance)
              return super(UserAddView, self).form_valid(form)
      
          def form_invalid(self, form):
              """
              form_invalid方法可以不用写,用于print表单报错.
              """
              # print('form_invalid', form.cleaned_data)
              # print(form.errors.as_json())
              return super(UserAddView, self).form_invalid(form)
      

      参数解读:

      • get_success_url:如果表单正常,return重定向到定义的url。
      • form_valid:如果表单正常,进入该函数,并通过make_password方法生成随机的密文,默认会通过form.save()写入数据库中。
      • form_invalid:如果表单异常,进入该函数(仅用于演示,可不写).
    • 模板配置
      文件路径:mysite/users/templates/form.html

      说明:用户新增和用户修改使用的是同一个模板,里面通过if条件进行区分.

      <!-- mysite/users/templates/form.html -->
      
      {% extends 'base1.html' %}
      
      {% load static %}
      
      {% block title %}
          {% if object %}
              用户更新
          {% else %}
              用户添加
          {% endif %}
      {% endblock %}
      
      {% block page-title %}
          {% if object %}
              用户更新
          {% else %}
              用户添加
          {% endif %}
      {% endblock %}
      
      {% block page-content %}
          <!-- Form-validation -->
      <div class="row">
          <div class="col-sm-12">
              <div class="panel panel-default">
      
                  <div class="panel-heading"><h3 class="panel-title">{% if object %}请更新一个用户{% else %}请添加一个用户{% endif %}</h3></div>
                  <div class="panel-body">
      
                      {% if form %}
                              <div class="alert  alert-dismissable">
                                  <button type="button" class="close" data-dismiss="alert" aria-hidden="true">x</button>
                                  <p style="color: red"> {{ form.errors }} </p>
                              </div>
                      {% endif %}
      
                      <div class=" form">
                          <form class="cmxform form-horizontal tasi-form" id="signupForm" method="post" action="" novalidate="novalidate">
                              <div class="form-group ">
                                  <label for="username" class="control-label col-lg-2">用户名 *</label>
                                  <div class="col-lg-10">
                                      <input class=" form-control" name="username" value="{% if object %}{{object.username}}{% endif %}" type="text">
                                  </div>
                              </div>
      
      
                              <div class="form-group ">
                                  <label for="cn_name" class="control-label col-lg-2">中文名 *</label>
                                  <div class="col-lg-10">
                                      <input class=" form-control" name="cn_name" value="{% if object %}{{ object.cn_name }}{% endif %}" type="text">
                                  </div>
                              </div>
      
                              <div class="form-group ">
                                  <label for="password" class="control-label col-lg-2">密码 *</label>
                                  <div class="col-lg-10">
                                      <input class=" form-control" name="password" value="" type="password">
                                  </div>
                              </div>
      
                              <div class="form-group ">
                                  <label for="confirm_password" class="control-label col-lg-2">再次输入密码 *</label>
                                  <div class="col-lg-10">
                                      <input class=" form-control" name="confirm_password" value="" type="password">
                                  </div>
                              </div>
      
                              <div class="form-group ">
                                  <label for="name" class="control-label col-lg-2">手机号 *</label>
                                  <div class="col-lg-10">
                                      <input class=" form-control" name="phone" value="{% if object %} {{ object.phone }} {% endif %}" type="text">
                                  </div>
                              </div>
      
                              <div class="form-group">
                                  <label for="level" class="control-label col-lg-2">性别 *</label>
                                  <div class="col-lg-10">
                                      <div class="radio-inline">
                                          <label class="cr-styled" >
                                              <input type="radio"  name="sex" value="0" {% if object %}{% if object.sex == 0 %}checked{% endif %}{% endif %} checked>
                                              <i class="fa"></i>
                                              男
                                          </label>
                                      </div>
                                      <div class="radio-inline">
                                          <label class="cr-styled">
                                              <input type="radio"  name="sex" value="1" {% if object %}{% if object.sex == 1 %}checked{% endif %}{% endif %}>
                                              <i class="fa"></i>
                                              女
                                          </label>
                                      </div>
                                  </div>
                              </div>
      
                              <div class="form-group">
                                  <div class="col-lg-offset-2 col-lg-10">
                                       <button class="btn btn-success" type="submit">确定</button>
                                       {% if object %}
                                           <button type="submit" name='_savedit' class="btn btn-purple">保存并继续编辑</button>
                                       {% endif %}
                                       <button type="submit" name='_addanother' class="btn btn-purple" >保存并添加另一个</button>
                                       <button type="button" class="btn btn-default" onclick="location.href='{% url 'users:userlist' %}'">取消</button>
                                  </div>
                              </div>
                          </form>
                      </div> <!-- .form -->
      
                  </div> <!-- panel-body -->
              </div> <!-- panel -->
          </div> <!-- col -->
      
      </div> <!-- End row -->
      {% endblock %}
      
        *说明:用户更新页面通过if 判断`object`为true,否则就是用户添加页面了*
      
      • 效果图

    1.3 用户查看

    • 视图配置

      from django.views.generic import ListView
      from pure_pagination.mixins import PaginationMixin
      from django.contrib.auth import get_user_model
      
      User = get_user_model()
      
      class IsActiveView(View):
          def post(self, request, **kwargs):
              pk = QueryDict(self.request.body).get('pk')
              value =int(QueryDict(self.request.body).get('value'))
              try:
                  user = User.objects.filter(id=pk)
                  if pk and value == 1:
                      user.update(is_active=1)
                      res = {'code': 0, 'result': '用户激活成功!'}
                  elif pk and value == 0:
                      user.update(is_active=0)
                      res = {'code': 0, 'result': '用户禁用成功!'}
                  else:
                      res = {'code': 1, 'result': '用户禁用或激活失败!'}
              except:
                  res = {'code': 1, 'result': '用户禁用或激活失败!'}
      
              return JsonResponse(res, safe=True)
          
          
      class UserListView(PaginationMixin, ListView):
          """
          查看用户
          """
          template_name = 'users/userlist.html'
          model = User
          context_object_name = 'users'
          paginate_by = 10
          keyword = ''
      
          def get_queryset(self):
              """ 数据过滤, return过滤后的数据 """
              # 获取所有数据
              queryset = super(UserListView, self).get_queryset()
              # print(queryset)
              # 获取搜索框的关键字
              self.keyword = self.request.GET.get('keyword', '')
              if self.keyword:
                  if self.keyword == '男':
                      queryset = queryset.filter(sex=0)
                      # print(queryset)
                  elif self.keyword == '女':
                      queryset = queryset.filter(sex=1)
                  else:
                      queryset = queryset.filter(Q(username__icontains=self.keyword)|
                                                 Q(cn_name__icontains=self.keyword)|
                                                 Q(is_superuser__icontains=self.keyword)|
                                                 Q(phone__icontains=self.keyword)|
                                                 Q(is_active__icontains=self.keyword))
              else:
                  pass
              return queryset
      
          def get_context_data(self, **kwargs):
              """上下文管理,用于传递给前端渲染的数据"""
              context = super(UserListView, self).get_context_data(**kwargs)
              # print(context)
              context['keyword'] = self.keyword
              return context
      

      参数解读:

      • is_active:缺省为true,is_active=1, is_active=0表示未激活
      • template_name:指定前端渲染的模板(html文件);
      • model:指定模型;
      • context_object_name:自定义上下文对象名称(传递给前端),缺省object_list。
      • paginate_by:分页,每一页10条数据;
      • get_queryset:该方法继承父类获取所有数据,并通过filter + Q过滤数据, 还可以跟order_by()进行排序(升序/降序)。
      • Q:Q对象提供更复杂的查询,如通过 &| 操作符和括号分组,本文使用或关系。
      • get_context_data:该方法用于传给前端渲染的数据,keyword为传给前端搜索框内显示用的。
    • 模板配置

      {% extends 'base1.html' %}
      {% load static %}
      
      {% block title %}
          用户列表
      {% endblock %}
      
      {% block page-title %}
          用户列表
      {% endblock %}
      
      
      {% block css %}
          <!-- sweet alerts -->
          <link rel="stylesheet" href="{% static "assets/sweet-alert/sweetalert2.min.css"%}">
          <link rel="stylesheet" href="{% static "assets/sweet-alert/sweetalert2.css"%}">
      
      {% endblock %}
      
      {% block page-content %}
      <div class="row">
      
          <div class="panel">
              <div class="panel-body">
                  <!--添加及搜索行 start-->
                  <div class="row">
                      <!--添加按钮-->
                      <div class="col-sm-6">
                          <div class="m-b-30">
                              <a href="{% url 'users:useradd' %}" type="button" class="btn btn-primary waves-effect waves-light">添加用户 <i class="fa fa-plus"></i></a>
                          </div>
                      </div> <!--添加按钮 ends-->
      
                      <!--搜索-->
                      <div class="col-md-3" style="float: right">
                          <form class="form-horizontal" role="form">
                              <div class="input-group">
                                  <input type="text"  name="keyword" class="form-control"  value="{{ keyword|default_if_none:'' }}" placeholder="请输入查询的关键字">
                                  <span class="input-group-btn">
                                      <button type="submit" class="btn btn-effect-ripple btn-primary">搜索</button>
                                  </span>
                              </div>
                          </form>
                      </div><!--搜索 ends-->
      
                  </div><!--添加及搜索行 ends-->
      
                  <!--表格 start-->
                  <table class="table table-bordered table-striped">
                      <thead>
                          <tr>
                              <th>UID</th>
                              <th>用户名</th>
                              <th>管理员</th>
                              <th>中文名</th>
                              <th>手机</th>
                              <th>性别</th>
                              <th>用户状态</th>
                              <th>上次登陆时间</th>
                              <th>操作</th>
                          </tr>
                      </thead>
      
                      <tbody>
                      {% for user in users %}
                      <tr class="gradeA">
                          <td>{{ user.id }}</td>
                          <td>{{ user.username }}</td>
                          <td>{% if user.is_superuser == 1 %}超级管理员 {% else %} 普通用户 {% endif %}</td>
                          <td>{{ user.cn_name }}</td>
                          <td>{{ user.phone }}</td>
                          <td>{{ user.get_sex_display }}</td>
                          <td>
                              {% if user.is_active == 1 %}
                                  <button type="button" class="btn btn-primary btn-xs">正常</button> |
                                  <button type="button" id="active" acitve_id="{{ user.id }}" value=0 class="btn btn-danger btn-xs"><i class="fa fa-ban fa-lg"></i> 禁用</button>
                              {% elif user.is_active == 0 %}
                                  <button type="button" class="btn btn-warning btn-xs">离线</button> |
                                  <button type="button" id="active" acitve_id="{{ user.id }}"value=1 class="btn btn-success btn-xs"><i class="fa fa-check-circle fa-lg"></i> 激活</button>
                              {% else %}
                                  未知
                              {% endif %}
                          </td>
                          <td>{% if user.last_login == None %}未登录{% else %} {{ user.last_login }} {% endif %}</td>
                          <td class="actions">
                          <a href="{% url 'users:useredit' user.id %}" class="btn btn-primary btn-xs">编辑</a>
                          <a id="delbtn" userid="{{ user.id }}" class="btn btn-danger btn-xs">删除</a>
                      </tr>
                      {% endfor %}
                      </tbody>
                  </table><!--表格 ends-->
              </div> <!-- panel-body ends-->
      
      
              <!--分页 start-->
              <div class="row">
                  <div class="col-md-4">
                     <p style="margin-top: 10px"> 显示 [{{ page_obj.paginator.count }}] 条数据中的 第 [{{ page_obj.start_index }}] 至 [{{ page_obj.end_index }}] 的数据</p>
                  </div>
                  <div class="col-md-8">
                       {% if page_obj.paginator.num_pages > 1 %}
                          {% include '_paginator.html' %}
                       {% endif %}
                  </div>
              </div> <!--分页 ends-->
      
          </div> <!-- end Panel -->
      
      </div> <!-- End row -->
      
      {% endblock %}
      
      {% block js %}
          <script src="{% static "js/jquery-3.6.0.js"%}"></script>
          <script src="{% static "assets/sweet-alert/sweetalert2.min.js"%}"></script>
          <script src="{% static "assets/sweet-alert/sweetalert2.all.min.js"%}"></script>
          <script src="{% static "assets/sweet-alert/sweetalert2.all.js"%}"></script>
          <script src="{% static "assets/sweet-alert/sweetalert2.js"%}"></script>
      
          <script>
              // 编辑删除按钮
              $("tbody").on("click","#delbtn", function () {
                  // 定义变量
                  var uid = $(this).attr('userid')
                  var url = "/user/userdel/" + uid + '/'
                  Swal.fire({
                      title: "确定删除该用户?",
                      text: "删除后可就无法恢复了。",
                      icon: "warning",
                      showCancelButton: true,
                      confirmButtonText: "是的,我要删除!",
                      cancelButtonText: "取消",
                      cancelButtonColor: '#d33',
                      confirmButtonColor: '#3085d6',
                  }).then((result) => {
                      if (result.isConfirmed) {
                          // ajax语法
                          $.ajax({
                              type: "post",
                              url: url,
                              success: function (res) {
                                  console.log(res)
                                  if (res.code == 0) {
                                      Swal.fire({
                                          title: "删除成功!",
                                          text: "该用户已经删除了.",
                                          icon: "success",
                                          timer: 3000  //单位是毫秒
                                      });
                                      setTimeout(function () {
                                          window.location.reload();
                                      }, 3000)  //单位是毫秒,重刷新页面
                                  }
                                  else {
                                      Swal.fire("OMG...", "出错拉", "error");
                                  }
                              },
                              error: function () {
                                  Swal.fire("OMG...", "接口调用失败!", "error")
                              }
                          })
                      }
                  })
              })
      
          </script>
      {% endblock %}
      

      参数解读:

      • 添加用户按钮:通过页面表单方式实现用户添加;
      • users:为后端 UserListViewcontext_object_name传递过来的;
      • 编辑按钮:和添加用户类型;
      • 删除按钮:通过ajax的弹窗方式进行删除,没有用到页面;
    • 效果图


    1.4 用户更新

    • 视图配置

      # mysite/users/views.py
      
      from .form import UserModelForm
      from django.views.generic import UpdateView
      from django.contrib.auth import get_user_model
      from django.contrib.messages.views import SuccessMessageMixin
      
      User = get_user_model()
      
      class UserEditView(SuccessMessageMixin, UpdateView):
          """"
          更新用户
          """
          template_name = 'users/form.html'
          model = User
          form_class = UserModelForm
          success_message = '%(username)s was update successfully'
      
          def get_success_url(self):
              # print(self.request.POST)
              if '_savedit' in self.request.POST:
                  # print(self.object.pk)
                  # 是一个ID
                  return reverse('users:useredit', kwargs={'pk':self.object.pk})
              return reverse('users:userlist')
      
      
          def form_valid(self, form):
              new_password = form.cleaned_data['password']
              # print(self.object)
              # 是一个用户
              self.object.set_password(new_password)
              self.object.save()
              return super(UserEditView, self).form_valid(form)
      

      参数解读:跟CreateView类似。

    • 模板配置

      用户添加的模板一致,共用一个模板。

    • 效果图

    1.5 用户删除

    • 视图配置

      from django.views.generic import DeleteView
      from django.contrib.auth import get_user_model
      
      User = get_user_model()
      
      class UserDelView(DeleteView):
          """
          删除用户
          """
          model = User
      
          def post(self, request, *args, **kwargs):
              # pk = self.kwargs
              # print(pk)
              try:
                  self.get_object().delete()
                  res = {"code": 0, "result": "删除用户成功"}
              except:
                  log.error('delete user error:{}'.format(traceback.format_exc()))
                  res = {"code": 1, "result": "删除用户失败"}
              return JsonResponse(res, safe=True)
      
    • 模板配置

      通过调用ajax删除用户,参考章节用户查看的模板文件。

    • 效果图

    总结:终于码完这篇文章了,虽然看起来就4个项目:用户的增删改查,其实一点都不容易,五味杂陈啊。我还是把CBV里的CreateViewListViewUpadteViewDeleteView都一一对应起来了,其实方法还是有很多种的。

    现在用户管理差不多就这样了,各位还可以持续去优化,做的更好,那么用户登陆认证怎么实现呢?待我去码下一篇文章...敬请期待!

    如果喜欢的我的文章,欢迎关注我的公号:点滴技术,扫码关注,不定期分享

    相关文章

      网友评论

        本文标题:Django之用户管理系统CBV-全新升级(5)

        本文链接:https://www.haomeiwen.com/subject/kguubltx.html