第 18 章 Django 入門


    當今的網站實際上都是富應用程序(rich application),就像成熟的桌面應用程序一樣。Python提供了一組開發Web應用程序的卓越工具。在本章中,我們將學習如何使用Django(http://djangoproject.com/)來開發一個名為"學習筆記"(learningLog)的項目,這是一個在線日志系統,讓我們能夠記錄所學習的有關特定主題的知識。

    我們將為這個項目指定規范,然后為應用程序使用的數據定義模型。我們將使用Django的管理系統來輸入一些初始數據,再學習編寫視圖和模板,讓Django能夠為我們的網站創建網頁。

    Django是一個Web框架——一套用於幫助開發交互式網站的工具。Django能夠響應網頁請求,還能讓我們更輕松地讀寫數據庫、管理用戶等。在第19章和第20章,我們將改進'學習筆記'項目,再將其部署到活動的服務器,讓我們和朋友能夠使用它。

18.1  建立項目

    建立項目時,首先需要以規范的方式對項目進行描述,再建立虛擬環境,以便在其中創建項目。

18.1.1  指定規范

    完整的規范詳細說明了項目的目標,闡述了項目的功能,並討論了項目的外觀和用戶界面。與任何良好的項目規划和商業計划書一樣,規范應突出重點,幫助避免項目偏離軌道。這里不會指定完整的項目規划,而只列出一些明確的目標,以突出開發的重點。我們制定的規范如下:

    我們要編寫一個名為"學習筆記"的Web應用程序,讓用戶能夠記錄感興趣的主題,並在學習每個主題的過程中添加日志條目。“學習筆記”的主頁對這個網站進行描述,並邀請用戶注冊或登錄。用戶登錄后,就可創建新主題、添加新條目以及閱讀既有的條目。

    學習新的主題時,記錄學到的知識可幫助跟蹤和復習這些知識。優秀的應用程序讓這個記錄過程簡單易行。

18.1.2  建立虛擬環境

    要使用Django,首先需要建立一個虛擬工作環境虛擬環境系統的一個位置,我們可以在其中安裝包,並將其於其他python包隔離。將項目的庫與其他的項目分離是有益的,且為了將"學習筆記"部署到服務器,這也是必須的。

    為項目新建一個目錄,將其命名為learning_log,再在終端中切換到這個目錄,並創建一個虛擬環境。如果我們使用的是Python3,可使用下面命令來創建虛擬環境:

    learning_log$ python -m venv 11_env

  learning_log$

    如果安裝不上,我們需要安裝(sudo apt-get install python3-venv)

    這里運行了模塊venv,並使用它來創建一個名為11_env的虛擬環境。如果這樣做管用,請跳到后面的18.1.4節;如果不管用,請閱讀18.1.3節。

18.1.3  安裝virtualenv

    如果你使用的是較早的Python版本,或者系統沒有正確地設置,不能使用模塊venv,可安裝virtualenv包。為此,可執行如下命令:

    $ pip install --user virtualenv

    別忘了,對於這個命令,我們可能需要使用稍微不同的版本。

注意:如果我們使用的是Linux系統,且上面的做法不管用,可使用系統的包管理器來安裝virtualenv。例如,要在Ubuntu系統中安裝virtualenv,可使用命令

sudo apt-get install python-virtualenv.

    在終端中切換到目錄learning_log,並像下面一樣創建一個虛擬環境:

learning_log$ virtualenv 11_env

New python executable in 11_env/bin/python

Installing setuptools,pip....done

learning_log$

注意:如果你的系統安裝了多個Python版本,需要指定virtualenv使用的版本。例如,命令virtualenv 11_env --python=python3創建一個使用python3的虛擬環境。

18.1.4  激活虛擬環境

    建立虛擬環境之后,需要使用下面的命令激活它:

    learning_log$ source 11_env/bin/activate

  (11_env)lenrning_log$             --(1)

  這個命令運行11_env/bin中的腳本activate。環境處於活動狀態時,環境名將包含在括號內,如(1)處所示。在這種情況下,我們可以在環境中安裝包,並使用已安裝的包。我們在11_env中安裝的包僅在該環境處於激活狀態時才可用。

注意:如果我們使用的時Windows系統,請使用命令11_env\Scripts\activate(不包含source)來激活這個虛擬環境。

    要停止使用虛擬環境,可執行命令deactivate:

    (11_env)learning_log$ deactivate

    learning_log$

    如果關閉運行虛擬環境的終端,虛擬環境也將不再處於活動狀態。

18.1.5  安裝Django

    創建並激活虛擬環境后,就可安裝Diango了:

    (11_env)learning_log$ pip install Django

  Installing collected packages:Diango

  Successfully installed Django

  Cleaning up....

  (11_env)learning_log$

    由於我們是在虛擬環境中工作,因此在所有的系統中,安裝Django的命令都形同:不需要指定標志--user,也無需使用python -m pip install package_name這樣較長的命令。

    別忘了,Django僅在虛擬環境處於活動狀態時才可用。

18.1.6  在Django中創建項目

    在依然處於活動的虛擬環境的情況下(11_env包含在括號內),執行如下命令來創建一個項目:

    (11_env)learning_log$ django-admin.py startproject learning_log .                    --(1)

  (11_env)learning_log$ ls                                                             --(2)

    learning_log 11_env manage.py

  (11_env)learning_log$ ls learning_log                                                --(3)

  __init__.py  settings.py  urls.py   wsgi.py

    (1)處的命令讓Django新建一個名為learning_log的新項目。這個命令末尾的句點讓新項目使用合適的目錄結構,這樣開發完成后可輕松地將應用程序

部署到服務器。

注意:千萬不要忘了這個句點,否則部署應用程序時將遭遇一些配置問題。如果忘記了這個句點,就將創建的文件和文件夾刪除(11_env除外),再重新運行這個命令。

    在(2)處,運行了命令ls(在windows系統上應為dir),結果表明Django新建了一個名為learning_log的目錄。它還創建了一個名為manage.py的文件,

這是一個簡單的程序,它接受命令並將其交給Django的相關部分去運行。我們將使用這些命令來管理諸如使用數據庫和運行服務器等任務

    目錄learning_log包含4個文件(見(3)),其中最重要的是settings.py、urls.py和wsgi.py.文件settings.py指定Django如何與我們的系統交互以及如何管理項目。在開發項目的過程中,我們將修改其中一些設置,並添加一些設置。文件urls.py告訴Django應創建哪些網頁來響應瀏覽器請求。文件wsgi.py幫助Django提供它創建的文件,這個文件名是web server gateway interface(Web服務器網關接口)的首字母縮寫。

18.1.7  創建數據庫

    Django將大部分與項目相關的信息都存儲在數據庫中,因此我們需要創建一個供Django使用的數據庫。為給項目"學習筆記"創建數據庫,請在處於活動虛擬環境中的情況下執行下面的命令:

    (11_env)learning_log$ python manage.py migrate

  Operations to perform:                                                   --(1)
    Apply all migrations: admin, auth, contenttypes, sessions
  Running 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 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 sessions.0001_initial... OK
  (11_env) zhuzhu@zhuzhu-K53SJ:~/learning_log$ ls

    11_env  db.sqlite3  learning_log  manage.py

    我們將修改數據庫稱為遷徙數據庫。首次執行命令migrate時,將讓Django確保數據庫與項目的當前狀態匹配。在使用SQLite(后面將更詳細地介紹)的新項目中首次執行這個命令時,Django將新建一個數據庫。在(1)處,Django指出它將創建必要的數據庫表,用於存儲我們將在這個項目(Synchronize unmigrated apps,同步未遷移的應用程序)中使用的信息,再確保數據庫結構與當前代碼(Apply all migrations,應用所有的遷移)匹配。

    在(2)處,我們運行了命令ls,其輸出表明Django又創建了一個文件--db.sqlite3.SQLite是一種使用單個文件的數據庫,時編寫簡單應用程序的理想選擇,因為它讓我們不用太關注數據庫管理的問題。

18.1.8  查看項目

    下面來核實Django是否正確地創建了項目。為此,可執行命令runserver,如下所示:

    (11_env)learning_log$ python manage.py runserver

    Performing system checks...
  System check identified no issues (0 silenced).                        --(1)
  April 08, 2017 - 02:46:03
  Django version 1.11, using settings 'learning_log.settings'            --(2)
  Starting development server at http://127.0.0.1:8000/                  --(3)
  Quit the server with CONTROL-C.
    Django啟動一個服務器,讓我們能夠查看系統中的項目,了解它們的工作情況。當我們在瀏覽器中輸入URL以請求網頁時,該Django服務器將進行相應:生成合適的網頁,並將其發送給瀏覽器。

    在(1)處,Django通過檢查確認正確地創建了項目;在(2)處,它指出了使用的Django版本以及當前使用的設置文件的名稱;在(3)處,它指出了項目的URL。URL https://127.0.0.1:8000/表明項目將在我們的計算機(即localhost)的端口8000上偵聽請求。localhost是一種只處理當前系統發出的請求,而不允許其他任何人查看我們正在開發的網頁的服務器。

    現在打開一款Web瀏覽器,並輸入URL: http://localhost:8000/;如果這個不管用,請輸入http://127.0.0.1:8000/。我們將看到類似於圖18-1所示的頁面,這個頁面時Django創建的,讓我們知道到目前為止一切正常。現在暫時不要關閉這個瀏覽器。若要關閉這個服務器,按ctrl+c即可。

注意:如果出現錯誤消息”That port is already in use"(指定端口已被占用),請執行命令Python mangae.py runserver 8001,讓Django使用另一個端口;如果這個端口也不可用,請不斷執行上述命令,並逐漸增大其中的端口號,直到找到可用的端口。

18.2  創建應用程序

    Django項目由一系列應用程序組成,它們協同工作,讓項目成為一個整體。我們暫時只創建一個應用程序,它將完成項目的大部分工作。在第19章,我們將再添加一個終端窗口(或標簽頁),並切換到manage.py所在的目錄。激活該虛擬環境,再執行命令startapp:

    當前,在前面打開的終端窗口中應該還運行着runserver.請再打開一個終端窗口(或標簽頁),並切換到manage.py所在的目錄。激活該虛擬環境,再執行命令startapp:

    learning_log$ source 11_env/bin/activate

  (11_env)learning_log$ python manage.py startapp learning_logs

  (11_env)learning_log$ ls                                          --(1)

  11_env  db.sqlite3  learning_log  learning_logs  manage.py
  (11_env)learning_logs$ ls learning_logs/                         --(2)

  admin.py  apps.py  __init__.py  migrations  models.py  tests.py  views.py
    命令startapp appanme讓Django建立創建應用程序所需的基礎設施。如果現在查看項目目錄,將看到其中新增了一個文件夾learning_logs.打開這個文件夾,看看Django都創建了什么。其中最重要的文件是models.py、admin.pyviews.py。我們將使用models.py來定義我們要在應用程序中管理的數據。admin.py和views.py將在稍后介紹。

18.2.1  定義模型

    我們來想想涉及的數據。每位用戶都需要在學習筆記中創建很多主題。用戶輸入的每個條目都與特定主題相關聯,這些條目將以文本的方式顯示。我們還需要存儲每個條目的時間戳,以便能夠告訴用戶各個條目都是什么時候創建的。

    from django.db import models

  # Create your models here.(在這里創建模型)

    這為我們導入了模塊models,還讓我們創建自己的模型模型告訴Django如何處理應用程序中存儲的數據。在代碼層面,模型就是一個類,就像前面討論的每個類一樣,包含屬性和方法。

下面是表示用戶將要存儲的主題的模型:

    from django.db import models

  class Topic(models.Model):

    '''用戶學習的主題'''

    text = models.CharField(max_length=200)

    date_added = models.DateTimeField(auto_now_add=True)

 

    def __str__(self):

      '''返回模型的字符串表示'''

      return self.text

    我們創建了一個名為Topic的類,它繼承了Model——Django中一個定義了模型基本功能的類。Topic類只有兩個屬性:text和date_added.

  屬性text是一個CharField——由字符或文本組成的數據。需要存儲少量的文本,如名稱、標題或城市時,可使用CharField。定義CharField屬性時,必須告訴Django該在數據庫中預留多少空間。在這里,我們將max_length設置成了200(即200個字符),這對存儲大多數主題名來說足夠了。

  屬性date_added是一個DateTimeField——記錄日期和時間的數據。我們傳遞了實參auto_add_now=True,每當用戶創建新主題時,這都讓Django將這個屬性自動設置成當前日期和時間。

注意:要獲悉可在模型中使用的各種字段,請參閱Django ModelField Reference(Django模型字段參考),其網址為https://docs.djangoproject.com/en/1.8/ref/models/fields/.就當前而言,我們無需全面了解其中的所有內容,但自己開發應用程序時,這些內容會提供極大的幫助。

    我們需要告訴Django,默認應使用那個屬性來顯示有關主題的消息。Django調用方法__str__(self)來顯示模型的簡單表示。在這里,我們編寫了方法__str__(),它放回存儲在text中的字符串。

注意:如果我們使用的是Python2.7,應調用方法__unicode__(),而不是__str__(),但其中的代碼相同。

18.2.2  激活模型

    要使用模型,必須讓Django將應用程序包含到項目中。為此,打開settings.py(它位於目錄learning_log/learning_log中),我們將看到一個這樣的片段,即告訴Django哪些應用程序安裝在項目中:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

    這是一個元祖,告訴Django項目有哪些應用程序組成的。請將INSTALLED_APPS修改成下面這樣,將前面的應用程序添加到這個元祖中:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'''我的應用程序'''
"learning_logs",
]
通過將應用程序編組,在項目不斷增大,包含更多的應用程序時,有助於對應用程序進行跟蹤。這里創建了一個名為My apps的片段,使其能夠存儲於模型
Topic相關的信息。為此,在終端窗口中執行下面的命令:
(11_env)learning_log$ python manage.py makemigrations learning_logs
Migrations for 'learning_logs':
0001-initial.py:
    - Create model Topic
  (11_env)learning_log$
  命令makemigrations讓Django確定該如何修改數據庫,使其能夠存儲與我們定義的新模型相關聯的數據。輸出表明Django創建了一個名為0001-initial.
py的遷徙文件,這個文件將在數據庫中為模型Topic創建一個表。
下面來應用這種遷移,讓Django替我們修改數據庫:
(11_env)learning_log$ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, learning_logs, sessions
Running migrations:
  Applying learning_logs.0001_initial... OK (1)
這個命令的大部分輸出都與我們首次執行命令migrate的輸出相同。我們需要檢查的是(1)處的輸出行,在這里,Django確認為learning_logs應用遷移時
一切正常(ok)。
  每當需要修改“學習筆記”管理的數據時,都采取如下三個步驟:修改models.py;對learning_logs調用makemigrations;讓Django遷移項目。

18.2.3 Django管理網站
  為應用程序定義模型時,Django提供的管理網站(admin site)讓我們能夠輕松地處理模型網站的管理員可以使用管理網站,但普通用戶不能使用。
在本節中,我們將建立管理網站,並通過它使用模型Topic來添加一些主題。

  1.創建超級用戶
  Django允許我們創建具備所有權限的用戶——超級用戶。權限決定了用戶可執行的操作。最嚴格的權限設置只允許用戶閱讀網站的公開信息;注冊了的
用戶通常可閱讀自己的私有數據,還可查看一些只有會員才能查看的信息。為有效地管理Web應用程序,網站所有者通常需要訪問網站存儲的所有信息。優秀的
管理員會小心對待用戶的敏感信息,因為用戶對其訪問的應用程序有極大的信任。
  為在Django中創建超級用戶,請執行下面的命令並按提示做:
  (11_env)learning_log$ python manage.py createsuperuser
  username(leave blank to use 'ehmatthes'): 11_admin
  Email address:
  Password:
  Password(again):
  Superuser created successfully.
  (11_env)learning_log$
我們執行命令createsuperuser時,Django提示我們輸入超級用戶的用戶名。這里我們輸入的時11_admin,但我們可以輸入任何用戶名,比如電子郵件
地址,也可以讓這個字段為空。我們需要輸入密碼兩次。

注意:可能會對網站管理員隱藏有些敏感信息。例如,Django並不存儲我們輸入的密碼,而存儲從該密碼派生出來的一個字符串——散列值。每當我們
輸入密碼時,Django都計算其散列值,並將結果於存儲的散列值進行比較。如果這兩個散列值相同,就通過了身份驗證。通過存儲散列值,即便黑客獲得了網
站的數據庫的訪問權,也只能獲取其中存儲的散列值,而無法獲得密碼。在網站配置正確的情況下,幾乎無法根據散列值推導出原始密碼。

2.向管理網站注冊模型
  Django自動在管理網站中添加了一些模型,如user和Group,但對於我們創建的模型,必須手工進行注冊。
  我們創建應用程序learning_logs時,Django在models.py所在的目錄中創建了一個名為admin.py的文件。
  admin.py
  from django.contrib import admin
  from learning_logs.models import Topic --(1)
  admin.site.register(Topic) --(2)
這些代碼導入我們要注冊的模型Topic(見(1)),再使用admin.site.register()(見(2))讓Django通過管理網站管理我們的模型。
現在,使用超級用戶賬戶訪問管理網站:訪問http://localhost:8000/admin/,並輸入我們剛創建的超級用戶的用戶名和密碼,我們將看到類似於下圖所
示的屏幕。這個網頁讓我們能夠添加和修改用戶組,還可以管理與剛才定義的模型Topic相關的數據。

  訪問http://localhost:8000/admin/,將提示我們輸入用戶名和密碼如上圖所示:接下來,我們登錄就可以看見我們創建的應用程序:如下所示:

注意:如果我們在瀏覽器中看到一條消息,指出訪問的網頁不可用,請確認我們在終端窗口中運行着Django服務器如果沒有請激活虛擬環境,並執行命令python manage.py runserver

  3.添加主題

  向管理網站注冊Topic后,我們來添加第一個主題。為此,單擊Topic進入主題網頁,它幾乎是空的,這是因為我們沒有添加任何主題。單擊Add,我們將看到一個用於添加主題的表單。在第一個方框中輸入Chess,再單擊Save,這將返回到主題管理頁面,其中包含剛創建的主題。

18.2.4  定義模型Entry

    要記錄學到的國際象棋和攀岩知識,需要為用戶可在學習筆記中添加的條目定義模型。每個條目都與特定主題相關聯,這種關系被稱為多對一關系,即多個條目可關聯到同一個主題。

    下面時模型Entry的代碼:

models.py

from django.db import models

class Topic(models.Model):

 '''用戶學習的主題'''
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)

def __str__(self):
'''返回模型的字符串表示'''
return self.text

class Entry(models.Model):                                          (1)

  '''學到的有關某個主題的具體知識'''

  topic = models.Foreignkey(Topic)                                 (2)

  text = models.TextField()                                        (3)

  date_added = models.DateTimeField(anto_now_add=True)

  class Meta:                                                       (4)

    verbose_name_plural = 'entries'

    def __str__(self):

      '''返回模型的字符串表示'''

      return self.text[:50] + "..."                              (5)

    像Topic一樣,Entry也繼承了Django基類Model。第一個屬性topic是一個Foreignkey實例。外鍵時一個數據庫術語,它引用數據庫中的另一條記錄這些代碼每個條目關聯到特定的主題。每個主題創建時,都給它分配一個鍵(或ID).需要在兩項數據之間建立聯系時,Django使用與每項信息相關聯的鍵。稍后我們將根據這些聯系獲取與特定主題相關聯的所有條目。

    接下來時屬性text,它是一個TextField實例。這種字段不需要長度限制,因為我們不想限制條目的長度。屬性date_added讓我們能夠按創建順序呈現條目,並在每個條目旁邊放置時間戳。

    在(4)處,我們在Entry類中嵌套了Meta類。Meta存儲用於管理模型的額外信息,在這里,它讓我們能夠設置一個特殊屬性,讓Django在需要時使用Entries來表示多少個條目。如果沒有這個類,Django將使用Entrys來表示多少個條目。最后,方法__str__()告訴Django,呈現條目時應顯示那些信息。由於條目包含的文本可能很長,我們讓Django只顯示text的前個字符。我們還添加了一個省略號,指出顯示的並非整個條目。

18.2.5  遷徙模型Entry

    由於我們添加了一個新模型,因此需要再次遷移數據庫。我們將慢慢地對這個過程了如指掌:修改models.py,執行命令python manage.py makemigrations app_name,再次執行命令python manage.py migrate.

  下面來遷移數據庫並查看輸出:

  (11_env) learning_log$ python manage.py makemigrations learning_logs

  Migrations for 'learning_logs':

    0002_entry.py                                              (1)

     - Create model Entry

  (11_env)learning_log$ python manage.py migrate

  Operations to perform:

    Applying learning_logs.0002_entry... OK                        (2)

    生成了一個新的遷移文件——0002_entry.py,它告訴Django如何修改數據庫,使其能夠存儲與模型Entry相關的信息。執行命令migrate,我們發現Django應用了這種遷移且一切順利。

18.2.6  向管理網站注冊Entry

  我們還需要注冊模型Entry。為此,需要將admin.py修改成類似於下面這樣:

  admin.py

  from django.contrib import admin

  from learning_logs.models import Topic,Entry

  admin.site.register(Topin)

  admin.site.register(Entry)

  返回到http://localhost:8000/adimin/,我們將看到learning_logs下列出了Entries。單擊Entries的Add鏈接,或者單擊Entries再選擇Add entry。我們將看到一個下拉列表,讓我們能夠選擇要為哪個主題創建條目,還有一個用於輸入條目的文本框。從下拉列表中選擇Chess,並添加一個條目。下面是我們添加的第一個條目。

    The opening is the first part of the game,roughly the first ten moves or so. In the opening,it's a good idea to do three things—— bring out your bishops and knights,try to control the center of the board,and castle your king.
    Of course,these are just guidelines.It will be important to learn when to follow these guidelines and when to disregard these suggestions.

    當我們點擊Save時,將返回到主條目管理頁面。在這里,我們將發現使用text[:50]作為條目的字符串表示的好處:管理界面中,只顯示了條目的開頭部分而不是其所有文本,這使得管理多個條目容易很多。

  再來創建一個國際象棋條目,並創建一個攀岩條目,以提供一些初始數據。下面時第二個國際象棋條目。

    The opening is the first part of the game,roughly the first ten moves or so. In the opening,it's a good idea to do three things—— bring out your bishops and knights,try to control the center of the board,and castle your king.
    Of course,these are just guidelines.It will be important to learn when to follow these guidelines and when to disregard these suggestions.

    繼續往下開發“學習筆記”時,這三個條目可為我們提供使用的數據。

18.2.7  Django shell

    輸入一些數據后,就可通過交互式終端會話以編程方式查看這些數據了。這種交互環境稱為Django shell,是預測項目和排除其故障的理想之地。下面是一個交互式shell會話示例:

  (11_env)learning_log$ python3 manage.py shell

  >>> from learning_logs.models import Topic

  >>> Topic.objects.all()
  <QuerySet [<Topic: Chess>, <Topic: Rock Climbing>]>
    在活動的虛擬環境中執行時,命令python manage.py shell啟動一個Python解釋器,可使用它來探索存儲在項目數據庫中的數據。在這里,我們導入了模塊learning_logs.models中的模型Topic,然后使用方法Topic.objects.all()來獲取模型Topic的所有實例;它返回的是一個列表,稱為查詢集(queryset).

>>> topics = Topic.objects.all()
>>> for topic in topics:
...     print(topic.id,topic)
...
1 Chess
2 Rock Climbing
    我們將返回的查詢存儲在topics中,然后打印每個主題的id屬性和字符串表示。從輸出可知,主題Chest的ID為1,而Rock Climbing的ID為2。

    知道對象的ID后,就可獲取對象並查看其任何屬性。下面來看看主題Chess的屬性text和date_added的值。

    >>> t = Topic.objects.get(id=1)
  >>> t.text
  'Chess'
  >>> t.date_added
  datetime.datetime(2017, 4, 8, 7, 50, 40, 109351, tzinfo=<UTC>)
    我們還可以查看與主題相關聯的條目。前面我們給模型Entry定義了屬性topic,這是一個ForeighKey,將條目和主題關聯起來。利用這種關聯,Django能夠獲取與特定主題相關聯的所有條目,如下所示:

  >>> t.entry_set.all()
  <QuerySet [<Entry: Entry object>, <Entry: Entry object>]>
    為通過外鍵關系獲取數據,可使用相關模型的小寫名稱、下划線和單詞set.例如,假設我們有模型Pizza和Topping,而Topping通過一個外鍵關聯到Pizza如果我們有一個名為my_pizza的對象,表示一張比薩,就可以使用代碼my_pizza.topping_set.all()來獲取這張比薩的所有配料。

    編寫用戶可請求的網頁時,我們將使用這種語法。確認代碼能夠獲取所需的數據時,shell很有用幫助。如果代碼在shell中的行為符合預期,那么它們在項目文件中也能正確地工作。如果代碼引發了錯誤或獲取的數據不符合預期,那么在簡單的shell環境中排除故障要比在生成網頁的文件中排除故障容易得多。我們不會太多地使用shell,但應繼續使用它熟悉對存儲在項目中的數據進行訪問的Django語法。

注意:每次修改模型后,我們都要重啟shell,這樣才能看到修改的效果。要退出shell會話,可按ctrl+D;如果我們使用的時windows,應按Ctrl+Z,再按回車鍵

18.3  創建網頁:學習筆記主頁

    使用Django創建網頁的過程通常分三個階段:定義URL、編寫視圖和編寫模板。首先,我們必須定義URL模式。URL模式描述了URL是如何設計的,讓Django知道如何將瀏覽器請求與網站URL匹配,以確定返回那個網頁。

    每個URL都被映射到特定的視圖——視圖函數獲取並處理網頁所需的數據。視圖函數通常調用一個模板,后者生成瀏覽器能夠理解的網頁。為明白其中的工作原理,我們來創建學習筆記的主頁。我們將定義該主頁的URL、編寫其視圖函數並創建一個簡單的模板。

  鑒於我們只是要確保"學習筆記"按要求的那樣工作,我們將暫時讓這個網頁盡可能簡單。Web應用程序能夠正常運行后,設置樣式可使其更有趣,但中看不中用的應用程序毫無意義。就目前而言,主頁只顯示標題和簡單的描述。

18.3.1  映射URL

    用戶通過在瀏覽器中輸入URL以及打擊鏈接來請求網頁,因此我們需要確定項目需要那些URL.主頁的URL最重要,它是用戶用來訪問項目的基礎URL.當前,基礎URL(http://localhost:8000/)返回默認的Django網站,讓我們知道正確地建立了項目。我們將修改這一點,將這個基礎URL映射到“學習筆記”的主頁。

  打開項目主文件夾learning_log中的urls.py,我們將看到如下代碼:

  urls.py

  from django.conf.urls import url
  from django.contrib import admin

  urlpatterns = [                                           --(3)
      url(r'^admin/', admin.site.urls),
  ]

    前兩行導入了為項目和管理網站管理URL的函數和模塊。這個文件的主體定義了變量urlpatterns。在這個針對整個項目的urls.py文件中,變量urlpatterns包含項目中的應用程序URL.(3)處的代碼包含模塊admin.site.urls,該模塊定義了可在管理網站中請求的所有URL.

    我們需要包含learning_logs的URL.

  from django.conf.urls import include,url

  from django.contrib import admin

  urlpatterns = [

      url(r'^admin/',include(admimn.site.urls),

      url(r'',include('learning_logs.urls,namespace='learning_logs')),                (1)

  ]

  在(1)處,我們添加了一行代碼來包含模塊learning_logs.urls。這行代碼包含實參namespace,讓我們能夠將learning_logs的URL同項目中其他的URL區分開來,這在項目開始擴展時很有幫助。

    默認的urls.py包含在文件夾learning_log中,現在我們需要在文件夾learning_logs中創建另一個urls.py文件:

    urls.py

  """定義learning_logs的URL模式"""                                   --(1)

  from django.conf.urls import url                                  --(2)

  from . import views                                               --(3)

  urlpatterns = [                                                   --(4)

  #主頁

    url(r'&^$',views.index,name='index'),                         --(5)

  ]

    為弄清楚當前位於哪個urls.py文件中,我們在這個文件開頭添加了一個文檔字符串(見(1))。接下來,我們導入了函數url,因為我們需要使用它來將URL映射到視圖(見(2))。我們還導入了模塊views(見(3)),其中的句點讓Python從當前的ruls.py模塊所在的文件夾中導入視圖。在這個模塊中,變量urlpatterns是一個列表,包含可在應用程序learning_logs中請求的網頁(見(4))。

    實際的URL模式是一個對函數url()的調用,這個函數接受三個實參。第一個是一個正則表達式Django在urlpatterns中查找與請求的URL字符串匹配的正則表達式,因此正則表達式定義了Django可查找的模式。

  我們來看看正則表達式r'^$。其中的r讓Python將接下來的字符串視為原始字符串,而引號告訴Python正則表達式始於和終於何處。脫字符(^)讓Python查看字符串的開頭,而美元符號讓Python查看字符串的末尾。總體而言,這個正則表達式讓Python查找開頭和末尾之間沒有任何東西的URL.Python忽略項目的基礎URL(http://localhost:8000/),因此這個正則表達式與基礎URL匹配。其他URL都與這個正則表達式不匹配。如果請求的URL不與任何URL模式匹配,Django將返回一個錯誤頁面。

  url()的第二個實參(見(5))指定了要調用的視圖函數。請求的URL與前述正則表達式匹配時,Django將調用views.index(這個視圖函數將在下一節編寫).

第三個實參將這個URL模式的名稱指定為index,讓我們能夠在代碼的其他地方引用它。每當需要提供到這個主頁的鏈接時,我們都將使用這個名稱,而不編寫URL.

注意:正則表達式通常被稱為regex,幾乎每種編程語言都使用它。它們的用途多的難以置信,但需要經過一定的練習才能熟悉。如果我們不明白前面介紹的內容,也不用擔心,我們在完成這個項目的過程中,將會看到很多正則表達式。

18.3.2  編寫視圖

    視圖函數接受請求中的信息,准備好生成網頁所需的數據,再將這些數據發送給瀏覽器——這通常時使用定義了網頁是什么樣的模板實現的。

    learning_logs中的文件views.py是我們執行命令python manage.py startapp時自動生成的,當前其內容如下:

  from django.shortcuts import render

  # Create your views here.(在這里創建視圖)

  def index(request):

  '''學習筆記主頁'''

    return render(request,'learning_logs/index.html')

    URL請求與我們剛才定義的模式匹配時,Django將在文件views.py中查找函數index(),再將請求對象傳遞給這個視圖函數。在這里,我們不需要處理任何數據,因此這個函數只包含調用render()的代碼。這里向函數render()提供了兩個實參:原始請求對象以及一個可用於創建網頁的模板。下面來編寫這個模板。

18.3.3  編寫模板

    模板定義了網頁的結構。模板指定了網頁時什么樣的,而每當網頁被請求時Django將填入相關的數據。我們的主頁視圖沒有提供任何數據,因此相應的模板非常簡答。

  在文件夾learning_logs中新建一個文件夾,並將其命名為templates。在文件夾templates中,在新建一個文件夾,並將其命名為learning_logs。這好像有點多余(我們在文件夾learning_logs中創建了文件夾templates,又在這個文件夾中創建了文件夾learning_logs),但建立了Django能夠明確解讀的結構,即便項目很大,包含很多應用程序亦如次。在最里面的文件夾learning_logs中,新建一個文件,並將其命名為index.html,再在這個文件中編寫如下代碼:

index.html

<p>Learning Log</p>

<p>Learning Log helps you keep track of your learning, for any topic you're learning about.</p>

    這個文件非常簡單。對於不熟悉HTML的讀者,這里解釋一下:標簽<p></P>標識段落;標簽<p>指出了段落的開頭位置,而標簽</p>指出了段落的結束位置。這里定義了兩個段落:第一個充當標題,第二個闡述了用戶可使用"學習筆記"來做什么。

  現在,如果我們請求這個項目的基礎URL——http://localhost:8000/,將看到剛才創建的網頁,而不是默認的Django網頁。Django接受請求的URL,發現該URL與模式r'^$'匹配,因此調用函數views.index(),這將使用index.html包含的模板來渲染網頁,結果如圖所示:

    創建網頁的過程看起來可能很復雜,但將URL、視圖和模塊分離的效果實際上很好。這讓我們能夠分別考慮項目的不同方面,且在項目很大時,讓各個參與者可專注於其最擅長的方面。例如,數據庫專家專注於模型,程序員專注於視圖代碼,而Web設計人員可專注於模板。

18.4  創建其他網頁

    制定創建網頁的流程后,可以開始擴充“學習筆記”項目了。我們將創建兩個顯示數據的網頁,其中一個列出了所有的主題,另一個顯示特定主題的所有條目。對於每個網頁,我們都將指定URL模式,編寫一個視圖函數,並編寫一個模板。但這樣做之前,我們先創建一個父模板,項目中的其他模板都將繼承它。

18.4.1  模板繼承

    創建網站時,幾乎都有一些所有網頁都將包含的元素。在這種情況下,可編寫一個包含通用元素的父模板,並讓每個網頁都繼承這個模板,而不必在每個網頁中重復定義這些通用元素。這種方法能讓我們專注於開發每個網頁的獨特方面,還能讓修改項目的整體外觀容易很多。

    1.父模板

    我們首先創建一個名為base.html的模板,並將其存儲在index.html所在的目錄中。這個文件包含所有頁面都有的元素;其他的模板都繼承base.html。當前,所有頁碼都包含的元素之后頂端的標題。我們將在每個頁面中包含這個模板,因此我們將這個標題設置為到主頁的鏈接:

    base.html

    <p>

      <a href="{% url 'learning_logs:index' %}">Learning Log</a>                --(1)

  </p>

  {% block content $}{% endblock content %}                                  --(2)

    這個文件的第一部分創建了一個包含項目名的段落,該段落也是一個到主頁的鏈接。為創建鏈接,我們使用了一個模板標簽,它是用大括號和百分號({% %})表示的。模板標簽是一小段代碼,生成要在網頁中顯示的信息。在這個實例中,模板標簽{% url 'learning_logs:index' %}生成一個URL,該URL與learning_logs/urls.py中定義的名為index的URL模式匹配。在這個示例中,learning_logs是一個命令空間,而index是該命名空間中一個獨特的URL模式。

    在簡單的HTML頁面中,鏈接是使用錨標簽定義的:

    <a href="link_url">link text</a>

    讓模板標簽來生成URL,可讓鏈接保持最新容易的多。要修改項目中的URL,只需修改urls.py中的URL模式,這樣網頁被請求時,Django將自動插入修改后的URL.在我們的項目中,每個網頁都將繼承base.html,因此從現在開始,每個網頁都包含到主頁的鏈接。

    在(2)處,我們插入了一對塊標簽。每個塊名為content,是一個占位符,其中包含的信息將由子模板指定。

    子模板並非必須定義父模板中的每個塊,因此在父模塊中,可使用任意多個塊來預留空間,而子模板可根據需要定義相應數量的塊。

注意:在Python代碼中,我們幾乎總是縮進四個空格。相比於Python文件,模板文件的縮進層級更多,因此每個層級通常只縮進兩個空格

 

2.子模板

    現在需要重新編寫index.html,使其繼承base.html,如下所示:

    index.html

  {% extends "learning_logs/base.html" %}                          --(1)

    {% block content %}                                              --(2)

     <p>Learning Log helps you keep track of your learning, for any topic you're learning about.</P>

    {% endblock content %}                                           --(3)

    如果將這些代碼與原來的index.html進行比較,可發現我們將標題Learning Log替換成了從父模板那里繼承的代碼(見1)。子模板的第一行必須包含標簽{% extends %},讓Django知道它繼承了哪個父模板。文件base.html位於文件夾learning_logs中,因此父模板路徑中包含learning_logs。這行代碼導入模板base.html的所有內容,讓index.html能夠指定要在content塊預留的空間中添加的內容。

    在(2)處,我們插入了一個名為content的{% block %}標簽,以定義content塊。不是從父模板繼承的內容都包含在content塊中,在這里是一個描述項目“學習筆記”的段落。在(3)處,我們使用標簽{% endblock content %}指出了內容定義的結束位置。

    模板繼承的有點開始顯現出來了:在子模板中,只需包含當前網頁特有的內容。這不僅簡化了每個模板,還使得網頁修改起來容易很多。要修改很多網頁都包含的元素,只需在父模板中修改該元素,我們所做的修改將傳導到繼承該父模板的每個頁面。在包含數十乃至數百個網頁的項目中,這種結構使得網站改進起來容易而且快捷得多。

注意:在大型項目中,通常有一個用於整個網站的父模板——base.html,且網站的每個主要部分都有一個父模板。每個部分的父模板都繼承base.html,而網站的每個網頁都繼承相應的部分的父模板。這讓我們能夠輕松地修改整個網站的外觀、網站任何一部分的外觀以及任何一個網頁的外觀。這種配置提供了一種效率極高的工作方式,讓我們樂意不斷去改進網站。

18.4.2  顯示所有主題的頁面

    有了高效的網頁創建方法,就能專注於另外兩個網頁了:顯示全部主題的網頁以及顯示特定主題中條目的網頁。所有主題頁面顯示用戶創建的所有主題,它是第一個需要使用數據的網頁。

    1.URL模式

    首先,我們來定義顯示所有主題的頁面的URL.通常,使用一個簡單的URL片段來指出網頁顯示的消息;我們將使用單詞topics,因此URL http://localhost:8000/topics/將返回顯示所有主題的頁面。下面演示了該如何修改learning_logs/urls.py:

    urls.py

    """為learning_logs定義URL模式"""

    from django.conf.urls import url
  from . import views
    urlpatterns = [

      #主頁

   url(r'^$',views.index,name='index'),

    #顯示所有的主題

   url(r'^topics/$',views.topics,name='topics'),                --(1)

  ]

    我們只是在用於主頁URL的正則表達式中添加了topics/(見(1)).Django檢查請求的URL時,這個模式與這樣的RUL匹配:基礎URL后面跟着topics。可以在末尾包含斜杠,也可以省略它,但單詞topics后面不能有任何東西,否則就與該模式不匹配。其URL與該模式匹配的請求都將交給views.py中的函數topics()進行處理。

    2.視圖

    函數topics()需要從數據庫中獲取一些數據,並將其發送給模板。我們需要在views.py中添加的代碼如下:

views.py

from django.shortcuts import render
from .models import Topic                                     --(1)

# Create your views here.
def index(request):                                     
    """學習筆記的主頁"""
    return render(request,'learning_logs/index.html')

def topics(request):                                          --(2)
    """顯示所有的主題"""
    topics = Topic.objects.order_by("date_added")             --(3)
    context = {'topics':topics}                           --(4)
    return render(request,'learning_logs/topics.html',context)  (5)

    我們首先導入了與所需數據相關聯的模型(見(1))。函數topics()包含一個形參:Django從服務器那里收到的request對象(見(2))。在(3)處,我們查詢數據庫——請求提供Topic對象,並按屬性date_added對它們進行排序。我們將返回的查詢集存儲在topics中。

    在(4)處,我們定義了一個將要發送給模板的上下文上下文是一個字典,其中的鍵是我們將在模板中用來訪問數據的名稱,而值是我們要發送給模板的數據。在這里,只有一個鍵-值對,它包含我們將在網頁中顯示的一組主題。創建使用數據的網頁時,處對象request和模板的路徑外,我們還將變量context傳遞給render()。

    3.模板

    顯示所有主題的頁面的模板接受字典context,以便能夠使用topics()提供的數據。請創建一個文件,將其命名為topics.html,並將其存儲到index.html所在的目錄中。下面演示了如何在這個模板中顯示主題:

topics.html

{% extends "learning_logs/base.html" %}

{% block content %}

  <p>Topics</p>
  <ul>                                                          --(1)
    {% for topic in topics %}                                   --(2)
      <li>{{topic}}</li>                                        --(3)
    {% empty %}                                                 --(4)
      <li>No topics have been added yet.</li>
    {% endfor %}                                                --(5)
  </ul>                                                         --(6)

{% endblock content %}

    就像模板index.html一樣,我們首先使用標簽{% extends %}來繼承base.html,再開始定義content塊。這個網頁的主體是一個項目的列表,其中列出了用戶輸入的主題。在標准HTML中,項目列表被稱為無序列表,用標簽<ul></ul>表示。包含所有主題的項目列表始於(1)處。

    在(2)處,我們使用了一個相當於for循環的模板標簽,它遍歷字典context中的列表topics。模板中使用的代碼與python代碼存在一些重要差別:Python使用縮進來指出那些代碼行是for循環的組成部分,而在模板中,每個for循環都必須使用{% endfor %}標簽來顯示地指出其結束位置。

    因此在模板中,循環類似於下面這樣:

    {% for item in list %}

      do something with each item

  {% endfor %}

    在循環中,我們要將每個主題轉換為一個項目列表項。要在模板中打印變量,需要將變量名用雙花括號括起來。每次循環時,(3)處的代碼{{topic}}都被替換為topic的當前值。這些花括號不會出現在網頁中,它們只是用於告訴Django我們使用了一個模板變量。HTML標簽<li></li>表示一個項目列表項,在標簽<ul></ul>之間的內容都是一個項目列表項。

    在(4)處,我們使用了模板標簽{% empty %} ,它告訴django在列表topics為空時該怎么辦:這里是打印一條消息,告訴用戶還沒有添加任何主題。最后兩行分別結束for循環和項目列表。

    現在需要修改父模板,使其包含到顯示所有主題的頁面的鏈接:

    base.html

<p>
  <a href="{% url 'learning_logs:index' %}">Learning Log</a> -               --(1)
  <a href="{% url 'learning_logs:topics' %}">Topics</a>                      --(2)
</p>

{% block content %}{% endblock content %}

    我們在到主頁的鏈接后面添加了一個連字符(見(1)),然后添加了一個到顯示所有主題的頁面的鏈接——使用的也是模板標簽url(見(2)).這一行讓Django生成一個鏈接,它與learning_logs/urls.py中名為topics的URL模式匹配。

    現在如果我們刷新瀏覽器中的主頁,將看到鏈接Topics。單擊這個鏈接,將看到類似於下圖所示的網頁:

18.4.3  顯示特定主題的頁面

    接下來,我們需要創建一個專注於特定主題的頁面——顯示該主題的名稱及該主題的所有條目。同樣,我們將定義一個新的URL模式,編寫一個視圖並創建一個模板。我們還將修改顯示所有主題的網頁,讓每個項目列表都是一個鏈接,單擊它將顯示相應主題的所有條目。

    1.URL模式

    顯示特定主題的頁面的URL模式與前面的所有URL模式都稍有不同,因為它將使用主題的ID屬性來指出請求的時哪個主題。例如,如果用戶要查看主題Chess (其id為1)的詳細頁面,URL將為http://localhost:8000/topics/1/。下面是與這個URL匹配的模式,它包含在learning_logs/ruls.py中:

'''定義learning_logs的URL模式'''
from django.conf.urls import url
from . import views

urlpatterns = [
    #主頁
    url(r'^$',views.index,name='index'),
        #顯示所有的主題
    url(r'^topics/$', views.topics,name='topics'),
        #特定主題的詳細頁面
    url(r'^topics/(?p<topic_id>\d+)/$',views.topic,name='topic'),
]
    我們來詳細研究這個URL模式中的正則表達式——r'^topics/(?p<topic_id>\d+)/$'.r讓Django將這個字符串視為原始字符串,並指出正則表達式包含在引號內。這個表達式的第二部分(?p<topic_id>\d+)與包含在兩個斜杠內的整數匹配,並將這個整數存儲在一個名為topic_id的實參中。這部分表達式兩邊的括號內捕獲URL中的值;?p<topic_id>將匹配的值存儲到topic_id中;而表達式\d+與包含在兩個斜杠內的任何數字都匹配,不管這個數字為多少位。

    發現URL與這個模式匹配時,Django將調用視圖函數topic(),並將存儲在topic_id中的值作為實參傳遞給它。在這個函數中,我們將使用topic_id的值來獲取相應的主題。

    2.視圖

    函數topic()需要從數據庫中獲取指定的主題以及與之相關聯的所有條目,如下所示:

    views.py

    --snip--

    def topic(request,topic_id):                                                     (1)
    """顯示單個主題及其所有的條目"""
    topic = Topic.objects.get(id=topic_id)                                           (2)
    entries = topic.entry_set.order_by('-date_added')                                (3)
    context = {'topic':topic,'entries':entries}                                      (4)
    return render(request, 'learning_logs/topic.html',context)                       (5)
    這是第一個除request對象外還包含另一個形參的視圖函數。這個函數接受正則表達式(?p<topic_id>\d+)捕獲的值,並將其存儲到topic_id中(見(1))。在(2)處,我們使用get()來獲取指定的主題,就像前面在Django shell中所做的那樣。在(3)處,我們獲取與該主題相關聯的條目,並將它們按date_added排序:
date_added前面的減號指定按降序排列,即先顯示最近的條目。我們將主題和條目都存儲在字典context中(見(4)),再將這個字典發送給模板topic.html。

注意:(2)處和(3)處的代碼被稱為查詢,因為它們向數據庫查詢特定的信息。在自己的項目中編寫這樣的查詢時,現在Django shell中進行嘗試大有裨益。相比於編寫視圖和模板,再在瀏覽器中檢查結果,在shell中執行代碼可更快地獲得反饋。

    3.模板

    這個模板需要顯示主題的名稱和條目的內容;如果當前主題不包含任何條目,我們還需向用戶指出這一點:

{% extends "learning_logs/base.html" %}

{% block content %}

  <p>Topic:{{ topic }}</p>                                           (1)
  <p>Entries:</p>

  <ul>                                                               (2)
    {% for entry in entries %}                                       (3)
      <li>
        <p>{{ entry.date_added|date:'M d,Y H:i'}}</p>                (4)
        <p>{{ entry.text|linebreaks }}</p>                           (5)
      </li>
    {% empty %}                                                      (6)
      <li>
        There are no entries for this topic yet.
      </li>
    {% endfor %}
  </ul>

{% endblock content %}

    像這個項目的其他頁面一樣,這里也繼承了base.html。接下來,我們顯示當前的主題,它存儲在模板變量{{ topic }}中。為什么可以使用變量topic呢?因為它包含在字典context中。接下來,我們開始定義一個顯示每個條目的項目列表,並像前面顯示所有主題一樣遍歷條目(見(3)).

    每個項目列表項都將列出兩項信息:條目的時間戳和完整的文本。為列出時間戳(見(4)),我們顯示屬性date_added的值。在Django模板中,豎線(|)表示模板過濾器——對模板變量的值進行修改的函數。過濾器date: 'M d,Y H:i'以這樣的格式顯示時間戳:january 1,2015 23:00.接下來的一行顯示text的完整值,而不僅僅是entry的前50個字符。過濾器linebreaks(見(5))將包含換行符的長條目轉換為瀏覽器能夠理解的格式,以免顯示為一個不間斷的文本塊。在(6)處,我們使用模板標簽{% empty %}打印一條消息,告訴用戶當前主題還沒有條目。

    4.將顯示所有主題的頁面中的每個主題都設置為鏈接

    在瀏覽器中查看顯示特定主題的頁面前,我們需要修改模板topics.html,讓每個主題都鏈接到相應的網頁,如下所示:

{% extends "learning_logs/base.html" %}

{% block content %}

  <p>Topics</p>
 
  <ul>
    {% for topic in topics %}
      <li>
        <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
      </li>
    {% empty %}
      <li>No topics have been added yet.</li>
    {% endfor %}
  </ul>

{% endblock content %}

    我們使用模板標簽url根據learning_logs中名為topic的URL模塊來生成合適的鏈接。這個URL模式要求提供實參topic_id,因此我們在模板標簽url中添加了屬性topic.id。現在,主題列表中的每個主題都是一個鏈接,鏈接到顯示相應主題的頁面,如http://localhost:8000/topics/1/.

    如果我們刷新顯示所有主題的頁面,再單擊其中的一個主題,將看到類似於圖18-5所示的頁面。

18.5  小結

    在本章中,我們首先學習了如何使用Django框架來創建Wed應用程序。我們制定了簡要的項目規范,在虛擬環境中安裝了Django,創建了一個項目,並核實項目已正確地創建。我們學習了如何創建應用程序,以及如何定義表示應用程序數據的模型。我們學習了數據庫,以及在我們修改模型后,Django可為你遷移數據庫提供什么樣的幫助。我們學習了如何創建可訪問管理網站的超級用戶,並使用管理網站輸入了一些初始數據。

    我們還探索了Django shell,它讓我們能夠在終端會話中處理項目的數據。我們學習了如何定義URL、創建視圖函數以及編寫為網站創建網頁的模板。最后,我們使用了模板繼承,它可簡化各個模板的結構,並使得修改網站更容易。

    在第19章,我們將創建對用戶友好而直觀的網頁,讓用戶無需通過管理網站就能添加新的主題和條目,以及編輯既有的條目。我們還添加了一個用戶注冊系統,讓用戶能夠創建賬戶和自己的學習筆記。讓任意數量的用戶都能與之交互,是Web應用程序的核心所在。

 

 

   

 

   

 

   

 

 

 

 

 

   

 

  

   

   

   

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM