title: 深入Django項目實戰與最佳實踐 date: 2024/5/19 21:41:38 updated: 2024/5/19 21:41:38 categories: 後端開發 tags: Django 基礎 項目實戰 最佳實踐 資料庫配置 靜態文件 部署 高級特性 第一章:Django ...
title: 深入Django項目實戰與最佳實踐
date: 2024/5/19 21:41:38
updated: 2024/5/19 21:41:38
categories:
- 後端開發
tags:
- Django 基礎
- 項目實戰
- 最佳實踐
- 資料庫配置
- 靜態文件
- 部署
- 高級特性
第一章:Django項目架構與設計原則
Django框架概述
Django是一個高級的Python Web框架,它鼓勵快速開發和乾凈、實用的設計。由於其“包含電池”的特性,Django提供了許多構建現代Web應用程式所需的工具和功能,從而減少了開發者需要從頭開始編寫的代碼量。
以下是Django框架的一些核心特點:
-
MTV架構模式: Django遵循模型-模板-視圖(MTV)架構模式,這是對傳統的模型-視圖-控制器(MVC)模式的一種變體。在Django中:
- 模型(Model):代表數據結構,通常對應資料庫中的表。
- 模板(Template):定義了應用程式的展示層,處理用戶界面的顯示。
- 視圖(View):從模型中獲取數據,並將其傳遞給模板進行渲染。
-
ORM(對象關係映射) : Django的ORM允許開發者使用Python代碼來定義和操作資料庫,而不是直接編寫SQL語句。這使得資料庫操作更加抽象和易於管理。
-
自動化管理界面: Django自帶一個自動化管理界面,它可以自動從模型中生成一個管理站點,用於管理網站內容。這個功能非常適合內容管理系統和後臺管理。
-
URL路由: Django提供了一個強大的URL路由系統,允許開發者定義URL模式,將URL映射到特定的視圖函數或類。
-
表單處理: Django提供了一套表單處理機制,可以輕鬆地創建表單、驗證用戶輸入,並處理表單提交。
-
模板系統: Django的模板系統允許開發者將設計與業務邏輯分離,支持模板繼承、包含和過濾器等功能。
-
認證系統: Django內置了一個用戶認證系統,可以處理用戶賬戶、組、許可權和用戶憑據。
-
國際化和本地化: Django支持多語言網站的開發,提供了翻譯文本、格式化日期、時間和數字等功能。
-
安全性: Django提供了多種安全特性,幫助開發者抵禦常見的Web攻擊,如跨站腳本(XSS)、跨站請求偽造(CSRF)和SQL註入等。
-
緩存框架: Django提供了一個靈活的緩存框架,可以提高網站的性能。
-
測試框架: Django內置了測試框架,支持編寫單元測試和集成測試。
-
中間件支持: Django的中間件是一種輕量級、底層級的“插件”系統,用於在全局範圍內改變Django的輸入或輸出。
Django的設計哲學強調了“不要重覆自己”(DRY)原則,鼓勵開發者儘可能地重用代碼,減少重覆勞動。此外,Django社區提供了大量的第三方應用和插件,可以進一步加快開發速度。
MVC與MTV設計模式
MVC(Model-View-Controller)和MTV(Model-Template-View)是兩種常見的設計模式,用於組織Web應用程式的代碼結構。這兩種模式都旨在分離應用程式的不同方面,以提高代碼的可維護性和可擴展性。
MVC(Model-View-Controller)
MVC模式將應用程式分為三個主要組件:
- 模型(Model) : 模型代表應用程式的數據結構和數據邏輯。它通常與資料庫交互,負責數據的存儲、檢索和任何相關的業務邏輯。
- 視圖(View) : 視圖是用戶界面的一部分,負責向用戶展示數據。在MVC中,視圖通常是模型的直接表示,不包含任何業務邏輯。
- 控制器(Controller) : 控制器是模型和視圖之間的中介。它接收用戶的輸入,調用模型來處理這些輸入,並決定哪個視圖應該用來展示結果。
MVC模式的核心思想是將應用程式的數據、用戶界面和控制邏輯分離,使得每個部分可以獨立地修改和測試。
MTV(Model-Template-View)
MTV模式是Django框架採用的一種設計模式,它在概念上與MVC相似,但有一些特定的變化:
- 模型(Model) : 與MVC中的模型相同,Django的模型負責定義數據結構和資料庫交互。
- 模板(Template) : 在MTV中,模板相當於MVC中的視圖。它定義了應用程式的展示層,包括HTML結構和如何顯示數據。模板通常不包含業務邏輯,只負責數據的呈現。
- 視圖(View) : 在Django的MTV模式中,視圖相當於MVC中的控制器。視圖從模型中獲取數據,並將其傳遞給模板進行渲染。視圖處理業務邏輯和決定使用哪個模板來展示數據。
MTV模式在Django中的實現強調了數據和用戶界面的分離,同時也分離了業務邏輯和數據呈現。這種分離使得開發者可以更容易地修改應用程式的外觀和行為,而不影響其他部分。
項目目錄結構與組件介紹
在開發一個基於MVC/MTV模式的Web應用程式時,項目目錄結構通常按照組件類型進行分類。以下是一個基本的項目目錄結構,並介紹了每個組件的職責。
項目目錄結構
project_name/
├── app1/
│ ├── migrations/
│ ├── templates/
│ ├── static/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── app2/
│ ├── migrations/
│ ├── templates/
│ ├── static/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── project_name/
│ ├── settings.py
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py
├── manage.py
└── requirements.txt
組件介紹
-
app1和app2: 這些是應用程式的不同部分,通常用於實現不同的功能。每個應用程式都有自己的模型、視圖、模板和靜態文件。
-
migrations: 該目錄包含資料庫遷移文件,用於在應用程式生命周期中更新資料庫結構。
-
templates: 該目錄包含所有應用程式的模板文件。模板用於定義應用程式的用戶界面,包括HTML結構和如何顯示數據。
-
static: 該目錄包含應用程式的所有靜態文件,如CSS、JavaScript、圖像和字體。
-
project_name: 該目錄包含項目的設置、URL模式和WSGI配置。
- settings.py: 項目的設置文件,包括資料庫配置、靜態文件目錄、安裝的應用程式列表、中間件和第三方庫等。
- urls.py: 項目的URL模式文件,用於將URL路由到相應的視圖函數。
- wsgi.py: 項目的WSGI(Web Server Gateway Interface)配置文件,用於連接Web伺服器和應用程式。
-
manage.py: 一個命令行工具,用於管理和維護Django項目。可以用它來運行遷移、創建應用程式、啟動本地伺服器和執行其他管理任務。
-
requirements.txt: 一個文本文件,包含項目所需的Python包和版本號。可以使用pip安裝所有依賴項:
pip install -r requirements.txt
這個項目結構可以幫助開發人員按照組件類型組織代碼,使得代碼更易於維護和擴展。在實際開發中,可以根據項目需求進行調整和擴展。
最佳實踐:遵循DRY原則、設計可擴展的應用
在開發Web應用程式時,遵循DRY(Don't Repeat Yourself)原則和設計可擴展的應用程式是非常重要的。以下是一些最佳實踐,幫助您遵循DRY原則和設計可擴展的應用程式:
-
遵循DRY原則
不要在多個地方重覆相同或相似的代碼。重覆代碼會導致維護和更新變得困難,並且容易出現錯誤。可以採用以下技巧來遵循DRY原則:
- 使用函數和類,將可重用的代碼封裝在一起。
- 使用django.contrib.auth中的用戶認證和授權功能,而不是自己實現。
- 使用Django的內置Form和ModelForm,而不是直接在視圖函數中處理表單數據。
- 使用Django的緩存系統,減少對資料庫的查詢和計算。
-
設計可擴展的應用
在設計應用程式時,要考慮到將來可能需要擴展的情況。可以採用以下技巧來設計可擴展的應用程式:
- 將應用程式分解成多個小應用,每個應用負責一個特定的功能。
- 使用Django的可插拔應用架構,將應用程式與項目解耦。
- 使用Django的信號系統,在應用程式之間進行解耦和通信。
- 使用Django的 rested_framework 或 Django REST framework 等第三方庫,為API設計可擴展的架構。
- 使用Django的分頁功能,提高應用程式的性能和用戶體驗。
-
使用版本控制和文檔
使用版本控制系統(如Git)來跟蹤代碼變更,併在團隊合作中保持代碼的一致性。同時,為應用程式編寫清晰易懂的文檔,幫助其他開發人員快速理解應用程式的功能和架構。
-
進行單元測試和集成測試
編寫單元測試和集成測試,以確保應用程式的正確性和穩定性。在開發新功能或修複bug時,首先編寫測試用例,然後編寫代碼。這有助於避免在代碼中引入新的錯誤,並確保應用程式的穩定性。
-
監控和優化性能
使用Django的調試工具和分析工具,監控應用程式的性能和記憶體使用情況。在開發過程中,定期對應用程式進行優化,以提高性能和可靠性。
第二章:Django模型與資料庫操作
模型定義與關係設計
在Django中,定義模型和設計關係是實現資料庫應用程式的基本工作。以下是一些最佳實踐,幫助您定義模型和設計關係:
-
使用Django的ORM(Object-Relational Mapping)
使用Django的ORM來定義模型,而不是直接使用SQL語句。Django的ORM可以使用Python代碼來定義資料庫模型,從而使得開發人員可以更加方便和高效地實現資料庫應用程式。
-
設計資料庫模型
在設計資料庫模型時,需要考慮以下幾點:
- 確定模型的屬性和欄位,包括主鍵、外鍵、唯一約束、預設值等。
- 確定模型之間的關係,包括一對一、一對多、多對多等。
- 確定模型的繼承關係,包括抽象模型和多表繼承等。
- 確定模型的索引和唯一性約束,以提高資料庫的查詢性能和數據的完整性。
-
使用外鍵來設計關係
在Django中,可以使用外鍵來設計模型之間的關係。外鍵可以確保數據的一致性和完整性,同時也可以使得數據的查詢和操作更加方便和高效。
-
使用多對多關係
在Django中,可以使用多對多關係來設計模型之間的關係。多對多關係可以使得模型之間的關聯更加靈活和高效,同時也可以使得數據的查詢和操作更加方便和高效。
-
使用模型的Meta選項
在Django中,可以使用模型的Meta選項來設置模型的元數據,包括資料庫表名、資料庫表的欄位、資料庫表的索引等。使用模型的Meta選項可以使得資料庫模型的定義更加簡單和高效。
-
使用Django的migrations功能
在Django中,可以使用migrations功能來管理資料庫模型的變更。migrations功能可以使得資料庫模型的變更更加簡單和高效,同時也可以確保資料庫模型的一致性和完整性。
-
使用Django的資料庫API
在Django中,可以使用資料庫API來實現資料庫的查詢和操作。資料庫API可以使得資料庫的查詢和操作更加方便和高效,同時也可以確保資料庫模型的一致性和完整性。
資料庫遷移與管理
資料庫遷移和管理是在開發過程中非常重要的一環,特別是在使用Django這樣的框架進行開發時。下麵是關於資料庫遷移和管理的一些重要內容:
-
資料庫遷移的概念:
資料庫遷移是指在開發過程中,當資料庫模型發生變化時,需要將這些變化應用到資料庫中,以保持資料庫結構與代碼的一致性。Django中使用
makemigrations
和migrate
命令來進行資料庫遷移。 -
生成遷移文件:
在Django中,通過運行
python manage.py makemigrations
命令,Django會檢測模型文件的變化,並生成相應的遷移文件。遷移文件包含了資料庫模型的變化信息,如創建表、添加欄位、修改欄位類型等。 -
應用遷移文件:
通過運行
python manage.py migrate
命令,Django會執行遷移文件中定義的資料庫操作,將資料庫結構與模型文件保持一致。這個過程會自動創建、修改或刪除資料庫表,欄位等。 -
遷移文件的管理:
Django會為每次遷移操作生成一個唯一的遷移文件,並記錄在資料庫中。可以通過
python manage.py showmigrations
查看已應用和未應用的遷移文件,通過python manage.py migrate <app_name> <migration_name>
來指定應用某個具體的遷移文件。 -
遷移的回滾:
如果需要回滾遷移操作,可以通過
python manage.py migrate <app_name> <migration_name>
命令指定回滾到某個具體的遷移文件,或者通過python manage.py migrate <app_name> zero
命令回滾到初始狀態。 -
資料庫狀態的管理:
Django會維護一個關於資料庫當前狀態的記錄,包括已應用的遷移文件、未應用的遷移文件等。可以通過
python manage.py showmigrations
和python manage.py dbshell
來查看資料庫的狀態和執行原生SQL語句。 -
遷移的最佳實踐:
- 在每次修改模型後及時生成遷移文件,保持資料庫結構與代碼的一致性。
- 在生產環境中謹慎操作遷移,確保備份資料庫並測試遷移操作的影響。
- 避免手動修改資料庫結構,應該通過遷移文件來管理資料庫結構的變化。
使用Django ORM進行資料庫操作
Django ORM(Object-Relational Mapping)是Django框架中的一部分,它提供了一種高級的API來操作資料庫,使開發人員可以使用面向對象的思想來執行資料庫操作。下麵是使用Django
ORM進行資料庫操作的一些重要內容:
-
定義數據模型:
在Django中,使用模型類(Model Class)來定義資料庫表結構,每個模型類對應一個資料庫表,每個模型類的屬性對應資料庫表的欄位。例如:
from django.db import models class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=100) price = models.FloatField()
-
創建資料庫表:
在Django中,使用
python manage.py makemigrations
和python manage.py migrate
命令來創建資料庫表。 -
增加數據:
使用模型類的實例化來創建數據,並使用
save()
方法來保存數據。例如:book = Book(title='Python', author='John', price=25.5) book.save()
-
查詢數據:
Django ORM提供了多種方式來查詢資料庫,可以使用
filter()
、exclude()
、get()
等方法來進行條件查詢,使用all()
方法來獲取所有數據。例如:# 獲取所有圖書 books = Book.objects.all() # 獲取所有價格大於30的圖書 books = Book.objects.filter(price__gt=30) # 獲取所有作者為John的圖書 books = Book.objects.filter(author='John') # 獲取所有作者為John且價格大於30的圖書 books = Book.objects.filter(author='John', price__gt=30) # 獲取所有作者為John且價格大於30的第一本圖書 book = Book.objects.get(author='John', price__gt=30)
-
更新數據:
使用模型類的實例化來獲取數據,並使用模型類的屬性來更新數據,最後使用
save()
方法來保存數據。例如:book = Book.objects.get(title='Python') book.price = 30.5 book.save()
-
刪除數據:
使用模型類的實例化來獲取數據,並使用
delete()
方法來刪除數據。例如:book = Book.objects.get(title='Python') book.delete()
-
資料庫操作的最佳實踐:
- 使用Django ORM提供的API來進行資料庫操作,避免使用原生SQL語句。
- 使用
select_related()
和prefetch_related()
方法來優化資料庫操作,減少資料庫查詢次數。 - 使用
values()
和values_list()
方法來獲取資料庫中的數據,而不是模型類的實例。 - 使用
QuerySet
的filter()
和exclude()
方法來進行條件查詢,避免使用get()
方法。 - 在進行資料庫操作時,使用資料庫事務來確保數據的一致性。
最佳實踐:優化資料庫查詢、使用索引提升性能
在使用 Django ORM 進行資料庫操作時,優化資料庫查詢和使用索引可以提高資料庫性能。以下是一些最佳實踐:
-
使用
select_related()
和prefetch_related()
方法:select_related()
方法可以在查詢時將相關對象的數據載入到記憶體中,避免在執行後續操作時進行多次資料庫查詢。例如:books = Book.objects.select_related('author').all()
prefetch_related()
方法可以在查詢時將相關對象的數據預取到記憶體中,避免在執行後續操作時進行多次資料庫查詢。例如:books = Book.objects.prefetch_related('reviews').all()
-
使用
values()
和values_list()
方法:values()
和values_list()
方法可以直接獲取資料庫中的數據,而不是模型類的實例,可以減少記憶體使用和提高查詢性能。例如:books = Book.objects.values('title', 'author', 'price') books = Book.objects.values_list('title', 'author', 'price')
-
使用索引:
在資料庫表中添加索引可以提高資料庫查詢的性能。可以在資料庫表的欄位上添加索引,例如在 Django 中可以使用
db_index=True
來添加索引。例如:class Book(models.Model): title = models.CharField(max_length=100, db_index=True) author = models.CharField(max_length=100, db_index=True) price = models.FloatField(db_index=True)
-
使用資料庫優化器:
資料庫優化器可以幫助您確定查詢中使用哪些索引,以獲得最佳性能。可以使用資料庫的查詢計劃工具來查看資料庫優化器選擇了哪些索引。
-
使用資料庫事務:
使用資料庫事務可以確保數據的一致性,並減少資料庫查詢次數。可以使用 Django ORM 提供的
atomic()
函數來執行資料庫事務。例如:from django.db import transaction with transaction.atomic(): # 執行資料庫操作
-
使用緩存:
使用緩存可以減少資料庫查詢次數,並提高應用程式的性能。可以使用 Django 提供的緩存框架來實現緩存。
第三章:Django視圖與URL配置
視圖函數與類視圖的編寫
在 Django 中,視圖函數和類視圖是處理 HTTP 請求並返回 HTTP 響應的主要方式。下麵分別介紹如何編寫視圖函數和類視圖。
視圖函數
視圖函數是一個簡單的 Python 函數,它接受一個 HttpRequest 對象作為參數,並返回一個 HttpResponse 對象。以下是一個簡單的視圖函數示例:
from django.http import HttpResponse
def hello_world(request):
return HttpResponse("Hello, world!")
在這個例子中,hello_world
函數接受一個 HttpRequest 對象request
,並返回一個包含文本 "Hello, world!" 的 HttpResponse 對象。
類視圖
類視圖是基於類的視圖,它允許你使用面向對象的技術來組織代碼。Django 提供了一些內置的類視圖,如ListView
、DetailView
等。以下是一個使用 Django 內置類視圖的示例:
from django.views import View
from django.http import HttpResponse
class HelloWorldView(View):
def get(self, request):
return HttpResponse("Hello, world!")
在這個例子中,HelloWorldView
是一個繼承自View
的類。它定義了一個get
方法,該方法在接收到 GET
請求時被調用,並返回一個包含文本 "Hello, world!" 的 HttpResponse 對象。
使用類視圖的好處
- 代碼重用:類視圖允許你定義通用的行為,這些行為可以在多個視圖中重用。
- 組織結構:類視圖提供了一種更結構化的方式來組織代碼,特別是對於複雜的視圖邏輯。
- 內置功能:Django 的類視圖提供了許多內置的功能,如分頁、表單處理等,這些功能可以很容易地集成到你的視圖中。
註冊視圖
無論是視圖函數還是類視圖,都需要在 Django 的路由配置中註冊,以便 Django 知道如何將 URL
映射到相應的視圖。以下是如何在urls.py
中註冊視圖的示例:
from django.urls import path
from . import views
urlpatterns = [
path('hello/', views.hello_world, name='hello_world'), # 註冊視圖函數
path('hello_class/', views.HelloWorldView.as_view(), name='hello_class'), # 註冊類視圖
]
在這個例子中,path
函數用於定義 URL 模式,views.hello_world
和views.HelloWorldView.as_view()
分別用於註冊視圖函數和類視圖。name
參數用於為 URL 模式命名,這在模板和視圖中引用 URL 時非常有用。
通過這種方式,Django 能夠根據 URL 來調用相應的視圖函數或類視圖,並處理 HTTP 請求。
URL路由配置與命名空間
在 Django 中,URL 路由配置是將 URL 映射到視圖函數或類視圖的過程。命名空間則是為瞭解決在多個應用中可能出現的 URL
命名衝突問題。下麵詳細介紹 URL 路由配置和命名空間的使用。
URL 路由配置
URL 路由配置通常在urls.py
文件中進行。每個 Django 項目都有一個根 URL 配置文件,通常位於項目根目錄下,而每個應用也可以有自己的
URL 配置文件。
項目級別的 URL 配置
項目級別的 URL 配置文件通常包含對應用 URL 配置的包含。以下是一個簡單的項目級別 URL 配置示例:
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')), # 包含 blog 應用的 URL 配置
path('forum/', include('forum.urls')), # 包含 forum 應用的 URL 配置
]
在這個例子中,include
函數用於包含其他應用的 URL 配置。這樣,當訪問/blog/
或/forum/
開頭的 URL 時,Django
會自動查找並使用blog
或forum
應用中的 URL 配置。
應用級別的 URL 配置
應用級別的 URL 配置文件通常包含該應用中所有視圖的 URL 映射。以下是一個簡單的應用級別 URL 配置示例:
from django.urls import path
from . import views
app_name = 'blog' # 設置應用命名空間
urlpatterns = [
path('', views.index, name='index'), # 主頁
path('post/<int:post_id>/', views.post_detail, name='post_detail'), # 文章詳情頁
]
在這個例子中,app_name
變數設置了應用的命名空間,urlpatterns
列表包含了該應用的所有 URL 映射。每個path
函數調用都定義了一個
URL 模式,並將其映射到相應的視圖函數,同時通過name
參數為 URL 模式命名。
命名空間
命名空間是為瞭解決在多個應用中可能出現的 URL 命名衝突問題。通過為每個應用設置一個命名空間,可以確保即使在不同的應用中使用了相同的
URL 名稱,Django 也能正確地解析 URL。
使用命名空間
在模板或視圖中引用帶有命名空間的 URL 時,可以使用{% url %}
模板標簽,如下所示:
<!-- 在模板中引用帶有命名空間的 URL -->
<a href="{% url 'blog:index' %}">主頁</a>
<a href="{% url 'blog:post_detail' post.id %}">閱讀更多</a>
在這個例子中,blog:index
和blog:post_detail
分別引用了blog
應用中的index
和post_detail
URL 模式。
命名空間的好處
- 避免衝突:命名空間可以確保即使在不同的應用中使用了相同的 URL 名稱,也不會發生衝突。
- 易於管理:通過命名空間,可以更容易地管理和維護大型項目中的 URL 配置。
請求與響應處理
在 Web 開發中,請求和響應是指客戶端向伺服器發送請求,伺服器處理請求並返回相應的響應。以下是 Django 中請求和響應的處理過程:
請求處理
當客戶端向伺服器發送請求時,Django 會根據請求的 URL 找到相應的視圖函數或類視圖,並將請求數據傳遞給視圖函數。視圖函數負責處理請求,並返回一個響應對象。
請求對象
Django 會將請求數據封裝成一個HttpRequest
對象,並將其傳遞給視圖函數。HttpRequest
對象包含以下屬性:
method
:請求方法,如GET
、POST
等。GET
:包含查詢字元串參數的字典。POST
:包含表單數據的字典。FILES
:包含上傳文件的字典。COOKIES
:包含請求的 Cookie 的字典。session
:包含請求的會話對象。user
:包含當前請求的用戶對象。
以下是一個簡單的視圖函數,該函數從請求對象中獲取查詢字元串參數:
from django.http import HttpResponse
def index(request):
name = request.GET.get('name')
return HttpResponse(f'Hello, {name}!')
中間件
中間件是 Django 的可擴展機制,可以在請求處理過程中插入自定義的處理邏輯。中間件可以在請求處理過程的不同階段執行自定義的操作,例如日誌記錄、身份驗證、許可權檢查等。
中間件是一種裝飾器模式,可以在項目或應用級別定義中間件。中間件可以在請求處理過程中修改請求對象、響應對象,或者直接終止請求處理。
響應處理
在視圖函數處理請求後,需要返回一個響應對象,以便 Django 向客戶端發送響應。
響應對象
HttpResponse
是 Django 中最常用的響應對象。可以使用HttpResponse
構造函數創建一個響應對象,並將響應數據作為參數傳遞給構造函數。
以下是一個簡單的視圖函數,該函數返回一個包含文本的響應對象:
from django.http import HttpResponse
def index(request):
return HttpResponse('Hello, World!')
重定向
在某些情況下,可能需要將請求重定向到其他 URL。可以使用HttpResponseRedirect
類創建重定向響應對象。
以下是一個簡單的視圖函數,該函數將請求重定向到其他 URL:
from django.http import HttpResponseRedirect
from django.urls import reverse
def login(request):
if request.method == 'POST':
# 處理登錄邏輯
return HttpResponseRedirect(reverse('home'))
else:
return render(request, 'login.html')
渲染模板
在實際開發中,通常會將視圖函數的響應數據渲染到 HTML 模板中,以便顯示給用戶。可以使用render
函數渲染模板,並將渲染後的 HTML
內容作為響應對象返回。
以下是一個簡單的視圖函數,該函數渲染一個包含用戶名的 HTML 模板:
from django.shortcuts import render
def index(request):
name = request.GET.get('name')
return render(request, 'index.html', {'name': name})
在上面的示例中,render
函數接收三個參數:請求對象、模板名稱和模板上下文。模板上下文是一個字典,包含模板中需要使用的變數。
最佳實踐:RESTful API設計、視圖邏輯與業務邏輯分離
在設計 RESTful API 時,視圖邏輯與業務邏輯的分離是一種良好的實踐,可以使代碼結構更清晰、易於維護,同時也符合 SOLID
原則中的單一職責原則。以下是關於 RESTful API 設計、視圖邏輯與業務邏輯分離的最佳實踐:
RESTful API 設計
- 資源命名:使用名詞表示資源,URL 中應該是資源的集合形式,如
/users
表示用戶資源的集合,/users/{id}
表示單個用戶資源。 - HTTP 方法:使用 HTTP 方法對資源進行操作,如
GET
獲取資源,POST
創建資源,PUT
更新資源,DELETE
刪除資源。 - 狀態碼:合理使用 HTTP 狀態碼,如
200 OK
、201 Created
、400 Bad Request
、404 Not Found
等,以便客戶端能夠正確處理響應。 - 版本控制:考慮在 URL 中包含版本號,以便在未來對 API 進行升級時能夠向後相容。
視圖邏輯與業務邏輯分離
- 視圖函數:視圖函數應該儘可能簡單,只處理請求的驗證、參數解析和響應的構建,不應包含複雜的業務邏輯。
- 業務邏輯層:將複雜的業務邏輯抽象成服務層或業務邏輯層,視圖函數調用這些服務來完成具體的業務邏輯操作。
- 模型層:將數據持久化操作封裝在模型層中,視圖函數和業務邏輯層應該通過模型層來進行數據的讀取和寫入。
- 異常處理:在業務邏輯層處理異常,並將異常信息返回給視圖函數,視圖函數負責將異常信息轉換成合適的 HTTP 狀態碼和響應。
示例代碼
以下是一個簡單的 Django REST framework 中的示例代碼,展示瞭如何設計 RESTful API 並分離視圖邏輯與業務邏輯:
# serializers.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
# views.py
from rest_framework import viewsets
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
class BookViewSet(viewsets.ViewSet):
def list(self, request):
queryset = Book.objects.all()
serializer = BookSerializer(queryset, many=True)
return Response(serializer.data)
# services.py
from .models import Book
class BookService:
@staticmethod
def get_book_by_id(book_id):
try:
return Book.objects.get(id=book_id)
except Book.DoesNotExist:
raise Exception('Book not found')
# urls.py
from django.urls import path
from rest_framework.routers import DefaultRouter
from .views import BookViewSet
router = DefaultRouter()
router.register(r'books', BookViewSet, basename='book')
urlpatterns = router.urls
在上面的示例中,我們將序列化器、視圖函數、服務類和模型分別進行了分離,使代碼結構更清晰,易於維護。視圖函數調用服務類來處理業務邏輯,而服務類負責與模型層交互,實現了視圖邏輯與業務邏輯的分離。
第四章:Django表單與驗證
表單定義與驗證規則
在 Web 開發中,表單是用戶輸入數據的重要手段。定義表單和驗證規則是實現可靠性、安全性和用戶體驗的關鍵。以下是有關表單定義和驗證規則的最佳實踐:
表單定義
- 使用 HTML 表單:使用 HTML 表單元素(
<form>
、<input>
、<textarea>
、<select>
等)來收集用戶輸入的數據。 - 使用
name
屬性:為表單元素添加name
屬性,以便在提交表單時能夠正確地將表單數據與表單元素關聯起來。 - 使用
action
屬性:為表單元素添加action
屬性,表示提交表單時將請求發送到哪個 URL。 - 使用
method
屬性:為表單元素添加method
屬性,表示提交表單時使用的 HTTP 方法,如GET
或POST
。
驗證規則
- 服務端驗證:在服務端實現驗證規則,不要僅依靠客戶端的驗證,因為客戶端可能會被繞過或被惡意攻擊。
- 必填項驗證:驗證必填項,確保用戶輸入了必要的數據。
- 格式驗證:驗證用戶輸入的數據格式,如電子郵件地址、手機號碼、日期、時間等。
- 長度驗證:驗證用戶輸入的數據長度,如用戶名、密碼、評論等。
- 唯一性驗證:驗證用戶輸入的數據是否唯一,如用戶名、郵箱地址、手機號碼等。
- 正則表達式:使用正則表達式來驗證用戶輸入的數據,如驗證電子郵件地址、手機號碼、URL 等。
- 自定義驗證器:在 Django 中,可以使用自定義驗證器函數或類來實現更複雜的驗證邏輯。
- 表單驗證:在 Django 中,可以使用
Form
類或ModelForm
類來實現表單驗證。
示例代碼
以下是一個 Django 中的表單驗證示例代碼,展示瞭如何使用Form
類和ModelForm
類實現表單驗證:
# forms.py
from django import forms
from .models import Book
class BookForm(forms.Form):
title = forms.CharField(max_length=100, required=True)
author = forms.CharField(max_length=100, required=True)
class BookModelForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'description']
# views.py
from django.shortcuts import render
from django.views.generic import FormView
from .forms import BookForm, BookModelForm
class BookFormView(FormView):
form_class = BookForm
template_name = 'book_form.html'
def form_valid(self, form):
# 驗證通過,處理表單數據
return super().form_valid(form)
def form_invalid(self, form):
# 驗證失敗,重新渲染表單模板
return super().form_invalid(form)
class BookModelFormView(FormView):
form_class = BookModelForm
template_name = 'book_model_form.html'
def form_valid(self, form):
# 驗證通過,保存模型實例
form.save()
return super().form_valid(form)
def form_invalid(self, form):
# 驗證失敗,重新渲染表單模板
return super().form_invalid(form)
在上面的示例中,我們分別使用Form
類和ModelForm
類實現了表單驗證。在BookForm
類中,我們手動定義了表單欄位和驗證規則,而在BookModelForm
類中,我們直接繼承了ModelForm
類,併在Meta
類中指定了模型和欄位,從而自動生成了表單欄位和驗證規則。
使用表單處理用戶輸入
在 Web 開發中,使用表單處理用戶輸入是非常常見的操作。下麵是一個簡單的 Django 示例,展示如何創建一個表單,接收用戶輸入,併在提交後進行處理:
創建表單
首先,我們需要創建一個表單,定義表單中的欄位和驗證規則。
# forms.py
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(label='Your Name', max_length=100)
email = forms.EmailField(label='Your Email')
message = forms.CharField(label='Your Message', widget=forms.Textarea)
創建視圖
接下來,我們需要創建一個視圖,用於展示表單頁面、接收用戶提交的數據並處理。
# views.py
from django.shortcuts import render
from .forms import ContactForm
def contact_view(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
message = form.cleaned_data['message']
# 在這裡可以對用戶輸入進行處理,比如發送郵件、保存到資料庫等
return render(request, 'success.html', {'name': name})
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
創建模板
最後,我們需要創建兩個模板文件,一個用於顯示表單頁面,另一個用於顯示提交成功頁面。
contact.html
:
<!-- contact.html -->
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
success.html
:
<!-- success.html -->
<h1>Thank you, {{ name }}!</h1>
<p>Your message has been successfully submitted.</p>
配置 URL
最後,別忘了在urls.py
中配置 URL 映射,將請求路由到對應的視圖函數。
# urls.py
from django.urls import path
from .views import contact_view
urlpatterns = [
path('contact/', contact_view, name='contact'),
]
通過以上步驟,我們就創建了一個簡單的表單頁面,用戶可以在頁面中輸入姓名、郵箱和消息,提交表單後會顯示提交成功頁面,並將用戶的姓名顯示在頁面上。在實際項目中,您可以根據需要對用戶輸入的數據進行進一步處理,比如發送郵件、保存到資料庫等操作。
自定義表單欄位與驗證器
在 Django 中,我們可以自定義表單欄位和驗證器,以適應更複雜的需求。下麵是一個自定義表單欄位和驗證器的示例。
自定義表單欄位
首先,我們需要自定義一個表單欄位,用於接收用戶輸入的手機號碼。
# forms.py
import re
from django import forms
class PhoneNumberField(forms.CharField):
default_error_messages = {
'invalid': 'Please enter a valid phone number.',
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.validators.append(
RegexValidator(
regex=r'^(\+\d{1,3}\s?)?((\(\d{1,3}\))|\d{1,3})[-.\s]?\d{1,4}[-.\s]?\d{1,4}[-.\s]?\d{1,9}$',
message=self.error_messages['invalid'],
)
)
在上面的示例中,我們繼承了 Django 的CharField
,並添加了一個自定義的驗證器,用於驗證用戶輸入的手機號碼是否合法。
自定義驗證器
接下來,我們需要自定義一個驗證器,用於驗證用戶輸入的年齡是否合法。
# validators.py
from django.core.exceptions import ValidationError
def validate_age(value):
if value < 18:
raise ValidationError('You must be at least 18 years old.')
在上面的示例中,我們創建了一個名為validate_age
的驗證器函數,用於驗證用戶輸入的年齡是否大於等於 18 歲。
使用自定義表單欄位和驗證器
最後,我們可以在表單中使用自定義表單欄位和驗證器,如下所示:
# forms.py
from django import forms
class UserForm(forms.Form):
name = forms.CharField(label='Your Name', max_length=100)
phone_number = PhoneNumberField(label='Your Phone Number')
age = forms.IntegerField(label='Your Age', validators=[validate_age])
在上面的示例中,我們在表單中使用了自定義的PhoneNumberField
欄位,並添加了自定義的validate_age
驗證器。在用戶提交表單時,Django
會自動應用這些驗證器,併在驗證失敗時返回錯誤消息。
通過以上步驟,我們就成功地創建了一個自定義表單欄位和驗證器,併在表單中使用它們。在實際項目中,您可以根據需要繼續創建更多的自定義表單欄位和驗證器,以適應更複雜的需求。
最佳實踐:前後端表單驗證、安全防護措施
在開發 Web 應用時,表單驗證和安全防護措施是確保應用安全和用戶體驗的關鍵部分。以下是一些最佳實踐,涵蓋了前後端表單驗證和安全防護措施。
前端表單驗證
- 使用 HTML5 表單驗證特性:利用 HTML5 提供的表單驗證特性,如
required
、min
、max
、pattern
等,可以快速進行基本的輸入驗證。 - JavaScript 驗證:使用 JavaScript 進行更複雜的驗證,如實時輸入檢查、自定義驗證邏輯等。這可以提供更好的用戶體驗,因為錯誤可以即時反饋給用戶。
- 避免敏感數據驗證:不要在前端驗證敏感數據,如密碼強度檢查,因為這些信息可能會被惡意用戶截獲。
- 非同步驗證:對於需要查詢後端資料庫的驗證(如用戶名唯一性檢查),應使用非同步請求進行驗證,以避免阻塞用戶界面。
後端表單驗證
- 伺服器端驗證:始終在伺服器端進行驗證,即使前端已經進行了驗證。這是防止惡意用戶繞過前端驗證的最後一道防線。
- 使用框架提供的驗證工具:大多數 Web 框架(如 Django、Flask、Spring 等)都提供了表單驗證工具,可以方便地進行欄位驗證、自定義驗證器等。
- 輸入清理:確保所有用戶輸入都經過清理,以防止 SQL 註入、跨站腳本(XSS)等安全漏洞。
- 錯誤處理:在驗證失敗時,返回適當的錯誤信息,但避免泄露敏感信息或系統細節。
安全防護措施
- 使用 HTTPS:通過 HTTPS 傳輸數據,以確保數據在傳輸過程中的安全。
- 防止 CSRF 攻擊:使用 CSRF 令牌來防止跨站請求偽造攻擊。
- 防止 SQL 註入:使用參數化查詢或 ORM 框架,避免直接拼接 SQL 語句。
- 防止 XSS 攻擊:對所有輸出到 HTML 的內容進行適當的轉義,使用內容安全策略(CSP)等技術。
- 密碼安全:使用強密碼策略,對密碼進行哈希存儲,並使用加鹽技術。
- 會話管理:合理管理用戶會話,包括會話超時、使用安全的會話存儲和傳輸方式。
- 限制錯誤嘗試:對於登錄等敏感操作,限制錯誤嘗試次數,以防止暴力破解。
- 定期更新和打補丁:確保所有軟體和依賴都是最新的,定期打補丁以修複已知的安全漏洞。
第五章:Django模板與靜態文件管理
模板語言與模板繼承
模板語言是一種簡化視圖渲染的工具,它允許在 HTML 模板中嵌入動態內容和邏輯。模板繼承是一種在模板中重用佈局和模板片段的技術,使得代碼更易維護和組織。
模板語言
模板語言通常包括以下幾個方面:
- 變數:在模板中使用特殊語法引用變數,如
${variable_name}
或{{ variable_name }}
。 - 控制結構:模板語言也提供基本的控制結構,如條件語句(if-else)和迴圈(for-each)。
- 過濾器:過濾器用於對變數進行格式化和處理,如日期格式化、數字格式化等。
- Include 和 Extends:這兩個關鍵字用於在模板中包含其他模板和擴展模板。
模板繼承
模板繼承允許在子模板中覆蓋父模板中的塊,以實現更好的代碼重用。主要有三個關鍵字:{% block %}
、{% blocktrans %}
和{% extends %}
。
-
{% block %} :在父模板中定義一個或多個塊,子模板可以覆蓋這些塊。
<!-- 父模板 --> <!DOCTYPE html> <html lang="en"> <head> <title>{% block title %}預設標題{% endblock %}</title> </head> <body> <div id="content">{% block content %}{% endblock %}</div> </body> </html>
-
{% blocktrans %} :用於翻譯模板中的文本,並支持參數化。
<!-- 父模板 --> {% blocktrans with name="John Doe" %} 歡迎,{{ name }}! {% endblocktrans %}
-
{% extends %} :在子模板中使用
{% extends "base.html" %}
語句來繼承父模板。<!-- 子模板 --> {% extends "base.html" %} {% block title %}子模板標題{% endblock %} {% block content %} 子模板內容 {% endblock %}
模板繼承使得開發人員可以更好地組織和維護代碼,避免在多個地方重覆寫相同的佈局。同時,模板語言也使得在 HTML 模板中嵌入動態內容和邏輯更加方便。
常見的模板語言有 Jinja2、Django 模板語言、Thymeleaf 等。
靜態文件配置與管理
靜態文件配置與管理是Web開發中的一個重要環節,它涉及到如何組織和提供CSS、JavaScript、圖片等靜態資源。以下是一些常見的靜態文件配置與管理方法:
1.配置靜態文件目錄
在Web框架中,通常需要指定一個目錄作為靜態文件的根目錄。例如,在Django中,可以通過設置STATIC_URL
和STATICFILES_DIRS
來指定靜態文件的位置:
# settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
在Flask中,可以通過static_folder
和static_url_path
來配置:
# app.py
app = Flask(__name__, static_folder='static', static_url_path='/static')
2.使用Web伺服器管理靜態文件
對於生產環境,通常使用Nginx或Apache等Web伺服器來管理靜態文件,因為它們可以更高效地處理靜態資源的請求。在Nginx的配置文件中,可以這樣設置:
# nginx.conf
server {
listen 80 ;
server_name example.com ;
location /static {
alias /path/to/static/files ;
}
}
3.使用構建工具
在現代Web開發中,通常使用構建工具(如Webpack、Gulp、Grunt等)來自動化靜態文件的處理,包括壓縮、合併、版本控制等。這些工具可以幫助優化資源載入速度和減少HTTP請求。
4.版本控制和緩存
為了防止瀏覽器緩存舊的靜態文件,可以在文件名中加入版本號或哈希值。例如,將main.css
重命名為main-v1.0.0.css
,這樣每次更新文件時,文件名都會變化,瀏覽器會重新下載新的文件。
5.CDN服務
使用內容分髮網絡(CDN)可以加速靜態文件的載入速度,因為CDN會將文件緩存到全球各地的伺服器上,用戶可以從最近的伺服器下載文件。
例:Django靜態文件配置
在Django中,靜態文件的配置和管理通常涉及以下幾個步驟:
- 在
settings.py
中設置靜態文件相關的配置:
# settings.py
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'project/static'),
]
- 在模板中引用靜態文件:
<!-- templates/base.html -->
{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}">
- 在開發環境中,Django會自動提供靜態文件。在生產環境中,需要運行
collectstatic
命令來收集所有靜態文件到STATIC_ROOT
指定的目錄:
python manage.py collectstatic
- 配置Web伺服器(如Nginx)來提供靜態文件服務。
使用模板標簽與過濾器
模板標簽和過濾器是在Web開發中用於在模板中處理數據和邏輯的重要工具。下麵分別介紹一下模板標簽和過濾器的基本用法:
. 模板標簽
模板標簽是用於在模板中執行一些邏輯操作的語法結構。在Django中,模板標簽使用{% %}
包裹,常見的模板標簽包括for
、if
、block
等。例如:
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
. 過濾器
過濾器用於對變數進行一些處理或轉換,以滿足特定需求。在Django中,過濾器使用{{ }}
包括,通過|
符號連接過濾器名稱。常見的過濾器包括date
、length
、title
等。例如:
{{ variable|date:"Y-m-d" }}
{{ text|truncatewords:10 }}
例:Django模板標簽與過濾器的應用
假設有一個Django視圖函數返回了一個包含文章列表的上下文變數articles
,我們可以在模板中使用模板標簽和過濾器來展示這些文章列表:
<!-- templates/articles.html -->
<ul>
{% for article in articles %}
<li>
<h2>{{ article.title }}</h2>
<p>{{ article.content|truncatewords:50 }}</p>
<p>發佈時間:{{ article.publish_date|date:"Y-m-d" }}</p>
</li>
{% endfor %}
</ul>
在上面的示例中,我們使用了for
標簽來遍歷articles
列表,通過過濾器truncatewords
來限制文章內容的長度,通過過濾器date
來格式化發佈時間。
最佳實踐:前端開發集成、性能優化技巧
在前端開發中,集成和性能優化是非常重要的話題。以下是一些最佳實踐和技巧,幫助你提高前端開發的效率和性能:
- 使用模塊化和組件化
使用模塊化和組件化可以提高前端項目的可維護性和可擴展性。可以使用工具如Webpack、Rollup等來進行模塊化開發。同時,可以使用組件庫如React、Vue等來構建可復用的組件。
- 使用CSS預處理器
使用CSS預處理器可以簡化CSS的開發和維護,如Sass、Less等。可以使用變數、混合、函數等特性來提高CSS的可讀性和可維護性。
- 使用圖片壓縮和優化工具
使用圖片壓縮和優化工具可以提高頁面的載入速度。可以使用工具如ImageOptim、TinyPNG等來壓縮和優化圖片。
- 使用HTTP/2
使用HTTP/2可以提高網頁的載入速度。HTTP/2支持多路復用、請求優先順序、頭部壓縮等特性,可以有效提高網頁的載入速度。
- 使用CDN
使用CDN可以提高網頁的載入速度。CDN可以將靜態資源分佈在全球的多個伺服器上,使用戶可以從離用戶最近的伺服器獲取資源。
- 使用懶載入和預載入
使用懶載入和預載入可以提高網頁的載入速度。可以使用JavaScript來實現懶載入和預載入,只載入當前可見區域的資源,提高用戶體驗。
- 使用服務端渲染
使用服務端渲染可以提高網頁的載入速度。服務端渲染可以將HTML渲染到伺服器端,減少客戶端的渲染時間,提高用戶體驗。
- 使用緩存
使用緩存可以提高網頁的載入速度。可以使用瀏覽器緩存、CDN緩存、伺服器緩存等方式來緩存靜態資源,減少請求次數,提高用戶體驗。
- 使用性能分析工具
使用性能分析工具可以幫助你找到性能瓶頸,如Google Lighthouse、WebPageTest等。
- 使用代碼壓縮和混淆
使用代碼壓縮和混淆可以提高網頁的載入速度。可以使用工具如UglifyJS、Terser等來壓縮和混淆JavaScript代碼。
第六章:Django認證與許可權控制
用戶認證與許可權管理
用戶認證與許可權管理是任何Web應用程式的核心組成部分,它確保只有授權的用戶才能訪問特定的資源和執行特定操作。在Django中,這主要通過以下幾個步驟和概念實現:
-
內置認證系統:
- 認證視圖:
django.contrib.auth.views
提供了一系列視圖,如login
,logout
,password_change
等,用於處理用戶登錄和登出。 - 用戶模型:Django預設提供
User
模型,但可以自定義,例如添加額外欄位或使用電子郵件作為唯一標識符。 - 認證後處理器:
AUTHENTICATION_BACKENDS
設置允許哪些後端進行認證。
- 認證視圖:
-
許可權管理:
- 許可權系統:Django的內置許可權系統基於模型的
has_perm()
和has_module_perms()
方法,允許檢查用戶是否具有特定的許可權。 - 基於角色的訪問控制(RBAC) :通過將用戶分配到角色,然後為角色賦予許可權,可以更靈活地控制用戶訪問。
- 許可權系統:Django的內置許可權系統基於模型的
-
自定義用戶模型:
- 如果需要擴展Django的用戶模型,可以創建新的模型類,繼承
AbstractBaseUser
或AbstractUser
,並定義額外的欄位。 - 在
settings.py
中設置AUTH_USER_MODEL
來指定自定義用戶模型。
- 如果需要擴展Django的用戶模型,可以創建新的模型類,繼承
-
身份驗證優化:
- 安全措施:使用HTTPS,密碼策略(如密碼複雜度要求),和雙因素認證(2FA)來增強安全性。
- 用戶體驗:提供“記住我”選項,方便用戶長期登錄,但需要管理好安全風險。
-
密碼管理:
- 密碼加密:Django的
User
模型預設使用哈希和鹽進行密碼存儲,確保即使資料庫泄露,密碼也無法直接恢復。 - 密碼重置:提供安全的密碼重置流程,通常需要通過電子郵件發送一個帶有鏈接的重置密碼表單。
- 密碼加密:Django的
使用Django內置認證系統
使用Django內置認證系統,你需要按照以下步驟進行操作:
-
創建Django項目和應用
django-admin startproject myproject cd myproject python manage.py startapp myapp
-
在
settings.py
中配置認證應用INSTALLED_APPS = [ # ... 'django.contrib.auth', 'django.contrib.contenttypes', ]
-
添加
LOGIN_URL
和LOGIN_REDIRECT_URL
# settings.py LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/'
-
在
urls.py
中添加認證視圖# myproject/urls.py from django.contrib import admin from django.urls import path, include from django.contrib.auth import views as auth_views urlpatterns = [ path('admin/', admin.site.urls), path('', include('myapp.urls')), path('accounts/', include([ path('login/', auth_views.LoginView.as_view(), name='login'), path('logout/', auth_views.LogoutView.as_view(), name='logout'), ])), ]
-
創建
myapp/templates/registration/login.html
根據Django模板繼承創建一個基本的登錄模板,如下所示:
{% extends "base_generic.html" %} {% block content %} <h2>{% trans 'Log in' %}</h2> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">{% trans 'Log in' %}</button> </form> {% endblock %}
-
測試應用程式
python manage.py runserver
然後在瀏覽器中訪問
http://127.0.0.1:8000/accounts/login/
。 -
自定義用戶模型