陳擎文教學網:python後台網頁Django
|
|||||
python資源 | |||||
官網 | python官網 | vscode官網 | |||
python 教學網站 | w3c school(中文版) | w3c school(英文版) | |||
線上執行python online |
https://repl.it/languages/python3 |
其它資源 | |||||
上課程式碼即時貼網站 | 線上黑板( Online blackboard) | 上課即時貼(guestBook) | 4月30日範例 | 有道翻譯 | |
考試題目 | 考試題目(Exam) | 畢業門檻(Graduation threshold) | 2018通識課規定 | DWCS3 | |
Goole 輸入法(Input software) | Goole輸入法(Input:exe) | Goole 輸入法(Input:zip) | online goole input(中文) | online goole input(英文) | |
Windows+Apache +MySQL+PHP整合安裝系統 |
phpstudy2014 | phpstudy2018 | XAMPP | wampserver | |
免費的網頁編輯軟體 | 微軟的vs code(visual studio code) | ||||
chp1.Django的簡介、安裝、簡單練習 | |||||
下載 |
下載本章project成果 | ||||
2.常用pip指令 | 3.建立一個django專案 | 4.建立第一個應用程式App | 5.環境設定(settings.py) | 6. MTV架構 | |
exp01_01:用MTV架構,在網頁顯示文字 | exp01_02:網址傳遞參數 | exp01_03:網址傳遞第二個變數 | exp01_04:回傳計算變數到模板指定網頁 | exp01_05:顯示圖片 | |
python下載點 |
|||||
vscode下載點 |
|||||
1.簡介: |
Django是一個開源的Python基於web開發而設計的應用框架,基於MVC的設計思想,大大簡化了網站開發的難度, 能夠簡單快速的開發網站。其中封裝的大量函式和方法,可以直接呼叫,同時擴充套件性非常好,可以擴充套件第三方外掛。 框架的主要三部分M(模型)V(檢視)T(模板)是基於MVC的思想在Django內的結構,其中V接受瀏覽器的資訊傳遞給M把資料存進資料庫,還可以接受M的返回結果讓T產生一個HTML頁面,Django的特點是大而全,內嵌了ORM框架,通過檔案遷移建立類和表的對應關係,操作資料庫不需要寫sql語句,而是通過類和物件對資料表操作, Django是目前Python開發網站最常用的後端框架。 |
||||
2.常用 pip 指令 |
(1).查詢目前python安裝了那些套件或模組 指令:pip list (2).卸除已經安裝的模組套件 pip uninstall 套件名稱 (3).安裝一個模組套件(例如:django) pip install django (4).更新安裝一個模組套件(例如:django) pip install --upgrade 套件名稱 pip install --upgrade django |
||||
3.建立一個django專案 |
建立目錄: md py_django 進入目錄: cd py_django 建立一個django專案語法:django-admin startproject 專案名稱 例如:django-admin startproject pj01 結果:發現已經建立一個pj01目錄 (1).manage.py (python命令檔,提供專案管理的功能) (2).子目錄:pj01(裡面有4個檔案) __init__.py (一個空檔) settings.py (設定檔) urls.py (url配置檔) wsgi.py (網頁伺服器的界面設定檔) |
||||
4.建立第一個應用程式application(App) |
(1).一個專案project可以有很多的App 要先到pj01目錄: cd pj01 語法:python manage.py startapp 應用程式名稱 例如:python manage.py startapp app01 結果: 產出一個app01目錄 裡面有6個檔案 (2).建立templates目錄 方法:md templates 功能:是模板,可以顯示*.html (3).建立static目錄 方法:md static 功能:存放圖片檔,CSS,javascript檔案的地方 (4).目前在pj01目錄下面有4個平行目錄 pj01 app01 templates static (5).建立migration資料檔 功能:若使用資料庫,可以建立資料表的架構與版本記錄,好處是未來可以追踪 語法:python manage.py makemigrations (app名稱) 例如:python manage.py makemigrations 若是沒有指定app01,就會對所有的app來記錄,建議不指定名稱 (6).將模型與資料庫同步 語法:python manage.py migrate (app名稱) 例如:python manage.py migrate 若是沒有指定app01,就會對所有的app來記錄,建議不指定名稱 ☎注意:不要指定app名稱,否則無法讀取資料表 結果: 會產生一個資料庫:db.sqlite3 (7).啟動server 語法:python manage.py runserver 結果: 手動開啟一個網頁,輸入:http://127.0.0.1:8000/ 結果顯示: The install worked successfully! Congratulations! (8).關閉server 輸入指令:ctrl+C,即可停止執行模式狀態 |
||||
5.環境設定(settings.py) |
(1).除錯模式:line 26 DEBUG = true (2).加入Application應用程式:line 40 'app01', (3).設定templates的存放目錄:line 58 'DIRS': [os.path.join(BASE_DIR,'templates')], (4).設定語系及時區:line 107,109 設定為繁體中文 LANGUAGE_CODE = 'zh-hant' 設定為台北時區 TIME_ZONE = 'Asia/Taipei' (5).設定static靜態檔的路徑:line 122 #static靜態檔 = 此目錄可以存放圖形檔,CSS,或javascript檔案 STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ] |
||||
6. MTV架構 |
(1).Django採用MTV架構,把網頁的執行與顯示,分成3個部分:model, template,view),類似ASP.NET的MVC架構。 M:模型Model T:模板Template V:視圖View 運作方法: (A).在Template目錄,放置顯示的樣板網頁*.html (B).在views.py定義執行的函式function 在views.py取得資料庫的資料,使用render函式的方式,傳遞給template模板*.html顯示 (C).在模型Model存取函數庫 流程圖: 資料庫 ➔ Model模型存取資料庫 ➔ View函式 ➔ 模板template網頁html (2).MVC架構(ASP.NET) M:模型Model V:視圖View C:控制Controller |
||||
(3).☎範例:exp01_01.py |
#目的:使用MTV架構,在網頁顯示:你好,歡迎光臨 (A).建立應用程式(App): app02 例如:python manage.py startapp app02 (A).在views.py先寫一個傳回文字的函式 ☎重點:如何在網頁輸出一段文字:HttpResponse(文字) 例如: from django.http import HttpResponse return HttpResponse('你好,歡迎光臨') 程式碼: from django.http import HttpResponse def sayhi(request): return HttpResponse('你好,歡迎光臨') (B).在urls.py設定views.py裡面的函式與執行網址的對應關係 在urls.py裡面: from django.conf.urls import url from app01.views import sayhi1 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$',sayhi1) ] (C).測試瀏覽網頁:127.0.0.1:8000 (D).若是出現錯誤訊息:UnicodeError:'utf-8' codec can't decode 原因:網頁有中文字,若是你是用筆記本note寫程式,存檔的格式要選utf8(不可以選ANSI) |
||||
(2).☎範例:exp01_02.py |
#目的:網址傳遞參數,http://127.0.0.1:8000/birthday,顯示你好,生日快樂 http://127.0.0.1:8000/newyear,顯示你好,新年快樂 (A).在views.py先寫一個傳回文字的函式 from django.http import HttpResponse def sayhi2(request): return HttpResponse('你好,生日快樂') def sayhi3(request): return HttpResponse('你好,新年快樂') (B).在urls.py設定views.py裡面的函式與執行網址的對應關係 在urls.py裡面: from django.conf.urls import url from app01.views import sayhi1,sayhi2,sayhi3 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$',sayhi1), url(r'^birthday/$',sayhi2), url(r'^newyear/$',sayhi3), ] (C).測試瀏覽網頁: 127.0.0.1:8000/birthday 127.0.0.1:8000/newyear |
||||
(3).☎範例:exp01_03.py |
#目的:網址傳遞第二個變數,http://127.0.0.1:8000/birthday/張三,顯示你好,生日快樂 http://127.0.0.1:8000/newyear/張三,顯示張三你好,新年快樂 (A).在views.py先寫一個傳回文字的函式 from django.http import HttpResponse def sayhi2(request): return HttpResponse('你好,生日快樂') def sayhi3(request): return HttpResponse('你好,新年快樂') def sayhi4(request,myname): return HttpResponse(myname + '你好,生日快樂') def sayhi5(request,myname): return HttpResponse(myname + '你好,新年快樂') (B).在urls.py設定views.py裡面的函式與執行網址的對應關係 在urls.py裡面: from django.conf.urls import url from app01.views import sayhi1,sayhi2,sayhi3,sayhi4,sayhi5 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$',sayhi1), url(r'^birthday/$',sayhi2), url(r'^newyear/$',sayhi3), url(r'^birthday/(\w+)/$',sayhi4), url(r'^newyear/(\w+)/$',sayhi5) ] (C).測試瀏覽網頁: 127.0.0.1:8000/birthday/李四 127.0.0.1:8000/newyear/王五 |
||||
(3).☎範例:exp01_04.py |
#☎目的:回傳計算變數到模板指定網頁sayhi05.html http://127.0.0.1:8000/newyear/張三,顯示:今天日期是,2019年9月26日,張三你好,新年快樂 #☎將所有views.py的變數都傳到模板templates(sayhi6.html)的方法: return render(request,'模板網頁',locals()) #☎範例: from django.shortcuts import render def sayhi6(request,myname): return render(request,'sayhi6.html',locals()) #☎locals():代表傳遞所有的區域變數 (A).修改settings.py環境設定 40行:新的app名稱 'app01', 58行:設定templates目錄位置 'DIRS': [os.path.join(BASE_DIR,'templates')], 107行:設定繁體中文,台北語區 LANGUAGE_CODE = 'zh-Hant' TIME_ZONE = 'Asia/Taipei' (B).在views.py先寫一個傳回文字的函式 from django.shortcuts import render from django.http import HttpResponse from datetime import datetime def sayhi6(request, myname): now = datetime.today() return render(request,'sayhi6.html',locals()) (C).在urls.py設定views.py裡面的函式與執行網址的對應關係 在urls.py裡面: from django.conf.urls import url from app01.views import sayhi1,sayhi2,sayhi3,sayhi4,sayhi5,sayhi6 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$',sayhi1), url(r'^birthday/$',sayhi2), url(r'^newyear/$',sayhi3), url(r'^birthday/(\w+)/$',sayhi4), url(r'^newyear/(\w+)/$',sayhi5), url(r'^now/(\w+)/$',sayhi6), ] (D).模板templates:sayhi6.html #☎在模板template顯示變數的方法:{{變數}} <HTML> <HEAD> <TITLE>sayhi6</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <h1>{{myname}}你好,新年快樂</h1> <h2>現在日期時間:{{now}}</h2> </BODY> </HTML> (E).測試瀏覽網頁: http://127.0.0.1:8000/now/王五 |
||||
(4).☎範例:exp01_05.py |
#☎目的:接上面範例,再顯示圖片icon01.png #☎觀念:django把圖片,css,javascript放在static目錄 #☎將所有views.py的變數都傳到模板templates(sayhi6.html)的方法: return render(request,'模板網頁',locals()) (A).建立static目錄,在建立images目錄 複製貼上圖片: (B).修改settings.py環境設定 122行:設定static的目錄 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), ] (C).模板templates:sayhi6.html #☎載入staticfiles的目錄設定:{% load staticfiles %} #☎顯示圖片檔案:src="{% static 'images/icon01.png' %}" <HTML> <HEAD> <TITLE>sayhi6</TITLE> {% load staticfiles %} <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <h1><img src="{% static 'images/icon01.png' %}">{{myname}}你好,新年快樂</h1> <h2>現在日期時間:{{now}}</h2> </BODY> </HTML> (D).測試瀏覽網頁: http://127.0.0.1:8000/now/王五 |
chp2.視圖View與模板templates | |||||
下載 |
下載本章project成果 | ||||
目錄 | MTV架構 | 在視圖View如何傳遞變數到Templates模板 | exp02_01顯示丟骰子的數字 | 宣告全域變數global | |
exp02_02.py顯示玩家姓名,年紀 | Templates語法:變數 | Templates語法:if | Templates語法:for | exp02_03.py傳遞串列到模板 | |
exp02_04.py:for:forloop | exp02_05.py:for:forloop參數revcounter | Templates語法:變數的過濾器:| | exp02_06.py過濾器 | Html標籤處理指令 | |
1. MTV架構 |
1. MTV架構 (1).Django採用MTV架構,把網頁的執行與顯示,分成3個部分:model, template,view),類似ASP.NET的MVC架構。 M:模型Model T:模板Template V:視圖View 運作方法: (A).在Template目錄,放置顯示的樣板網頁*.html (B).在views.py定義執行的函式function 在views.py取得資料庫的資料,使用render函式的方式,傳遞給template模板*.html顯示 (C).在模型Model存取函數庫 流程圖: 資料庫 ➔ Model模型存取資料庫 ➔ View函式 ➔ 模板template網頁html |
||||
2.在視圖View如何傳遞變數到Templates模板 |
2.在視圖View如何傳遞變數到Templates模板 (1).使用render語法: from django.shortcuts import render render(request, 模板名稱, 字典) ☎字典: 例如1:所有的區域變數 = locals() 例如1:指定單一字典變數 = {'num':9001} 例如1:{'name':'tom','age':25} ☎在模板templates容易顯示字典變數dict1: (正確){{name}} (錯誤){{dict1.name}} ☎例如: from django.shortcuts import render def sayhi6(request, myname): return render(request,'sayhi6.html',locals()) |
||||
範例:exp02_01.py |
(2).☎範例:exp02_01.py ☎#目的:顯示丟骰子的數字 ☎前置作業 _(A).關閉vscode ,然後再開啟vscode _(B).建立專案 django-admin startproject pj02 _(C).建立應用程式app python manage.py startapp app01 _(D).修改settings.py 40行:新的app名稱 'app01', 58行:設定templates目錄位置 'DIRS': [os.path.join(BASE_DIR,'templates')], 107行:設定繁體中文,台北語區 LANGUAGE_CODE = 'zh-Hant' TIME_ZONE = 'Asia/Taipei' 122行:設定static的目錄 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), ] _(E).到目前專案目錄 cd pj02 _(F).執行本專案程式 python manage.py startapp app01 _(G).修改函式(視圖views.py) ☎傳遞字典: = {'num':num} from django.shortcuts import render import random def dice1(request): num = random.randint(1,6) #return render(request, 'dice1.html',locals()) return render(request, 'dice1.html',{'num':num}) _(H).修改(urls.py) from django.conf.urls import url from app01.views import dice1 urlpatterns = [ path('admin/', admin.site.urls), url(r'^dice1/$', dice1), ] _(I).修改模板(templates/dice1.html) <HTML> <HEAD> <TITLE>丟骰子</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <h1>骰子點數 = {{num}}</h1> </BODY> </HTML> _(J).測試結果:http://127.0.0.1:8000/dice1/ 骰子點數 = 1 |
||||
3.宣告全域變數global |
3.如何宣告全域變數(global),如何傳遞全域變數 (1).如何宣告全域變數: 語法:global 變數 (2).如何傳遞全域變數: local()參數無法傳遞全域變數。 解決方法:區域變數 = 全域變數 (3).注意:網站不要用全域變數global1 原因:因為在個人主機雖然正常,但在專業主機如heroku,全域變數會亂變,跳來跳去, 解決方法:所以還是要用session變數,數據才穩 (4).如何傳遞字典型別的變數 例如: a1 = {"name":"tom","age":25} 如何在模板*.html要如何顯示姓名,年紀 姓名 = {{a1.name}} 年紀 = {{a1.age}} ☎注意:在模板的字典變數,不是使用傳統的方式:a1['name'] |
||||
範例:exp02_02.py顯示玩家姓名,年紀.. |
(5).範例:exp02_02.py #目的:顯示玩家姓名,年紀,骰子數字,累計次數times #全域變數 = times #views.py times = 0 def dice2(request): global times stu = {"name":"張三","age":25} num = random.randint(1,6) times = times +1 local_times = times return render(request, 'dice2.html',locals()) #urls.py urlpatterns = [ path('admin/', admin.site.urls), url(r'^dice1/$', dice1), url(r'^dice2/$', dice2) ] #dice2.html <HTML> <HEAD> <TITLE>丟骰子</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <h1>姓名 = {{stu.name}},年紀 = {{stu.age}}</h1> <h2>骰子點數 = {{num}}</h2> <h2>累計次數 = {{local_times}}</h2> </BODY> </HTML> (6).測試結果:http://127.0.0.1:8000/dice2/ 姓名 = 張三,年紀 = 25 骰子點數 = 6 累計次數 = 18 |
||||
4.Templates語法:變數 |
4.Templates語法:變數語法: (1).字典dict變數用法: python語法:dict1[name] templates語法:{{dict1.name}} (2).串列list變數用法: python語法:list1[0] templates語法:{{list1.0}} (3).物件變數的屬性用法: python語法:obj1.name templates語法:{{obj.name}} (4).物件變數的方法用法: python語法:obj1.show() templates語法:{{obj1.show}} (5).違反的變數名稱(會出現錯誤): class,del |
||||
5.Templates語法:if |
5.Templates語法:if語法: ☎注意:明顯與python的語法不同 (1).單向選擇 {% if a >= b %} ... ... {% endif %} (2).雙向選擇 {% if a >= b %} ... {% else %} ... {% endif %} (3).多向選擇 {% if a >= 60 %} ... {% elif a>=70 %} ... {% elif a>=80 %} ... {% endif %} |
||||
6.Templates語法:for |
6.Templates語法:for語法: ☎注意:明顯與python的語法不同 (1).for迴圈語法: {% for 變數item in 串列 %) ...讀取串列資料(item) (% empty %} ...若是沒有串列資料(空串列)的處理方法 {% endfor %} (2).for-反轉迴圈語法:(reversed ) {% for 變數item in 串列 reversed %) ...讀取串列資料(item) (% empty %} ...若是沒有串列資料(空串列)的處理方法 {% endfor %} (3).for迴圈的forloop參數: forloop屬性 forloop.counter = forloop的計數器,由1開始遞增到迭代總數 forloop.counter0 = forloop的計數器,由0開始遞增到迭代總數減1 forloop.revcounter = forloop的倒數器,由迭代總數遞減到1 forloop.revcounter0 = forloop的倒數器,由迭代總數減1遞減到0 forloop.first = 真假值,若是第一次for迴圈,此值為真,否則為假 forloop.last = 真假值,若是最後一次for迴圈,此值為真,否則為假 forloop.parentloop = 父迴圈(上一層迴圈)的forloop變量 |
||||
<範例:exp02_03.py傳遞串列到模板 |
☎(2).範例:exp02_03.py #目的:練習傳遞串列到模板(顯示本班三位同學的聯絡資料) #views.py def stu3(request): man1 = {"name":"張三","tel":"0945789456","age":20} man2 = {"name":"李四","tel":"0922786656","age":19} man3 = {"name":"王五","tel":"0911774156","age":21} man = [man1,man2,man3] return render(request, 'stu3.html', locals()) #urls.py from app01.views import dice1,dice2,stu3 urlpatterns = [ path('admin/', admin.site.urls), url(r'^dice1/$', dice1), url(r'^dice2/$', dice2), url(r'^stu3/$',stu3), ] #stu3.html <HTML> <HEAD> <TITLE>顯示學生資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> {% for item in man %} <h1>姓名 = {{item.name}}</h1> <h2>手機 = {{item.tel}},年紀 = {{item.age}}</h2> {% empty %} <h2>沒有任何資料</h2> {% endfor %} </BODY> </HTML> #測試結果:http://127.0.0.1:8000/stu3/ 姓名 = 張三 手機 = 0945789456,年紀 = 20 姓名 = 李四 手機 = 0922786656,年紀 = 19 姓名 = 王五 手機 = 0911774156,年紀 = 21 |
||||
.範例:exp02_04.py:for:forloop |
☎(4).範例:exp02_04.py #目的:練習for:forloop參數(顯示本班第n位同學的聯絡資料) #重點:第 {{ forloop.counter }} 位學生資料 #views.py def stu4(request): man1 = {"name":"張三","tel":"0945789456","age":20} man2 = {"name":"李四","tel":"0922786656","age":19} man3 = {"name":"王五","tel":"0911774156","age":21} man = [man1,man2,man3] return render(request, 'stu4.html', locals()) #urls.py from app01.views import dice1,dice2,stu3,stu4 urlpatterns = [ path('admin/', admin.site.urls), url(r'^dice1/$', dice1), url(r'^dice2/$', dice2), url(r'^stu3/$',stu3), url(r'^stu4/$',stu4), ] #stu4.html <HTML> <HEAD> <TITLE>顯示學生資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> {% for item in man %} <h1>第 {{ forloop.counter }} 位學生資料:</h1> <h2>姓名 = {{item.name}},手機 = {{item.tel}},年紀 = {{item.age}}</h2> {% empty %} <h2>沒有任何資料</h2> {% endfor %} </BODY> </HTML> #測試結果:http://127.0.0.1:8000/stu4/ 第 1 位學生資料: 姓名 = 張三,手機 = 0945789456,年紀 = 20 第 2 位學生資料: 姓名 = 李四,手機 = 0922786656,年紀 = 19 第 3 位學生資料: 姓名 = 王五,手機 = 0911774156,年紀 = 21 |
||||
範例:exp02_05.py:for:forloop參數revcounter |
☎(5).範例:exp02_05.py #目的:練習for:forloop參數revcounter(反轉顯示本班第n位同學的聯絡資料) #重點:{% for item in man reversed %} <h1>第 {{ forloop.revcounter }} 位學生資料 </h1> #views.py def stu5(request): man1 = {"name":"張三","tel":"0945789456","age":20} man2 = {"name":"李四","tel":"0922786656","age":19} man3 = {"name":"王五","tel":"0911774156","age":21} man = [man1,man2,man3] return render(request, 'stu5.html', locals()) #urls.py from app01.views import dice1,dice2,stu3,stu4,stu5 urlpatterns = [ path('admin/', admin.site.urls), url(r'^dice1/$', dice1), url(r'^dice2/$', dice2), url(r'^stu3/$',stu3), url(r'^stu4/$',stu4), url(r'^stu5/$',stu5), ] #stu5.html <HTML> <HEAD> <TITLE>顯示學生資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> {% for item in man reversed %} <h1>第 {{ forloop.revcounter }} 位學生資料:</h1> <h2>姓名 = {{item.name}},手機 = {{item.tel}},年紀 = {{item.age}}</h2> {% empty %} <h2>沒有任何資料</h2> {% endfor %} </BODY> </HTML> #測試結果:http://127.0.0.1:8000/stu5/ 第 3 位學生資料: 姓名 = 王五,手機 = 0911774156,年紀 = 21 第 2 位學生資料: 姓名 = 李四,手機 = 0922786656,年紀 = 19 第 1 位學生資料: 姓名 = 張三,手機 = 0945789456,年紀 = 20 |
||||
7.Templates語法:變數的過濾器:| |
7.Templates語法:變數的過濾器:|(pipe) 7-1.各種指令語法: 過濾器:|(pipe)= 篩檢程式 1.可以通過篩檢程式來修改變數的顯示, 篩檢程式的形式是:{{ variable | filter }}, 管道符號'|'代表使用篩檢程式 2.篩檢程式能夠採用鏈式的方式使用, 例如:{{ text | escape | linebreaks }} 3.篩檢程式還可以帶參數, 例如: {{ bio|truncatewords:30 }} 4.篩檢程式的參數中如果帶有空格,那麼需要用引號引起來, 例如:{{ list | join : ", "}} 5.django中30個內建的篩檢程式 (1)add 使用形式為:{{ value | add: "2"}} 意義:將value的值增加2 {{ 123|add:"5" }} 給value加上一個數值 (2)addslashes 使用形式為:{{ value | addslashes }} 意義:在value中的引號前增加反斜線 {{ "AB'CD"|addslashes }} 單引號加上轉義號,一般用於輸出到javascript中 (3)capfirst 使用形式為:{{ value | capfirst }} 意義:value的第一個字元轉化成大寫形式 {{ "abcd"|capfirst }} 第一個字母大寫 (4)cut 使用形式為:{{ value | cut:arg}}, 例如,如果value是“String with spaces” arg是" "那麼輸出是"Stringwithspaces" 意義:從給定value中刪除所有arg的值 {{ "123spam456spam789"|cut:"spam" }} 查找刪除指定字串 (5)date 使用形式為:: (a) {{ value | date:"D d M Y" }},例如,如果value是一個datetime物件(datetime.datetime.now())那麼輸出將是字串"Wed 09 Jan 2008" (b) {{ value | date }},這種形式沒有格式化字串,這時候,格式化字串會自動採用DATE_FORMAT所設置的形式。 意義:將日期格式資料按照給定的格式輸出 例如:格式化:{{ pub_date | date:"F j, Y" }} (6)default 使用形式:{{ value | default: "nothing" }},例如,如果value是“”,那麼輸出將是nothing 意義:如果value的意義是False,那麼輸出使用缺省值 {{ value|default:"(N/A)" }} 值不存在,使用指定值 (7)default_if_none 使用形式:{{ value | default_if_none:"nothing" }},例如,如果value是None,那麼輸出將是nothing 意義:如果value是None,那麼輸出將使用缺省值 {{ value|default_if_none:"(N/A)" }} 值是None,使用指定值 (8)dictsort 意義:如果value的值是一個字典,那麼返回值是按照關鍵字排序的結果 {{ 清單變數|dictsort:"數字" }} 排序從小到大 使用形式:{{ value | dictsort:"name"}}, 例如, 如果value是: [ {‘name’: ‘zed’, ‘age’: 19}, {‘name’: ‘amy’, ‘age’: 22}, {‘name’: ‘joe’, ‘age’: 31}, ] 那麼,輸出是: [ {‘name’: ‘amy’, ‘age’: 22}, {‘name’: ‘joe’, ‘age’: 31}, {‘name’: ‘zed’, ‘age’: 19}, ] (9)dictsortreversed 意義:如果value的值是一個字典,那麼返回值是按照關鍵字排序的結果的反序 使用形式:與上述(8)完全相同。 {{ 清單變數|dictsortreversed:"數字" }} 排序從大到小 (10)divisibleby 使用形式:{{ value | divisibleby:arg}},如果value是21,arg是3,那麼輸出將是True 意義:如果value能夠被arg整除,那麼返回值將是True {% if 92|pisibleby:"2" %} 判斷是否整除指定數字 (11)escape 使用形式:{{ value | escape}} 意義:替換value中的某些字元,以適應HTML格式,包括: < is converted to < > is converted to > ’ (single quote) is converted to ' ” (double quote) is converted to " & is converted to & {{ string|escape }} 轉換為html實體 escape僅僅在輸出的時候才起作用,所以escape不能夠用在鏈式篩檢程式的中間, 他應該總是最後一個篩檢程式,如果想在鏈式篩檢程式的中間使用,那麼可以使用force_escape (12)escapejs 使用形式:{{ value | escapejs }} 意義:替換value中的某些字元,以適應JAVASCRIPT和JSON格式。 (13)filesizeformat 使用形式:{{ value | filesizeformat }} 意義:格式化value,使其成為易讀的檔大小,例如:13KB,4.1MB等。 {{ 21984124|filesizeformat }} 以1024為基數,計算最大值,保留1位小數,增加可讀性 (14)first 使用形式:{{ value | first }} 意義:返回列表中的第一個Item,例如,如果value是列表[‘a’,’b’,’c’],那麼輸出將是’a’。 {{ list|first }} 返回清單第一個元素 (15)floatformat 使用形式:{{ value | floatformat}}或者{{value|floatformat:arg}}, arg可以是正數也可以是負數。沒有參數的floatformat相當於floatformat:-1 (1)如果不帶arg,那麼引擎會四捨五入,同時最多只保留一位小數。 {{ 13.414121241|floatformat }} 保留1位小數,可為負數,幾種形式 {{ 13.414121241|floatformat:"2" }} 保留2位小數 34.23234 {{ value|floatformat }} 34.2 34.00000 {{ value|floatformat }} 34 34.26000 {{ value|floatformat }} 34.3 (2)如果arg是正數,那麼引擎會四捨五入,同時保留arg位的小數。 34.23234 {{ value|floatformat:3 }} 34.232 34.00000 {{ value|floatformat:3 }} 34.000 34.26000 {{ value|floatformat:3 }} 34.260 (3)如果arg是負數,那麼引擎會四捨五入,如果有小數部分,那麼保留arg位元小數;否則,則沒有任何小數部分。 34.23234 {{ value|floatformat:”-3” }} 34.232 34.00000 {{ value|floatformat:”-3” }} 34 34.26000 {{ value|floatformat:”-3” }} 34.26 (16)get_digit 使用形式:{{ value | get_digit:”arg”}},例如,如果value是123456789,arg是2,那麼輸出是8 意義:給定一個數位,返回,請求的數字,記住:1代表最右邊的數字,如果value不是合法輸入, 那麼會返回所有原有值。 {{ 23456 |get_digit:"1" }} 從個位數開始截取指定位置的1個數字 (17)iriencode 使用形式:{{value | iriencode}} 意義:如果value中有非ASCII字元,那麼將其進行抓化成URL中適合的編碼,如果value已經進行過URLENCODE, 改操作就不會再起作用。 (18)join 使用形式:{{ value | join:”arg”}},如果value是[‘a’,’b’,’c’],arg是’//’那麼輸出是a//b//c 意義:使用指定的字元串連接一個list,作用如同python的str.join(list) {{ list|join:", " }} 用指定分隔符號號連接列表 (19)last 使用形式:{{ value | last }} 意義:返回列表中的最後一個Item (20)length 使用形式:{{ value | length }} 意義:返回value的長度。 {{ list|length }} 返回列表個數 (21)length_is 使用形式:{{ value | length_is:”arg”}} 意義:返回True,如果value的長度等於arg的時候,例如:如果value是[‘a’,’b’,’c’],arg是3,那麼返回True {% if 列表|length_is:"3" %} 列表個數是否指定數值 (22)linebreaks 使用形式:{{value|linebreaks}} 意義:value中的”\n”將被 替代,並且整個value使用包圍起來,從而適和HTML的格式 {{ "ABCD"|linebreaks }} 用新行用 (23)linebreaksbr 使用形式:{{value |linebreaksbr}} 意義:value中的”\n”將被 替代 {{ "ABCD"|linebreaksbr }} 用新行用標記包裹 (24)linenumbers 使用形式:{{value | linenumbers}} 意義:顯示的文本,帶有行數。 {{ 變數|linenumbers }} 為變數中每一行加上行號 (25)ljust 使用形式:{{value | ljust}} 意義:在一個給定寬度的欄位中,左對齊顯示value {{ "abcd"|ljust:"50" }} 把字串在指定寬度中對左,其它用空格填充 (26)center 使用形式:{{value | center}} 意義:在一個給定寬度的欄位中,中心對齊顯示value {{ "abcd"|center:"50" }} 輸出指定長度的字串,並把值對中 (27)rjust 使用形式:{{value | rjust}} 意義:在一個給定寬度的欄位中,右對齊顯示value {{ string|rjust:"50" }} 把字串在指定寬度中對右,其它用空格填充 (28)lower 使用形式:{{value | lower}} 意義:將一個字串轉換成小寫形式 {{ "ABCD"|lower }} 小寫 (29)make_list 使用形式:{{value | make_list}} 意義:將value轉換成一個list,對於字串,轉換成字元list;對於整數,轉換成整數list 例如value是Joel,那麼輸出將是[u’J’,u’o’,u’e’,u’l’];value是123,那麼輸出將是[1,2,3] {% for i in "1abc1"|make_list %}ABCDE,{% endfor %} 把字串或數位的字元個數作為一個清單 (30)pluralize 使用形式:{{value | pluralize}},或者{{value | pluralize:”es”}},或者{{value | pluralize:”y,ies”}} 意義:如果value不是1,則返回一個複數尾碼,缺省的尾碼是’s’ {{ 清單或數位|pluralize }} 單詞的複數形式,如清單字串個數大於1,返回s,否則返回空串 {{ 清單或數字|pluralize:"es" }} 指定es {{ 清單或數字|pluralize:"y,ies" }} 指定ies替換為y (31)random 使用形式:{{value | random}} 意義:從給定的list中返回一個任意的Item {{ 列表|random }} 返回列表的隨機一項 (32)removetags 使用形式:{{value | removetags:”tag1 tag2 tag3…”}} 意義:刪除value中tag1,tag2….的標籤。例如,如果value是Joel a slug tags是”b span”,那麼輸出將是:Joel a slug {{ string|removetags:"br p p" }} 刪除字串中指定html標記 (33)safe 使用形式:{{value | safe}} 意義:當系統設置autoescaping打開的時候,該篩檢程式使得輸出不進行escape轉換 (34)safeseq 與上述safe基本相同,但有一點不同的就是:safe是針對字串,而safeseq是針對多個字串組成的sequence (35)slice 使用形式:{{some_list | slice:”:2”}} 意義:與python語法中的slice相同,:2表示第一的第二個元素 {{ 列表|slice:":2" }} 切片 (36)slugify 使用形式:{{value | slugify}} 意義:將value轉換成小寫形式,同事刪除所有分單詞字元,並將空格變成橫線 例如:如果value是Joel is a slug,那麼輸出將是joel-is-a-slug {{ string|slugify }} 字串中留下減號和底線,其它符號刪除,空格用減號替換 (37)stringformat 這個不經常用,先不說 {{ value|stringformat:”E” }} If value is 10, the output will be 1.000000E+01. {{ 3|stringformat:"02i" }} 字串格式,使用Python的字串格式語法 (38)striptags 使用形式:{{value | striptags}} 意義:刪除value中的所有HTML標籤 {{ "EABCD"|striptags }} 剝去[X]HTML語法標記 (39)time 使用形式:{{value | time:”H:i”}}或者{{value | time}} 意義:格式化時間輸出,如果time後面沒有格式化參數,那麼輸出按照TIME_FORMAT中設置的進行。 {{ datetime|timesince }} 給定日期到現在過去了多少時間 {{ datetime|timesince:"other_datetime" }} 兩日期間過去了多少時間 {{ datetime|timeuntil }} 給定日期到現在過去了多少時間,與上面的區別在於2日期的前後位置。 {{ datetime|timeuntil:"other_datetime" }} 兩日期間過去了多少時間 (40)title 轉換一個字串成為title格式。 {{ 時間變數|time:"P" }} 日期的時間部分格式 {{ "abdsadf"|title }} 首字母大寫 (41)truncatechars 如果字串長度超過指定的字元數,則截斷該字串。截斷的字串將以可翻譯省略號字元(“…”)結尾。 論點: 要截斷到的字元數 例如:: {{ value|truncatechars:7 }} 如果 value 是 "Joel is a slug" ,輸出為 "Joel i…" . (42)truncatechars_html 類似 truncatechars ,但它知道HTML標記。在字串中打開但在截斷點之前未關閉的所有標記在截斷後立即關閉。 例如:: {{ value|truncatechars_html:7 }} 如果 value 是 " Joel is a slug " ,輸出為 "Joel i… " .將保留HTML內容中的分行符號。 (41)truncatewords 在一定數量的單詞後截斷字串。 論點: 後面要截斷的字數 例如:: {{ value|truncatewords:2 }} 如果 value 是 "Joel is a slug" ,輸出為 "Joel is …" . 將刪除字串中的分行符號。 (42)truncatewords_html 類似 truncatewords ,但它知道HTML標記。在字串中打開但在截斷點之前未關閉的所有標記在截斷之後立即關閉。 這比 truncatewords ,因此只能在傳遞HTML文本時使用。 例如:: {{ value|truncatewords_html:2 }} 如果 value 是 " Joel is a slug " ,輸出為 "Joel is … " .將保留HTML內容中的分行符號。 (41)truncatewords 使用形式:{{value | truncatewords:2}} 意義:將value切成truncatewords指定的單詞數目 例如,如果value是Joel is a slug 那麼輸出將是:Joel is … 例如,顯示前30個字:{{ bio | truncatewords:"30" }} {{ "A B C D E F"|truncatewords:"3" }} 截取指定個數的單詞 (42)truncatewords_html 使用形式同(41) 意義:truncation點之前如果某個標籤打開了,但是沒有關閉,那麼在truncation點會立即關閉。 因為這個操作的效率比truncatewords低,所有只有在value是html格式時,才考慮使用。 {{ "111221"|truncatewords_html:"2" }} 截取指定個數的html標記,並補完整 (43)upper 轉換一個字串為大寫形式 {{ string|upper }} 全部大寫 (44)urlencode 將一個字串進行URLEncode (45)urlize 意義:將一個字串中的URL轉化成可點擊的形式。 使用形式:{{ value | urlize }} 例如,如果value是Check out www.djangoproject.com,那麼輸出將是: Check out www.djangoproject.com {{ string|urlize }} 將URLs由純文字變為可點擊的連結。 (46)urlizetrunc 使用形式:{{ value | urlizetrunc:15}} 意義:與(45)相同,但是有一點不同就是現實的連結字元會被truncate成特定的長度,後面以…現實。 {{ string|urlizetrunc:"30" }} 同上,多個截取字元數。 (47)wordcount 返回字串中單詞的數目 {{ "B C D E F"|wordcount }} 單詞數 (48)wordwrap 使用形式:{{value | wordwrap:5}} 意義:按照指定的長度包裝字串 例如,如果value是Joel is a slug,那麼輸出將會是: Joel is a slug {{ "a b c d e f g h i j k"|wordwrap:"5" }} 每指定數量的字元就插入回車符 (49)timesince 使用形式:{{value |since:arg}} 意義:返回參數arg到value的天數和小時數 例如,如果 blog_date 是一個日期實例表示 2006-06-01 午夜, 而 comment_date 是一個日期實例表示 2006-06-01 早上8點, 那麼 {{ comment_date|timesince:blog_date }} 將返回 “8 hours”. (50)timeuntil 使用形式:{{value | timeuntil}} 意義:與(50)基本相同,一個不同點就是,返回的是value距離當前日期的天數和小時數。 (51)yesno {{ boolean|yesno:"Yes,No,Perhaps" }} 對三種值的返回字串,對應是 非空,空,None。 |
||||
範例:exp02_06.py過濾器 |
☎7-2:範例:exp02_06.py #目的:練習過濾器 #重點:{% for item in man reversed %} <h1>第 {{ forloop.revcounter }} 位學生資料 </h1> #views.py from datetime import datetime def filter6(request): str1 = "today is a good day" str2 = "<p>how are you?</p>" str3 = "how\nare\nyou?" str4 = "taiwan?" list1 = ['tom','jane','mike','john'] dict1 = [{'name':'tom','age':25},{'name':'brown','age':21},{'name':'mike','age':27}] num1 = 7 date1 = datetime.now() bool1 = num1>5 return render(request,'filter6.html',locals()) #urls.py from app01.views import dice1,dice2,stu3,stu4,stu5,filter6 urlpatterns = [ path('admin/', admin.site.urls), url(r'^dice1/$', dice1), url(r'^dice2/$', dice2), url(r'^stu3/$',stu3), url(r'^stu4/$',stu4), url(r'^stu5/$',stu5), url(r'^filter6/$',filter6) #filter6.html <HTML> <HEAD> <TITLE>templates的過濾器filter</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <h2>字串處理指令:</h2> <p>第一個字開頭大寫capfirst = {{str1|capfirst}}</p> <p>每個字開頭大寫title = {{str1|title}}</p> <p>全部小寫lower = {{str1|lower}}</p> <p>全部大寫upper = {{str1|upper}}</p> <p>只顯示前面10個字...(truncatechars:10) = {{str1|truncatechars:10}}</p> <p>計算幾個word字(wordcount) = {{str1|wordcount}}</p> <p>輸出文字前顯示編號(linenumbers) = {{str1|linenumbers}}</p> <p>空白處用-顯示(slugify) = {{str1|slugify}}</p> <p>刪除字串裡面的子字串(cut:'is') = {{str1|cut:'is'}}</p> <p>把字串轉成串列(make_list) = {{str4|make_list}}</p> <h2>Html標籤處理指令:</h2> <p>輸出html tag(escape) = {{str2|escape}}</p> <p>刪除html tag(striptags) = {{str2|striptags}}</p> <p>取得innerHtml(safe) = {{str2|safe}}</p> <p>把\n換成<br/><p>(linebreaks) = {{str3|linebreaks}}</p> <p>把\n換成<br/>(linebreaksbr) = {{str3|linebreaksbr}}</p> <h2>串列處理指令:</h2> <p>輸出串列第一個元素(first) = {{list1|first}}</p> <p>輸出串列最後一個元素(last) = {{list1|last}}</p> <p>輸出串列共幾個元素(length) = {{list1|length}}</p> <p>判別串列元素是否為5個(length_is:5) = {{list1|length_is:5}}</p> <p>輸出串列元素連接成一個字串(join:',') = {{list1|join:','}}</p> <p>傳回串列的前幾個元素(slice:n) = {{list1|slice:3}}</p> <p>以亂數輸出串列元素(random) = {{list1|random}}</p> <h2>字典處理指令:</h2> <p>以字典的年紀排序(dictsort:'age') = {{dict1|dictsort:'age'}}</p> <p>以字典的年紀反向排序(dictsortreversed:'age') = {{dict1|dictsortreversed:'age'}}</p> <h2>數字處理指令:</h2> <p>加上數字5(add:5) = {{num1|add:5}}</p> <p>數字以科學記號顯示(stringformat:'E') = {{num1|stringformat:'E'}}</p> <h2>顯示日期格式處理指令:</h2> <p>顯示今日日期:月 日(星期) 年(M d日(D) Y年) = {{date1|date:'M d日(D) Y年'}}</p> <h2>boolean處理指令:</h2> <p>7>5 是否為真(yesno:'是,否,取消') = {{bool1|yesno:'是,否,取消'}}</p> </BODY> </HTML> #測試結果:http://127.0.0.1:8000/filter6/ 字串處理指令: 第一個字開頭大寫capfirst = Today is a good day 每個字開頭大寫title = Today Is A Good Day 全部小寫lower = today is a good day 全部大寫upper = TODAY IS A GOOD DAY 只顯示前面10個字...(truncatechars:10) = today is … 計算幾個word字(wordcount) = 5 輸出文字前顯示編號(linenumbers) = 1. today is a good day 空白處用-顯示(slugify) = today-is-a-good-day 刪除字串裡面的子字串(cut:'is') = today a good day 把字串轉成串列(make_list) = ['t', 'a', 'i', 'w', 'a', 'n', '?'] |
||||
Html標籤處理指令 |
Html標籤處理指令: 輸出html tag(escape) = how are you? 刪除html tag(striptags) = how are you? 取得innerHtml(safe) = how are you? 把\n換成<br/><p>(linebreaks) = how are you? 把\n換成<br/>(linebreaksbr) = how are you? 串列處理指令: 輸出串列第一個元素(first) = tom 輸出串列最後一個元素(last) = john 輸出串列共幾個元素(length) = 4 判別串列元素是否為5個(length_is:5) = False 輸出串列元素連接成一個字串(join:',') = tom,jane,mike,john 傳回串列的前幾個元素(slice:n) = ['tom', 'jane', 'mike'] 以亂數輸出串列元素(random) = john 字典處理指令: 以字典的年紀排序(dictsort:'age') = [{'name': 'brown', 'age': 21}, {'name': 'tom', 'age': 25}, {'name': 'mike', 'age': 27}] 以字典的年紀反向排序(dictsortreversed:'age') = [{'name': 'mike', 'age': 27}, {'name': 'tom', 'age': 25}, {'name': 'brown', 'age': 21}] 數字處理指令: 加上數字5(add:5) = 12 數字以科學記號顯示(stringformat:'E') = 7.000000E+00 顯示日期格式處理指令: 顯示今日日期:月 日(星期) 年(M d日(D) Y年) = 九月 28日(星期六) 2019年 boolean處理指令: 7>5 是否為真(yesno:'是,否,取消') = 是 |
||||
chp3.模型model讀取資料庫 | |||||
目錄 | View如何傳遞變數到Templates | exp03_01建立資料庫管理者的帳號密碼 | exp03_02建立資料表類別student | django 模型models 常用欄位 | |
django 模型models 欄位常用參數 | 表單使用get傳遞變數三種方法 | exp03_03在模板templates顯示一筆 | exp03_04y在模板templates顯示全部 | exp03_05網頁基礎模板base.htm | |
下載 |
下載本章project成果 | ||||
在視圖View如何傳遞變數到Templates模板 |
1. MTV架構 2.在視圖View如何傳遞變數到Templates模板 (1).使用render語法: from django.shortcuts import render render(request, 模板名稱, 字典) |
||||
範例:exp03_01.py建立資料庫管理者的帳號密碼 |
(2).☎範例:exp03_01.py ☎#目的:建立資料庫管理者的帳號密碼 ☎前置作業 _(A).關閉vscode ,然後再開啟vscode _(B).建立專案 django-admin startproject pj03 _(C).建立應用程式app python manage.py startapp app01 _(D).修改setting.py 40行:新的app名稱 'app01', 58行:設定templates目錄位置 'DIRS': [os.path.join(BASE_DIR,'templates')], 107行:設定繁體中文,台北語區 LANGUAGE_CODE = 'zh-Hant' TIME_ZONE = 'Asia/Taipei' 122行:設定static的目錄 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), ] _(E).到目前專案目錄 cd pj02 建立templates:md templates 建立static:md static _(F).建立migration資料檔 功能:若使用資料庫,可以建立資料表的架構與版本記錄,好處是未來可以追踪 語法:python manage.py makemigrations (app名稱) 例如:python manage.py makemigrations 若是沒有指定app01,就會對所有的app來記錄,建議不指定名稱 _(G).將模型與資料庫同步 語法:python manage.py migrate (app名稱) 例如:python manage.py migrate 若是沒有指定app01,就會對所有的app來記錄,建議不指定名稱 ☎注意:不要指定app名稱,否則無法讀取資料表 _(H).建立資料庫管理者的帳號與密碼 指令:python manage.py createsuperuser 使用者名稱 (leave blank to use 'administrator'): admin 電子信箱: admin@gmail.com Password:admin Password (again):admin 這個密碼與使用者名稱太相近。 這個密碼過短。請至少使用 8 個字元。 _(I).登入資料庫管理者系統 網頁:http://127.0.0.1:8000/admin |
||||
範例:exp03_02.py建立資料表類別student,輸入三筆 |
(3).☎範例:exp03_02.py ☎#目的:建立資料表類別student,並輸入三筆資料 ☎#特別注意:欄位名稱不可以取為『url』,否則會出現csrf_token找不到或錯誤 _(A).修改models.ply from django.db import models # Create your models here. class student(models.Model): cname = models.CharField(max_length=20, null=False) csex = models.CharField(max_length=4, default='男',null=False) cbirthday = models.DateField(null=False) cemail = models.CharField(max_length=50,blank=True, default='') ctel = models.CharField(max_length=20, blank=True, default='') caddress = models.CharField(max_length=255, blank=True, default='') def __str__(self): return self.cname _(B).修改admin.ply(資料庫管理者,讀入model裡面的資料表類別) from django.contrib import admin from app01.models import student # Register your models here. admin.site.register(student) ☎注意:只要資料表有修改新增,就要重新執行migration _(C).建立migration資料檔 功能:若使用資料庫,可以建立資料表的架構與版本記錄,好處是未來可以追踪 語法:python manage.py makemigrations (app名稱) 例如:python manage.py makemigrations 若是沒有指定app01,就會對所有的app來記錄,建議不指定名稱 _(D).將模型與資料庫同步 語法:python manage.py migrate (app名稱) 例如:python manage.py migrate 若是沒有指定app01,就會對所有的app來記錄,建議不指定名稱 ☎注意:不要指定app名稱,否則無法讀取資料表 _(E).資料庫管理者系統,瀏覽資料表 網頁:http://127.0.0.1:8000/admin 點按:新增->新增3筆記錄 |
||||
django 模型models 常用欄位元 |
_(F).django 模型models 常用欄位元 ☎注意:不能為空值的寫法(null = False) ☎注意:可以是空白值的寫法(blank = True) ☎#特別注意:欄位名稱不可以取為『url』,否則會出現csrf_token找不到或錯誤 1、models.AutoField 自增列 = int(11) 如果沒有的話,默認會生成一個名稱為 id 的列 如果要顯式的自定義一個自增列,必須設置primary_key=True。 2、models.CharField 字串欄位元 必須設置max_length參數 3、models.BooleanField 布爾類型=tinyint(1) 不能為空,可添加Blank=True 4、models.ComaSeparatedIntegerField 用逗號分割的數字=varchar 繼承CharField,所以必須 max_lenght 參數 5、models.DateField 日期類型 date DateField.auto_now:保存時自動設置該欄位為現在日期,最後修改日期 DateField.auto_now_add:當該對象第一次被創建是自動設置該欄位為現在日期,創建日期。 6、models.DateTimeField 日期時間類型 datetime 同DateField的參數 7、models.Decimal 十進位小數類型 = decimal DecimalField.max_digits:數字中允許的最大位數 DecimalField.decimal_places:存儲的十進位位數 8、models.EmailField 一個帶有檢查 Email 合法性的 CharField 9、models.FloatField 浮點類型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 長整形 integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 12、models.GenericIPAddressField 一個帶有檢查 IP位址合法性的 CharField 13、models.NullBooleanField 允許為空的布爾類型 14、models.PositiveIntegerFiel 正整數 15、models.PositiveSmallIntegerField 正smallInteger 16、models.SlugField 減號、下劃線、字母、數字 17、models.SmallIntegerField 數字 資料庫中的欄位有:tinyint、smallint、int、bigint 18、models.TextField 大文本。默認對應的form標籤是textarea。 19、models.TimeField 時間 HH:MM[:ss[.uuuuuu]] 20、models.URLField 一個帶有URL合法性校驗的CharField。 21、models.BinaryField 二進位 存儲二進位數據。不能使用filter函數獲得QuerySet。 22、models.ImageField 圖片 ImageField.height_field、ImageField.width_field:如果提供這兩個參數,則圖片將按提供的高度和寬度規格保存。 該欄位要求 Python Imaging 庫Pillow。 會檢查上傳的對象是否是一個合法圖片。 23、models.FileField(upload_to=None[, max_length=100, ** options]) 文件 FileField.upload_to:一個用於保存上傳檔的本地檔系統路徑,該路徑由 MEDIA_ROOT 中設置 這個欄位不能設置primary_key和unique選項.在資料庫中存儲類型是varchar,默認最大長度為100 24、models.FilePathField(path=None[, math=None, recursive=False, max_length=100, **options]) FilePathField.path:文件的絕對路徑,必填 FilePathField.match:用於過濾路徑下檔案名的正則表達式,該表達式將用在檔案名上(不包括路徑)。 FilePathField.recursive:True 或 False,默認為 False,指定是否應包括所有子目錄的路徑。 例如:FilePathField(path="/home/images", match="foo.*", recursive=True) 將匹配「/home/images/foo.gif」但不匹配「/home/images/foo/bar.gif」 |
||||
django 模型models 欄位常用參數 |
2. django 模型models 欄位常用參數 1、null 如果是True,Django會在資料庫中將此欄位的值置為NULL,默認值是False 2、blank 如果為True時django的 Admin 中添加數據時可允許空值,可以不填。如果為False則必須填。默認是False。 null純粹是與資料庫有關係的。而blank是與頁面必填項驗證有關的 3、primary_key = False 主鍵,對AutoField設置主鍵後,就會代替原來的自增 id 列 4、auto_now 和 auto_now_add auto_now 自動創建---無論添加或修改,都是當前操作的時間 auto_now_add 自動創建---永遠是創建時的時間 5、choices 一個二維的元組被用作choices,如果這樣定義,Django會select box代替普通的文本框, 並且限定choices的值是元組中的值 GENDER_CHOICE = ( (u'M', u'Male'), (u'F', u'Female'), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 欄位長度 7、default 默認值 8、verbose_name Admin中欄位的顯示名稱,如果不設置該參數時,則與屬性名。 9、db_column 資料庫中的欄位名稱 10、unique=True 不允許重複 11、db_index = True 資料庫索引 12、editable=True 在Admin里是否可編輯 13、error_messages=None 錯誤提示 14、auto_created=False 自動創建 15、help_text 在Admin中提示幫助信息 16、validators=[] 驗證器 17、upload-to 文件上傳時的保存上傳文件的目錄 |
||||
範例:exp03_03.py在模板templates顯示一筆 |
(4).☎範例:exp03_03.py ☎#目的:在模板templates顯示一筆資料 ☎#方法:資料表類別.objects.get(查詢指令) _(A).修改視圖view.ply 程式碼: from django.shortcuts import render from app01.models import student # Create your views here. def show_one(request): #讀取一筆資料:cname =張三 try: item = student.objects.get(cname='張三') except Exception as e: errormsg = '讀取資料出現錯誤:' + e return render(request,'show_one.html',locals()) _(B).修改視圖urls.ply 程式碼: from django.conf.urls import url from app01.views import show_one urlpatterns = [ path('admin/', admin.site.urls), url(r'^show_one/$',show_one), ] _(C).修改視圖templates/show_one.html 程式碼: <HTML> <HEAD> <TITLE>顯示一筆學生資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <h2>姓名 = {{item.cname}}</h2> <p>性別 = {{item.csex}}</p> <p>生日 = {{item.cbirthday}}</p> <p>郵件 = {{item.cemail}}</p> <p>電話 = {{item.ctel}}</p> <p>住址 = {{item.caddress}}</p> </BODY> </HTML> _(D).測試:http://127.0.0.1:8000/show_one/ 自動編號 = 1 姓名 = 張三 性別 = 男 生日 = 2019年9月28日 郵件 = abc@gmail.com 電話 = 0956123456 住址 = 台南市勝利路250號 |
||||
exp03_04.py在模板templates顯示全部 |
(5).☎範例:exp03_04.py ☎#目的:在模板templates顯示全部的資料 ☎#方法:資料表類別.objects.all() _(A).修改視圖view.ply ☎注意:搜尋全部資料:student.objects.all() ☎注意:搜尋全部資料,以id欄位排序:student.objects.all().order_by('id') ☎注意:搜尋全部資料,以id欄位,反向排序:student.objects.all().order_by('-id') 程式碼: from django.shortcuts import render from app01.models import student def show_all(request): items = student.objects.all().order_by('-id') return render(request,'show_all.html',locals()) _(B).修改視圖urls.ply 程式碼: from app01.views import show_one,show_all urlpatterns = [ path('admin/', admin.site.urls), url(r'^show_one/$',show_one), url(r'^show_all/$',show_all), ] _(C).修改視圖templates/show_all.html ☎注意:雖然建立資料表的時候沒有建立『自動編號』欄位,但是系統會建立『自動編號』欄位(id) 程式碼: <HTML> <HEAD> <TITLE>顯示全部學生資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <h2>顯示全部學生資料</h2> <table border="1" cellsapcings='0' cellpadding='0'> <th>編號</th><th>姓名</th><th>性別</th><th>生日</th><th>郵件</th><th>電話</th><th>住址</th> {% for item in items %} <tr> <td>{{item.id}}</td> <td>{{item.cname}}</td> <td>{{item.csex}}</td> <td>{{item.cbirthday}}</td> <td>{{item.cemail}}</td> <td>{{item.ctel}}</td> <td>{{item.caddress}}</td> </tr> {% endfor %} </table> </BODY> </HTML> _(D).測試:http://127.0.0.1:8000/show_all/ 顯示全部學生資料 編號 姓名 性別 生日 郵件 電話 住址 3 王五 男 2019年9月25日 wu@yahoo.com 0945123789 高雄市 2 李四 女 2019年9月24日 ok@gmail.com 02-57188883 台北市 1 張三 男 2019年9月28日 abc@gmail.com 0956123456 台南市勝利路250號 |
||||
範例:exp03_05.py網頁基礎模板base.html |
(5).☎範例:exp03_05.py ☎#目的:將模板*.html分割成兩個(網頁基礎模板base.html+呼叫模板網頁) ☎#方法:網頁基礎模板templates/base.html <HTML> <HEAD> {% block title %} {% endblock %} </HEAD> <BODY> {% block content %} {% endblock %} </BODY> </HTML> ☎#方法:呼叫模板網頁templates/base.html {% extends 'base.html' %} {% %} {% block title %} ............ {% endblock %} {% block content %} ............ {% endblock %} _(A).修改視圖view.ply ☎注意:搜尋全部資料:student.objects.all() 程式碼: from django.shortcuts import render from app01.models import student def show_all_base(request): items = student.objects.all('cbirthday') return render(request,'show_all_base.html',locals()) _(B).修改視圖urls.ply 程式碼: from django.conf.urls import url from app01.views import show_one,show_all urlpatterns = [ path('admin/', admin.site.urls), url(r'^show_one/$',show_one), url(r'^show_all/$',show_all), url(r'^show_all_base/$',show_all), ] _(C).修改基礎模板templates/base.html 程式碼: <HTML> <HEAD> {% block title %} {% endblock %} </HEAD> <BODY> {% block content %} {% endblock %} </BODY> </HTML> _(D).呼叫基礎模板templates/show_all_base.html 程式碼: {% extends 'base.html' %} {% %} {% block title %} <TITLE>顯示全部學生資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <h2>顯示全部學生資料</h2> <table border="1" cellsapcings='0' cellpadding='0'> <th>編號</th><th>姓名</th><th>性別</th><th>生日</th><th>郵件</th><th>電話</th><th>住址</th> {% for item in items %} <tr> <td>{{item.id}}</td> <td>{{item.cname}}</td> <td>{{item.csex}}</td> <td>{{item.cbirthday}}</td> <td>{{item.cemail}}</td> <td>{{item.ctel}}</td> <td>{{item.caddress}}</td> </tr> {% endfor %} </table> {% endblock %} _(E).測試:http://127.0.0.1:8000/show_all_base/ 顯示全部學生資料 編號 姓名 性別 生日 郵件 電話 住址 3 王五 男 2019年9月25日 wu@yahoo.com 0945123789 高雄市 2 李四 女 2019年9月24日 ok@gmail.com 02-57188883 台北市 1 張三 男 2019年9月28日 abc@gmail.com 0956123456 台南市勝利路250號 |
||||
chp4.新增,修改,刪除資料表 | |||||
目錄 | 表單form傳遞資料的兩種方法post,get | django後台(view.py)接收前端網頁(*.html)的資料 | exp04_01前端表單傳送姓名年紀 | exp04_02前端表單新增一筆:不驗證 | exp04_03新增驗證欄位 |
exp04_04刪除指定編號資料 | exp04_05修改指定編號資料 | 表單使用get傳遞變數 | exp04_06表單使用get傳遞,方法一 | exp04_07表單使用get傳遞,方法二 | exp04_08整合性表單使用get傳遞,方法三 |
下載 |
下載本章project成果 | ||||
表單form傳遞資料的兩種方法(post,get) |
1.表單form傳遞資料的兩種方法(post,get) |
||||
在django後台(view.py),如何接收前端網頁(*.html)傳來的資料 |
2.在django後台(view.py),如何接收前端網頁(*.html)傳來的資料(post,get) |
||||
範例:exp04_01.py:前端表單傳送姓名年紀給後台view.py |
(4).☎範例:exp04_01.py ☎#目的:前端表單傳送姓名,年紀,如何在後台view.py接收並顯示 _(A).前置作業 #建立專案pj04:django-admin startproject pj04 cd pj04 #建立app01:python manage.py startapp app01 #建立目錄 md static md templates #修改settings.py 40行:新的app名稱 'app01', 58行:設定templates目錄位置 'DIRS': [os.path.join(BASE_DIR,'templates')], 107行:設定繁體中文,台北語區 LANGUAGE_CODE = 'zh-Hant' TIME_ZONE = 'Asia/Taipei' 122行:設定static的目錄 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), ] _(B).在templates/建立form1.html傳送2個參數 程式碼: <HTML> <HEAD> <TITLE>表單傳送資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <form method="POST" name="myform" action="/POST/"> 輸入姓名=<input type="text" id='myname' /> <br/> 輸入年紀=<input type="text" id='myage' /> <input type="submit" value="傳送資料" /> </form> </BODY> </HTML> _(C).在views.py接收2個參數 from django.shortcuts import render # Create your views here. ☎注意:request.method == 'POST',POST必須大寫 def form1(request): if request.method == 'POST': #POST必須大寫 myname = request.POST['myname'] myage = request.POST['myage'] else: myname = '資料沒有採用post傳送' myage = '資料沒有採用post傳送' return render(request,'form1.html',locals()) _(D).在templates/顯示傳回form1.html的2個參數 ☎注意:action="/form1/",表示會執行http://127.0.0.1:8000/form1/ ☎注意:method="post"時,表單欄位代號必須用name(不用id) ☎注意:{% csrf_token %}必須放在form 表單裡面 ☎注意:若是採用POST方式來傳送資料,就必須啟動CRSF防護,避免伺服器被攻擊。 若是沒有啟動CRSF防護,就會產生錯誤訊息 ☎注意:為什麼要啟動CRSF防護?及其原理 原因:伺服器要檢查這個資料的傳送,是否是當初自己給的,若不是,就是外來的攻擊 原理:當我們開啟django一個前端網頁時,同時django主機也順便傳送一個亂數產生的token到前端網頁了。 而前端網頁傳送資料回主機時,django主機會檢查這個token是否是當初主機給的值 程式碼: <HTML> <HEAD> <TITLE>表單傳送資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> </HEAD> <BODY> <form method="post" name="myform" action="/form1/"> {% csrf_token %} 輸入姓名=<input type="text" name='myname' /> <br/> 輸入年紀=<input type="text" name='myage' /> <input type="submit" value="傳送資料" /> </form> django主機傳回:<br/> 姓名 = {{ myname }}<br/> 年紀 = {{ myage }}<br/> </BODY> </HTML> _(E).設定urls.py from django.conf.urls import url from app01.views import form1 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$', form1), url(r'^form1/$', form1), ] _(F).測試:http://127.0.0.1:8000/ 輸入姓名= 輸入年紀= django主機傳回: 姓名 = john 年紀 = 23 |
||||
範例:exp04_02.py前端表單新增一筆資料(不驗證欄位資料) |
(5).☎範例:exp04_02.py(不驗證欄位資料) ☎#目的:前端表單新增一筆資料(不驗證欄位資料),如何在後台view.py接收並顯示 _(A).前置作業 #models.py建立資料表類別 程式碼: class stu(models.Model): cname = models.CharField(max_length=20,null=False) csex = models.CharField(max_length=2,null=False) cbirthday = models.DateField(null=False) cmail = models.EmailField(max_length=30,default='',blank=True) ctel = models.CharField(max_length=20,default='',blank=True) caddress = models.CharField(max_length=255,default='',blank=True) def __str__(self): return self.cname #admin.py建立資料表類別 from app01.models import stu # Register your models here. admin.site.register(stu) #執行資料表庫migration python manage.py makemigrations #同步資料表庫migration python manage.py migrate ☎注意:不要指定app名稱,否則無法讀取資料表 #測試資料庫 python manage.py runserver http://127.0.0.1:8000/admin (需要帳號密碼) #建立superuser的帳號密碼 指令:python manage.py createsuperuser 使用者名稱 (leave blank to use 'administrator'): admin 電子信箱: admin@gmail.com Password:admin Password (again):admin 這個密碼與使用者名稱太相近。 這個密碼過短。請至少使用 8 個字元。 #新增三筆資料 http://127.0.0.1:8000/admin _(B).建立一個網頁,顯示全部資料,並有新增按鈕(show_all.html) #在views.py建立show_all函式 from app01.models import stu def show_all(request): items = stu.objects.all() return render(request,'shoow_all.html',locals()) #在show_all.html建立網頁(使用base.html) ☎注意:『新增』的超連結的網址,不寫網址,而是寫view.py的函式名稱(例如<a href='/add01/'>) ☎在view.py:def add01(request): return render(request,'add01.html',locals()) 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>顯示所有學生資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <h2>顯示全部學生資料: <a href='/add01/'>新增一筆(不驗證)</a> <a href='/add02/'>新增一筆(驗證)</a> <a href='/del01/'>刪除</a> <a href='/edit01/'>修改</a> <a href='/add03/'>新增(get方法)</a> </h2> <table border="1" cellsapcings='0' cellpadding='0'> <th>編號</th><th>姓名</th><th>性別</th><th>生日</th><th>郵件</th><th>電話</th><th>住址</th> {% for item in items %} <tr> <td>{{item.id}}</td> <td>{{item.cname}}</td> <td>{{item.csex}}</td> <td>{{item.cbirthday}}</td> <td>{{item.cmail}}</td> <td>{{item.ctel}}</td> <td>{{item.caddress}}</td> </tr> {% endfor %} </table> {% endblock %} #在views.py:建立add01函式 def add01(request): return render(request,'add01.html',locals()) _(C).建立一個網頁,可以新增一筆記錄(add01.html) ☎注意:因為有從主機傳回值,所以要驗證token ,方法:{% csrf_token %} ☎注意:若表單form送出到主機的位置與目前一樣,那麼action = ".",或是action = "" ☎注意:日期欄位的格式是:2019-5-5(不是209/5/5) 例如:生日=<input type="text" placeholder="2019-9-2" name='mybirthday' /> 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>新增一筆資料,資料不作驗證</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="post" name="myform" action="."> {% csrf_token %} 姓名=<input type="text" name='myname' /> <br/> 性別=<input type="text" placeholder="男" name='mysex' /> <br/> 生日=<input type="text" placeholder="2019-9-2" name='mybirthday' /> <br/> 郵件=<input type="text" placeholder="abc@gmail.com" name='mymail' /> <br/> 電話=<input type="text" name='mytel' /> <br/> 住址=<input type="text" name='myaddress' /> <br/> <input type="submit" value="送出" /> <input type="reset" value="重設" /> </form> <p style="color: magenta">{{message01}}</p> {% endblock %} _(D).修改views.py:修改add01函式(處理上傳資料給主機新增一筆記錄) ☎django轉網址有三種方法(一):redirect('/xxx/') ☎注意:要先import redirect函式(from django.shortcuts import redirect) ☎新增一筆記錄的語法 recd = stu.objects.create(欄位=變數,欄位=變數,cbirthday=mybirthday) recd.save() 程式碼: from django.shortcuts import render,redirect def add01(request): if request.method == 'POST': myname = request.POST['myname'] mysex = request.POST['mysex'] mybirthday = request.POST['mybirthday'] mymail = request.POST['mymail'] mytel = request.POST['mytel'] myaddress = request.POST['myaddress'] #新增一筆記錄 recd = stu.objects.create(cname=myname,csex=mysex,cbirthday=mybirthday,cmail=mymail,ctel=mytel,caddress=myaddress) recd.save() return redirect('/show_all/') else: message01 = '請輸入資料(資料不作驗證)' return render(request,'add01.html',locals()) _(E).設定urls.py from django.contrib import admin from django.urls import path from django.conf.urls import url from app01.views import form1,show_all,add01 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$', form1), url(r'^form1/$', form1), url(r'^show_all/$', show_all), url(r'^add01/$', add01), ] |
||||
範例:exp04_03.py驗證欄位資料 |
(6).☎範例:exp04_03.py(要驗證欄位資料) ☎#目的:前端表單新增一筆資料(要驗證欄位資料),如何在後台view.py接收並顯示 _(A).前置作業:#form.py建立驗證欄位類別 ☎注意:預設都是欄位必須有值,除非註明required=False ☎注意:預設值的設定用initial=''(不是用default='') ☎注意:若是日期欄位,設定為forms.DateField(),則可以輸入2019/8/9,或是209-8-9 ☎注意:若是email欄位,設定為forms.EmailField(),則會檢驗是否符合email格式 在app01目錄底下,新增檔案:form.py 程式碼: from django import forms class PostForm(forms.Form): myname = forms.CharField(max_length=20,initial='') mysex = forms.CharField(max_length=2,initial='男') mybirthday = forms.DateField() mymail = forms.EmailField(max_length=20, initial='',required=False) mytel = forms.CharField(max_length=10, initial='',required=False) myaddress = forms.CharField(max_length=100, initial='',required=False) _(B).在views.py建立add02函數 #功能:可以顯示新增一筆資料網頁(add02.html),可以處理新增記錄存入資料庫(recd.save()) ☎注意:PostForm()會建立一個空白PostForm物件 ☎注意:PostForm(request.POST)會把表單form的輸入參數,建立一個PostForm物件(有表單參數) ☎驗證PostForm物件是否正確:postform.is_valid() ☎接收表單的myname欄位 postform.cleaned_data['myname'] ☎切換網頁:return redirect('/show_all/') 程式碼: from app01.form import PostForm def add02(request): if request.method=='POST': #建立form物件 postform = PostForm(request.POST) #如果通過forms驗證 if postform.is_valid(): myname = postform.cleaned_data['myname'] mysex = postform.cleaned_data['mysex'] mybirthday = postform.cleaned_data['mybirthday'] mymail = postform.cleaned_data['mymail'] mytel = postform.cleaned_data['mytel'] myaddress = postform.cleaned_data['myaddress'] #新增一筆記錄 recd = stu.objects.create(cname=myname,csex=mysex,cbirthday=mybirthday,cmail=mymail,ctel=mytel,caddress=myaddress) recd.save() message01 = '已經成功儲存' return redirect('/show_all/') else: message01 = '輸入欄位驗證錯誤' else: message01 = '有幾個欄位是必須輸入的:姓名,生日,性別' postform = PostForm() return render(request,'add02.html',locals()) _(C).在urls.py建立網址設定公式 程式碼: from app01.views import form1,show_all,add01,add02 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$', form1), url(r'^form1/$', form1), url(r'^show_all/$', show_all), url(r'^add01/$', add01), url(r'^add02/$', add02), ] _(D).建立模板顯示網頁add02.html ☎顯示textbox欄位 = {{ postform.myname }} 因為它會引用form.py裡面的驗證欄位來顯示 ☎注意:若是日期欄位,設定為forms.DateField(),則可以輸入2019/8/9,或是209-8-9 ☎注意:若是email欄位,設定為forms.EmailField(),若是有輸入文字,則會檢驗是否符合email格式 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>新增一筆資料,資料不作驗證</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="post" name="myform" action="."> {% csrf_token %} 姓名 = {{ postform.myname }} <br/> 性別 = {{ postform.mysex }} <br/> 生日 = {{ postform.mybirthday}} <br/> 郵件 = {{ postform.mymail }} <br/> 電話 = {{ postform.mytel }} <br/> 住址 = {{ postform.myaddress }} <br/> <input type="submit" value="送出" /> <input type="reset" value="重設" /> </form> <p style="color: magenta">{{message01}}</p> {% endblock %} 結果: |
||||
範例:exp04_04.py刪除指定編號資料 |
(7).☎範例:exp04_04.py(刪除指定編號資料) ☎#目的:刪除指定編號資料 _(A).在views.py建立del01函數 ☎注意:刪除一筆資料的語法 recd = stu.objects.get(編號=myid) recd.delete() ☎注意:如何取得由post傳來的myid數字 = request.POST['myid'] def del01(request): if request.method=="POST": myid = request.POST['myid'] try: recd = stu.objects.get(id=myid) recd.delete() return redirect('/show_all/') except: message01 = '這個id不存在' return render(request,'del01.html',locals()) _(B).在urls.py建立網址設定公式 from app01.views import form1,show_all,add01,add02,del01 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$', form1), url(r'^form1/$', form1), url(r'^show_all/$', show_all), url(r'^add01/$', add01), url(r'^add02/$', add02), url(r'^del01/$', del01), ] _(C).建立模板顯示網頁del01.html {% extends 'base.html' %} {% block title %} <TITLE>刪除一筆資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="post" name="myform" action="."> {% csrf_token %} 輸入想刪除的編號=<input type="text" name='myid' /> <br/> <input type="submit" value="刪除" /> </form> <p style="color: magenta">{{message01}}</p> {% endblock %} 結果: |
||||
範例:exp04_05.py修改指定編號資料 |
(8).☎範例:exp04_05.py(修改指定編號資料) ☎#目的:修改指定編號資料(首先要指定編號,然後顯示所有資料,修改後,再回存) _(A).在views.py建立edit01函數(首先要指定編號) ☎注意:不同網頁之間,傳遞變數的方法:request.session['myid'] ☎注意:如何判別這個id不存在?(使用try...except,查詢資料表id=myid是否存在 myid = request.POST['myid'] try: recd = stu.objects.get(id=myid) return redirect('/edit02/') except: message01 = '這個id不存在' 程式碼: def edit01(request): if request.method=='POST': request.session['myid'] = request.POST['myid'] myid = request.POST['myid'] try: recd = stu.objects.get(id=myid) return redirect('/edit02/') except: message01 = '這個id不存在' return render(request,'edit01.html',locals()) _(B).在views.py建立edit02函數(顯示所有資料,修改後,再回存) ☎注意:查詢資料表後,顯示某個欄位的方法是:recd.欄位名稱 recd = stu.objects.get(id=myid) myname = recd.cname ☎注意:修改資料表的語法 #先查詢某筆資料 recd = stu.objects.get(id=myid) #直接把表單post傳遞來的值覆蓋在recd上 recd.cname = request.POST['myname'] #存檔recd,就是修改了 recd.save() ☎注意:修改顯示日期2019年9月19日,改成2019-9-19格式(修改後才不會出現錯誤) 方法:str(recd.cbirthday).replace('年','-').replace('月','-').replace('日','-') 程式碼: def edit02(request): #顯示資料表尚未修改前的數據 myid = request.session['myid'] recd = stu.objects.get(id=myid) myname = recd.cname mysex = recd.csex #修改顯示日期2019年9月19日,改成2019-9-19格式 mybirthday = str(recd.cbirthday).replace('年','-').replace('月','-').replace('日','-') mymail = recd.cmail mytel = recd.ctel myaddress = recd.caddress if request.method=='POST': #若是經由POST傳來,表示已經被修改了 #修改資料表寫法(先查到改變,再覆蓋值) recd = stu.objects.get(id=myid) recd.cname = request.POST['myname'] recd.csex = request.POST['mysex'] recd.cbirthday = request.POST['mybirthday'] recd.cmail = request.POST['mymail'] recd.ctel = request.POST['mytel'] recd.caddress = request.POST['myaddress'] recd.save() #修改完畢 return redirect('/show_all/') return render(request,'edit02.html',locals()) _(C).在urls.py建立網址設定公式、 程式碼: from app01.views import form1,show_all,add01,add02,del01,edit01,edit02 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$', form1), url(r'^form1/$', form1), url(r'^show_all/$', show_all), url(r'^add01/$', add01), url(r'^add02/$', add02), url(r'^del01/$', del01), url(r'^edit01/$', edit01), url(r'^edit02/$', edit02), ] _(D).建立模板網頁edit01.html(指定編號資料) 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>修改一筆資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="post" name="myform" action="."> {% csrf_token %} 輸入想修改的編號=<input type="text" name='myid' /> <br/> <input type="submit" value="確定" /> </form> <p style="color: magenta">{{message01}}</p> {% endblock %} _(E).建立模板網頁edit02.html(顯示所有資料,修改後,再回存) ☎在input顯示主機傳來的資料:value="{{ myname }}" <input type="text" name='myname' value="{{ myname }}" /> 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>修改一筆資料,資料不作驗證</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="post" name="myform" action="."> {% csrf_token %} 姓名=<input type="text" name='myname' value="{{ myname }}" /> <br/> 性別=<input type="text" placeholder="男" name='mysex' value="{{ mysex }}" /> <br/> 生日=<input type="text" placeholder="2019-9-2" name='mybirthday' value="{{ mybirthday }}" /> <br/> 郵件=<input type="text" placeholder="abc@gmail.com" name='mymail' value="{{ mymail }}" /> <br/> 電話=<input type="text" name='mytel' value="{{ mytel }}" /> <br/> 住址=<input type="text" name='myaddress' value="{{ myaddress }}" /> <br/> <input type="submit" value="修改" /> </form> <p style="color: magenta">{{message01}}</p> {% endblock %} 結果: |
||||
3.網頁表單使用get傳遞變數,有三種方法 |
3.網頁表單使用get傳遞變數 (1).網頁表單使用get傳遞變數,有三種方法: ☎方法1:需要form表單,在action指定雙層參數 <form method="get" name="myform" action="/add03/save/"> #在view.py def add03(request,mode=None): if mode == 'save': myname = str(request.GET.get('myname')) ☎方法2:需要form表單 <form method="get" name="myform" action=""> <input type="submit" value="送出" name='submitButton' /> #在view.py def add04(request): if request.GET.get('submitButton') =='送出': myname = request.GET.get('myname') ☎方法3:不需要form表單,直接超連結 <a href='/del05/?myid={{item.id}}'>刪除</a> <a href='/del05/?myid=2'>刪除</a> |
||||
範例:exp04_06.py表單使用get傳遞,方法一 |
(2).☎範例:exp04_06.py(表單使用get傳遞,方法一) ☎#目的:新增一筆記錄,但是表單使用get傳遞 _(A).修改:show_all.html <h2>顯示全部學生資料: <a href='/add01/'>新增一筆(不驗證)</a> <a href='/add02/'>新增一筆(驗證)</a> <a href='/del01/'>刪除</a> <a href='/edit01/'>修改</a> <a href='/add03/'>新增(get方法)</a> </h2> _(A).在view.py建立add03函數(表單使用get傳遞,方法一) ☎注意:兩種GET接收變數的方法: #若是由form傳來get變數:request.GET['pagebtn'] #若是由網址?pagebtn=..傳來的get變數:request.GET.get('pagebtn') ☎注意:接收get變數的方法:request.GET.get('myname') 例如:myname = str(request.GET.get('myname')) ☎注意:get變數的型態不是字串,還要用str(...)轉換 ☎注意:無法用if request.method == 'GET'來判別是否是get的表單按鈕submit傳遞來的 原因:因為只要是網頁傳遞來的,預設就是用get模式(可能是網址後?id=b0001傳來的) 所以若是用if request.method == 'GET'來判別,任何網頁的呼叫(除了post外)都會符合 ☎解決方法:如何才能判別是真的由get表單按了submit傳遞來的 方法:action使用雙參數:action="/add03/save/" #模板: <form method="get" name="myform" action="/add03/save/"> #視圖view def add03(request,mode=None): if mode == 'save': views.py程式碼: #使用get方法傳遞,新增一筆 def add03(request,mode=None): #因為網頁預設就是GET方法,所以雖然沒有按submit,也是用get方法,所以不能用request.method == 'GET'來判別是否按了submit #改良方法:用第二個參數mode #if request.method == 'GET': if mode == 'save': myname = str(request.GET.get('myname')) mysex = str(request.GET.get('mysex')) mybirthday = str(request.GET.get('mybirthday')) mymail = str(request.GET.get('mymail')) mytel = str(request.GET.get('mytel')) myaddress = str(request.GET.get('myaddress')) #新增一筆記錄 recd = stu.objects.create(cname=myname,csex=mysex,cbirthday=mybirthday,cmail=mymail,ctel=mytel,caddress=myaddress) recd.save() return redirect('/show_all/') else: message01 = '請輸入資料(資料不作驗證)' return render(request,'add03.html',locals()) _(C).在urls.py建立網址設定公式、 程式碼: from app01.views import form1,show_all,add01,add02,del01,edit01,edit02,add03 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$', form1), url(r'^form1/$', form1), url(r'^show_all/$', show_all), url(r'^add01/$', add01), url(r'^add02/$', add02), url(r'^del01/$', del01), url(r'^edit01/$', edit01), url(r'^edit02/$', edit02), url(r'^add03/$', add03), url(r'^add03/(\w+)/$', add03), ] _(D).建立模板網頁add03.html 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>新增一筆資料,資料不作驗證</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="get" name="myform" action="/add03/save/"> {% csrf_token %} 姓名=<input type="text" name='myname' /> <br/> 性別=<input type="text" placeholder="男" name='mysex' /> <br/> 生日=<input type="text" placeholder="2019-9-2" name='mybirthday' /> <br/> 郵件=<input type="text" placeholder="abc@gmail.com" name='mymail' /> <br/> 電話=<input type="text" name='mytel' /> <br/> 住址=<input type="text" name='myaddress' /> <br/> <input type="submit" value="送出" /> <input type="reset" value="重設" /> </form> <p style="color: magenta">{{message01}}</p> {% endblock %} |
||||
範例:exp04_07.py表單使用get傳遞,方法二 |
(3).☎範例:exp04_07.py(表單使用get傳遞,方法二) ☎#目的:新增一筆記錄,但是表單使用get傳遞 _(A).修改:show_all.html <h2>顯示全部學生資料: <a href='/add01/'>新增一筆(不驗證)</a> <a href='/add02/'>新增一筆(驗證)</a> <a href='/del01/'>刪除</a> <a href='/edit01/'>修改</a> <a href='/add03/'>新增(get方法一)</a> <a href='/add04/'>新增(get方法二)</a> </h2> _(A).在views.py建立add04函數(表單使用get傳遞,方法二) ☎如何才能判別是真的由get表單按了submit傳遞來的 方法:type="submit" 設定雙參數: value="送出" name='submitButton' #模板: <input type="submit" value="送出" name='submitButton' /> #視圖view if request.GET.get('submitButton') =='送出' 程式碼: #使用get方法傳遞,新增一筆 def add04(request): if request.GET.get('submitButton') =='送出': myname = request.GET.get('myname') myname = str(request.GET.get('myname')) mysex = str(request.GET.get('mysex')) mybirthday = str(request.GET.get('mybirthday')) mymail = str(request.GET.get('mymail')) mytel = str(request.GET.get('mytel')) myaddress = str(request.GET.get('myaddress')) #新增一筆記錄 recd = stu.objects.create(cname=myname,csex=mysex,cbirthday=mybirthday,cmail=mymail,ctel=mytel,caddress=myaddress) recd.save() return redirect('/show_all/') else: message01 = '請輸入資料(資料不作驗證)' return render(request,'add04.html',locals()) _(C).在urls.py建立網址設定公式、 程式碼: from app01.views import form1,show_all,add01,add02,del01,edit01,edit02,add03 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$', form1), url(r'^form1/$', form1), url(r'^show_all/$', show_all), url(r'^add01/$', add01), url(r'^add02/$', add02), url(r'^del01/$', del01), url(r'^edit01/$', edit01), url(r'^edit02/$', edit02), url(r'^add03/$', add03), url(r'^add03/(\w+)/$', add03), url(r'^add04/$', add04), ] _(D).建立模板網頁add04.html 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>新增一筆資料,資料不作驗證</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="get" name="myform" action=""> {% csrf_token %} 姓名=<input type="text" id='myname' name='myname' /> <br/> 性別=<input type="text" placeholder="男" name='mysex' /> <br/> 生日=<input type="text" placeholder="2019-9-2" name='mybirthday' /> <br/> 郵件=<input type="text" placeholder="abc@gmail.com" name='mymail' /> <br/> 電話=<input type="text" name='mytel' /> <br/> 住址=<input type="text" name='myaddress' /> <br/> <input type="submit" value="送出" name='submitButton' /> </form> <p style="color: magenta">{{message01}}</p> {% endblock %} |
||||
範例:exp04_08.py整合性表單,使用get傳遞,方法三 |
(4).☎範例:exp04_08.py(整合性表單,使用get傳遞,方法三) ☎#目的:新增一筆記錄,但是表單使用get傳遞 _(A).建立:show_all_05.html ☎重點:如何才能使用get(?myid=2)傳遞這一行的myid:href='/del05/?myid={{item.id}}' <a href='/del05/?myid={{item.id}}'>刪除</a> ☎重點:而且這種?myid=...的方法,不需要放在form表單裡面 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>顯示所有學生資料</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <h2>顯示全部學生資料: <a href='/add01/'>新增一筆(不驗證)</a> <a href='/add02/'>新增一筆(驗證)</a> </h2> <table border="1" cellsapcings='0' cellpadding='0'> <th>編號</th><th>姓名</th><th>性別</th><th>生日</th><th>郵件</th><th>電話</th><th>住址</th><th>刪除</th><th>編輯</th> {% for item in items %} <tr> <td>{{item.id}}</td> <td>{{item.cname}}</td> <td>{{item.csex}}</td> <td>{{item.cbirthday}}</td> <td>{{item.cmail}}</td> <td>{{item.ctel}}</td> <td>{{item.caddress}}</td> <td><a href='/del05/?myid={{item.id}}'>刪除</a></td> <td><a href='/edit05/?myid={{item.id}}'>編輯</a></td> </tr> {% endfor %} </table> {% endblock %} _(B).在views.py建立add04函數(整合性表單,使用get傳遞,方法三) ☎接收get變數的兩種方法: ☎注意:兩種GET接收變數的方法: #若是由form傳來get變數:request.GET['pagebtn'] #若是由網址?pagebtn=..傳來的get變數:request.GET.get('pagebtn') 方法1: myid = request.GET.get('myid') 方法2: myid = request.GET['myid'] ☎接收post變數的方法: myid = request.POST['myid'] 程式碼: def del05(request): if request.method=="GET": #兩種get取值方法都可以 myid = request.GET.get('myid') #myid = request.GET['myid'] message01 = myid recd = stu.objects.get(id=myid) recd.delete() return redirect('/show_all05/') def edit05(request): if request.method=="GET": #顯示資料表尚未修改前的數據 myid = request.GET['myid'] recd = stu.objects.get(id=myid) myname = recd.cname mysex = recd.csex #修改顯示日期2019年9月19日,改成2019-9-19格式 mybirthday = str(recd.cbirthday).replace('年','-').replace('月','-').replace('日','-') mymail = recd.cmail mytel = recd.ctel myaddress = recd.caddress return render(request,'edit05.html',locals()) elif request.method=='POST': #若是經由POST傳來,表示已經被修改了 #修改資料表寫法(先查到改變,再覆蓋值) myid = request.POST['myid'] recd = stu.objects.get(id=myid) recd.cname = request.POST['myname'] recd.csex = request.POST['mysex'] recd.cbirthday = request.POST['mybirthday'] recd.cmail = request.POST['mymail'] recd.ctel = request.POST['mytel'] recd.caddress = request.POST['myaddress'] recd.save() #修改完畢 return redirect('/show_all05/') _(C).在urls.py建立網址設定公式、 程式碼: from app01.views import form1,show_all,add01,add02,del01,edit01,edit02,add03,add04,show_all05,del05,edit05 urlpatterns = [ path('admin/', admin.site.urls), .......... url(r'^show_all05/$', show_all05), url(r'^del05/$', del05), url(r'^edit05/$', edit05), ] _(D).建立:edit05.html ☎重點:要建立編號欄位(因為要接收post變數myid) 編號=<input type="text" name='myid' readonly value="{{ myid }}" /> 程式碼: {% extends 'base.html' %} {% block title %} <TITLE>修改一筆資料,資料不作驗證</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="post" name="myform" action="."> {% csrf_token %} 編號=<input type="text" name='myid' readonly value="{{ myid }}" /> <br/> 姓名=<input type="text" name='myname' value="{{ myname }}" /> <br/> 性別=<input type="text" placeholder="男" name='mysex' value="{{ mysex }}" /> <br/> 生日=<input type="text" placeholder="2019-9-2" name='mybirthday' value="{{ mybirthday }}" /> <br/> 郵件=<input type="text" placeholder="abc@gmail.com" name='mymail' value="{{ mymail }}" /> <br/> 電話=<input type="text" name='mytel' value="{{ mytel }}" /> <br/> 住址=<input type="text" name='myaddress' value="{{ myaddress }}" /> <br/> <input type="submit" value="修改" /> </form> <p style="color: magenta">{{message01}}</p> {% endblock %} |
||||
chp5. Session 與 Cookie | |||||
下載 |
下載本章project成果 | ||||
目錄 | 為什麼要有Session 與 Cookie | Session | exp05-01設定session變數,取出變數 | exp05-02判斷會員是否已經登入 | |
設定session的期限三種方法 | exp05-03設定session,刪除session | exp05-04登入帳號密碼後記錄session,登出後刪除 | Cookie | exp05-05用cookie顯示瀏覽本頁人數 | |
1.為什麼要有Session 與 Cookie |
1.為什麼要有Session 與 Cookie |
||||
2.Session |
2.Session |
||||
exp05-01.py設定session變數,取出變數 |
(4).範例:exp05-01.py(設定session變數,取出session變數) |
||||
exp05-02判斷會員是否已經登入 |
(5).範例:exp05-02.py(判斷會員是否已經登入了) (A).在views.py設定函數 ☎重點:如何判別在session裡面有沒有這個變數login if not "login" in request.session: 程式碼: def isMember(request): if not "login" in request.session: request.session['login'] = True return HttpResponse('會員現在登入') else: return HttpResponse('會員已經在線上') (B).在urls.py設定 from app01.views import setS,getS,isMember urlpatterns = [ path('admin/', admin.site.urls), ..... url(r'^isMember/$',isMember), ] (C).測試:http://127.0.0.1:8000/isMember/ |
||||
設定session的期限,刪除session的方法 |
(6).設定session的期限,刪除session的方法 (A).設定session的時限:方法一(在views.py函式內) 指令:request.session.set_expiry(n*60) n分鐘 (B).設定session的時限:方法二(在settings.py函式內) SESSION_COOKIE_AGE = 1440 (24分鐘 = 24 × 60 = 1440 秒) (C).設定關閉瀏覽器後,session自動消失(在settings.py函式內) SESSION_EXPIRE_AT_BROWSER_CLOSE = True (預設是False,關閉後還是會存在) (D).關閉指定名稱session(在views.py函式內) del request.session[名稱] (E).關閉所有的session(在views.py函式內) request.session.clear() |
||||
exp05-03.py設定session的時間,刪除session |
(7).範例:exp05-03.py(設定session的時間,刪除session) (A).在views.py設定函數 def setStime(request): if 'myname' in request.session: request.session.set_expiry(60*60) #60分鐘 return HttpResponse('已經設定session變數:myname有效時間為:60分鐘' ) else: return HttpResponse('沒有這個session變數:myname ') def delS(request): #刪除myname #del request.session['myname'] #刪除全部的session request.session.clear() return HttpResponse('已經清除全部的session變數') (B).在urls.py設定 from app01.views import setS,getS,isMember,setStime,delS urlpatterns = [ path('admin/', admin.site.urls), ..... url(r'^setStime/$',setStime), url(r'^delS/$',delS), ] (C).測試:http://127.0.0.1:8000/setStime/ 測試:http://127.0.0.1:8000/delS/ (D).在Chrome開發者工具,觀看session變數(發現都不見了) F12 Appplication Storage -> Cookies -> http://127.0.0.1:8000 |
||||
exp05-04.py登入帳號密碼後記錄session,登出後刪除 |
(3).範例:exp05-04.py(登入帳號密碼後記錄session,登出後刪除session) (A).在views.py設定函數 程式碼: def login(request): if request.method == "POST": if not 'username' in request.session: if request.POST['myname'] == 'john' and request.POST['mypw'] == 'john': request.session['username'] = request.POST['myname'] request.session['password'] = request.POST['mypw'] login = True message = '歡迎光臨,' + request.session['username'] + '你登入了' else: message = '帳號密碼錯誤!' else: login = True message = request.session['username'] + ',你已經在線上了' return render(request,'login.html',locals()) def logout(request): if 'username' in request.session: login = False message = '再見,' + request.session['username'] + ',你登出了' del request.session['username'] del request.session['password'] return render(request,'login.html',locals()) (B).在urls.py設定 from app01.views import setS,getS,isMember,setStime,delS,login,logout urlpatterns = [ path('admin/', admin.site.urls), ..... url(r'^login/$',login), url(r'^logout/$',logout), ] (C).在模板建立login.html ☎注意:用if else 來顯示登入,與登出畫面 {% extends 'base.html' %} {% block title %} <TITLE>會員登入</TITLE> <META content="text/html; charset=utf-8" http-equiv=Content-Type> {% endblock %} {% block content %} <form method="post" name="myform" action="."> {% csrf_token %} {% if login == True %} <a href='/logout/'>登出系統</a> {% else %} 會員帳號:<input type="text" name='myname' /> <br/> 會員密碼:<input type="text" name='mypw' /> <br/> <input type="submit" value="登入" /> {% endif %} </form> <p style="color: magenta">{{message}}</p> {% endblock %} (D).測試:http://127.0.0.1:8000/login/ |
||||
3. Cookie |
3. Cookie (1).特色與限制: A.若關閉瀏覽器,cookie還是繼續保存資料 B.可以設定cookie的保存期限 C.每個瀏覽器只能使用300個 cookie D.每個瀏覽器只能對同一個伺服器存取20個 cookie E.每個cookie的大小,只有4k Bytes F.cookie資料被儲存在電腦內,所以容易被分析而竊取。 (2).存取cookie變數方法:(用字典方式存取) A.設定cookie變數 response.set_cookie(變數,值,max_age = None,expires=None) 例如: from django.http import HttpResponse response = HttpResponse('newcookie01') response.set_cookie('username','john') response.set_cookie('username','john',max_age=3600) #一個小時=3600秒 max_age = 秒數 expires = 某日的日期時間 B.讀進cookie變數 變數 = request.COOKIES[變數] 例如: myname = request.COOKIES['username'] (3).設定cookie的期限,刪除cookie的方法 (A).設定cookie的時限:(在views.py函式內) response.set_cookie(變數,值,max_age = None,expires=None) max_age = 秒數 expires = 某日的日期時間 例如:response.set_cookie('username','john',max_age=3600) #一個小時=3600秒 (D).刪除指定名稱cookie(在views.py函式內) delete_cookie(名稱) 例如: from django.http import HttpResponse response = HttpResponse('newcookie01') response.delete_cookie(名稱) |
||||
exp05-05.py使用cookie顯示目前瀏覽本頁人數 |
(4).範例:exp05-05.py(使用cookie來顯示目前瀏覽本頁人數) (A).在views.py設定函數 ☎注意:判別num變數是否在COOIES裡面:if 'num' in request.COOKIES: ☎注意:讀取目前的COOIES變數num:int(request.COOKIES['num']) ☎注意:設定目前最新的COOIES變數num: rsp = HttpResponse('網頁瀏覽人數 = '+ str(num)) rsp.set_cookie('num',num) 程式碼: def shownum(request): if 'num' in request.COOKIES: num = int(request.COOKIES['num']) num += 1 else: num = 1 rsp = HttpResponse('網頁瀏覽人數 = '+ str(num)) rsp.set_cookie('num',num) return rsp (B).在urls.py設定 from app01.views import setS,getS,isMember,setStime,delS,login,logout,shownum urlpatterns = [ path('admin/', admin.site.urls), ...... url(r'^shownum/$',shownum), ] |
||||
chp6. 會員管理套件(auth套件) | |||||
下載 |
下載本章project成果 | ||||
目錄 | 設定會員資料管理套件auth | 建立會員資料auth | exp06-01顯示所有會員的名稱 | exp06-02查詢john會員是否存在 | |
寫程式新增一筆使用者User | exp06-03新增一筆使用者User | 使用者資料表user來進行登入登出 | exp06-04使用者資料表user來進行登入登出 | ||
設定會員資料管理套件auth |
1.設定會員資料管理套件(auth) |
||||
建立會員資料auth |
2.建立會員資料(auth) |
||||
exp06-01顯示所有會員的名稱 |
(3).範例:exp06-01.py(顯示所有會員的名稱) |
||||
exp06-02查詢john會員是否存在 |
(4).範例:exp06-02.py(查詢john會員是否存在) (A).在views.py設定函數 from django.contrib.auth.models import User from django.http import HttpResponse def find(request): try: a1 = User.objects.get(username='john') return HttpResponse('找到john') except: a1 = None return HttpResponse('查無此人') (B).在urls.py設定 from django.conf.urls import url from app01.views import showall urlpatterns = [ path('admin/', admin.site.urls), url(r'^find/$',find), ] 測試:http://127.0.0.1:8000/find/ |
||||
寫程式新增一筆使用者User |
(5).寫程式新增一筆使用者User A.語法: ☎新增一筆的會員宗利 from django.contrib.auth.models import User a2 = User.objects.create_user('姓名','郵件','密碼') a2.first_name = '名字' a2.last_name = '姓' a2.is_staff = True a2.save() ☎切換網頁 from django.shortcuts import redirect return redirect('/函式/') |
||||
exp06-03.py新增一筆使用者User |
(6).範例:exp06-03.py(新增一筆使用者User) (A).在views.py設定函數 程式碼: from django.contrib.auth.models import User from django.http import HttpResponse from django.shortcuts import redirect def add(request): #要新增一筆:tom #先判別是否已經存在資料表內 try: a1 = User.objects.get(username='mike') except: a1 = None #若無,則新增一筆 if a1==None: a2 = User.objects.create_user('mike','mike@gmail.com','mike963852') a2.first_name = '麥克' a2.last_name = '李' a2.is_staff = True a2.save() return redirect('/showall/') else: return HttpResponse('mike 已經存在') (B).在urls.py設定 from django.conf.urls import url from app01.views import showall,find,add urlpatterns = [ path('admin/', admin.site.urls), url(r'^showall/$',showall), url(r'^find/$',find), url(r'^add/$',add), ] 測試:http://127.0.0.1:8000/add/ |
||||
使用者資料表user來進行登入,登出 |
3.使用者資料表(user)來進行登入,登出 (1).進行登入登出,要做的動作 A.登入時,要先進行會員驗證 from django.contrib.auth import authenticate from django.contrib import auth 方法:user = auth.authenticate(username=帳號, password=密碼) B.判別是否通過驗證 方法:if request.user.is_authenticated == True #通過驗證 C.判別是否為通過驗證,且為有效成員(帳號已經啟用) 方法:if user.is_active == True #通過驗證,且帳號已經啟用 ☎範例:驗證是否是user資料表成員 a1 = auth.authenticate(username=myname,password=mypw) #判別是否為有效成員,且通過驗證 if a1 is not None: if a1.is_active: ☎重點:若是沒有該成員,則a1 = None ☎重點:若是有該成員(通過驗證),且帳號已經啟用,則a1 = True ☎重點:若是有該成員(通過驗證),但帳號還沒開始啟用,則a1 = False D.成員登入系統 from django.contrib.auth import authenticate from django.contrib import auth 方法:auth.login(request,user) E.成員登出系統 方法:auth.logout(request) |
||||
exp06-04使用者資料表user來進行登入,登出 |
(2).範例:exp06-04.py(使用者資料表(user)來進行登入,登出) (A).在views.py設定函數 ☎重點:驗證是否是user資料表成員 a1 = auth.authenticate(username=myname,password=mypw) #判別是否為有效成員,且通過驗證 if a1 is not None: if a1.is_active: ☎重點:若是沒有該成員,則a1 = None ☎重點:若是有該成員,且通過驗證,則a1 = True ☎重點:若是有該成員,但沒有通過驗證,則a1 = False ☎注意:切換網頁,有兩種方法(都可以把變數傳遞過去) 方法一:return redirect('/index/') 方法二:return render(request,'index.html',locals()) ☎注意:但是return redirect('網頁A'),網頁A不可以說目前自己網頁 程式碼:views.py from django.contrib.auth.models import User from django.http import HttpResponse from django.shortcuts import redirect def login(request): mylogin = False if request.method =='POST': myname = request.POST['myname'] mypw = request.POST['mypw'] #驗證是否是user資料表成員 a1 = auth.authenticate(username=myname,password=mypw) #判別是否為有效成員,且通過驗證 if a1 is not None: if a1.is_active: auth.login(request,a1) message = '已經成功登入' return redirect('/index/') #return render(request,'index.html',locals()) else: message = '帳號還沒有開始啟用' else: message = '沒有這個帳號' return render(request,'login.html',locals()) #return redirect('/login/') def logout(request): auth.logout(request) #return render(request,'index.html',locals()) return redirect('/index/') (B).在urls.py設定 from django.conf.urls import url from app01.views import showall,find,add,index,login,logout urlpatterns = [ path('admin/', admin.site.urls), ..... url(r'^login/$',login), url(r'^logout/$',logout), (C).首頁index.html ☎重點:在模板要判別是否通過驗證 {% if request.user.is_authenticated == False %} 程式碼: <!DOCTYPE html> <htm> <head> <meta http-equiv="Content-Type" content="text/html" charset="utf-8"> <title>首頁</title> </head> <bod> {% csrf_token %} <h1>淘寶網首頁</h1> {% if request.user.is_authenticated == False %} <p>你尚未登入</p> <p></p><a href="/login/">登入</a></p> {% else %} <p></p><a href="/logout/">登出</a></p> {% endif %} <p></p> <p style="color: palevioletred">{{ message }}</p> </body> </htm> (D).登入頁login.html <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html" charset="utf-8"> <title>登入頁</title> </head> <body> <form action="" method="post" name='myform'> {% csrf_token %} <p>輸入帳號:<input type="text" name="myname" ></p> <p>輸入密碼:<input type="text" name="mypw" ></p> <p><input type="submit" name="mysubmit" value="登入" ></p> </form> <p style="color: palevioletred">{{ message }}</p> </body> </html> |
||||
Chp7.新聞公告系統 | |||||
下載 |
下載本章project成果 | ||||
目錄 | 前置作業 | 下載已經建立好的網頁模板:templates,static | 瀏覽或修改既有舊的sqlite資料庫 | exp07-01顯示NEWSAPP_NEWSUNIT資料表所有資料 | |
資料表共13中查詢(ORM查詢) | 資料表的三種常用查詢 | 三種常用查詢:filter、exclude、get | 資料表查詢 vs 排除查詢:比較filter(),exclude() | ||
資料表的排序:order_by() | 顯示某個欄位的全部筆數(消除重複資料) | 限制查詢結果的筆數數目與起始筆(適用分頁) | 資料表的精確查詢 vs 關鍵字查詢 | ||
查詢第一筆,最後一筆記錄 | 連表查詢 | 複雜查詢:Q查询 | exp07-02讀取新聞資料庫,一頁顯示8筆,上下頁瀏覽 | ||
exp07-03完整新聞發布系統:可會員登入,可編輯,新增,刪除新聞 | |||||
1.前置作業 |
1.前置作業 |
||||
下載已經建立好的網頁模板:templates,static |
2.下載已經建立好的網頁模板:templates,static |
||||
瀏覽或修改既有舊的sqlite資料庫 |
4.如何瀏覽,或修改既有舊的sqlite資料庫 |
||||
exp07-01顯示NEWSAPP_NEWSUNIT資料表所有資料 |
8.自行撰寫程式,讀取外來資料庫 (1).範例:exp07-01.py(顯示NEWSAPP_NEWSUNIT資料表所有資料,並可以編輯修改) (A).在views.py設定函數 ☎注意:欄位名稱在admin裡面顯示都會是以大寫開頭(Title),但是實際欄位卻是title views.py程式碼: from django.shortcuts import redirect from app01.models import NewsappNewsunit as news def showall(request): items = news.objects.all() return render(request,'showall.html',locals()) def edit(request): if request.method=='POST': id = request.POST['id'] recd = news.objects.get(id=id) recd.title = request.POST['title'] recd.catego = request.POST['catego'] recd.message = request.POST['message'] recd.nickname = request.POST['nickname'] recd.press = request.POST['press'] try: recd.save() return redirect('/showall/') except: message01 = '修改資料發生錯誤' return render(request,'edit.html',locals()) #return redirect('/showall/') elif request.method=='GET': myid = request.GET['id'] items = news.objects.get(id=myid) id = items.id title = items.title catego = items.catego message = items.message nickname = items.nickname press = items.press return render(request,'edit.html',locals()) (B).在urls.py設定 from app01.views import index,showall,edit urlpatterns = [ path('admin/', admin.site.urls), url(r'^$',index), url(r'^showall/$',showall), url(r'^edit/$',edit), ] (C).顯示全部資料網頁showall.html {% extends 'base.html' %} {% block title %} <title>顯示所有新聞</title> {% endblock %} {% block content %} <h1>新聞列表</h1> {% csrf_token %} <table border='1' cellsapcing='0' cellpadding='0' > <th>標題</th><th>分類</th><th>訊息</th><th>發表者</th><th>點閱</th><th>修改</th><th>刪除</th> {% for item in items %} <tr> <td>{{item.title}}</td> <td>{{item.catego}}</td> <td>{{item.message}}</td> <td>{{item.nickname}}</td> <td>{{item.press}}</td> <td><a href='/edit/?id={{item.id}}'>編輯</a></td> <td><a href='/del/?id={{item.id}}'>刪除</a></td> </tr> {% endfor %} </table> <p style="color: magenta">{{message01}}</p> {% endblock %} (D).編輯一筆資料網頁edit.html {% extends 'base.html' %} {% block title %} <title>修改資料</title> {% endblock %} {% block content %} <h1>修改新聞資料</h1> <form name='myform' action="" method="POST"> {% csrf_token %} <table border='1' cellsapcing='0' cellpadding='0' > <tr> <td>編號</td><td><input type="text" name='id' readonly value="{{id}}"></td> </tr> <tr> <td>標題</td><td><input type="text" name='title' value="{{title}}"></td> </tr> <tr> <td>分類</td><td><input type="text" name='catego' value="{{catego}}"></td> </tr> <tr> <td>訊息</td><td><input type="text" name='message' value="{{message}}"></td> </tr> <tr> <td>發表者</td><td><input type="text" name='nickname' value="{{nickname}}"></td> </tr> <tr> <td>點閱</td><td><input type="text" name='press' value="{{press}}"></td> </tr> </table> <p></p> <input type="submit" name='bnt1' value="確認修改"> <p></p> <p style="color: magenta">{{message01}}</p> </form> {% endblock %} |
||||
資料表共13中查詢(ORM查詢) |
9.資料表共13中查詢(ORM查詢) 一,傳統的資料庫查詢語法:SQL查詢語法 二,Django的查詢稱為:ORM查詢,有13種查詢 (1).all(): 查詢所有結果 (2).filter(**kwargs): 它包含了與所給篩選條件相匹配的物件 (3).get(**kwargs): 返回與所給篩選條件相匹配的物件,返回結果有且只有一個,如果符合篩選條件的物件超過一個或者沒有都會丟擲錯誤。 (4).exclude(**kwargs): 它包含了與所給篩選條件不匹配的物件 (5).values(*field): 返回一個ValueQuerySet——一個特殊的QuerySet,執行後得到的並不是一系列model的例項化物件,而是一個可反覆運算的字典序列 (6).values_list(*field): 它與values()非常相似,它返回的是一個元組序列,values返回的是一個字典序列 (7).order_by(*field): 對查詢結果排序 (8).reverse(): 對查詢結果反向排序,請注意reverse()通常只能在具有已定義順序的QuerySet上呼叫(在model類的Meta中指定ordering或呼叫order_by()方法)。 (9).distinct(): 從返回結果中剔除重複紀錄(如果你查詢跨越多個表,可能在計算QuerySet時得到重複的結果。此時可以使用distinct(),注意只有在PostgreSQL中支援按欄位去重。) (10).count(): 返回資料庫中匹配查詢(QuerySet)的物件數量。 (11).first(): 返回第一條記錄 (12).last(): 返回最後一條記錄 (13).exists(): 如果QuerySet包含資料,就返回True,否則返回False 三,何謂ORM,Object Relational Mapping = 物件關聯對映 ORM,英文錯誤 Object Relational Mapping, 中文稱為:物件關聯對映。 ORM 在網站開發結構中,是在『資料庫』和『 Model 資料容器』兩者之間,將關聯式資料庫映射至物件導向的資料抽象化技術 簡單來說,它是一個幫助使用者更簡便、安全的去從資料庫讀取資料, 其理念是將資料庫的內容映射為物件,讓程式開發人員可以用操作物件的方式對資料庫進行操作,而不直接使用SQL語法對資料庫進行操作 因為 ORM 的一個特性為: 透過程式語言(Ruby, Java),去操作資料庫語言( SQL )。 而這也是實作了物件導向的概念,產生的一種工具模式 四,ORM的優缺點 (1).優點 _(A).安全性:有一種常見的網路攻擊叫做 SQL 注入( SQL injection ),就是駭客在傳輸到網站伺服器裡的資料直接寫 SQL , _(B).簡化性:程式碼簡單 _(C).通用性:網站未來有資料庫轉移的問題,也比較不會遇到需要改寫程式的狀況。因為不同的資料庫間,SQL 語句的語法也會稍有差異, 例如:比較下麵 MySQL 和 MsSQL 做兩件同樣事 // MySQL SELECT * FROM TestTable WHERE id=12 LIMIT 10 // MsSQL SELECT TOP 10 * FROM TestTable WHERE id=12 這兩個程式碼都要做同一件事,可是寫法會有所不同, 但是使用 ORM 就比較不會有這個狀況, (2).缺點 _(A).效能差:當ORM達成了方便性,通常都會犧牲到效能的問題, _(B).學習曲線高 _(C).複雜查詢維護性低:目前若是簡單的查詢,ORM還能完成,但是對於複雜的查詢,ORM 的使用上就較為力不從心。 |
||||
資料表的三種常用查詢 |
10.資料表的三種常用查詢:(比較get(),filter()的差別) (1).三種方法: 方法1:items = news.objects.all(),顯示所有資料列表list 方法2:items = news.objects.filter(name='john'),查詢結果也是list(結果可是多個:ltems[0], itmes[1],...) 方法3:items = news.objects.get(name='john'),(結果只能唯一的一個:ltems),但若是查不到會報錯,所以要用try..except (2).方法1:items = news.objects.all(),顯示所有資料列表list 查詢結果有多個::ltems[0], itmes[1],... 若是沒有資料,不會報錯 所以使用news.objects.all(),不用配合try...except... 例如: def show_all(request): items = student.objects.all().order_by('-id') return render(request,'show_all.html',locals()) (3).方法2:items = news.objects.filter(name='john') 查詢結果也是list 所以結果可是多個:ltems[0], itmes[1],... 若是沒有資料,不會報錯 所以使用news.objects.filter(...),不用配合try...except... 例如: objs = MyModel.objects.filter(id=1) if len(objs) == 1: obj = objs[0] else: message = '沒有找到資料' (4).方法3:items = news.objects.get(name='john'), ☎結果只能唯一的一個:ltems, ☎但若是查不到會報錯,所以.get(..)一定要配合用try..except ☎應用:因為刪除(delete)資料表,修改(update)資料表,都要配合objects.get(id=..)先查詢,然後在delete(),或是save()修改, 所以刪除(delete)資料表,修改(update)資料表,在使用.get()時,也要配合配合try...except... 例如:查詢 def show_one(request): #讀取一筆資料:cname =張三 try: item = student.objects.get(cname='張三') except Exception as e: errormsg = '讀取資料出現錯誤:' + e return render(request,'show_one.html',locals()) 例如:刪除 recd = stu.objects.get(編號=myid) recd.delete() 例如:修改 recd = stu.objects.get(id=myid) recd.cname = request.POST['myname'] recd.save() |
||||
三種常用查詢:filter、exclude、get |
12.三種常用查詢:filter、exclude、get
(1).在Django中,查詢一般就是使用filter、exclude、get三個方法來實現 (2).在mysql中,想要查詢數據,就需要使用where關鍵字加上字段條件去查詢, (3).在Django的orm之中,查詢經常使用filter、exclude、get關鍵詞加上field+__+condition作為關鍵詞去查詢 |
||||
資料表查詢 vs 排除查詢:比較filter(),exclude() |
13.資料表查詢 vs 排除查詢:(比較filter(),exclude()) (1).filter表示=,exclude表示 != (2).查詢:filter(**kwargs) 可以根據代入的參數來決定輸出的物件。 例如: objs = MyModel.objects.filter(id=1) if len(objs) == 1: obj = objs[0] else: message = '沒有找到資料' (3).排除查詢:exclude(**kwargs) 輸出排除輸入的參數以外的物件。 例如:sut.objects.filter(name='john') => 列出名稱為john的 物件 例如:stu.objects.exclude(name='john') => 列出名稱為非john的物件 |
||||
資料表的排序:order_by() |
14.資料表的排序:order_by() (1).語法:order_by('a','b','c'...) 將搜尋出來的QuerySet利用order_by的順序再次排序。 例如: stu.objects.filter(sex='M').order_by('-height', 'name') 將stu的Object利用filter搜尋出來之後,再將此QuerySet按照height降冪,name升冪的方式排序 15.查詢少用的指令 (1).查詢資料是否存在: 語法:exist() 回傳True, 如果QuerySet存在 (2).消除重複資料 語法:distinct() 當搜尋多個Table時,有可能會出現重複的資料,利用 distinct() 即可以消除重複的項目。 |
||||
顯示某個欄位的全部筆數(消除重複資料) |
16.如何顯示某個欄位的全部筆數(消除重複資料) (1).傳統SQL語法只顯示name欄位: select distinct name from Author select distinct name,email from Author (2).django的ORM寫法: a = Author.objects.values_list(name).distinct() b = Author.objects.values_list(name,email).distinct() (3).兩種語法與後續的取值: #若要讀取某個欄位catego的所有欄位值select catego form news = 有兩種方法: (兩種方法的功能相同,只是寫法不同) ☎方法1:a1 = news.objects.values('catego').distinct() ☎方法2:a1 = news.objects.values_list('catego').distinct() _(A).方法一: ☎方法1:a1 = news.objects.values('catego').distinct() django讀值方法 = a1['catego'] 在模板網頁讀值 = item.catego {% for item in a1 %} <option>{{item.catego}}</option> {% endfor %} _(B).方法二: ☎方法2:a1 = news.objects.values_list('catego').distinct() 讀值方法 = a1[0] 在模板網頁讀值 = item {% for item in a1 %} <option>{{item}}</option> {% endfor %} |
||||
限制查詢結果的筆數數目與起始筆(適用分頁) |
17.限制查詢結果的筆數數目與起始筆(適用分頁) (1).取得前8筆記錄:[:8] 語法:資料表物件.objects.all()[:n] 例如:stu.objects.all()[:8] (2).取得第8筆~第16記錄:[8:16] 語法:資料表物件.objects.all()[m:n] 例如:stu.objects.all()[8:16] (3).取得最後8筆記錄:[8:] 語法:資料表物件.objects.all()[n:] 例如:stu.objects.all()[8:] |
||||
資料表的精確查詢 vs 關鍵字查詢 |
18.資料表的:『精確查詢』 vs 『關鍵字查詢』 (1).精確查詢:__exact 例如 a1 = stu.objects.filter(name='王五') 或是 a1 = stu.objects.filter(name__exact='王五') 顯示:王五的記錄 (2).關鍵字查詢:__contains _(A).contains:在mysql中相當於‘like‘模糊查詢, 但是在這裏值的前後都會加上%,意思是要查詢的字段中是否包含某個字符串, 這個條件過濾時是大小寫敏感的,也就是轉化成原生SQL的時候會在值的前面加上BINARY關鍵字: 例如 a1 = stu.objects.filter(name__contains='王') 顯示有關鍵字:王的所有記錄 例如: a1 = 論文.objects.filter(title__contains='鋼鐵') 對應的的SQL語法: SELECT `article`.`id`, `article`.`title`, `article`.`content` FROM `論文` WHERE `論文`.`title` LIKE BINARY %鋼鐵% 19.欄位查詢常用指令: (1).語法:查詢格式:field__lookuptype=value (2).數字,日期範圍的查詢,可以使用的指令: GT (Greater than): 大於 LT (Less than): 小於 GTE (Greater Than or Equal): 大於或等於 LTE (Less Than or Equal): 小於或等於 (3).名稱的查詢可以使用: startswith: 大小寫,開頭的字串相符 istartswith: 大小寫不須一樣,開頭的字串相符 endswith: 大小寫,結尾的字串相符 iendswith: 大小寫不須一樣,結尾的字串相符 exact: 精確的比對 iexact: 不精確的比對(大小寫不須相同) contains: 包含此文字 (4).其它查詢: __in 存在於一個list範圍內 __range 在…範圍內 __year 日期欄位的年份 __month 日期欄位的月份 __day 日期欄位的日 __isnull=True/False (5).範例: # 查詢id大於1 且 小於10的值 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 查詢id等於11、22、33的資料 models.Tb1.objects.filter(id__in=[11, 22, 33]) # not in models.Tb1.objects.exclude(id__in=[11, 22, 33]) # 關鍵字查詢name欄位包含"ven"的 models.Tb1.objects.filter(name__contains="ven") # 關鍵字查詢name欄位包含"ven"的(但是icontains大小寫不敏感) models.Tb1.objects.filter(name__icontains="ven") # 查詢id範圍是1到3的,等價於SQL的bettwen and models.Tb1.objects.filter(id__range=[1, 3]) 類似的還有:startswith,istartswith, endswith, iendswith #查詢date欄位(2019年) models.Class.objects.filter(first_day__year=2019) |
||||
查詢第一筆,最後一筆記錄 |
20.查詢第一筆,最後一筆記錄 (1).語法: stu.objects.first() stu.objects.last() 例如: # 第一本書物件 book_obj = models.Book.objects.first() |
||||
連表查詢 |
21.連表查詢 (1).有兩個資料表類別,彼此關聯,可以進行關聯查詢 範例一: class A(models.Model): name = models.CharField() class B(models.Model): aa = models.ForeignKey(A) 關聯查詢:通过B的外键找到A中name字段包含test内容的数据 B.objects.filter(aa__name__contains='test') (2).範例二 class A(models.Model): name = models.CharField() class B(models.Model): aa = models.ForeignKey(A,related_name="FAN") bb = models.CharField() 關聯查詢:反向查询,查询出所有(B.aa=A且B.bb=XXXX)的A实例 A.objects.filter(FAN__bb='XXXX') |
||||
複雜查詢:Q查询 |
22.複雜查詢:Q查詢 (1).功能: 當filter方法中有多個欄位篩選時,是使用AND將其連接在一起的, 但如果想要更複雜的過濾條件(OR),這時候就必須用Django為提供的Q查詢 (2).語法範例: from django.db.models import Q Q(name__contains='ang') 邏輯運算:在filter中的多個欄位過濾是使用AND連接的,而OR或其他邏輯運算無法在filter中使用, 而Q物件之間可以使用如|、&、~等邏輯運算, (2).『或,or』查詢的範例:| 例如: from django.db.models import Q Q(name__contains='Z') | Q(name_contains='Q') #等同於下麵的WHERE子句 WHERE name LIKE '%Z%' OR name LIKE '%Q%' (3).『且,and』查詢的範例:&& #查找不以z開頭並且名稱中包含有a或b的書籍 for book in Book.objects.filter( ~ Q(name__startswith='z') && (Q(name__contains='a') | Q(name__contains='b')) ): print(book) (4).使用查詢對象: 所有接受關鍵字參數的查找方法,例如get/exclude/filter等都可以使用Q物件,多個Q物件之間如果沒有使用邏輯運算,則會被以AND連接,如果Q物件和普通關鍵字參數混在一起,Q對象要放在普通關鍵字前面, 例如: Book.objects.filter(Q(pubdate__year=2019) | Q(pubdate__day=31) , name__contains='z') |
||||
exp07-02讀取新聞資料庫,一頁顯示8筆,上下頁瀏覽 |
23.寫程式,讀取新聞資料庫,一頁顯示8頁,上頁,下頁瀏覽,並且可以觀看新聞內容 (1).範例:exp07-02.py (A).在views.py設定函數(page1,detail) ☎注意:兩種GET接收變數的方法: #若是由form傳來get變數:request.GET['pagebtn'] #若是由網址?pagebtn=..傳來的get變數:request.GET.get('pagebtn') ☎注意:網址傳來筆數,一律都是文字(就算是數字,也是文字)== '1' 例如: (正確)if request.GET.get('pagebtn') == '1': (錯誤)if request.GET.get('pagebtn') == 1: ☎注意:指定查詢結果的筆數數目與起始筆(適用分頁) startnum = (pagenum-1)*pagesize endnum = pagenum*pagesize items = news.objects.filter(enabled=True).order_by('id')[startnum:endnum] ☎注意:由目前pagenum來計算相關顯示數據 startnum = (pagenum-1)*pagesize endnum = pagenum*pagesize items = news.objects.filter(enabled=True).order_by('id')[startnum:endnum] ☎注意:全域變數的使用方法 ☎注意:網站不要用全域變數global1 原因:因為在個人主機雖然正常,但在專業主機如heroku,全域變數會亂變,跳來跳去, 解決方法:所以還是要用session變數,數據才穩 pagenum = 1 def page1(request): global pagenum 程式碼: pagenum = 1 def page1(request): global pagenum pagesize = 8 #可以顯示的必須enabled=True items = news.objects.filter(enabled=True) #計算筆數兩種方法:(1).items.count()。(2)len(items) #totalnum = len(items) totalnum = items.count() #totalpagenum = totalnum//pagesize totalpagenum = math.ceil(totalnum/pagesize) #下一頁 #若是由form傳來get變數:request.GET['pagebtn'] #若是由網址?pagebtn=..傳來的get變數:request.GET.get('pagebtn') #網址傳來筆數,一律都是文字(就算是數字,也是文字)== '1' #由目前pagenum來計算相關顯示數據 startnum = (pagenum-1)*pagesize endnum = pagenum*pagesize items = news.objects.filter(enabled=True).order_by('id')[startnum:endnum] #若是下一頁,上一頁,再修改所要顯示的數據 if request.GET.get('pagebtn') == '1': if pagenum <= totalpagenum-1: pagenum += 1 startnum = (pagenum-1)*pagesize endnum = pagenum*pagesize items = news.objects.filter(enabled=True).order_by('id')[startnum:endnum] #上一頁 elif request.GET.get('pagebtn') == '-1': if pagenum >= 2: pagenum -= 1 startnum = (pagenum-1)*pagesize endnum = pagenum*pagesize items = news.objects.filter(enabled=True).order_by('id')[startnum:endnum] #把全域變數設定到local筆數 currentpagenum = pagenum return render(request,'page1.html',locals()) ---------------- ☎注意:使用filter查詢的寫法: item = news.objects.filter(id=...) if len(item)>0: ☎注意:計算筆數的兩種寫法: 方法一:len(item) 方法二:item.count() ☎注意:若用filter查詢,結果是個list陣列,第一筆資料為item[0](get查詢不是list陣列) 例如: item = news.objects.filter(id=id) title = item[0].title def detail(request): id = request.GET.get('id') item = news.objects.filter(id=id) if len(item)>0: #注意:若用filter查詢,結果是個list陣列,第一筆資料為item[0](get查詢不是list陣列) title = item[0].title catego = item[0].catego message = item[0].message nickname = item[0].nickname pubtime = item[0].pubtime pubtime = item[0].pubtime else: message01 = '找不到資料' return render(request,'detail.html',locals()) (B).在urls.py設定 from app01.views import index,showall,edit,page1,detail urlpatterns = [ path('admin/', admin.site.urls), url(r'^$',index), .... url(r'^page1/$',page1), url(r'^detail/$',detail), ] (C).顯示全部資料網頁page1.html ☎注意:for 資料表筆若是沒有資料的處理:empty {% for item in items %} 。。。。。。 {% empty %} 。。。。。。 {% endfor %} ☎注意:顯示圖片時會用到static參數來指定圖片目錄 注意格式語法: {% load staticfiles %} <img src='{% static "images/prevpage.png" %}'> <br> 程式碼: {% extends 'base.html' %} {% load staticfiles %} {% block title %} <title>顯示所有新聞</title> {% endblock %} {% block content %} <div class="contentbox"> <h1>新聞列表</h1> {% csrf_token %} <table> <th>分類</th><th>標題</th><th>發表時間</th><th>點閱</th><th>修改</th><th>刪除</th> {% for item in items %} <tr> <td><div class="typeblock">{{item.catego}}</div></td> <td><a href='/detail/?id={{item.id}}'>{{item.title}}</a></td> <td>{{item.pubtime}}</td> <td>{{item.press}}</td> <td><a href='/edit/?id={{item.id}}'>編輯</a></td> <td><a href='/del/?id={{item.id}}'>刪除</a></td> </tr> {% empty %} <div class="status warning"> <img src='{% static "images/icon_warning.png" %}'> <span>目前新聞資料庫中沒有任何資料!</span> </div> {% endfor %} </table> <div class="topfunction"> {% if currentpagenum >= 2 %} <a href='/page1/?pagebtn=-1'><img src='{% static "images/prevpage.png" %}' alt='上一頁'></a> {% endif %} {% if currentpagenum < totalpagenum %} <a href='/page1/?pagebtn=1'><img src='{% static "images/nextpage.png"%}' alt='下一頁'></a> {% endif %} </div> <p style="color: magenta">{{message01}}</p> </div> {% endblock %} (D).瀏覽一筆詳細資料網頁detail.html 程式碼: {% extends "base.html" %} {% load staticfiles %} {% block content %} <div class="contentbox"> <table width="100%"> <tr> <th align="left"><span class="typeblock">{{catego}} </span> {{title}}</th> </tr> <tr> <td> <span class="newsinfo"> <img src="{% static "images/date.png" %}" alt="" width="16" height="16" /> {{pubtime}} <img src="{% static "images/user.png" %}" alt="" width="16" height="16" /> {{nickname}} <p> {{message}}</p> </span> </td> </tr> </table> <div class="topfunction"> <a href="/page1/" title="返回首頁"> <img src="{% static "images/home.png" %}" alt="返回首頁" width="86" height="32" /></a> </div> <p style="color: magenta">{{message01}}</p> </div> {% endblock %} |
||||
exp07-03完整新聞發布系統:可會員登入,可編輯,新增,刪除新聞 |
24.寫程式,完整新聞發布系統(若是會員登入,可以編輯,新增,刪除新聞) (1).範例:exp07-03.py ☎結構:page2,detail2就跟前面一樣,只是加上一個login的登入會員帳號按鈕 ☎結構:若是login2登入後,就會顯示page_admin2,del2,edit2,add2 (A).在urls.py設定 from app01.views import index,showall,edit,page1,detail,page2,detail2,login2,page_admin2,logout2,edit2,del2,add2 urlpatterns = [ path('admin/', admin.site.urls), url(r'^$',index), ..... url(r'^page2/$',page2), url(r'^detail2/$',detail2), url(r'^login2/$',login2), url(r'^page_admin2/$',page_admin2), url(r'^logout2/$',logout2), url(r'^edit2/$',edit2), url(r'^edit2/(\w+)/$',edit2), url(r'^del2/(\w+)/$',del2), url(r'^del2/$',del2), url(r'^add2/$',add2), ] (B).在views.py設定函數(base2,page2,detail2,login2,page_admin2,del2,edit2,add2) 程式碼: #page2是一般瀏覽者都可以看到的網頁資料(只是在右上加個登入管理者按鈕) pagenum2 = 1 def page2(request): global pagenum2 pagesize = 8 #可以顯示的必須enabled=True items = news.objects.filter(enabled=True).order_by('-id') totalnum = items.count() totalpagenum = math.ceil(totalnum/pagesize) #下一頁 #若是由form傳來get變數:request.GET['pagebtn'] #若是由網址?pagebtn=..傳來的get變數:request.GET.get('pagebtn') #網址傳來筆數,一律都是文字(就算是數字,也是文字)== '1' #由目前pagenum2來計算相關顯示數據 startnum = (pagenum2-1)*pagesize endnum = pagenum2*pagesize items = news.objects.filter(enabled=True).order_by('-id')[startnum:endnum] #若是下一頁,上一頁,再修改所要顯示的數據 if request.GET.get('pagebtn') == '1': if pagenum2 <= totalpagenum-1: pagenum2 += 1 startnum = (pagenum2-1)*pagesize endnum = pagenum2*pagesize items = news.objects.filter(enabled=True).order_by('-id')[startnum:endnum] #上一頁 elif request.GET.get('pagebtn') == '-1': if pagenum2 >= 2: pagenum2 -= 1 startnum = (pagenum2-1)*pagesize endnum = pagenum2*pagesize items = news.objects.filter(enabled=True).order_by('-id')[startnum:endnum] #把全域變數設定到local筆數 currentpagenum = pagenum2 return render(request,'page2.html',locals()) ☎注意:這邊測試用filter查詢,結果要用item[0] def detail2(request): id = request.GET.get('id') item = news.objects.filter(id=id) if len(item)>0: #注意:若用filter查詢,結果是個list陣列,第一筆資料為item[0](get查詢不是list陣列) title = item[0].title catego = item[0].catego message = item[0].message nickname = item[0].nickname pubtime = item[0].pubtime pubtime = item[0].pubtime else: message01 = '找不到資料' return render(request,'detail2.html',locals()) ☎注意:驗證會員身份是否通過的公式: user = auth.authenticate(username=username,password=password) if user is not None: if user.is_active: auth.login(request,user) def login2(request): if request.method == 'POST': username = request.POST['username'] password = request.POST['password'] message01 = username #驗證是否為會員 user = auth.authenticate(username=username,password=password) if user is not None: if user.is_active: auth.login(request,user) message01 = '已經成功登入' return redirect('/page_admin2/') else: message01 = '帳號尚未被啟用' else: message01 = '沒有這個帳號,登入錯誤' return render(request,'login2.html',locals()) ☎注意:管理者登入後,顯示新增,修改,刪除按鈕,而且顯示筆數不完全是enabled=true,而是全部消失 pagenum3=1 def page_admin2(request): global pagenum3 pagesize = 8 items = news.objects.all().order_by('-pubtime') totalnum = items.count() totalpagenum = math.ceil(totalnum/pagesize) #由目前pagenum3來計算相關顯示數據 startnum = (pagenum3-1)*pagesize endnum = pagenum3*pagesize items = news.objects.all().order_by('-pubtime')[startnum:endnum] #若是下一頁,上一頁,再修改所要顯示的數據 if request.GET.get('pagebtn') == '1': if pagenum3 <= totalpagenum-1: pagenum3 += 1 startnum = (pagenum3-1)*pagesize endnum = pagenum3*pagesize items = news.objects.all().order_by('-pubtime')[startnum:endnum] #上一頁 elif request.GET.get('pagebtn') == '-1': if pagenum3 >= 2: pagenum3 -= 1 startnum = (pagenum3-1)*pagesize endnum = pagenum3*pagesize items = news.objects.all().order_by('-pubtime')[startnum:endnum] #把全域變數設定到local筆數 currentpagenum = pagenum3 return render(request,'page_admin2.html',locals()) def logout2(request): auth.logout(request) return redirect('/page2/') ☎注意:傳遞變數用雙參數,不是用?id=... 要鑑別兩種情形(有值,無值) if id is not None: elif id is None: ☎注意:讀取模板網頁幾種特殊的元件(select,texarea,radio) ☎讀取select的option值,直接POST[name] recd.catego = request.POST['catego'] ☎讀取textarea的值,直接POST[name] recd.nickname = request.POST['nickname'] ☎讀取radiobutton,乃是讀取radio-name值(不是id),因為有兩個radio,所以只能靠radio-value來鑑別了 #若radio-value = 'yes',則設定recd.enabled = True yesno = request.POST['enabled'] if yesno=='yes': recd.enabled = True else: recd.enabled = False ☎讀取目前某個欄位(catego),並且消除重複值 #若要讀取某個欄位catego的所有欄位值select catego form news = 有兩種方法: #方法1:a1 = news.objects.values('catego').distinct(),讀值方法 = a1['catego']。(在模板網頁 = a1.catego) #方法2:a1 = news.objects.values_list('catego').distinct(),讀值方法 = a1。(在模板網頁 = a1) categos = news.objects.values('catego').distinct() categos = news.objects.values_list('catego').distinct() def edit2(request,id=None): if id is not None: if request.method=='POST': recd = news.objects.get(id=id) recd.title = request.POST['title'] #讀取select的option值,直接POST[name] recd.catego = request.POST['catego'] recd.message = request.POST['message'] #讀取textarea的值,直接POST[name] recd.nickname = request.POST['nickname'] recd.press = request.POST['press'] #讀取radiobutton,乃是讀取radio-name值(不是id),因為有兩個radio,所以只能靠radio-value來鑑別了 #若radio-value = 'yes',則設定recd.enabled = True yesno = request.POST['enabled'] if yesno=='yes': recd.enabled = True else: recd.enabled = False try: recd.save() return redirect('/page_admin2/') except: message01 = '修改資料發生錯誤' return render(request,'edit2.html',locals()) else: #取得所有的catego #消除重複資料語法:distinct() #若要讀取某個欄位catego的所有欄位值select catego form news = 有兩種方法: #方法1:a1 = news.objects.values('catego').distinct(),讀值方法 = a1['catego']。(在模板網頁 = a1.catego) #方法2:a1 = news.objects.values_list('catego').distinct(),讀值方法 = a1。(在模板網頁 = a1) categos = news.objects.values('catego').distinct() #categos = news.objects.values_list('catego').distinct() items = news.objects.get(id=id) id = items.id title = items.title catego = items.catego message = items.message nickname = items.nickname press = items.press enabled = items.enabled return render(request,'edit2.html',locals()) elif id is None: message01 = '沒有給定要顯示的id' #return redirect('/page_admin2/') return render(request,'edit2.html',locals()) ☎注意:傳遞變數用雙參數,不是用?id=... 要鑑別兩種情形(有值,無值) if id is not None: elif id is None: def del2(request,id=None): if id is not None: recd = news.objects.get(id=id) try: recd.delete() return redirect('/page_admin2/') except: message01 = '刪除發生錯誤' return render(request,'page_admin2.html',locals()) elif id is None: message01 = '沒有給定要刪除的id' return redirect('/page_admin2/') #return render(request,'page_admin2.html',locals()) ☎注意:新增一般記錄說,某個非null欄位,一定要給值 ☎注意:時間欄位給定目前時間:pubtime = datetime.now() def add2(request): if request.method=='POST': title = request.POST['title'] catego = request.POST['catego'] message = request.POST['message'] nickname = request.POST['nickname'] press = 0 yesno = request.POST['enabled'] #讀取radiobutton,乃是讀取radio-name值(不是id),因為有兩個radio,所以只能靠radio-value來鑑別了 #若radio-value = 'yes',則設定recd.enabled = True if yesno=='yes': enabled = True else: enabled = False #pubtime欄位不可以為null,一定要給值 pubtime = datetime.now() recd = news.objects.create(title=title,catego=catego,message=message,nickname=nickname,press=press,enabled=enabled,pubtime=pubtime) try: recd.save() return redirect('/page_admin2/') except: message01 = '新增一筆資料發生錯誤' return render(request,'add2.html',locals()) else: #message01 = '無法新增資料' categos = ['公告','更新','活動','其它'] return render(request,'add2.html',locals()) (C).顯示全部資料網頁page2.html ☎注意:在block login加入登入的按鈕 {% extends 'base2.html' %} {% load staticfiles %} {% block login %} <div align='right'> <a href="/login2/" title="登入管理介面"> <img src='{% static "images/Lock.png" %}' alt="登入管理介面"/></a> </div> {% endblock %} {% block content %} <div class="contentbox"> <h1>新聞列表</h1> {% csrf_token %} <table width='100%'> <th>分類</th><th>標題</th><th>發表時間</th><th>點閱</th> {% for item in items %} <tr> <td><div class="typeblock">{{item.catego}}</div></td> <td><a href='/detail2/?id={{item.id}}'>{{item.title}}</a></td> <td>{{item.pubtime}}</td> <td>{{item.press}}</td> </tr> {% empty %} <div class="status warning"> <img src='{% static "images/icon_warning.png" %}'> <span>目前新聞資料庫中沒有任何資料!</span> </div> {% endfor %} </table> <div class="topfunction"> {% if currentpagenum >= 2 %} <a href='/page2/?pagebtn=-1'><img src='{% static "images/prevpage.png" %}' alt='上一頁'></a> {% endif %} {% if currentpagenum < totalpagenum %} <a href='/page2/?pagebtn=1'><img src='{% static "images/nextpage.png"%}' alt='下一頁'></a> {% endif %} </div> <p style="color: magenta">{{message01}}</p> </div> {% endblock %} (D).登入網頁login2.html ☎注意:要加上<link href='{% static "css/style.css" %}' rel="stylesheet" type="text/css" /> 把style.css加入,才能夠顯示登入左邊的背景圖,與邊框 ☎注意:若是返回首頁按鈕的程式寫法:onclick="window.location='/page2/' <input type="button" name='btn2' value="返回首頁" onclick="window.location='/page2/'" /> 程式碼: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>管理者登入</title> {% load staticfiles %} <link href='{% static "css/style.css" %}' rel="stylesheet" type="text/css" /> </head> <body> <div class="boxLogin"> <form name='myform' action="" method="POST"> {% csrf_token %} <div class='fields'> <div class='sep'> <label for="username">管理者帳號</label> <input type="text" name='username' required /> </div> <div class='sep'> <label for="password">管理者密碼</label> <input type="text" name='password' required /> </div> <div class='sep'> <input type="submit" name='btn1' value="登入系統"/> <input type="button" name='btn2' value="返回首頁" onclick="window.location='/page2/'" /> </div> </div> <p style="color: magenta">{{message01}}</p> </form> </div> </body> </html> (E).修改網頁edit2.html ☎注意:下拉式選單,清單有目前所有欄位的值(消除重複),且顯示資料表的欄位值 <select name="catego"> {% for item in categos %} {% if item.catego == catego %} <option selected='selected'>{{item.catego}}</option> {% else %} <option>{{item.catego}}</option> {% endif %} {% endfor %} </select> ☎注意:radio按鈕給定同一個name,但是value不同,在views裡面感覺value來判別 {% if enabled == True %} 已通過<input type='radio' name=enabled checked='checked' value='yes' id='enable_yes'> 審核中<input type='radio' name=enabled id='enable_no' value="no"> {% else %} 已通過<input type='radio' name=enabled id='enable_yes' value="yes"> 審核中<input type='radio' name=enabled checked='checked' id='enable_no' value="no"> {% endif %} 程式碼: {% extends 'base.html' %} {% block title %} <title>修改資料</title> {% endblock %} {% block content %} <h1>修改新聞資料</h1> <form name='myform' action="" method="POST"> {% csrf_token %} <table width='100%' border='1' cellsapcing='0' cellpadding='0' > <tr> <td>編號</td><td><input type="text" name='id' readonly value="{{id}}"></td> </tr> <tr> <td>標題</td><td><input type="text" name='title' value="{{title}}" size='60'></td> </tr> <tr> <td>分類</td><td> <select name="catego"> {% for item in categos %} {% if item.catego == catego %} <option selected='selected'>{{item.catego}}</option> {% else %} <option>{{item.catego}}</option> {% endif %} {% endfor %} </select> </td> </tr> <tr> <td>訊息</td><td><textarea type="text" name='message' cols="60" rows="10">{{message}}</textarea></td> </tr> <tr> <td>發表者</td><td><input type="text" name='nickname' value="{{nickname}}"></td> </tr> <tr> <td>點閱</td><td><input type="text" name='press' value="{{press}}"></td> </tr> <tr> <td>審核</td><td> {% if enabled == True %} 已通過<input type='radio' name=enabled checked='checked' value='yes' id='enable_yes'> 審核中<input type='radio' name=enabled id='enable_no' value="no"> {% else %} 已通過<input type='radio' name=enabled id='enable_yes' value="yes"> 審核中<input type='radio' name=enabled checked='checked' id='enable_no' value="no"> {% endif %} </td> </tr> </table> <p></p> <input type="submit" name='bnt1' value="確認修改"> <input type="button" name='bnt2' value="返回首頁" onclick="window.location='/page_admin2/'"> <p></p> <p style="color: magenta">{{message01}}</p> </form> {% endblock %} (F).新增網頁add2.html 程式碼: {% extends 'base2.html' %} {% load staticfiles %} {% block login %} <div align='right'> <a href="/add2/" title="新增新聞"> <img src='{% static "images/append.png" %}' alt="新增新聞"/></a> <a href="/logout2/" title="登出管理介面"> <img src='{% static "images/LockOff.png" %}' alt="登入管理介面"/></a> </div> {% endblock %} {% block content %} <div class="contentbox"> <h1>新增一般新聞資料</h1> <form name='myform' action="" method="POST"> {% csrf_token %} <table width='100%' border='1' cellsapcing='0' cellpadding='0' > <tr> <td>分類</td><td> <select name="catego"> {% for catego in categos %} <option>{{catego}}</option> {% endfor %} </select> </td> </tr> <tr> <td>標題</td><td><input type="text" name='title' value="{{title}}" size="60"></td> </tr> <tr> <td>訊息</td><td><textarea type="text" name='message' value="{{message}}" cols="60" rows="10" ></textarea></td> </tr> <tr> <td>發表者</td><td><input type="text" name='nickname' value="{{nickname}}"></td> </tr> <tr> <td>審核</td><td> 已通過<input type='radio' name=enabled checked='checked' value="yes" id='enable_yes'> 審核中<input type='radio' name=enabled id='enable_no' value="no"> </td> </tr> </table> <p></p> <input type="submit" name='bnt1' value="確認新增"> <input type="button" name='bnt2' value="返回首頁" onclick="window.location='/page_admin2/'"> <p></p> <p style="color: magenta">{{message01}}</p> </form> </div> {% endblock %} |
||||
Chp8.圖形驗證碼(Captcha) | ||||||
下載 |
下載本章project成果 | |||||
目錄 | 圖形驗證碼功能 | Django的圖形驗證碼Captcha套件 | 建立一個djiango的虛擬環境 | 把一個已經寫好的專案拿來測試 | ||
撰寫程式的前置作業 | 圖形驗證的關鍵三步驟 | exp08-02驗證是否為管理者 | exp08-03修改驗證圖形碼的樣式 | |||
圖形驗證碼功能 |
1.功能: |
|||||
Django的圖形驗證碼(Captcha)=django-simple-captcha套件 |
2.Django的圖形驗證碼(Captcha)=django-simple-captcha套件 |
|||||
如何建立一個djiango的虛擬環境 |
4.如何建立一個djiango的虛擬環境 |
|||||
如何把一個已經寫好的專案拿來測試 |
4.如何把一個已經寫好的專案拿來測試(不一定要在虛擬環境內執行) |
|||||
自行撰寫程式的前置作業 |
5.自行撰寫程式的前置作業 |
|||||
圖形驗證的關鍵三步驟 |
6.觀念:圖形驗證的關鍵三步驟 |
|||||
exp08-02驗證是否為管理者 |
7.範例:exp08-02.py(自行寫程式,驗證是否為管理者(帳號密碼),驗證圖形碼) |
|||||
exp08-03修改驗證圖形碼的樣式 |
8.範例:exp08-03.py(修改驗證圖形碼的樣式) |
|||||
chp9:上課加分系統 | |||||
觀看 |
本範例的成果圖片1, 圖片2, 圖片3, 圖片4, 圖片5, 圖片6, 圖片7, 圖片8 | ||||
下載 |
下載本章project成果檔案 | ||||
下載 |
下載班級學生csv資料庫 | ||||
下載 |
下載班級學生sqlite資料庫 | ||||
chp10. 經文查詢系統 | |||||
觀看 |
本範例的成果圖片1, 圖片2, | ||||
下載 |
下載本章project成果檔案 | ||||
下載 |
下載經文csv資料庫 | ||||
下載 |
下載經文sqlite資料庫 | ||||
chp11.django如何讀取js檔案 | |||||
如何讀取jquery-1.9.1.js | 用onclick直接呼叫views.py的function | 用onclick直接呼叫views.py的function,且傳遞get變數 | |||
如何讀取jquery-1.9.1.js |
1.例如,在django裡面,模板是jquery mobile網頁,如何讀取jquery.mobile-1.4.2/jquery-1.9.1.min.js |
||||
用onclick直接呼叫views.py裡面的function |
2.如何不用form,不用submit,直接讓checkbox用onclick直接呼叫views.py裡面的function |
||||
用onclick直接呼叫views.py的function,且傳遞get變數 |
3.checkbox如何用onclick直接呼叫views.py裡面的function,並且傳遞get變數 |
||||
exp11_3 |
|
||||
exp11_4 |
|
||||
chp12. django如何與ajax互動 | |||||
exp12_1:多頁面的處理 | exp12_2:多頁面之間傳遞變數 | exp12_3:多頁面應用:台北動物園導覽 | |||
exp12_1 |
|
||||
exp12_2 |
|
||||
exp12_3 |
|
||||
chp13.各種views.py函數小技巧 | |||||
如何修改資料表欄位=其它欄位(方法:使用F('其它欄位')) | 如何在views.py讀取templates的全部欄位變數 | 取得資料庫資料表某欄位的最大值(2種方法) | 修改資料update的兩種寫法 | ||
如何修改資料表欄位=其它欄位(方法:使用F('其它欄位')) |
1.如何修改資料表欄位=其它欄位(方法:使用F('其它欄位')) |
||||
如何在views.py讀取templates的全部欄位變數 |
2.如何在views.py讀取templates的全部欄位變數 |
||||
取得資料庫資料表某欄位的最大值(2種方法) |
3.■如何取得資料庫資料表某欄位的最大值 |
||||
修改資料update的兩種寫法 |
4.■修改資料update的兩種寫法 |
||||
|
|||||
|
|||||
chp14.各種模板templates小技巧 | |||||
在網頁顯示的數字(顯示1位小數) | |||||
在網頁顯示的數字(顯示1位小數) |
1.■如何在網頁顯示的數字(顯示1位小數) |
||||
|
|||||
exp12_3 |
|
||||
chp20. 上傳到horuku網站 | |||||
先安裝git | 申請horuku網站帳號 | 在虛擬環境建立建立django專案 | 登入heroku並上傳 | 若修改原始檔案後再上傳到heroku的方法 | |
若 Push出現錯誤訊息rejected的方法 | |||||
先安裝git |
1.安裝horuku前,要先安裝git |
||||
申請horuku網站帳號 |
2.申請horuku網站帳號 |
||||
在虛擬環境建立建立django專案 |
在虛擬環境建立建立django專案 |
||||
登入heroku並上傳 |
登入heroku並上傳 |
||||
若修改原始檔案後再上傳到heroku的方法 |
若修改原始檔案後再上傳到heroku的方法 |
||||
若 Push出現錯誤訊息rejected的方法 |
若 Push出現錯誤訊息rejected的方法 |
||||
|
|||||
chp21. 將Django架設在IIS上 | |||||
1. |
1.先確認你的windows是否已經安裝IIS,且安裝CGI |
||||