Django 系統
- 環境
- Python 3.6
- Django 1.8
- 參考資料
- [Django中文教程](https://yiyibooks.cn/xx/django_182/index.html)
- [Python 新手使用 - Django 架站的16堂課](實體書)
環境搭建
- anaconda + pycharm
- anaconda使用
- conda list : 顯示當前環境安裝的包
- conda env list : 顯示安裝的虛擬環境列表
- conda create -n env_name python=3.6 如:conda create -n tl_django python=3.6
- 激活conda的虛擬環境
- source activeate env_name (Linux下激活)
- conda activate env_name (Windows下激活) 如: conda activate tl_django
- 激活的含義是:進入某環境專用命令行界面, 并針對該環境進行設置
- Django安裝:
- conda activate tl_django (首先激活Django的環境, PS:激活后命令行前面回帶一個(tl_django)這樣的前綴)
- pip install django==1.8
后臺流程
創建第一個Django程序
- django-admin startproject tulingxueyuan (創建Django項目: tulingxueyuan)
命令行啟動:
- cd tulingxueyuan
- python manage.py runserver (啟動服務器)
PyCharm啟動
- 1.配置python環境:
- 點擊File菜單 -> Settings -> Project:Python -> Project Interpreter-> “小齒輪”圖標 -> ADD -> Conda Environment -> Existing environment-> “...” 圖標 ->
- Linux系統:
Anaconda安裝路徑下的/envs/相應的虛擬環境名稱/bin/python.sh - Windows系統:
1、 C:\Users\用戶名\Anaconda3\envs\相應的虛擬環境名稱\python.exe
2、 C:\ProgramData\Anaconda3\envs\相應虛擬環境名稱\python.exe
3、 C:\Users\rocka.conda\envs\相應虛擬環境名稱\python.exe
Windows情況有點特殊,我分別在以上三個位置找到過。 - 注意:剛剛配置好的環境,PyCharm還會把各種包整理一下,當IDE主界面右下方有一條細細的進度條在跑的時候,說明環境還在Update中尚未準備就緒,程序中某些import 包的語句還會被語法提示器認為是錯誤語句,此時要耐心等待。
- Linux系統:
- 點擊File菜單 -> Settings -> Project:Python -> Project Interpreter-> “小齒輪”圖標 -> ADD -> Conda Environment -> Existing environment-> “...” 圖標 ->
- 2.配置manage.py文件:
- 鼠標指向manage.py文件-> 直接點運行 -> 將會報錯
- 此時需要點界面右上角下拉菜單(位于啟動按鈕左邊) -> 選 Edit Configurations ->在Parameters輸入參數: runserver -> 確定 -> 出來后點運行即可
路由系統 - urls
- 創建app
- app: 負責一個具體業務或者一類具體業務的模塊
- python manage.py startapp teacher (在app根目錄下執行,生成一個teacher的目錄,即teacher路由)
- 路由
- 按照具體的請求url, 導入到相應的業務
- django的信息控制中樞
-
本質上就是接受URL和相應的處理模塊的一個映射
03A.png - 在接受URL請求的匹配上使用了RE
- URL的具體內容在urls.py文件中 (閱讀該文件的代碼,發現內部是使用正則在處理URL和對應模塊的對應關系)
- 需要關注的兩點:
- 接受的URL是什么, 即如何用RE對傳入的URL進行匹配
- 已知URL匹配到哪個處理模塊
- URL匹配規則:
- 從上到下一個一個比對
- URL格式是分級格式,則按照級別一級一級往下比對,主要對應URL包含子URL的情況
- 子URL一旦被調用,則不會返回到主URL
- '/one/two/three/'
- 正則以r開頭, 表示不需要轉義, 注意尖號(^)和美元符號($)
- '/one/two/three' 配對正則: r'^one/'
- '/oo/one/two/three' 不配對正則: r'^one/'
- '/one/two/three/' 配對正則: r'^three/$
- '/oo/one/two/three/oo/' 不配對正則: r'three/$'
- 第一個反斜杠并不需要(系統自動忽略)
- 如果從上到下都沒有找到合適的匹配內容,則報錯
2. 正常映射
- 把某一個符合RE的URL映射到事務處理函數中去
- 舉例如下:
from showeast import views as sv urlpatterns = [ url(r'admin/',adming.site.urls), url(r'^normalmap/', sv.normalmap), ]
3.URL 中帶參數映射
在多事件處理代碼中需要由URL傳入參數,形如/myurl/param中的param
參數都是字符串形式,如果需要整數等形式需要自行傳喚
-
統稱的形式如下:
/search/page/432 中的432需要經常性變化內容,就是參數
-
一個較為復雜的例子:
url(r'^withparam/(?P<year>[0-9])/(?P<month>[0,1][0-9)',tv.withparam)
- 尖號表示從字符串左邊第一個字符開始匹配
- 圓括號表示的是一個參數,里面的內容作為參數傳遞給被調用的函數
參數名稱以問號加大寫P開頭嗎,尖括號里面就是參數的名字
后面花括號表示出現的次數,此處的4 表示只能出現4個0-9的數字
4. URL在APP中處理
如果所有應用URL都集中在tulingxueyuan/urls.py中,可能導致文件臃腫
可以把urls具體功能逐漸分散到每個app中
- 從djanco.conf.urls導入include
- 注意此時RE部分的寫法
- 添加include 導入
- 使用方法:
確保include被導入
- 在根目錄的urls.py中寫url (1個功能模塊只對應1個url)
- 寫子路由 (功能模塊里的子模塊,在各自的文件夾內的:模塊名_url.py內添加)
- 編寫各個功能模塊的views函數,包括各個子路由的views函數
- 與直接在主urls.py中寫理由一樣,分散在各個模塊文件夾下面寫獨立的子路由,同樣可以使用參數
5. URL中嵌套參數
- 捕獲某個參數的一部分
- 例如URL /index/page-3 , 需要捕獲數字3作為參數
- 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)
- 以上就是指從一個參數中再提煉一個參數(我個人認為第三個正則更簡單明了一些)
6. 傳遞額外的參數
- 參數不僅僅來自于URL, 還可能是我們自己定義的內容
url(r'extrem/$',sv.extremParam,{'name':'liuying'}), - 附加參數同樣適用于include語句, 此時對include內所有都添加.
7.URL的反向解析 reverse
- 防止硬編碼
- 本質上是對每一個URL進行命名
- 以后在編碼代碼中使用URL的值,原則上都應該使用反向解析
- reverse的好處是,只要給一個路由設好名字, 無論URL怎么變, 都可以用名字來引用,方便,主要用于模版
VIEWS 視圖
1. 視圖概述
- 視圖即視圖函數,接受WEB請求返回WEB相應的事務處理函數.
- 響應指符合http協議要求的任何內容,包括json, string, html等
- 本章忽略事務處理, 重點在如何返回處理結果上
2. 其他簡單視圖
- django.http為我們提供了很多和HttpResponse類似的簡單視圖,
通過查看django.http的源代碼我們直到. - 此類視圖使用方法基本類似,可以通過return語句直反饋給瀏覽器
- Http404為Exception子類, 所以需要用raise來顯式調用
- Debug模式的關閉:
- 打開根路徑下settings.py文件
- 將Debug = True 改為 False
- ALLOWED_HOSTS 改為 ["*"] (允許所有主機訪問)
3. HttpResponse詳解
- 方法:
- init : 使用頁內容實例化HttpResponse對象
- write(content) : 以文件的方式寫
- flush(): 以文件的方式輸出緩存區
- set_cookie(key, value='', max_age = none,expires = None): 設置cookie
- key , value 是字符串類型
- max_age 是一個整數, 表示在指定秒數后過期
- expires 是一個datetime或timedelta對象, 會話將在這個指定的日期/時間過期
- max_age 和 expires , 二選一
- 如果不指定過期時間,則兩個星期后過期
- delete_cookie(key): 刪除指定的key的Cookie, 如果key不存在, 也不會報錯
4. HttpRespnseRedirect
- 重定向, 服務器端跳轉
- 構造函數的第一個參數用來指定重定向的地址
- 例子: ShowViews/views.py
- 在east/urls中添加以下內容:
url(r'^v10_1/', views.v10_1),
url(r'^v10_2/', views.v10_2),
url(r'^v11/"' views.v11, name = "v11"),
# /east/ShowViews/views 中添加以下內容
def v10_1(request):
return HttpRespnseRedirect("/v11")
def v10_2(request):
return HttpRespnseRedirect(reverse("v11"))
def v11(request):
return HttpRespnseRedirect(""這是v11 的返回值")
5.Request 對象
-
Request介紹
- 服務器接受到http協議的請求后,會根據報文創建HttpRequest對象
- 視圖函數的第1個參數就是HttpRequest對象(在Python中,形參只跟位置相關,而跟具體的參數名無關,例如self亦是如此)
- 在django.http模塊中定義了HttpRequest對象的API
-
屬性
- 下面除非特別說明,屬性都是只讀的 (就像你給張三寫一封信, 張三收到后就已經沒有修改的意義了)
- path : 一個字符串, 表示請求頁面的完整路徑, 不包含域名
- method : 一個字符串,表示使用的HTTP方法,常用時包括:'GET'/'POST'
- encoding : 一個字符串,表示提交的數據的編碼方式
- 如果為None則表示使用瀏覽器的默認設置,一般為utf-8
- 這個屬性是可寫的,可以通過修改他來修改訪問表單數據使用的編碼
- GET : 一個類似字典的對象, 包含get請求方式的所有參數
- POST : 一個類似字典的對象, 包含post請求方式的所有參數
- FILES : 一個類似字典的對象, 包含所有的上傳文件
- COOKIES : 一個標準的Python字典, 包含所有cookie, 鍵和值都包含其中
- session: 一個即可獨有可寫的類似于字典的對象,表示當前會話.
- 只有當Django啟用會話時才可用.
- 詳細內容見"狀態保持".
-
方法
- is_ajax() : 如果請求是通過XMLHttpRequest發起的,則返回True
-
QueryDict 對象 [這個是Django特設的對象,HTTP本身沒有]
- 定義在django.http.QueryDict里
- request對象的屬性GET, POST都是QueryDict類型的對象
- 與Python 字典不同,QueryDict類型的對象用來處理同一個鍵帶多個值的情況.
- 方法get(): 根據鍵取值
- 只能獲取鍵的一個值
- 如果一個鍵同時擁有多個值,獲取最后一個值
- 方法getlist():根據鍵獲取值
- 將鍵的值以列表返回,可以獲取一個鍵的多個值
-
GET屬性 [此對象對應http協議的GET操作]
- QueryDict類型的對象
- 包含get請求方式的所有參數
- 與url請求地址中的參數隊形,位于?后面
- 參數的格式是鍵值對,如key1 = value1
- 多個參數之間,用&鏈接,如key1=value1&key2=value2
- 鍵是開發人員定下來的,值是可變的
- 例子: ShowViews/views/v8_get
-
POST 屬性
- QueryDict類型的對象
- 包含post請求方式的所有參數
- 與form表單中的空間對應
- 表單中的控件必須有name屬性,name為鍵,value為值
- checkbox存在一鍵多值的問題
- 鍵是開發人員定下來的,值是可變的
- 例子 ShowViews/views/v9_post
- setting中設置模版位置, 在根目錄下建立一個templates文件夾,然后在setting.py里修改為:
*('DIRS': [os.path.join(BASE_DIR,"templates")],)
- setting中CRSF跨站攻擊防護要關閉,此行需要注釋掉)
> * django.middleware.csrf.CsrfViewMiddleware',
- 設置get頁面的urls和參數
需要在路由文件中添加兩個路由:
> * url(r'^v9_get/', v.v9_get),
> * url(r'^v9_post/', v.v9_post),
- setting中設置模版位置, 在根目錄下建立一個templates文件夾,然后在setting.py里修改為:
-
手動編寫視圖
實驗目的:
利用django快捷函數手動編寫視圖處理函數
編寫過程中理解視圖運行原理
VIEW的目的:
1.. 業務處理
2.. 返回Respongse子類步驟:
1. 拿到模版
2. 拿到數據
3. 環境變量(插入到HTML代碼中,以此定位數據填充的位置)
4. 返回-
分析:
- django把所有請求信息封裝入request
- django通過URLS模塊把相應請求跟時間處理函數鏈接起來, 并把request作為參數傳入.
- 在相應的處理函數中,我們需要完成兩部分
- 處理業務
- 把結果封裝并返回,我們可以使用簡單HttpResponse, 同樣也可以自己處理此功能
- 本例子不介紹業務處理, 把目光集中在如何渲染結果并返回
-
render(request, templater_name [,context][,context_omstamce][,content_type])
- 使用模版和一個戈丁的上下文環境,返回一個渲染后的HttpResponse對象
- request: django的傳入請求
- templater_name : 模版名稱
- content_instance : 上下文環境
- 參見例子: teacher_app/views/render_test
-
render_to_response
- 根據給定的上下文字典渲染給定模版,返回渲染后的HttpResponse
- 參見例子: teacher_app/views/render4_test
-
系統內建視圖
- 系統內建視圖,可以直接使用:
- 404
- default.page_not_found(request, template_name = '404.html')
- 系統引發Http404時觸發
- 默認窗體request_path變量給模版,即導致錯誤的URL
- DEBUG = True則不會調用404, 取而代之是調試信息
- 404視圖會被傳遞到一個RequestContext帝鄉寧切可以訪問模版上下文處理器提供的變量.
- 500
- default.server_error
- DEBUG = True 不觸發
- 403
- default.permission_denied
- DEBUG = True 不觸發
- 500
- default.bad_request
- DEBUG = True 不觸發
Models 模型 (ORM)
- ORM
- Object Relation Map(對象關系映射) : 把面向對象思想轉換成關系數據庫思想.操作上把類等價于表格
- 類對應表格
- 類中的屬性對應表中的字段
- 在應用中的models.py文件中定義class
- 所有需要使用ORM的class都必須是 models.Model 的子類
- class中的所有屬性對應表格中的字段
- 字段的類型都必須使用 models.xxx 不能使用python中的類型
-
在django種,Models負責跟數據庫交互
ORM.png
Django 鏈接數據庫
- 自帶默認數據庫Sqllite3
- 關系型數據庫
- 輕量級
- 建議開發用sqlite3, 部署用mysql之類數據庫
- 切換數據庫在settings中進行設置
-
用django 連接 mysql
DATABASES = [ 'default' = { 'ENGINE' : 'django.db.backends.mysql', 'NAME' : '數據庫名', 'PASSWORD' : '數據庫密碼', 'HOST' : '127.0.0.1', 'PORT' : '3306', } ]
- django 連接 mysql需要在項目文件下的init文件中導入pymysql包
- import pymysql
- pymysql.install_as_MySQLdb()
models類的創建與使用
-
定義和數據庫表映射的類
- 在應用中的models.py文件中定義class [每一個app下面都有這個文件]
- 所有需要使用ORM的class都必須是 models.Model 的子類
- class中的所有屬性對應表格中的字段
- 字段的類型都必須使用 modles.xxx 不能使用python中的類型
-
字段常用參數
- max_length : 規定數值的最大長度
- blank : 是否允許字段為空,默認不允許
- null : 在DB中控制是否保存為null, 默認為false
- default : 默認值
- unique : 唯一
- verbose_name : 假名
-
數據庫的遷移(在models里創建類后通知數據庫)
- 在命令行中,生成數據遷移的語句(生成sql語句)
- python manage.py makemigrations
- 在命令行中,輸入數據遷移的指令
- python manage.py migrate
- 如果遷移中沒有變化或者報錯,可以強制遷移
- python manage.py makemigrations 應用名
- python manage.py migrate 應用名
- 對于默認數據庫,為了避免出現混亂,前提是數據庫中沒有數據,可以刪除自定義app下的migrations文件夾和db.sqlites3數據庫
- 如果報錯,顯示"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', )
查看數據庫中的數據
- 1.啟動命令行:python manage.py shell
注意點:對orm的操作分為靜態函數和非靜態函數兩種,靜態函數是指在內存中類共用的,非靜態函數是指每個實例掌握的 - 2.在命令行中導入對應的映射類
- from app名.models import 類名
- 一個完整的例子:
from teacher.models import Teacher
dana = Teacher()
dana.name = "Dana"
dana.age = 18
dana.address = "北京圖靈學院"
dana.save() # 保存
ta = Teacher.objects.all() # 返回集合
ta[0].name # 訪問name屬性,顯示: Dana
ta[0].age # 訪問age屬性,顯示: 18
ta[0].address # 訪問address屬性,顯示: '北京圖靈學院'
ta[0].course # 訪問course屬性,顯示為空
- 如上操作向Teacher表中增加幾條記錄之后,用for循環遍歷:
for t in ta:
print("Name: {0}, Age{1},Address:{2},Course:{3}".format(t.name,t.age,t.address,t.course))
顯示結果:
Name: Dana, Age18,Address:北京圖靈學院,Course:
Name: Daozhang, Age45,Address:程度小北路,Course:
Name: WangGonh, Age29,Address:,Course:Java
- 查詢age=45的記錄
- ta = Teacher.objects.filter(age=45)
- ta <BR>
直接輸入ta回車,顯示ta的內容,age=45的記錄只有一個就是daozhang, 顯示為:<BR>[<Teacher: Daozhang>]
- 3.使用object屬性操作數據庫,object是模型中實際和數據進行交互的
- 4.查詢命令
- 類名.objects.all()查詢數據庫表中的所有內容,返回的結果是一個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:不區分大小寫
- contains:包含
- startwith:以..開頭
- endwith:以..結尾
數據庫表關系
- 多表聯查:利用多個多聯合查找某一項信息或者多項信息
-
1:1 OneToOne
- 建立關系:在模型任意一邊即可,使用OneToOneField
- add: (增)有兩種方式:
- 實例化方法,直接實例化保存
- create方法,返回類型是<class 'rlt.models.Manager'>,推薦這種方法
- PS: 添加有關系的一邊,使用create方法,或者使用實例創建
- 例如:
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: (查)
- 由子表查母表(定義關系的表叫子表),由子表的屬性直接提取信息:
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> # 查詢成功
- 由子表查母表(定義關系的表叫子表),由子表的屬性直接提取信息:
- change:(改)
- 單個修改后使用save保存
s.school_name = "南京圖靈學院" s.save() s <School: 南京圖靈學院> # 修改成功
- 批量修改使用update
ss = School.objects.all() ss.update(school_name="圖靈學院") ss [<School: 圖靈學院>, <School: 圖靈學院>] # 批量修改成功
- 無論是對子表還是母表修改方法都一樣
- 單個修改后使用save保存
- delete:直接使用delete刪除
-
1:N OneToMany
- 一個表格的一個數據項/對象等,可有很多個另一個表格的數據項
- 比如,一個學校可有很多個老師,一般一個老師只會在一個學校上課
- 使用上
- 使用ForeignKey
- 在多的那一邊,比如上面的例子就是在Teacher表格里進行定義
- add: (增)
- 跟一對一方法類似,通過cerate和new來添加
- create:把屬性都填滿,然后不需要手動保存
- new(也就是實例化方法):可以屬性或者參數為空,必須用save保存
- query:
- 以學校和老師舉例
- 如果知道老師,查學校,則通過增加的關系屬性,直接使用
- 例如:查找t1老師是哪個學校的:
t1.teacher_name '劉大拿' t1.my_school <School: 圖靈學院>
- 反查
- 由學校,想查下這個學校所有老師,則在學校后跟老師這個類(類名稱小寫)接下劃線set來表示
- 可以簡單理解成teacher_set是School類里的一個隱藏屬性
- 例如,查詢1號學校下面有多少個老師:
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
- 表示任意一個表的數據可以擁有對方表格多項數據,反之亦然
- 比如典型例子就是老師和學生,老師可以有多個學生,學生也可以有多個老師
- 使用上,在任意一方,使用ManyToMany定義,只需要定義一邊
- add:
- 添加老師,則在Student實例.teachers.add(),也可以用create方法
- 注意,用實例添加多對多數據,需要兩次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'
- 注意:如果想實現雙向互查,必須在類代碼里面兩邊都相互添加一行:
models.ManyToManyField
s1 = Student.objects.all()[0] tt = s1.teacher_set.all() tt[0].teacher_name '劉大拿'
- 跟一對多類似,使用隱含屬性set查詢
-
模版(Template)
- 模板:一組相同或者相似的頁面,在需要個性化的地方進行留白,需要的時候只是用相應數據進行填充
- 步驟
- 在settings.py中進行設置:TEMPLATES
- 在templates文件夾下編寫模板并調用
一個最簡單的完整的例子: 1. 激活環境: activate tl_django 2. 創建項目: django-admin startproject django_tpl 3. 創建app: python manage.py startapp mytpl 4. 在項目的根目錄下建立一個templates的目錄 5. 在templates目錄下新建一個one.html文件,內容如下: <html> <body> <h1>Hello World!</h1> </body> </html> 6. 編輯Django系統自帶的settings.py文件: 找到Templates下的DIR位置,修改為: 'DIRS': [os.path.join(BASE_DIR, "templates")], 7. 為manager.py添加啟動變量runserver (僅限Pycharm環境) 8. 編輯Django系統自帶的urls.py: 在頭部添加包引用:import mytpl.views as v (如果這行Pycharm出紅線,就選File菜單的Invalidate Caches/Restart, 重啟后鼠標單擊項目目錄,Mark Directory As -> Sources Root 如果有很多個Sources Root(Root目錄的顏色不同),取消其他的, 確保只有一個Root且必須是當前目錄) 最后在下方依葫蘆畫瓢添加一個路由:url(r'^one/', v.one), 9. 打開mytpl下的views.py 在頭部添加包引用:from django.http import HttpResponse 添加一個函數one: def one(request): return render(request,r"one.html") 10. 運行manage.py 11. 在瀏覽器輸入:127.0.0.1:8000/one
- 步驟
模板-變量
- 變量的表示方法:{{var_name}}
- 在系統調用模板的時候,會有相應的數據查找相應的變量名稱,如果找到,則填充也叫渲染,否則跳過
- 參見例子:two.html
模板-標簽
-
for標簽:
{% for .. in .. %} 循環語句 {% endfor %}
參見例子:three.html,顯示班級成績
-
if標簽,用來判斷條件
{% if 條件 %} 條件成立執行語句 {% elif 條件 %} 條件成立執行語句 {% else %} 以上條件都不成立執行語句 {% endif %}
參見例子:four.html
csrf標簽,跨站請求偽造
- 在提交表單的時候,表單頁面需要加上{% csrf_token %}
- 參見例子five_get請求表單地址, five_post發送表單信息地址
- 原理:
- 瀏覽器提交一個get請求到服務器,服務器返回一個帶csrf_token的form回瀏覽器
- 此時瀏覽器正常提交form,隱含提交了csrf_token
- 服務器驗證這個新提交上來的csrf_token是否剛才服務器自己生成的那個csrf_token?
- 如果csrf_token不一致,說明本次提交是偽造的
- 在settings.py:
- 'django.middleware.csrf.CsrfViewMiddleware', 是控制csrf_token的開關,
- 如果此選項關閉,則不對csrf_token進行檢查,反之則一定會檢查,如果打開了此設置但是在html代碼里又不含{% csrf_token %},則將報錯: CSRF token missing or incorrect.
SESSION
- 為了應對HTTP的無協議性
- 用來保存用戶比較敏感的信息
- 他是屬于request的一個屬性
- 常用操作:
- request.session.get(key,defaultValue)
- request.session.clear():清除全部
- request.session[key] = value : 賦值
- request.session.flush() : 刪除當前會話并清除會話的cookie
- del request.session[key]
分頁
- django提供現成的分頁器用來對結果進行分頁
- from django.core.paginator import Paginator
Ajax
8. 基于類的視圖
- 和基于函數的視圖的優勢和區別:
- http方法的methode可以有各自的方法,不需要使用條件分支來解決
- 可以使用OOP技術(例如Mixin)
- 概述
- 核心是允許使用不同的實例方法來響應不同的HTTP請求方法,而避開條件分支實現
- as_view函數作為類的可調用入庫,該方法創建一個實例并調用dispatch方法,按照請求方法對請求進行分發,如果該方法沒有定義,則引發HttpResponseNotAllowed
- 類屬性使用
- 在類定義時直接覆蓋
- 在調用as_view的時候直接作為參數使用,例如:
urlpatterns = [ url(r'^about/', GreetingView.as_view(greeting="Greetxxx")), ]
- 對基于類的視圖的擴充大致有三種方法: Mixin, 裝飾as_view, 裝飾dispatch
- 使用Mixin
- 多繼承的一種形式,來自弗雷的行為和屬性組合在一起
- 解決多繼承問題
- View的子類只能單繼承,多繼承會導致不可期問題
- 多繼承帶來的問題:
- 結構復雜
- 優先順序模糊
- 功能沖突
- 解決方法
- 規格繼承 # java interface
- 實現繼承 # 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)
- 首先進行數據遷移,然后創建一個超管帳號
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表可以管理,
- 在模型建立完畢后,界面會增加很多內容,可以設置各個模型(也就是數據庫的表,這里稱為模型)
- 先在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
- 記得模型建立后,還需要進行一次完整的數據遷移才會真正在數據庫中建表
2. 綁定管理模型
- 在app目錄下修改admin.py:
admin.site.register(Student, StudentAdminInfo) admin.site.register(ClassRoom, ClassRoomAdminInfo) admin.site.register(Teacher, TeacherAdminInfo)
3. 設置admin管理類
-
實現方式(包括顯示、增、刪、改都集成在里面了)
- ModelAdmin
- 在admin.py里為每個模型添加管理類:
class ClassRoomAdminInfo(admin.ModelAdmin): pass class TeacherAdminInfo(admin.ModelAdmin): pass class StudentAdminInfo(admin.ModelAdmin): pass
- 裝飾器
list_per_page : 修改頁面顯示數量:
actions_on_top/buttom :操作選項在屏幕上方還是下方
list_display=[] : 控制列表中顯示的內容:
-
以上設置都在admin.py的管理類里面修改:
class TeacherAdminInfo(admin.ModelAdmin): list_per_page = 2 actions_on_top = False actions_on_bottom = True list_display = ["name","room"]
-
除了顯示字段外,還可以將方法作為列顯示:
- 函數必須有返回值
- short_description : 設置作為顯示內容
- admin_order_field : 排序綁定
- PS:默認情況下,點擊列的標題,可以以列為依據排序,但是以方法作為列是不能排序的,<BR>
這種情況下也可以為它綁定一個列,起到排序的功能 - 在Teacher類里面加入以下代碼:
# 定義一個方法,這個方法可以作為列顯示 def curTime(self): return time.time() curTime.short_description = "當前時間" # 如果不設此行,默認顯示為類名curTime curTime.admin_order_field = "name" # 以字段名name為排序依據
-
關聯對象(多表顯示)
- 使用方法
- 在Teacher類里面加入以下代碼:
def getRoomName(self): return self.room.roomName # 因為Teacher和ClassRoom是一對一關系,因此Teacher里可以訪問ClassRoom的字段 getRoomName.short_description = "教室"
-
搜索功能 (search_fields)
- 在admin.py文件的TeacherAdminInfo里面增加:
search_fields = ["name"] # 搜索 name 列
- 界面將會出現一個搜索框,并以name列為條件搜索
-
字段屏蔽 - fields
- 默認情況下,字段是全部顯示的,但是,也可以屏蔽
- 同樣的,在TeacherAdminInfo里面增加:
fields = ["name","course"] # 只顯示name和course,屏蔽了Room
-
分組設置 - fieldsets
- 為了方便管理和讓顯示效果更好,字段也可以分組:
- 在TeacherAdminInfo里面增加元組fieldsets:
# fields = ["name", "course"] fieldsets = ( ("基本信息", {"fields": ["name", ]}), ("其他信息", {"fields": ["room", "course"]}), )
- 特別注意:fields和fieldsets不能共存,否則報錯。
-
其他設置 - admin.site
- 在admin.site下有許多設置,可以控制站點信息
admin.site.site_header = "這是站頭" admin.site.site_title = "這是站標題" admin.site.index_title = "這是首頁標語"