Django-Python重量級Web框架
Django是一套完整的MVC開發架構,雖然在微服務盛行的今時今日再談MVC有些老土,不過對於python這種解決小專案的開發語言來說,MVC仍然是最優的選擇。
嚴格來說,Django是MTC,因為其表現層用的是模板(Template)
Django的目錄結構
manage.py:Django的命令列工具,可以讓我們通過命令形式與Django進行互動。
templates:前臺模板檔案存放的目錄,該目錄有時也會放在專案mysite目錄的裡面,是在settings.py中配置的。
urls.py:路由資訊,配置了url地址與程式碼的對映關係,像Java中的Struts
wsgi.py: WSGI 相容的Web 伺服器的入口,以便執行你的專案
這裡著重要了解下settings.py中的一些配置:
ROOT_URLCONF = 'mysite.urls'
對應路由資訊第一級的入口,對於路由多級及詳細配置,下面會解釋
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'mysite/templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] 這個是配置模板資訊的,特別需要注意DIRS這個配置,代表著模板存放的位置,所以前面提到過templates目錄的位置是可以自己按照習慣自定義的,當然必須要與這個配置匹配。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '',
'NAME': 'mysite_dev',
'USER': '',
'PASSWORD': '',
}
}
持久層資料庫的配置資訊,用於資料庫連線
STATICFILES_DIRS = ( os.path.join(BASE_DIR, '/mysite/static'), ) STATIC_URL = '/static/' Js、css、圖片等靜態檔案配置,dirs配置的是靜態檔案存放的位置,url配置的是請求靜態檔案的url字首
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
中介軟體的配置,相當於java的spring中的AOP,前置加強、後置加強、迴圈加強、異常加強等。
INSTALLED_APPS = [
'mysite.apps.job',
'mysite.apps.product',
'mysite.apps.plan',
]
一組業務的MVC在Django中被稱為一個app,INSTALLED_APPS配置的就是裝在了哪些app,一個app的目錄結構如下:
apps.py:程式碼很簡單,為了完成app的宣告:
from django.apps import AppConfig
class TemplateConfig(AppConfig):
name = 'cloudm.apps.plan'
models.py是持久層ormapping的程式碼,後面會詳細介紹
urls.py是路由的詳細配置資訊,後面會詳細介紹
view.py是屬於buusiness層的程式碼,接收頁面的request,處理業務邏輯,呼叫持久層入庫操作結果,返回response給到前臺,這個後面也會詳細介紹。
路由控制URL:
urls.py是整個Django專案的筋絡,也是每個app的門戶。前面settings中已經介紹了DITS裡配置的是路由的總入口,以2層路由為例,看下路由的配置資訊。
第一層:urlpatterns = [
url(r'^$', views.index),
url(r'^job/', include("mysite.apps.job.urls")),
url(r'^product/', include("mysite.apps.product.urls")),
url(r'^template/', include("mysite.apps.template.urls")),
url(r'^plan/', include("mysite.apps.plan.urls")),
]
很好理解,根據第一層url的不同引入後續的urls
第二層,以plan為例:
urlpatterns = [
url(r'^$', views.index, name='plan-views-index'),
url(r'^name/?$', views.create, name='plan-views-name'),
url(r'^add_plan/?$', views.add_plan, name='plan-views-add'),
url(r'^add_component/?$', views.add_component, name='plan-views-add-component'),
url(r'^edit_component/(?P<plan_id>\d+)/?$', views.edit_component, name='plan-views-edit-component'),
url(r'^edit/(?P<id>\d+)/?$', views.edit, name='plan-views-edit'),
url(r'^detail/(?P<plan_id>\d+)/?$', views.detail, name='plan-views-detail'),
url(r'^update_comp/?$', views.update_component, name='plan-views-update-component'),
url(r'^delete_comp/?$', views.delete_component, name='plan-views-delete-component'),
]
每條配置有3部分,左邊部分是url的內容,中間部分對應業務邏輯層views.py中的具體函式,右邊部分是在該地址在Django專案中的唯一標識,內部可以直接請求這個標識而不是url發起業務請求。
Model層
django中遵循 CodeFrist 的原則,程式碼既資料,可以通過python manage.py migrate將改動更新到資料庫。對於Java開發者理解的ORMapping來說,先建表,然後基於表寫模型程式碼和ORMapping的配置檔案。而對於Python開發者來說,模型程式碼就是表結構本身,寫程式碼的過程是直接建表的過程,而不是對映的過程。
看下plan的models.pyfrom django.db import models
class Plan(models.Model):
id = models.BigAutoField(primary_key=True)
detail = models.TextField(blank=True, null=True)
create_time = models.DateTimeField(auto_now_add=True)
update_time = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, blank=True, null=True)
name = models.CharField(max_length=40, blank=True, null=True)
class Meta:
managed = True
db_table = 'plan'
效果圖:
models定義了很多種屬性,涵蓋了關係型資料庫中的所有型別。
看下幾種常用的屬性:
models.BigAutoField:自增長列,一般用於主鍵
models.CharField:最常用的,需要定義長度;
models.BooleanField:布林型別
models.DateField:日期型別,auto_now代表每次更新是否設定為當前時間,auto_now_add代表只有第一次建立時會設定為當前時間。這兩個入參很明顯一個用在createDate場景,一個用在updateDate場景。
models.Decimal:必須設定精度
models.IntegerField:整型
models.TextField:大文字型別
models.BinaryField:大二進位制型別
每個model還定義了一個元資料資訊:
db_table:對應在資料庫中的表名
managed:是否被python manage.py來管理
index_together:聯合索引
unique_together:聯合唯一約束
ORMpping中最難掌握的也是唯一的難點,就是Relationship,這裡只介紹常用的多對一和多對多。Django中處理多對一的關鍵字是ForeignKey,同理多對多也是通過橋表來轉化成2個多對一。
假設我的任務表叫job,代表每個需要執行的任務。任務不見得每次都能執行成功而且可以重複執行,所以給執行結果儲存在job_history中,這樣1個job就對應多個job_history,每個job_history通過foreignkey與job關聯。
Job_History的核心程式碼如下:
class JobHistory(models.Model):
job = models.ForeignKey('Job', models.DO_NOTHING)
其中foreignkey配置的是model的名字,但是在資料庫層對應的是model的id。第二個引數代表job刪除時關係如何維護,可選項有:
- models.CASCADE,刪除關聯資料,與之關聯也刪除
- models.DO_NOTHING,刪除關聯資料,引發錯誤IntegrityError
- models.PROTECT,刪除關聯資料,引發錯誤ProtectedError
- models.SET_NULL,刪除關聯資料,與之關聯的值設定為null(前提FK欄位需要設定為可空)
- models.SET_DEFAULT,刪除關聯資料,與之關聯的值設定為預設值(前提FK欄位需要設定預設值) - models.SET,刪除關聯資料,
多對多可以拆解成2個多對一,假設操作人user和job是多對多的關係,一個job可以被多人經手操作,同理一個人可能參與多個job,我們可以建立一個user2job的model:
class User2Job(models.Model):
job = models.ForeignKey('Job', models.DO_NOTHING)
user= models.ForeignKey('User', models.DO_NOTHING)
class Meta:
unique_together = ("job","user")
Django對多對多還提供了ManyToManyField這種方式,我自己傾向於拆解。
增刪改查:
Object.save()其實是saveOrUpdate(),object.delete()是刪除,所以模型的增刪改查就剩下查詢比較複雜了。
常用的查詢方式有:
Get:直接通過條件獲取確定的model物件,例如:
resource = Resource.objects.get(id=resource_id)
Filter:相當於where條件過濾
resource = Resource.objects.filter(job_id=job_id,type_id=1).first()
查詢後跟.count()是取總數,不帶任何條件直接.all()是取全部,.order_by是按屬性排序
批量刪除:
Application.objects.filter(id=data['app_id']).delete()
範圍查詢:
models.Tb1.objects.filter(id__lt=10,id__gt=1)
id小於1切大於10
models.Tb1.objects.exclude(id__in=[11, 22,33])
id not in [11,22,33]
關於Django的模型先介紹到這裡,注意:每個app的模型定義的python檔名是models而不是model,也就是說並不是每張表結構建立一個app,我們要把多個相關的模型定義在一個模型檔案中,views.py、urls.py同理,那麼問題來了,哪些表屬於同一個app?這就涉及到軟體開發設計領域的另一個課題DDD(領域驅動設計),建議大家學習掌握。
View層:
View要做的事情主要有2部分,第一、處理頁面的request並response,第二、組織業務邏輯並呼叫持久層(models)。對持久層的操作就是增刪改查,對於業務邏輯的程式設計那就是跟自己業務相關的了,沒什麼好介紹的,那麼View層唯一需要掌握的就剩下Request和Response了。
View層函式入參是request,代表客戶端傳來的請求,我們需要根據http的具體請求方法(get、post、put等)來選擇如何獲取request中的內容。
Response一般分直接返回Json和返回頁面2種。
返回Json:return JsonResponse(ret)
返回頁面:
return render(request, "job/index.html", {'jobs': jobs})
obs是”job/index.html”這個前臺頁面需要載入的變數內容。
Template層:
這一層是概念理解上最簡單,但是後期工作量最大的一層。核心思想就是block,利用模板的繼承,前面flask有類似的使用,這裡也不再詳細描述了。
最後看下Django的常用命令:
python manage.py migrate
前面已經介紹過了,是models與資料庫的同步命令。
python manage.py runserver ip:port
是專案的啟動命令,ip:port是接收服務的地址,一般配置為0:8000
python manage.py createsuperuser
建立超級管理員