本文作者:Eric
作者 Github : https://github.com/Ratherman
自由團隊將從0到1 手把手教各位讀者學會(1)Python基礎語法、(2)Python Web 網頁開發框架 – Django 、(3)Python網頁爬蟲 – 周易解夢網、(4)Tensorflow AI語言模型基礎與訓練 – LSTM、(5)實際部屬AI解夢模型到Web框架上。
AI . FREE Team 讀者專屬福利 → Python Basics 免費學習資源
建立 Django 的 APP
觀察APP內 urls.py 與 views.py 之間是如何運作
建立 model.py
首先我們先到昨天建立的 Django_AI_APP 裡面 (該虛擬環境的起點),然後進入虛擬環境,接著再進入與 manage.py 相同的路徑。我們昨天使用了 manage.py RUN 起了最初的 server,在今天,我們會使用 manage.py 多做一些其他的事情。
$ cd PIPENV_ROOT $ cd Django_AI_APP $ pipenv shell $ cd DI_project
Note: 我們昨天是在 Django_AI_APP 裡面建立虛擬環境的,所以要先進入該資料夾才做 pipenv shell
。
Django App 是我們在今天要探討的重要概念。被稱作App,是因為它就有點像是我們平常在用手機時,透過 Google Play 或是 Apple Store 下載的App。它具備特定的服務(功能),以我們的最終目標為例,我們就會讓 App 具備解析文字、回答問題的功能。而 App 也可以依照開發者的需求/喜好,於設定檔(DI_project/settings.py)調整是否要上線,裝拆方便。
我們從今天開始,會利用簡單的例子,和大家走一次開發 App 會走過的流程。
在與 manage.py 同一個路徑的地方,輸入以下指令。此處 demo_app 為我們 App 的名字,通常大家可以從 App 的名字猜出該 App 的用途為何,在這邊的功能為 demo ,所以就取名為 demo_app 了。
$ python manage.py startapp demo_app
在這裡做的事情就是建立一個 demo_app 的 package,可以發現 Django 專案除了原本就有的 manage.py 和 DI_project 之外還多了 demo_app 的資料夾,整體結構如下:
DI_project/
migrations/
init.py
admin.py
apps.py
models.py
tests.py
views.py
demo_app/ # 剛剛生成的
DI_project/ # 昨天介紹過
manage.py # 昨天介紹過
Note: 我們之後一連好幾天都會在 demo_app 裡面撰寫程式碼,開發新功能。
在這個檔案裡面,會設計好幾個負責接收 HttpRequest 的方法(所以是 view + “s”),並且對應的回傳的 Response。Response 在網路世界裡面非常多樣,可以是一個 json檔案,也可以是一串文字,當然也可以是一個服務好用,外觀又好看的網頁。
眼尖的大家應該有發現,目前在 demo_app 底下,並沒有看到 urls.py 這個檔案,這是沒錯的,在最開始透過 manage.py startapp 的時候是不會自動生成 urls.py 這個檔案,所以這個是要請大家手動在 demo_app 資料夾底下新增 urls.py 喔。
建立好此 urls.py 後,我們再來看看該 urls.py 的用途。
urls.py 顧名思義,這個檔案要做的事情和url連結是高度相關的,此檔案負責的任務是將不同的 url 映射(map)到對應的 view,我們將會在此設計 url 的 pattern。
與資料庫高度相關的檔案,根據不同類型的專案,會有不同樣式的 model。假設我們我們想要做一個古人查詢系統,(順便複習一下國高中國文XD),那我們可能就會有「古人」、「學派」兩個 model
順帶一提「古人」和「學派」之間的關係可以用外鍵(Foreign Key) 關聯在一起。舉例: 我們可以先找到道家,再利用外鍵關連到老子。詳細的設計我們就留到撰寫 model 的時候再來討論吧。
我們馬上就來針對第三部分的內容進行開發吧。(這邊推薦使用 VScode 等文字編輯器協助我們做開發)
打開 DI_project/demo_app/views.py,並將以下內容寫入。
from django.shortcuts import render from django.http import HttpResponse def taoism_detail(request): return HttpResponse("Taoism 是道家的英文。") def confucianism_detail(request): return HttpResponse("Confucianism 是儒家的英文")
第三部分有提到 views.py 的功能,就是要接收過來的 HttpRequest,所以在我們自定義的方法中(i.e. taoism_detail 和 confucianism_detail),他們其中的 inpurt argument (i.e. request)會是一個 HttpRequest;接著再回傳一個 Response,這邊的 Response 會是 HttpResponse,所以我們需要 import HttpResponse後再於 return 中使用。
以上在 views.py 中的兩個方法(其實就是兩種 view)將會被 DI_project/demo_app/urls.py 所呼叫到。
打開 DI_project/demo_app/urls.py,並將以下內容寫入。
Note: 如果剛剛沒有自己手動新增檔案的話,現在要記得先新增檔案喔。
from django.urls import path from demo_app import views urlpatterns = [ path("Confucianism", views.confucianism_detail, name="confucianism"), path("Taoism", views.taoism_detail, name="taosim") ]
urlpatterns 是一個 list 的結構,list 裡頭的元素是一個 path object,在 Django 就是透過這種 object 做到映射(mapping) url 至特定 view 這件事情的。其實也相當好聯想,不同的 path,自然就會對應到不同的終點,就好像人在台中,若是搭乘向北(path01_to_north)的高鐵往北走就可以到台北(view_Taipei),或是搭乘(path_02_to_south)的高鐵就可以到台南(view_Tainan)。
另外,在這邊也可以看到,在 urls.py 裡面呼叫到 views.py 的方式:
在 views.py import 目標檔案
*$ from demo_app import views
*上方行為等價於下方,原因是 “.” 就表示當前所在資料夾,也就是 demo_app/
*$ from . import views
*透過 views.Function_Name,來呼叫特定 view
*$ views.confucianism_detail
*$ views.taoism_detail
path("Confucianism", views.confucianism_detail, name="confucianism"),
第一個 input argument 是 路徑
*假設是設定"Taoism"的話,那在 Server Run 起來之後就可以在http://127.0.0.1:8000/demo_app/Taoism 找到對應的 view。
第二個 input argument 是 view
*我們已經在上方了解如何呼叫對應設計的view了。
第三個 input argument 是name
*這個有空餘時間的話,就會在之後的網頁呈現上介紹到喔。
想要深入了解 path object 的各位可以點此以了解更多。
除了上面提到的 DI_project/demo_app/urls.py 以外,我們還需要做一件事情才能在 server RUN 起來後看到 view,那就是,我們需要在 DI_project/urls.py 引入我們剛剛設計的 demo_app/urls.py,當 Django Project 在運作的時候,會以 DI_project/urls.py 為基準。
所以打開 DI_project/urls.py,並在 urlpatterns,多 include demo_app 中的 urls。
from django.contrib import admin from django.urls import path from django.urls import include # 多這一行 urlpatterns = [ path('admin/', admin.site.urls), # 別忘記逗點囉! path("demo_app/", include("demo_app.urls")) # 和多這一行 ]
最後,我們就來看看截至目前的成果吧!
$ python manage.py runserver
並開啟網頁,前往以下兩個網址,應該就可以分別看到下方兩張截圖的結果了。
大家可以稍微比對一下,目前 url 網址,和我們在 DI_project/urls.py path的設計,以及確認看看我們看到的回傳結果,是不是也和 DI_project/views.py 裡面的設計一樣喔。
這邊我們就按照在第3部分舉的例子,也就是建立古人查詢系統所可以聯想的到的 model 吧,model 其實就有點像是一個可以用來代表一個本質的表格,目前在古人查詢系統中,我們可以簡單的聯想到 「古人」和「學派」兩種表格。以下就列出兩個 model (i.e. 古人、學派)的樣子讓大家看看。
在這邊先幫大家整理一下古人的資訊和對應學派的資訊。然後幫各個古人隨機給定一個發表該言論的歲數。
古人 | 名言 | 歲數 |
---|---|---|
孔子 | 有朋自遠方來,不亦樂乎? 見利思義,見危受命。 | 27 |
孟子 | 獨樂樂,與人樂樂,孰樂? | 65 |
荀子 | 鍥而舍之,朽木不折;鍥而不捨,金石可鏤。 | 67 |
老子 | 治大國,若烹小鮮。 | 18 |
莊子 | 真者,精誠之志也,不精不誠,不能動人。 | 22 |
在這邊,假設學派就像是遊戲中的公會一樣,也有總人數這樣子的參數存在,
所以在這裡也隨機給定一個該學派的全盛時期人數。
學派 | 中心價值 | 全盛時期人數 |
---|---|---|
儒家 | 人與自然的和諧相處 | 4777 |
道家 | 人與人之間要「仁」與「禮」 | 3952 |
有清楚 model 可能的樣子之後,我們就可以來設計我們的 models.py 了。
打開 DI_project/demo_app/models.py,並將以下內容寫入。
from django.db import models class School(models.Model): # 學派名稱 school_name = models.CharField(max_length=20) # 中心價值 core_value = models.CharField(max_length=100) # 人數 num_member = models.IntegerField() class Ancient_People(models.Model): # 學派 school = models.ForeignKey(School, on_delete=models.CASCADE) # 名字 name = models.CharField(max_length=10) # 名言 statement = models.CharField(max_length=100) # 歲數 age = models.IntegerField()
都寫好之後,記得儲存檔案。在 Django 裡面,若開發的動作牽涉到 models.py 的改動,則需要通知 Django 我們有在 demo_app 裡面有對 model 的設計做蕭正,以讓 Django 對資料庫的設定做進一步更新。 所以我們會需要執行以下指令
$ python manage.py makemigrations demo_app
結果回傳什麼呢?
No installed app with label 'demo_app'.
原來是因為我們還沒有在 DI_project 裡面的 settings.py 對 INSTALLED_APPS 做註冊 APP (i.e. demo_app)的動作,所以打開 DI_project/ settings.py,並在 INSTALLED_APPS 加入 "demo_app.apps.DemoAppConfig",完成後應該要與下方一致。
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', "demo_app.apps.DemoAppConfig" #加入此行 ]
大家會不會覺得有疑問,為什麼是 demo_app.apps.DemoAppConfig 呢? 其實不難發現,demo_app 就是 demo_app 資料夾,而 apps 指的就是 apps.py 這個檔案,最後的 DemoAppConfig 則是 apps 這個 module 裡面的 class。Django 就是透過這樣一層又一層解析的方式,將 app 串聯在一起的。再次執行剛剛的指令就會有正確了:
$ python manage.py makemigrations demo_app 以下為回傳內容... Migrations for 'demo_app': demo_app\migrations\0001_initial.py - Create model School - Create model Ancient_People
成功利用 manage.py 執行 makemigrations 後,現在我們已經成功產生兩個 model 生成所需的指令了,接下來,我們需要在執行以下指令,真正的去建立兩個 model 所對應的資料庫表格。執行以下指令:
$ python manage.py migrate以下為回傳內容...Operations to perform: Apply all migrations: admin, auth, contenttypes, demo_app, sessionsRunning migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying auth.0012_alter_user_first_name_max_length... OK Applying demo_app.0001_initial... OK Applying sessions.0001_initial... OK
在最下面的兩筆紀錄中,顯示 OK 就表示 migrate 成功,兩個 model 所對應的表格都有被成功建立了。不過除了這兩筆紀錄,還有很多其他有關 admin 以及 auth 的 migrate 是什麼呢? 它們是一開始就被 Django Project 内建好的 migrations,只是我們在這次以前都沒有 migrate,所以才會在這次一起 migrate 喔。
今天的內容蠻多的,截至目前,我們不僅成功地串接 urls.py 和 views.py,也建立了 models,接下來的一天,我們會從 model 出發,和大家談談該如何將資料新增到資料庫裡面,也稍微修改我們在今天有用到的 views.py 和 urls.py,讓 HttpRequest 和 HttpResponse 變得更加有彈性!
自由團隊 官方網站:https://aifreeblog.herokuapp.com/
自由團隊 Github:https://github.com/AI-FREE-Team/
自由團隊 粉絲專頁:https://www.facebook.com/AI.Free.Team/
自由團隊 IG:https://www.instagram.com/aifreeteam/
自由團隊 Youtube:https://www.youtube.com/channel/UCjw6Kuw3kwM_il39NTBJVTg/
文章同步發布於:第十二屆 IT 挑戰賽部落格