
Django 系統(tǒng)
- 環(huán)境
- Python 3.6
- Django 1.8
- 參考資料
- [Django中文教程](https://yiyibooks.cn/xx/django_182/index.html)
- [Python 新手使用 - Django 架站的16堂課](實體書)
環(huán)境搭建
- anaconda + pycharm
- anaconda使用
- conda list : 顯示當(dāng)前環(huán)境安裝的包
- conda env list : 顯示安裝的虛擬環(huán)境列表
- conda create -n env_name python=3.6 如:conda create -n tl_django python=3.6
- 激活conda的虛擬環(huán)境
- source activeate env_name (Linux下激活)
- conda activate env_name (Windows下激活) 如: conda activate tl_django
- 激活的含義是:進入某環(huán)境專用命令行界面, 并針對該環(huán)境進行設(shè)置
- Django安裝:
- conda activate tl_django (首先激活Django的環(huán)境, PS:激活后命令行前面回帶一個(tl_django)這樣的前綴)
- pip install django==1.8
后臺流程

創(chuàng)建第一個Django程序
- django-admin startproject tulingxueyuan (創(chuàng)建Django項目: tulingxueyuan)
命令行啟動:
- cd tulingxueyuan
- python manage.py runserver (啟動服務(wù)器)
PyCharm啟動
- 1.配置python環(huán)境:
- 點擊File菜單 -> Settings -> Project:Python -> Project Interpreter-> “小齒輪”圖標(biāo) -> ADD -> Conda Environment -> Existing environment-> “...” 圖標(biāo) ->
- Linux系統(tǒng):
Anaconda安裝路徑下的/envs/相應(yīng)的虛擬環(huán)境名稱/bin/python.sh - Windows系統(tǒng):
1、 C:\Users\用戶名\Anaconda3\envs\相應(yīng)的虛擬環(huán)境名稱\python.exe
2、 C:\ProgramData\Anaconda3\envs\相應(yīng)虛擬環(huán)境名稱\python.exe
3、 C:\Users\rocka.conda\envs\相應(yīng)虛擬環(huán)境名稱\python.exe
Windows情況有點特殊,我分別在以上三個位置找到過。 - 注意:剛剛配置好的環(huán)境,PyCharm還會把各種包整理一下,當(dāng)IDE主界面右下方有一條細(xì)細(xì)的進度條在跑的時候,說明環(huán)境還在Update中尚未準(zhǔn)備就緒,程序中某些import 包的語句還會被語法提示器認(rèn)為是錯誤語句,此時要耐心等待。
- Linux系統(tǒng):
- 點擊File菜單 -> Settings -> Project:Python -> Project Interpreter-> “小齒輪”圖標(biāo) -> ADD -> Conda Environment -> Existing environment-> “...” 圖標(biāo) ->
- 2.配置manage.py文件:
- 鼠標(biāo)指向manage.py文件-> 直接點運行 -> 將會報錯
- 此時需要點界面右上角下拉菜單(位于啟動按鈕左邊) -> 選 Edit Configurations ->在Parameters輸入?yún)?shù): runserver -> 確定 -> 出來后點運行即可
路由系統(tǒng) - urls
- 創(chuàng)建app
- app: 負(fù)責(zé)一個具體業(yè)務(wù)或者一類具體業(yè)務(wù)的模塊
- python manage.py startapp teacher (在app根目錄下執(zhí)行,生成一個teacher的目錄,即teacher路由)
- 路由
- 按照具體的請求url, 導(dǎo)入到相應(yīng)的業(yè)務(wù)
- django的信息控制中樞
-
本質(zhì)上就是接受URL和相應(yīng)的處理模塊的一個映射
03A.png - 在接受URL請求的匹配上使用了RE
- URL的具體內(nèi)容在urls.py文件中 (閱讀該文件的代碼,發(fā)現(xiàn)內(nèi)部是使用正則在處理URL和對應(yīng)模塊的對應(yīng)關(guān)系)
- 需要關(guān)注的兩點:
- 接受的URL是什么, 即如何用RE對傳入的URL進行匹配
- 已知URL匹配到哪個處理模塊
- URL匹配規(guī)則:
- 從上到下一個一個比對
- URL格式是分級格式,則按照級別一級一級往下比對,主要對應(yīng)URL包含子URL的情況
- 子URL一旦被調(diào)用,則不會返回到主URL
- '/one/two/three/'
- 正則以r開頭, 表示不需要轉(zhuǎn)義, 注意尖號(^)和美元符號($)
- '/one/two/three' 配對正則: r'^one/'
- '/oo/one/two/three' 不配對正則: r'^one/'
- '/one/two/three/' 配對正則: r'^three/$
- '/oo/one/two/three/oo/' 不配對正則: r'three/$'
- 第一個反斜杠并不需要(系統(tǒng)自動忽略)
- 如果從上到下都沒有找到合適的匹配內(nèi)容,則報錯
2. 正常映射
- 把某一個符合RE的URL映射到事務(wù)處理函數(shù)中去
- 舉例如下:
from showeast import views as sv urlpatterns = [ url(r'admin/',adming.site.urls), url(r'^normalmap/', sv.normalmap), ]
3.URL 中帶參數(shù)映射
在多事件處理代碼中需要由URL傳入?yún)?shù),形如/myurl/param中的param
參數(shù)都是字符串形式,如果需要整數(shù)等形式需要自行傳喚
-
統(tǒng)稱的形式如下:
/search/page/432 中的432需要經(jīng)常性變化內(nèi)容,就是參數(shù)
-
一個較為復(fù)雜的例子:
url(r'^withparam/(?P<year>[0-9])/(?P<month>[0,1][0-9)',tv.withparam)
- 尖號表示從字符串左邊第一個字符開始匹配
- 圓括號表示的是一個參數(shù),里面的內(nèi)容作為參數(shù)傳遞給被調(diào)用的函數(shù)
參數(shù)名稱以問號加大寫P開頭嗎,尖括號里面就是參數(shù)的名字
后面花括號表示出現(xiàn)的次數(shù),此處的4 表示只能出現(xiàn)4個0-9的數(shù)字
4. URL在APP中處理
如果所有應(yīng)用URL都集中在tulingxueyuan/urls.py中,可能導(dǎo)致文件臃腫
可以把urls具體功能逐漸分散到每個app中
- 從djanco.conf.urls導(dǎo)入include
- 注意此時RE部分的寫法
- 添加include 導(dǎo)入
- 使用方法:
確保include被導(dǎo)入
- 在根目錄的urls.py中寫url (1個功能模塊只對應(yīng)1個url)
- 寫子路由 (功能模塊里的子模塊,在各自的文件夾內(nèi)的:模塊名_url.py內(nèi)添加)
- 編寫各個功能模塊的views函數(shù),包括各個子路由的views函數(shù)
- 與直接在主urls.py中寫理由一樣,分散在各個模塊文件夾下面寫?yīng)毩⒌淖勇酚?同樣可以使用參數(shù)
5. URL中嵌套參數(shù)
- 捕獲某個參數(shù)的一部分
- 例如URL /index/page-3 , 需要捕獲數(shù)字3作為參數(shù)
- url(r'index_1/(page-(\d+)/)?$, sv.myindex_1)
- url(r'index_2/(?:page-(?P<page_number>\d+)/)?$', sv.myindex_2)
- url(r'^book/page-(?P<pn>\d)/$', tv.do_param2)
- 以上就是指從一個參數(shù)中再提煉一個參數(shù)(我個人認(rèn)為第三個正則更簡單明了一些)
6. 傳遞額外的參數(shù)
- 參數(shù)不僅僅來自于URL, 還可能是我們自己定義的內(nèi)容
url(r'extrem/$',sv.extremParam,{'name':'liuying'}), - 附加參數(shù)同樣適用于include語句, 此時對include內(nèi)所有都添加.
7.URL的反向解析 reverse
- 防止硬編碼
- 本質(zhì)上是對每一個URL進行命名
- 以后在編碼代碼中使用URL的值,原則上都應(yīng)該使用反向解析
- reverse的好處是,只要給一個路由設(shè)好名字, 無論URL怎么變, 都可以用名字來引用,方便,主要用于模版
VIEWS 視圖
1. 視圖概述
- 視圖即視圖函數(shù),接受WEB請求返回WEB相應(yīng)的事務(wù)處理函數(shù).
- 響應(yīng)指符合http協(xié)議要求的任何內(nèi)容,包括json, string, html等
- 本章忽略事務(wù)處理, 重點在如何返回處理結(jié)果上
2. 其他簡單視圖
- django.http為我們提供了很多和HttpResponse類似的簡單視圖,
通過查看django.http的源代碼我們直到. - 此類視圖使用方法基本類似,可以通過return語句直反饋給瀏覽器
- Http404為Exception子類, 所以需要用raise來顯式調(diào)用
- Debug模式的關(guān)閉:
- 打開根路徑下settings.py文件
- 將Debug = True 改為 False
- ALLOWED_HOSTS 改為 ["*"] (允許所有主機訪問)
3. HttpResponse詳解
- 方法:
- init : 使用頁內(nèi)容實例化HttpResponse對象
- write(content) : 以文件的方式寫
- flush(): 以文件的方式輸出緩存區(qū)
- set_cookie(key, value='', max_age = none,expires = None): 設(shè)置cookie
- key , value 是字符串類型
- max_age 是一個整數(shù), 表示在指定秒數(shù)后過期
- expires 是一個datetime或timedelta對象, 會話將在這個指定的日期/時間過期
- max_age 和 expires , 二選一
- 如果不指定過期時間,則兩個星期后過期
- delete_cookie(key): 刪除指定的key的Cookie, 如果key不存在, 也不會報錯

4. HttpRespnseRedirect
- 重定向, 服務(wù)器端跳轉(zhuǎn)
- 構(gòu)造函數(shù)的第一個參數(shù)用來指定重定向的地址
- 例子: ShowViews/views.py
- 在east/urls中添加以下內(nèi)容:
url(r'^v10_1/', views.v10_1),
url(r'^v10_2/', views.v10_2),
url(r'^v11/"' views.v11, name = "v11"),
# /east/ShowViews/views 中添加以下內(nèi)容
def v10_1(request):
return HttpRespnseRedirect("/v11")
def v10_2(request):
return HttpRespnseRedirect(reverse("v11"))
def v11(request):
return HttpRespnseRedirect(""這是v11 的返回值")

5.Request 對象
-
Request介紹
- 服務(wù)器接受到http協(xié)議的請求后,會根據(jù)報文創(chuàng)建HttpRequest對象
- 視圖函數(shù)的第1個參數(shù)就是HttpRequest對象(在Python中,形參只跟位置相關(guān),而跟具體的參數(shù)名無關(guān),例如self亦是如此)
- 在django.http模塊中定義了HttpRequest對象的API
-
屬性
- 下面除非特別說明,屬性都是只讀的 (就像你給張三寫一封信, 張三收到后就已經(jīng)沒有修改的意義了)
- path : 一個字符串, 表示請求頁面的完整路徑, 不包含域名
- method : 一個字符串,表示使用的HTTP方法,常用時包括:'GET'/'POST'
- encoding : 一個字符串,表示提交的數(shù)據(jù)的編碼方式
- 如果為None則表示使用瀏覽器的默認(rèn)設(shè)置,一般為utf-8
- 這個屬性是可寫的,可以通過修改他來修改訪問表單數(shù)據(jù)使用的編碼
- GET : 一個類似字典的對象, 包含get請求方式的所有參數(shù)
- POST : 一個類似字典的對象, 包含post請求方式的所有參數(shù)
- FILES : 一個類似字典的對象, 包含所有的上傳文件
- COOKIES : 一個標(biāo)準(zhǔn)的Python字典, 包含所有cookie, 鍵和值都包含其中
- session: 一個即可獨有可寫的類似于字典的對象,表示當(dāng)前會話.
- 只有當(dāng)Django啟用會話時才可用.
- 詳細(xì)內(nèi)容見"狀態(tài)保持".
-
方法
- is_ajax() : 如果請求是通過XMLHttpRequest發(fā)起的,則返回True
-
QueryDict 對象 [這個是Django特設(shè)的對象,HTTP本身沒有]
- 定義在django.http.QueryDict里
- request對象的屬性GET, POST都是QueryDict類型的對象
- 與Python 字典不同,QueryDict類型的對象用來處理同一個鍵帶多個值的情況.
- 方法get(): 根據(jù)鍵取值
- 只能獲取鍵的一個值
- 如果一個鍵同時擁有多個值,獲取最后一個值
- 方法getlist():根據(jù)鍵獲取值
- 將鍵的值以列表返回,可以獲取一個鍵的多個值
-
GET屬性 [此對象對應(yīng)http協(xié)議的GET操作]
- QueryDict類型的對象
- 包含get請求方式的所有參數(shù)
- 與url請求地址中的參數(shù)隊形,位于?后面
- 參數(shù)的格式是鍵值對,如key1 = value1
- 多個參數(shù)之間,用&鏈接,如key1=value1&key2=value2
- 鍵是開發(fā)人員定下來的,值是可變的
- 例子: ShowViews/views/v8_get
-
POST 屬性
- QueryDict類型的對象
- 包含post請求方式的所有參數(shù)
- 與form表單中的空間對應(yīng)
- 表單中的控件必須有name屬性,name為鍵,value為值
- checkbox存在一鍵多值的問題
- 鍵是開發(fā)人員定下來的,值是可變的
- 例子 ShowViews/views/v9_post
- setting中設(shè)置模版位置, 在根目錄下建立一個templates文件夾,然后在setting.py里修改為:
*('DIRS': [os.path.join(BASE_DIR,"templates")],)
- setting中CRSF跨站攻擊防護要關(guān)閉,此行需要注釋掉)
> * django.middleware.csrf.CsrfViewMiddleware',
- 設(shè)置get頁面的urls和參數(shù)
需要在路由文件中添加兩個路由:
> * url(r'^v9_get/', v.v9_get),
> * url(r'^v9_post/', v.v9_post),
- setting中設(shè)置模版位置, 在根目錄下建立一個templates文件夾,然后在setting.py里修改為:
-
手動編寫視圖
實驗?zāi)康?
利用django快捷函數(shù)手動編寫視圖處理函數(shù)
編寫過程中理解視圖運行原理
VIEW的目的:
1.. 業(yè)務(wù)處理
2.. 返回Respongse子類步驟:
1. 拿到模版
2. 拿到數(shù)據(jù)
3. 環(huán)境變量(插入到HTML代碼中,以此定位數(shù)據(jù)填充的位置)
4. 返回-
分析:
- django把所有請求信息封裝入request
- django通過URLS模塊把相應(yīng)請求跟時間處理函數(shù)鏈接起來, 并把request作為參數(shù)傳入.
- 在相應(yīng)的處理函數(shù)中,我們需要完成兩部分
- 處理業(yè)務(wù)
- 把結(jié)果封裝并返回,我們可以使用簡單HttpResponse, 同樣也可以自己處理此功能
- 本例子不介紹業(yè)務(wù)處理, 把目光集中在如何渲染結(jié)果并返回
-
render(request, templater_name [,context][,context_omstamce][,content_type])
- 使用模版和一個戈丁的上下文環(huán)境,返回一個渲染后的HttpResponse對象
- request: django的傳入請求
- templater_name : 模版名稱
- content_instance : 上下文環(huán)境
- 參見例子: teacher_app/views/render_test
-
render_to_response
- 根據(jù)給定的上下文字典渲染給定模版,返回渲染后的HttpResponse
- 參見例子: teacher_app/views/render4_test
-
系統(tǒng)內(nèi)建視圖
- 系統(tǒng)內(nèi)建視圖,可以直接使用:
- 404
- default.page_not_found(request, template_name = '404.html')
- 系統(tǒng)引發(fā)Http404時觸發(fā)
- 默認(rèn)窗體request_path變量給模版,即導(dǎo)致錯誤的URL
- DEBUG = True則不會調(diào)用404, 取而代之是調(diào)試信息
- 404視圖會被傳遞到一個RequestContext帝鄉(xiāng)寧切可以訪問模版上下文處理器提供的變量.
- 500
- default.server_error
- DEBUG = True 不觸發(fā)
- 403
- default.permission_denied
- DEBUG = True 不觸發(fā)
- 500
- default.bad_request
- DEBUG = True 不觸發(fā)
Models 模型 (ORM)
- ORM
- Object Relation Map(對象關(guān)系映射) : 把面向?qū)ο笏枷朕D(zhuǎn)換成關(guān)系數(shù)據(jù)庫思想.操作上把類等價于表格
- 類對應(yīng)表格
- 類中的屬性對應(yīng)表中的字段
- 在應(yīng)用中的models.py文件中定義class
- 所有需要使用ORM的class都必須是 models.Model 的子類
- class中的所有屬性對應(yīng)表格中的字段
- 字段的類型都必須使用 models.xxx 不能使用python中的類型
-
在django種,Models負(fù)責(zé)跟數(shù)據(jù)庫交互
ORM.png
Django 鏈接數(shù)據(jù)庫
- 自帶默認(rèn)數(shù)據(jù)庫Sqllite3
- 關(guān)系型數(shù)據(jù)庫
- 輕量級
- 建議開發(fā)用sqlite3, 部署用mysql之類數(shù)據(jù)庫
- 切換數(shù)據(jù)庫在settings中進行設(shè)置
-
用django 連接 mysql
DATABASES = [ 'default' = { 'ENGINE' : 'django.db.backends.mysql', 'NAME' : '數(shù)據(jù)庫名', 'PASSWORD' : '數(shù)據(jù)庫密碼', 'HOST' : '127.0.0.1', 'PORT' : '3306', } ] - django 連接 mysql需要在項目文件下的init文件中導(dǎo)入pymysql包
- import pymysql
- pymysql.install_as_MySQLdb()
models類的創(chuàng)建與使用
-
定義和數(shù)據(jù)庫表映射的類
- 在應(yīng)用中的models.py文件中定義class [每一個app下面都有這個文件]
- 所有需要使用ORM的class都必須是 models.Model 的子類
- class中的所有屬性對應(yīng)表格中的字段
- 字段的類型都必須使用 modles.xxx 不能使用python中的類型
-
字段常用參數(shù)
- max_length : 規(guī)定數(shù)值的最大長度
- blank : 是否允許字段為空,默認(rèn)不允許
- null : 在DB中控制是否保存為null, 默認(rèn)為false
- default : 默認(rèn)值
- unique : 唯一
- verbose_name : 假名
-
數(shù)據(jù)庫的遷移(在models里創(chuàng)建類后通知數(shù)據(jù)庫)
- 在命令行中,生成數(shù)據(jù)遷移的語句(生成sql語句)
- python manage.py makemigrations
- 在命令行中,輸入數(shù)據(jù)遷移的指令
- python manage.py migrate
- 如果遷移中沒有變化或者報錯,可以強制遷移
- python manage.py makemigrations 應(yīng)用名
- python manage.py migrate 應(yīng)用名
- 對于默認(rèn)數(shù)據(jù)庫,為了避免出現(xiàn)混亂,前提是數(shù)據(jù)庫中沒有數(shù)據(jù),可以刪除自定義app下的migrations文件夾和db.sqlites3數(shù)據(jù)庫
- 如果報錯,顯示"App 'APP名字' could not be found. Is it in INSTALLED_APPS?", 說明沒有在settings.py里注冊:
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'teacher', # 把自定義的app填進去 'orm', )
查看數(shù)據(jù)庫中的數(shù)據(jù)
- 1.啟動命令行:python manage.py shell
注意點:對orm的操作分為靜態(tài)函數(shù)和非靜態(tài)函數(shù)兩種,靜態(tài)函數(shù)是指在內(nèi)存中類共用的,非靜態(tài)函數(shù)是指每個實例掌握的 - 2.在命令行中導(dǎo)入對應(yīng)的映射類
- from app名.models import 類名
- 一個完整的例子:
from teacher.models import Teacher
dana = Teacher()
dana.name = "Dana"
dana.age = 18
dana.address = "北京圖靈學(xué)院"
dana.save() # 保存
ta = Teacher.objects.all() # 返回集合
ta[0].name # 訪問name屬性,顯示: Dana
ta[0].age # 訪問age屬性,顯示: 18
ta[0].address # 訪問address屬性,顯示: '北京圖靈學(xué)院'
ta[0].course # 訪問course屬性,顯示為空
- 如上操作向Teacher表中增加幾條記錄之后,用for循環(huán)遍歷:
for t in ta:
print("Name: {0}, Age{1},Address:{2},Course:{3}".format(t.name,t.age,t.address,t.course))
顯示結(jié)果:
Name: Dana, Age18,Address:北京圖靈學(xué)院,Course:
Name: Daozhang, Age45,Address:程度小北路,Course:
Name: WangGonh, Age29,Address:,Course:Java
- 查詢age=45的記錄
- ta = Teacher.objects.filter(age=45)
- ta <BR>
直接輸入ta回車,顯示ta的內(nèi)容,age=45的記錄只有一個就是daozhang, 顯示為:<BR>[<Teacher: Daozhang>]
- 3.使用object屬性操作數(shù)據(jù)庫,object是模型中實際和數(shù)據(jù)進行交互的
- 4.查詢命令
- 類名.objects.all()查詢數(shù)據(jù)庫表中的所有內(nèi)容,返回的結(jié)果是一個QuerySet查詢集合類型
- 類名.object.filter(條件)
- 常見查找方法
- 通用查找格式:屬性名__條件符號=值
- 例如, 查找所有age大于18的記錄:
ta = Teacher.objects.filter(age__gt > 18) - 條件符號有:
- gt:大于
- gte:大于等于
- lt:小于
- lte:小于等于
- range:范圍
- year:年份
- isnull:是否為空
- 2、查找等于指定值的格式:屬性名=值
- 3、模糊查找:屬性名__查找方式=值
- 查找course中包含字母T的老師<BR>
ta = Teacher.objects.filter(course__contains = "T") - 查找方式有:
- exact:精確等于
- iexact:不區(qū)分大小寫
- contains:包含
- startwith:以..開頭
- endwith:以..結(jié)尾
數(shù)據(jù)庫表關(guān)系
- 多表聯(lián)查:利用多個多聯(lián)合查找某一項信息或者多項信息
-
1:1 OneToOne
- 建立關(guān)系:在模型任意一邊即可,使用OneToOneField
- add: (增)有兩種方式:
- 實例化方法,直接實例化保存
- create方法,返回類型是<class 'rlt.models.Manager'>,推薦這種方法
- PS: 添加有關(guān)系的一邊,使用create方法,或者使用實例創(chuàng)建
- 例如:
s = School() s.school_id = 2 s.school_name = "nanjingtulingxueyuan" s.save() #方法1:直接實例化 m =Manager() m.manager_id=10 m.manager_name = "dana" m.my_school=s m.save() #方法2:使用create m = Manager.objects.create(manager_id=20,manager_name="erna",my_school=s)`
- query: (查)
- 由子表查母表(定義關(guān)系的表叫子表),由子表的屬性直接提取信息:
m = Manager.objects.get(manager_name="dana") m <Manager: dana> m.my_school <School: nanjing tulingxueyuan> m.my_school.school_name 'nanjing tulingxueyuan' # 查詢成功 - 又或者可以把上述操作串起來一次性操作:
Manager.objects.get(manager_name="dana").my_school.school_name 'nanjing tulingxueyuan' # 查詢成功 - 由母表查子表,使用雙下劃線:
s = School.objects.get(manager__manager_name="dana") s <School: nanjing tulingxueyuan> # 查詢成功
- 由子表查母表(定義關(guān)系的表叫子表),由子表的屬性直接提取信息:
- change:(改)
- 單個修改后使用save保存
s.school_name = "南京圖靈學(xué)院" s.save() s <School: 南京圖靈學(xué)院> # 修改成功 - 批量修改使用update
ss = School.objects.all() ss.update(school_name="圖靈學(xué)院") ss [<School: 圖靈學(xué)院>, <School: 圖靈學(xué)院>] # 批量修改成功 - 無論是對子表還是母表修改方法都一樣
- 單個修改后使用save保存
- delete:直接使用delete刪除
-
1:N OneToMany
- 一個表格的一個數(shù)據(jù)項/對象等,可有很多個另一個表格的數(shù)據(jù)項
- 比如,一個學(xué)校可有很多個老師,一般一個老師只會在一個學(xué)校上課
- 使用上
- 使用ForeignKey
- 在多的那一邊,比如上面的例子就是在Teacher表格里進行定義
- add: (增)
- 跟一對一方法類似,通過cerate和new來添加
- create:把屬性都填滿,然后不需要手動保存
- new(也就是實例化方法):可以屬性或者參數(shù)為空,必須用save保存
- query:
- 以學(xué)校和老師舉例
- 如果知道老師,查學(xué)校,則通過增加的關(guān)系屬性,直接使用
- 例如:查找t1老師是哪個學(xué)校的:
t1.teacher_name '劉大拿' t1.my_school <School: 圖靈學(xué)院>
- 反查
- 由學(xué)校,想查下這個學(xué)校所有老師,則在學(xué)校后跟老師這個類(類名稱小寫)接下劃線set來表示
- 可以簡單理解成teacher_set是School類里的一個隱藏屬性
- 例如,查詢1號學(xué)校下面有多少個老師:
ts = s1.teacher_set.all() ts [<Teacher: Teacher object>, <Teacher: Teacher object>] ts[0].teacher_name '劉大拿' - 又或者精確查找:
t = s1.teacher_set.all().filter(teacher_name="劉大拿") t[0].teacher_name '劉大拿'
-
N:N ManyToMany
- 表示任意一個表的數(shù)據(jù)可以擁有對方表格多項數(shù)據(jù),反之亦然
- 比如典型例子就是老師和學(xué)生,老師可以有多個學(xué)生,學(xué)生也可以有多個老師
- 使用上,在任意一方,使用ManyToMany定義,只需要定義一邊
- add:
- 添加老師,則在Student實例.teachers.add(),也可以用create方法
- 注意,用實例添加多對多數(shù)據(jù),需要兩次save
s1 = Student() s1.student_name = "aoteng" s1.save() t1 = Teacher.objects.all()[0] s1.teachers.add(t1) s1.save() t = s1.teachers.all() t[0].teacher_name '劉大拿'
- 添加老師,則在Student實例.teachers.add(),也可以用create方法
- query:
- 跟一對多類似,使用隱含屬性set查詢
t1 = Teacher.objects.all()[0] ss = t1.student_set.all() ss[0].student_name 'aoteng' - 注意:如果想實現(xiàn)雙向互查,必須在類代碼里面兩邊都相互添加一行:
models.ManyToManyField
s1 = Student.objects.all()[0] tt = s1.teacher_set.all() tt[0].teacher_name '劉大拿'
- 跟一對多類似,使用隱含屬性set查詢
-
模版(Template)
- 模板:一組相同或者相似的頁面,在需要個性化的地方進行留白,需要的時候只是用相應(yīng)數(shù)據(jù)進行填充
- 步驟
- 在settings.py中進行設(shè)置:TEMPLATES
- 在templates文件夾下編寫模板并調(diào)用
一個最簡單的完整的例子: 1. 激活環(huán)境: activate tl_django 2. 創(chuàng)建項目: django-admin startproject django_tpl 3. 創(chuàng)建app: python manage.py startapp mytpl 4. 在項目的根目錄下建立一個templates的目錄 5. 在templates目錄下新建一個one.html文件,內(nèi)容如下: <html> <body> <h1>Hello World!</h1> </body> </html> 6. 編輯Django系統(tǒng)自帶的settings.py文件: 找到Templates下的DIR位置,修改為: 'DIRS': [os.path.join(BASE_DIR, "templates")], 7. 為manager.py添加啟動變量runserver (僅限Pycharm環(huán)境) 8. 編輯Django系統(tǒng)自帶的urls.py: 在頭部添加包引用:import mytpl.views as v (如果這行Pycharm出紅線,就選File菜單的Invalidate Caches/Restart, 重啟后鼠標(biāo)單擊項目目錄,Mark Directory As -> Sources Root 如果有很多個Sources Root(Root目錄的顏色不同),取消其他的, 確保只有一個Root且必須是當(dāng)前目錄) 最后在下方依葫蘆畫瓢添加一個路由:url(r'^one/', v.one), 9. 打開mytpl下的views.py 在頭部添加包引用:from django.http import HttpResponse 添加一個函數(shù)one: def one(request): return render(request,r"one.html") 10. 運行manage.py 11. 在瀏覽器輸入:127.0.0.1:8000/one
- 步驟
模板-變量
- 變量的表示方法:{{var_name}}
- 在系統(tǒng)調(diào)用模板的時候,會有相應(yīng)的數(shù)據(jù)查找相應(yīng)的變量名稱,如果找到,則填充也叫渲染,否則跳過
- 參見例子:two.html
模板-標(biāo)簽
-
for標(biāo)簽:
{% for .. in .. %} 循環(huán)語句 {% endfor %} 參見例子:three.html,顯示班級成績
-
if標(biāo)簽,用來判斷條件
{% if 條件 %} 條件成立執(zhí)行語句 {% elif 條件 %} 條件成立執(zhí)行語句 {% else %} 以上條件都不成立執(zhí)行語句 {% endif %} 參見例子:four.html
csrf標(biāo)簽,跨站請求偽造
- 在提交表單的時候,表單頁面需要加上{% csrf_token %}
- 參見例子five_get請求表單地址, five_post發(fā)送表單信息地址
- 原理:
- 瀏覽器提交一個get請求到服務(wù)器,服務(wù)器返回一個帶csrf_token的form回瀏覽器
- 此時瀏覽器正常提交form,隱含提交了csrf_token
- 服務(wù)器驗證這個新提交上來的csrf_token是否剛才服務(wù)器自己生成的那個csrf_token?
- 如果csrf_token不一致,說明本次提交是偽造的
- 在settings.py:
- 'django.middleware.csrf.CsrfViewMiddleware', 是控制csrf_token的開關(guān),
- 如果此選項關(guān)閉,則不對csrf_token進行檢查,反之則一定會檢查,如果打開了此設(shè)置但是在html代碼里又不含{% csrf_token %},則將報錯: CSRF token missing or incorrect.
SESSION
- 為了應(yīng)對HTTP的無協(xié)議性
- 用來保存用戶比較敏感的信息
- 他是屬于request的一個屬性
- 常用操作:
- request.session.get(key,defaultValue)
- request.session.clear():清除全部
- request.session[key] = value : 賦值
- request.session.flush() : 刪除當(dāng)前會話并清除會話的cookie
- del request.session[key]
分頁
- django提供現(xiàn)成的分頁器用來對結(jié)果進行分頁
- from django.core.paginator import Paginator
Ajax
8. 基于類的視圖
- 和基于函數(shù)的視圖的優(yōu)勢和區(qū)別:
- http方法的methode可以有各自的方法,不需要使用條件分支來解決
- 可以使用OOP技術(shù)(例如Mixin)
- 概述
- 核心是允許使用不同的實例方法來響應(yīng)不同的HTTP請求方法,而避開條件分支實現(xiàn)
- as_view函數(shù)作為類的可調(diào)用入庫,該方法創(chuàng)建一個實例并調(diào)用dispatch方法,按照請求方法對請求進行分發(fā),如果該方法沒有定義,則引發(fā)HttpResponseNotAllowed
- 類屬性使用
- 在類定義時直接覆蓋
- 在調(diào)用as_view的時候直接作為參數(shù)使用,例如:
urlpatterns = [ url(r'^about/', GreetingView.as_view(greeting="Greetxxx")), ]
- 對基于類的視圖的擴充大致有三種方法: Mixin, 裝飾as_view, 裝飾dispatch
- 使用Mixin
- 多繼承的一種形式,來自弗雷的行為和屬性組合在一起
- 解決多繼承問題
- View的子類只能單繼承,多繼承會導(dǎo)致不可期問題
- 多繼承帶來的問題:
- 結(jié)構(gòu)復(fù)雜
- 優(yōu)先順序模糊
- 功能沖突
- 解決方法
- 規(guī)格繼承 # java interface
- 實現(xiàn)繼承 # python,ruby
- 使用Mixin
- 在URLconf中裝飾
from django.contrib.auth.decorators import login_required, permission_required
from django.views.generic import TemplateView
from .views import VoteView
urlpatterns = [
url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
url(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
]
- 裝飾類
- 類的方法和獨立方法不同,不能直接運用裝飾器,需要用methode_decorator進行裝飾
from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator from django.views.generic import TemplateView class ProtectedView(TemplateView): template_name = 'secret.html' @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ProtectedView, self).dispatch(*args, **kwargs)
Admin管理模塊 (可以理解為Django自帶的可定制型phpMyAdmin)
- 首先進行數(shù)據(jù)遷移,然后創(chuàng)建一個超管帳號
python manage.py makemigrations python manage.py migrate python manage.py createsuperuser - settings.py里面改為漢語:
LANGUAGE_CODE ='zh-Hans' #'en-us' TIME_ZONE = 'Asia/Shanghai' #'UTC' - 最后在瀏覽器輸入:127.0.0.1/admin
- 進入管理界面后,只有一個空的項目和User和Group表可以管理,
- 在模型建立完畢后,界面會增加很多內(nèi)容,可以設(shè)置各個模型(也就是數(shù)據(jù)庫的表,這里稱為模型)
- 先在models.py里建立3個模型:ClassRoom、Teacher、Student
from django.db import models
# Create your models here.
class ClassRoom(models.Model):
roomID= models.IntegerField()
loc = models.CharField(max_length=20)
roomName = models.CharField(max_length=20)
def __str__(self):
return self.roomName
class Teacher(models.Model):
name = models.CharField(max_length=5)
course = models.CharField(max_length=20)
room = models.OneToOneField(ClassRoom)
def __str__(self):
return self.name
class Student(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField()
room = models.ForeignKey(ClassRoom)
def __str__(self):
return self.name
- 記得模型建立后,還需要進行一次完整的數(shù)據(jù)遷移才會真正在數(shù)據(jù)庫中建表
2. 綁定管理模型
- 在app目錄下修改admin.py:
admin.site.register(Student, StudentAdminInfo) admin.site.register(ClassRoom, ClassRoomAdminInfo) admin.site.register(Teacher, TeacherAdminInfo)
3. 設(shè)置admin管理類
-
實現(xiàn)方式(包括顯示、增、刪、改都集成在里面了)
- ModelAdmin
- 在admin.py里為每個模型添加管理類:
class ClassRoomAdminInfo(admin.ModelAdmin): pass class TeacherAdminInfo(admin.ModelAdmin): pass class StudentAdminInfo(admin.ModelAdmin): pass - 裝飾器
list_per_page : 修改頁面顯示數(shù)量:
actions_on_top/buttom :操作選項在屏幕上方還是下方
list_display=[] : 控制列表中顯示的內(nèi)容:
-
以上設(shè)置都在admin.py的管理類里面修改:
class TeacherAdminInfo(admin.ModelAdmin): list_per_page = 2 actions_on_top = False actions_on_bottom = True list_display = ["name","room"] -
除了顯示字段外,還可以將方法作為列顯示:
- 函數(shù)必須有返回值
- short_description : 設(shè)置作為顯示內(nèi)容
- admin_order_field : 排序綁定
- PS:默認(rèn)情況下,點擊列的標(biāo)題,可以以列為依據(jù)排序,但是以方法作為列是不能排序的,<BR>
這種情況下也可以為它綁定一個列,起到排序的功能 - 在Teacher類里面加入以下代碼:
# 定義一個方法,這個方法可以作為列顯示 def curTime(self): return time.time() curTime.short_description = "當(dāng)前時間" # 如果不設(shè)此行,默認(rèn)顯示為類名curTime curTime.admin_order_field = "name" # 以字段名name為排序依據(jù)
-
關(guān)聯(lián)對象(多表顯示)
- 使用方法
- 在Teacher類里面加入以下代碼:
def getRoomName(self): return self.room.roomName # 因為Teacher和ClassRoom是一對一關(guān)系,因此Teacher里可以訪問ClassRoom的字段 getRoomName.short_description = "教室" -
搜索功能 (search_fields)
- 在admin.py文件的TeacherAdminInfo里面增加:
search_fields = ["name"] # 搜索 name 列- 界面將會出現(xiàn)一個搜索框,并以name列為條件搜索
-
字段屏蔽 - fields
- 默認(rèn)情況下,字段是全部顯示的,但是,也可以屏蔽
- 同樣的,在TeacherAdminInfo里面增加:
fields = ["name","course"] # 只顯示name和course,屏蔽了Room -
分組設(shè)置 - fieldsets
- 為了方便管理和讓顯示效果更好,字段也可以分組:
- 在TeacherAdminInfo里面增加元組fieldsets:
# fields = ["name", "course"] fieldsets = ( ("基本信息", {"fields": ["name", ]}), ("其他信息", {"fields": ["room", "course"]}), )- 特別注意:fields和fieldsets不能共存,否則報錯。
-
其他設(shè)置 - admin.site
- 在admin.site下有許多設(shè)置,可以控制站點信息
admin.site.site_header = "這是站頭" admin.site.site_title = "這是站標(biāo)題" admin.site.index_title = "這是首頁標(biāo)語"

