项目背景
公司内部测试使用的手机历史不是很多,没有专门纳管。后面随着规模变大,测试手机也越来越多,测试、开发、设计等人员都会借用。时间长了不确定手机都在谁的手里,不方便管理。
测试提出需求,需要有个简单的小系统能进行手机统一管理。
需求有
1、管理员可以进行手机录入、修改、删除、查询等功能。
2、除了手机管理里面,测试、开发、设计等人员可以查看手机列表
、手机借用列表
以及申请手机
三个核心功能
3、测试、开发、设计等人员申请手机之后,自动发送消息(邮件)给管理员。然后找管理员认领手机
4、手机使用完毕归还时,先交还手机给 管理员,然后管理员修改 ”手机借用列表“ 中的对应记录的 ”归还时间“
设计思路
1、定义 Phone 和 BorrowRecord 两个模型
2、利用Django自带的后台快速实现
3、在Django后台自定义action,进行”手机申请“
4、申请按钮点击之后,同步给管理员发送消息(邮箱、钉钉)
进入开发
1、模型定义
这里除了手机序列号,还添加了 手机品牌和手机型号两个属性,便于后续扩展。
另外时间上设计了 采购时间、入库时间和报废时间三个属性。
手机的状态有 空闲中、被借走、已故障三种,当然你可以结合自己实际的情况设置其他状态。
# cmdb/models/phone.py
from django.db import models
from django.contrib.auth import get_user_model
User = get_user_model()
class Phone(models.Model):
STATUS = (
('空闲中', '空闲中'),
('被借走', '被借走'),
('已故障', '已故障')
)
brand = models.CharField(max_length=32, unique=True, verbose_name='手机品牌')
model = models.CharField(max_length=32, verbose_name='手机型号')
serial_number = models.CharField(max_length=64, unique=True, verbose_name='手机序列号')
create_time = models.DateTimeField(auto_now=True, verbose_name='入库时间')
buy_time = models.DateField(null=True, blank=True, verbose_name='采购时间')
fault_time = models.DateField(null=True, blank=True, verbose_name='故障时间')
status = models.CharField(max_length=12, choices=STATUS, default='空闲中', verbose_name='手机状态')
def __str__(self) -> str:
return f'{self.model}/{self.serial_number}'
class Meta:
verbose_name = '测试手机管理'
verbose_name_plural = verbose_name
class BorrowRecord(models.Model):
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='手机借用人')
phone = models.ForeignKey(Phone, on_delete=models.SET_NULL, null=True, blank=True, verbose_name='借用的手机')
borrow_date = models.DateTimeField(auto_now_add=True, verbose_name='借用时间')
return_date = models.DateTimeField(null=True, blank=True, verbose_name='归还时间')
def __str__(self) -> str:
return f'{self.user.get_username}/{self.phone.model}'
class Meta:
verbose_name = '手机借用/归还记录'
verbose_name_plural = verbose_name
2、进行配置和绑定应用
# 配置可访问主机IP
ALLOWED_HOSTS = ['127.0.0.1']
# 绑定应用到项目
INSTALLED_APPS = [
... ...
'cmdb'
]
# 设置 templates 根目录
# 默认会从 appname/templates/appname 目录寻找 ('APP_DIRS': True 参数决定)
TEMPLATES = [
... ...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
... ...
]
这里是项目演示,所以数据库使用默认的 Sqlite 数据库即可
3、后台的自定义
因为是借助于Django自带后台快速开发一个简易版手机管理系统,所有手机的管理和用户的借用都是在 Django默认后台实现的。
默认创建模型之后,在应用的 admin.py中进行绑定,然后就可以通过 自带的后台进行模型的管理,比如这里的 手机和手机借用记录的管理。
但是默认是没有”申请借用“的功能的,这个就需要我们开发对应的功能,并且添加到Django Admin后台去。
核心知识: 通过继承admin.ModelAdmin来实现自定义 模型的ModelAdmin 行为 (展示、搜索、排序、方法等)
这里先给出代码,然后进行代码分析
# cmdb/admin.py
from django.contrib import admin, messages
from cmdb.models import BorrowRecord, Phone
from django.http import HttpResponseRedirect
from django.urls import reverse
class PhoneAdmin(admin.ModelAdmin):
list_display = ('brand', 'model', 'serial_number', 'fault_time', 'create_time', 'status', 'fault_time')
list_filter = ('brand', 'status')
search_fields = ('status', 'model', 'serial_number')
actions = ['apply_for_borrow']
def apply_for_borrow(self, request, queryset):
if len(queryset) > 1:
self.message_user(request, '抱歉,每次只能申请一台手机', level=messages.ERROR)
else:
if queryset[0].status != '空闲中':
self.message_user(request, '抱歉,不能选择已故障或者被借走的手机', level=messages.ERROR)
else:
obj = queryset[0]
next_url = '/admin/cmdb/phone/'
base_url = reverse('cmdb:borrow-phone', kwargs={'pk': obj.id})
borrow_url = f'{base_url}?next={next_url}'
return HttpResponseRedirect(borrow_url)
apply_for_borrow.short_description = '申请借用'
class BorrowRecordAdmin(admin.ModelAdmin):
list_display = ('phone', 'user', 'borrow_date', 'return_date')
# Register your models here.
admin.site.register(Phone, PhoneAdmin)
admin.site.register(BorrowRecord, BorrowRecordAdmin)
上面定义了 PhoneAdmin 和 BorrowRecordAdmin 两个ModelAdmin类,然后通过 admin.site.register 把 ModelAdmin 类绑定到 模型上,注册到Django的后台去。
其中
- list_display
- list_filter
- search_fields
- actions 存放自定义的”操作性方法“,比如我们需要的 ”申请借用“ 的功能
这里在 PhoneAdmin 中定义方法 apply_for_borrow, 在这个方法中我们进行”申请借用“ 资源的限制 (因为是从后台选择定义然后进行处理)
3.1、每次只能选择一个手机 len(queryset) 只能等于1
3.2、选择的手机状态只能是 ”空闲中“ 的
3.3、选择 ”一个空闲中“的手机之后,跳转到 ”借用“逻辑处理的view视图,进行实际的借用逻辑处理。
3.4、这里做了个特殊的处理
,就是借用逻辑处理完毕之后,再跳回到当前后台的手机记录页面。
4、借用逻辑开发
这里先给出完整代码,然后进行分析说明
# cmdb/views.py
from django.shortcuts import render, HttpResponse, redirect
from django.contrib.auth.decorators import login_required
from cmdb.models import Phone, BorrowRecord
from django.utils import timezone
from django.http import HttpResponseRedirect
from django.contrib import messages
@login_required
def borrow_phone(request, pk):
"""
申请借用手机视图
"""
phone = Phone.objects.get(pk=pk)
pr = BorrowRecord()
pr.user = request.user
pr.borrow_date = timezone.now()
pr.phone = phone
pr.save()
phone.status = '被借走'
phone.save()
messages.success(request, '手机借用成功')
return redirect(request.GET.get('next', 'admin:index'))
4.1、这里先获取到待借用的手机 (phone = Phone.objects.get(pk=pk))
4.2、然后新增借用记录 15到19行,其中配置了借用人(request.user)、借用时间 (timezone.now() 当期时间)已经借用的手机,就是第14行获取到的手机。
4.3、同时记得修改手机的状态,从 “空闲中“ 修改为 "被借走"
4.4、这里额外使用的 Django的message机制,通过它可以在Django后台进行页面消息提示 (第24行)
4.5、最后根据获取到的next
跳转回到之前的页面。
5、消息通知开发
这是主要是通过发送邮件,让管理员知道“谁在借用手机,借用的是哪个手机”,好提前做准备。
具体功能也是通过Django的 send_mail 函数来实现。
5.1、settings配置
# proj/settings.py
# 配置邮件信息
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qiye.163.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'ops@colinspace.com'
EMAIL_HOST_PASSWORD = 'xxxxxxxx'
DEFAULT_FROM_EMAIL = 'ops@colinspace.com'
# 管理员邮箱
ADMIN_EMAIL = 'admin@colinspace.com'
5.2、views中借用逻辑修改
# cmdb/views.pu
@login_required
def borrow_phone(request, pk):
"""
申请借用手机视图
"""
... ...
# 发送邮件逻辑
subject = f'[{request.user}] 申请借用手机'
message = f'[{request.user}] 申请借用手机 ({phone.brand} - {phone.model} - {phone.serial_number})'
recipient_list = [settings.ADMIN_EMAIL]
send_mail(subject, message, settings.DEFAULT_FROM_EMAIL, recipient_list)
messages.success(request, '手机借用成功')
return redirect(request.GET.get('next', 'admin:index'))
然后普通用户在后台申请借用手机之后,管理员就会收到如下的邮件信息
image.png6、权限管控配置
主要是在Django Admin后台新增用户的时候,配置相关权限(User permissions) 如下图所示
image.png只给 两个视图的view(查看)权限即可。
在ModelAdmin类中定义的方法,是没有做权限限制的
每个人都可以使用申请借用的功能
下图所示是普通用户James登录看到的效果,他只有 两个视图的view的权限
看到左侧没有”➕“ 不能新增模型记录,然后在列表的action中,只有 ”申请借用“ 选项,而没有默认的 ”Deleted select 测试手机管理“ 选项。
image.png通过如上的开发和配置,我们就实现测试提出的 手机管理系统的基本需求。
然后给服务配置域名,就可以交付给测试组进行使用了。是不是很快就上手了一个小系统呢~
系统的详细代码详见 https://gitee.com/colin5063/django-examples/tree/main/django_phone_management (复制到浏览器再打开哦)
克隆到本地之后,按照 django_phone_management/ReadMe.md 提示进行操作即可运行项目。
有问题及时反馈哦~
如果你觉得有所收获,欢迎关注公众号"菩提老鹰"
进行点赞和喜欢哦~
一起交流,分享知识,快乐生活,我是老鹰,我们下一期见~
网友评论