多應用統一目錄管理
在實際Django項目開發中,創建工程之後比如demoproj,在工程目錄下會存在一個同名的文件夾作爲項目的入口(比如,公共配置、URL規則等)和一個manage.py管理文件。
默認創建應用的時候,會在 manage.py 同級目錄下創建,隨着開發,應用可能越來越多,這個時候建議把所有應用統一放到一個目錄下管理
,比如都放到apps目錄下。
項目結構編程如下
| - demoproj
| - - demoproj
| - - manage.py
| - - apps
| - - - user(app)
| - - - cmdb(app)
| - - - ticket(app)
| - - - ops(app)
| - - - ...
目錄結構調整之後,需要修改 settings.py
配置來適配結構
# demoproj/settings.py
import os
import sys
#
BASE_DIR = Path(__file__).resolve().parent.parent
# 以下是新增
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
這個時候,從命令行模式使用角度來說,項目是沒有任何問題的。
但是有幾個特殊的地方還是需要注意下:
1、創建新的應用app的時候
cd apps
python ../manage.py startapp new_appname
或者在 manage.py 同級目錄下創建之後,在手動移動到apps 下,建議前者
2、如果是使用命令行開發、或者 Sublime、Vscode 工具開發,到此就不需要額外配置什麼
3、如果是使用 PyCharm 工具開發,需要把 apps 配置成 Source Root
,這由於該工具本身的特性決定的
配置的目的是: 讓Pycharm工具本身知道
應用的根
是從apps目錄計算的,這樣在apps目錄下的各個應用中,依賴導入的時候,以應用本身開始就行
比如在 cmdb 應用的導入 user應用的User模型
# cmdb/models.py
from user.models import User
這樣就不會有錯誤提示
, 不然就會有 Unresolved reference 'user'
這樣的錯誤提示。
具體如何配置可以參考網上教程。
應用之外使用Model
一般Django項目開發中,功能邏輯都是寫到某個應用中去的,然後通過Django的URL進行方法。
但是在某些情況下會出現在應用之外使用某個應用中定義的模型來完成一些特性功能。
舉個例子,在開發運維管理平臺中,定了 CDN 資產模型完成了邏輯功能開發,在項目上線之前,需要做一次數據初始化,一般會開發一個工具腳本,從雲廠商接口獲取數據寫入對應的數據庫,數據寫入會藉助於對應的模型來實現。
該腳本工具肯定是獨立在Django應用之外的。但是又要使用 Django 中定義的模型。比如下面結構中的 init_cdn.py
| - demoproj
| - - demoproj
| - - manage.py
| - - apps
| - - - cmdb(app)
| - - - ...
| - - scripts
| - - - init_cdn.py
這個時候就需要在腳本中做特殊配置
# scripts/init_cdn.py
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'demoproj.settings')
# 很關鍵的配置
django.setup()
from cmdb.models import CDN
# 其他常規功能邏輯
1、如上的配置需要寫到該文件的最開始部分
2、切記需要 django.setup()
晚上很多教程說只要 os.environ.setdefault
這個配置項就行了,但是實際測試中這樣是有問題,需要添加上下面一步
擴展1:自定義模型公共部分
一般在Django開發中,每個模型都會id字段、創建時間、更新時間。或者有時候都會有 是否刪除和刪除時間字段。
既然是每個模型都會有的,那麼在每個模型中重複性的把這些字段定義一遍肯定是代碼冗餘和低效的表現。
高效的方式是把這些公共字段自定義到一個
抽象模型
中去,然後其他模型來依賴
1、定義功能抽象模型
# apps/baseModel.py
class BaseModel(models.Model):
created_time = models.DateTimeField(auto_now_add=True)
updated_time = models.DateTimeField(auto_now=True)
deleted_time = models.DateTimeField(default=None, null=True, blank=True, verbose_name="刪除時間")
is_deleted = models.BooleanField(default=False)
class Meta:
abstract = True
2、應用模型中繼承
# cmdb/models.py
from baseModel import BaseModel
class CDN(BaseModel):
name = models.CharField(max_length=64, verbose_name="CDN域名")
... ...
擴展2: UUID作爲模型主鍵
在定義Django模型的時候,繼承了models.Model
之後,一般不會顯示的定義模型主鍵
,默認會有一個id
作爲自增的主鍵
id = models.AutoField(primary_key=True)
有些情況下使用自增的ID主鍵又不合適,比如可以通過 id 的值推測出當前數據庫中的數據總條目、甚至可以推斷出相鄰數據的主鍵等等
所有有時候會使用 UUID 作爲主鍵 相對比較合適些。UUID 是一種全局唯一標識符,通常用32位的字符串來表現,類似 33d1f6b3-ffae-4ebe-9c88-a5becd71a0bc。
實現方式
# apps/baseModel.py
# 需要導入該python庫
import uuid
class BaseModel(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True, editable=False)
... ...