項目背景
公司內部測試使用的手機歷史不是很多,沒有專門納管。后面隨著規模變大,測試手機也越來越多,測試、開發、設計等人員都會借用。時間長了不確定手機都在誰的手里,不方便管理。
測試提出需求,需要有個簡單的小系統能進行手機統一管理。
需求有
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'))
然后普通用戶在后臺申請借用手機之后,管理員就會收到如下的郵件信息
6、權限管控配置
主要是在Django Admin后臺新增用戶的時候,配置相關權限(User permissions) 如下圖所示
只給 兩個視圖的view(查看)權限即可。
在ModelAdmin類中定義的方法,是沒有做權限限制的
每個人都可以使用申請借用的功能
下圖所示是普通用戶James登錄看到的效果,他只有 兩個視圖的view的權限
看到左側沒有”?“ 不能新增模型記錄,然后在列表的action中,只有 ”申請借用“ 選項,而沒有默認的 ”Deleted select 測試手機管理“ 選項。
通過如上的開發和配置,我們就實現測試提出的 手機管理系統的基本需求。
然后給服務配置域名,就可以交付給測試組進行使用了。是不是很快就上手了一個小系統呢~
系統的詳細代碼詳見 https://gitee.com/colin5063/django-examples/tree/main/django_phone_management (復制到瀏覽器再打開哦)
克隆到本地之后,按照 django_phone_management/ReadMe.md 提示進行操作即可運行項目。
有問題及時反饋哦~
如果你覺得有所收獲,歡迎關注公眾號"菩提老鷹"
進行點贊和喜歡哦~
一起交流,分享知識,快樂生活,我是老鷹,我們下一期見~