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

时间过的真快,又接近4个月没更新文章了,不是我闲着,家里事情是真多,时间都给了溜娃还是溜娃,剩余点时间就学习Django的知识,为了打磨好这一篇文章,可费了九牛二虎之力,完成该篇文章。
为了各位读者有较好的UI视觉、有动力去学习和摸索,前端可投入不少时间。毕竟作为一名网工,去搞前端,那还真不是一件容易的事情,你想,Django这个后端知识体系已经够学一阵一阵子的了。
前端有啥学习?HTML、javascrip、jQuery、ajAX、Vue...
后端有啥学习?Django就够了...
前方高能,请看如下效果图...
Django之用户管理系统CBV-全新升级(5)
文章图片

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

  • 用户列表展示

?
  • 新增用户
    Django之用户管理系统CBV-全新升级(5)
    文章图片
  • 更新用户
    Django之用户管理系统CBV-全新升级(5)
    文章图片
  • 删除用户
    Django之用户管理系统CBV-全新升级(5)
    文章图片

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

1.1 基础配置 说明:有一些共性的东西,我就提前在这个章节写出来。
  • settings.py 配置
    文件路径:mysite/settings.py
    static文件夹路径:用于存放前端的一些cssjsicon等文件。
    AUTH_USER_MODEL:重写内置的用户管理。
    DATABASES:使用的是mysql数据库,一直用的这个。
    INSTALLED_APPS:新建和注册app,就不多讲了,请看之前的文章。
# mysite/settings.pyINSTALLED_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内,避免导致页面加载慢,按需页面加载即可。
{% loadstatic %} {% block title %}自动化运维平台{% endblock %} - 锐客网 {% block css %}{% endblock %} 自动化运维平台{% block page-title %} {% endblock %}
{% block page-content %} {% endblock %}
2021?自动化运维平台
{% block js %}{% endblock %}

  • 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 AbstractUserclass 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.pyfrom django.contrib import admin from django.urls import path, includeurlpatterns = [ path('admin/', admin.site.urls), path('user/', include('users.urls'))# 新建 ]

    子路由urls(app为users):
    # mysite/users/urls.pyfrom 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[0-9]+)?/', UserEditView.as_view(), name='useredit'), # 用户删除 re_path('userdel/(?P[0-9]+)?/', UserDelView.as_view(), name='userdel'), ]

  • 分页
    文件路径:mysite/templates/_paginator.html
    效果是这样子的:
    Django之用户管理系统CBV-全新升级(5)
    文章图片

    templates目录下创建_paginator.html,写入如下代码:
    说明:这个分页文件会在userlist.html被调用,这个模板是别人写好的,拿来用即可.
    # mysite/templates/_paginator.html
      {% if page_obj.has_previous %}
    • 首页
    • 上一页
    • {% else %}
    • 首页
    • 上一页
    • {% endif %} {% for page in page_obj.pages %} {% if page %} {% ifequal page page_obj.number %}
    • {{ page }}
    • {% else %}
    • {{ page }}
    • {% endifequal %} {% else %}
    • ...
    • {% endif %} {% endfor %} {% if page_obj.has_next %}
    • 下一页
    • 尾页
    • {% else %}
    • 下一页
    • 尾页
    • {% endif %}

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 reclass 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.pyfrom django.views.generic import CreateView from django.contrib.messages.views import SuccessMessageMixin from django.contrib.auth import get_user_model from .form import UserModelFormUser = 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条件进行区分.
    {% extends 'base1.html' %}{% load static %}{% block title %} {% if object %} 用户更新 {% else %} 用户添加 {% endif %} {% endblock %}{% block page-title %} {% if object %} 用户更新 {% else %} 用户添加 {% endif %} {% endblock %}{% block page-content %}{% if object %}请更新一个用户{% else %}请添加一个用户{% endif %}
    {% if form %} {{ form.errors }}
    {% endif %}
    {% if object %} {% endif %}
    {% endblock %}

    ? 说明:用户更新页面通过if 判断object为true,否则就是用户添加页面了
    • 效果图
      Django之用户管理系统CBV-全新升级(5)
      文章图片

1.3 用户查看
  • 视图配置
    from django.views.generic import ListView from pure_pagination.mixins import PaginationMixin from django.contrib.auth import get_user_modelUser = get_user_model()class IsActiveView(View): def post(self, request, **kwargs): pk = QueryDict(self.request.body).get('pk') value =https://www.it610.com/article/int(QueryDict(self.request.body).get('value')) try: user = User.objects.filter(id=pk) if pk and value =https://www.it610.com/article/= 1: user.update(is_active=1) res = {'code': 0, 'result': '用户激活成功!'} elif pk and value =https://www.it610.com/article/= 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 querysetdef 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 %} {% endblock %}{% block page-content %}添加用户
    {% for user in users %} {% endfor %}
    UID 用户名 管理员 中文名 手机 性别 用户状态 上次登陆时间 操作
    {{ user.id }} {{ user.username }} {% if user.is_superuser == 1 %}超级管理员 {% else %} 普通用户 {% endif %} {{ user.cn_name }} {{ user.phone }} {{ user.get_sex_display }} {% if user.is_active == 1 %} | {% elif user.is_active == 0 %} | {% else %} 未知 {% endif %} {% if user.last_login == None %}未登录{% else %} {{ user.last_login }} {% endif %} 编辑 删除
    显示 [{{ page_obj.paginator.count }}] 条数据中的 第 [{{ page_obj.start_index }}] 至 [{{ page_obj.end_index }}] 的数据
    {% if page_obj.paginator.num_pages > 1 %} {% include '_paginator.html' %} {% endif %} {% endblock %}{% block js %}{% endblock %}

    参数解读:
    • 添加用户按钮:通过页面表单方式实现用户添加;
    • users:为后端 UserListViewcontext_object_name传递过来的;
    • 编辑按钮:和添加用户类型;
    • 删除按钮:通过ajax的弹窗方式进行删除,没有用到页面;
  • 效果图
1.4 用户更新
  • 视图配置
    # mysite/users/views.pyfrom .form import UserModelForm from django.views.generic import UpdateView from django.contrib.auth import get_user_model from django.contrib.messages.views import SuccessMessageMixinUser = 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类似。
  • 模板配置
    用户添加的模板一致,共用一个模板。
  • 效果图
    Django之用户管理系统CBV-全新升级(5)
    文章图片

1.5 用户删除
  • 视图配置
    from django.views.generic import DeleteView from django.contrib.auth import get_user_modelUser = get_user_model()class UserDelView(DeleteView): """ 删除用户 """ model = Userdef 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删除用户,参考章节用户查看的模板文件。
  • 效果图
    Django之用户管理系统CBV-全新升级(5)
    文章图片

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

总结:终于码完这篇文章了,虽然看起来就4个项目:用户的增删改查,其实一点都不容易,五味杂陈啊。我还是把CBV里的CreateViewListViewUpadteViewDeleteView都一一对应起来了,其实方法还是有很多种的。
现在用户管理差不多就这样了,各位还可以持续去优化,做的更好,那么用户登陆认证怎么实现呢?待我去码下一篇文章...敬请期待! 如果喜欢的我的文章,欢迎关注我的公众号:点滴技术,扫码关注,不定期分享
【Django之用户管理系统CBV-全新升级(5)】Django之用户管理系统CBV-全新升级(5)
文章图片

    推荐阅读