視覺化介面之資料增刪改查
補充
在模型類中定義雙下str方法可以在資料物件被執行列印操作的時候方便的檢視
self應該是欄位物件 print(物件)時會觸發__str__
並且這個方法的return一定要返回字串型別的資料
觸發提交動作的按鈕:
'''
form表單中能夠觸發提交動作的按鈕只有兩個
<input type='submit'/>
<button></button>
ps: reset重置按鈕
'''
1.建表
建表、加索引可以體現程式設計師的工作經驗。
建表之前需要考慮,極端情況下 這個欄位最多能存多少資料?
欄位長度短了會導致服務出問題,欄位長度長了會佔用空間,浪費資源
在model.py使用ORM建表時,可以在類中不寫主鍵欄位(id),django會自動幫你建立一個名為id的主鍵欄位。
可以在models.py中給欄位新增註釋 比如age欄位 可以透過另外的方式檢視欄位的意義:
方式1.在mysql中使用show create table 表名
可以檢視註釋
方式2.mysql中有快取表可以看
2.資料展示功能
開設介面、獲取資料、傳遞頁面、展示資料
資料展示頁面示例:
資料展示頁表格html:
針對資料物件主鍵欄位的獲取可以使用更加方便的 obj.pk獲取
3.資料新增功能
開設介面、獲取資料、傳送資料、校驗資料、錄入資料、重定向
我們點選a標籤按鈕,跳轉到資料新增頁面,進行新增資料。
a標籤相當於朝你指定的頁面傳送get請求:
資料新增頁表單:
資料新增views層:
TODO是協同開發的時候用的 每天開發的程式碼要上傳到網路
上傳程式碼時,這個todo會彈出來,給你提供一些提示。
新增邏輯判斷,新增成功之後,重定向到資料展示頁面:
4.資料編輯功能
開設介面、後端如何區分所要編輯的資料(問號攜帶引數)、後端獲取使用者資料、前端展示預設資料、獲取使用者並完成更新
編輯使用者資訊的時候 如何讓新頁面知道 你想編輯的是哪個使用者?
a標籤預設傳送get請求 我們可以使用get請求攜帶一些資訊。
攜帶主鍵值:
示例:
資料編輯views:
使用request.GET.get
獲取get請求問號後面攜帶的主鍵值。
targetEditPage: 將後端透過id值查到的資料 塞到資料新增頁面表單的預設值(value)裡面去!
views新增相關邏輯:
5.資料刪除功能
開設介面、問號攜帶引數、刪除二次確認
擴充套件1:在資料表中新建一個列舉欄位,用於表示資料是否被刪除,如果刪除則將此欄位變為false。資料展示的時候不展示false的資料。
擴充套件2:刪除的時候可以在前端寫一個模態框進行二次確認
用get請求給後端傳遞主鍵值,告知資料庫到底要刪除哪個資料:
在views層接收主鍵值,呼叫資料庫執行刪除操作:
新增模態框。給a標籤新增類名,注意這裡因為在迴圈中,所以不能新增id屬性。
當模態框獲取使用者輸入的結果是false時,使用return false取消a標籤的預設事件:
django請求生命週期流程圖
學習流程
路由層、檢視層、模板層、模型層、元件、BBS專案
crsf
中介軟體:相當於安保系統 比如form表單提交 會被中介軟體攔住 crsf就是中介軟體相關配置
crsf概念理解:
你這可以這麼理解CSRF攻擊:攻擊者盜用了你的身份,以你的名義傳送惡意請求。
瞭解更多:https://blog.csdn.net/qq_45803593/article/details/124727762
wsgirel 與 uwsgi
django預設使用wsgiref模組寫了socket服務端
沒上線用wsgiref伺服器 這個支援的併發量很小
專案上線之後 會使用uwsgi伺服器 支援的併發量大
針對web框架閘道器介面有一個協議:WSGI協議
wsgiref、uwsgi都是實現WSGI協議的不同功能模組
WSGI(Python Web Server Gateway Interface, Python Web伺服器閘道器介面)由PEP333提出,它是一種指定Web伺服器與Python Web應用程式之間通訊的一種標準,目的就是將Web伺服器與Python Web應用解耦。
瞭解更多:https://www.cnblogs.com/goOJBK/p/16161273.html
nginx
對於大多數使用者來說,Nginx只是一個靜態檔案伺服器或者http請求轉發器,它可以把靜態檔案的請求直接返回靜態檔案資源,把動態檔案的請求轉發給後臺的處理程式
瞭解更多:https://blog.redis.com.cn/doc/
django路由層
1.路由匹配
django2.X及以上 path第一個引數寫什麼就匹配什麼
django1.X第一個引數是正規表示式
無論什麼版本django都自帶加斜槓字尾的功能 也可以取消
也就是說:django會幫你加斜槓重新給你從上到下匹配一次,一共匹配兩次
示例:如下傳送了兩次請求
第一次請求匹配失敗:
配置檔案中設定APPEND_SLASH = False
可以取消這個特性但是建議不要這麼做:
2.轉換器功能 path
正常情況下很多網站都會有很多相似的網址 如果我們每一個都單獨開設路由不合理
用django設定路由 這路由太多了不太合適
我們不可能一個介面一個介面的寫啊 相似的介面要整合在一起
django2.X及以上版本路由動態匹配有轉換器(五種)
str:匹配除路徑分隔符外的任何非空字串。
int:匹配0或者任意正整數。
slug:匹配任意一個由字母或數字組成的字串。
uuid:匹配格式化後的UUID。
path:能夠匹配完整的URL路徑
ps:還支援自定義轉換器(自己寫正規表示式匹配更加細化的內容)
路由不是寫死的 而是動態變化的 django提供相應的功能--> 轉換器
轉換器 : 將對應位置匹配到的資料轉換成固定的資料型別
path('index/<str:info>/', views.index_func),
# index_func(實參request物件,info='轉換器匹配到的型別轉換之後的內容')
path('index/<str:info>/<int:id>/', views.index_func)
# index_func(實參request物件,info='轉換器匹配到的型別轉換之後的內容',id='轉換器匹配到的型別轉換之後的內容')
轉化器的info會當做位置引數傳給檢視函式:
在views層接收傳來的info:
3.正則匹配
django2.X及以上版本有re_path 第一個引數是正則
匹配的本質是隻要第一個正規表示式能夠從使用者輸入的路由中匹配到資料就算匹配成功會立刻停止路由層其他的匹配直接執行對應的檢視函式
示例:re_path('^test/$', views.test)
舉例說明:
對於如下re_path,只要目標字串中 有test/
就能匹配成功
django1.X路由匹配使用的是url() 功能與django2.X及以上的re_path()一致。
django1.x首頁的路由應該這樣寫:
4.正則匹配的無名有名分組
無名分組
無需給匹配條件取名字。
re_path('^test/(\d{4})/', views.test)
會將括號內正則匹配到的內容當做位置引數傳遞給檢視函式(一個括號對應一個位置實參)
接受時候的形參無所謂,可以自己取名。
有名分組
re_path('^test/(?P<year>\d{4})/', views.test)
會將括號內正則匹配到的內容當做關鍵字引數傳遞給檢視函式 year=\d{4}匹配到的內容
注意上述的分組不能混合使用!!! 不能同一個路由 既使用無名分組 又使用有名分組
反向解析
為什麼要有反向解析?
當專案特別龐大 很多頁面 都寫了a標籤進行跳轉 a標籤都指向同一個路由:
如果我們換路由 會將之前所有a標籤全部失效!
總不能手動一個個換吧。所以要使用反向解析。
基本使用
透過一個名字可以反向解析出一個結果 該結果可以訪問到某個對應的路由
1.路由匹配關係起別名
path('login/', views.login, name='login_view')
2.反向解析語法
html頁面上模板語法 {% url 'login_view' %}
後端語法 reverse('login_view')
使用模板語法,當路由改變時,a標籤能透過名字login_name
找到這個名字對應的路由,也動態的進行改變:
後端使用reverse反向解析:
總結:
1.起別名
2.透過這個別名不論是在前端還是在後端都能解析出來一個路由
3.這個路由就是path的第一個引數
動態路由的反向解析
path('func1/<str:others>/', views.func1_func, name='func1_view')
html頁面上模板語法 {% url 'func1_view' 'jason' %}
後端語法 reverse('func1_view', args=('嘿嘿嘿',))
動態路由的情況下正常情況是無法解析的,因為構成這個路由的結果可能有,無數個。
要把動態的部分確定下來,必須得傳一個具體的值(這個值可以物件點name 傳資料的主鍵值):
如果有兩個動態的引數,就傳兩個,用空格隔開。
後端語法:
透過args傳位置引數,將動態的部分確定下來。
練習
實現一個urlpatterns的path匹配多個路由。
原匹配方式:
urlpatterns = [
path('', views.show_func),
path('user/show/', views.show_func),
path('user/add/', views.user_add_func),
path('user/edit/', views.user_edit_func),
path('user/delete/', views.user_delete_func),
]
使用分組將多個使用者頁面 用一個path匹配:
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.show_func),
path('user/<str:info>/', views.main_func , name='user_view')
]
在views層:
將info關鍵字引數傳入main_func。
比如輸入網頁127.0.0.1/user/show/
就會執行show_func
比如輸入網頁127.0.0.1/user/add/
就會執行user_add_func
並且使用res接受返回值,作為main_func的返回值返回。
def main_func(request, info):
print(info)
res = func_dict.get(info)(request)
return res
func_dict = {
'show': show_func,
'add': user_add_func,
'edit': user_edit_func,
'delete': user_delete_func,
}
在前端使用反向解析:
在html頁面透過user_view這個名字加上delete這個限制條件,可以解析出/user/delete/
這個網頁字尾。於是相當於點選這個a標籤,就向127.0.0.1/user/delete/
傳送get請求,同時使用get請求的?傳輸主鍵值。
訪問127.0.0.1/user/delete/
會執行user_delete_func。
在後端使用反向解析:
我們希望刪除資料之後,可以重定向到展示頁面。
此時可以透過reverse解析出show_page的路由/user/show/
。
reverse的第一個引數是一個名字,這個名字可以確定一個路由的動態匹配規則:
\user\<str:info>
第二個引數,相當於將原本不確定的路由給確定下來,變成:
\user\show\
最後作為一個相對路由,傳入redirect。