Python中的Django視圖與路由
Django作為Python生態(tài)中最流行的Web框架之一,其視圖(View) 與URL路由(URLconf) 是連接用戶請(qǐng)求與業(yè)務(wù)邏輯的核心環(huán)節(jié)。無(wú)論是搭建簡(jiǎn)單的個(gè)人博客,還是開(kāi)發(fā)復(fù)雜的企業(yè)級(jí)應(yīng)用,理解這兩大模塊的工作原理,都能讓我們更高效地構(gòu)建穩(wěn)定、易維護(hù)的Web項(xiàng)目。接下來(lái),我們就從基礎(chǔ)概念到實(shí)戰(zhàn)代碼,一步步拆解Django視圖與路由的核心知識(shí)點(diǎn)。
一、Django視圖基礎(chǔ):連接請(qǐng)求與數(shù)據(jù)的橋梁
視圖是Django中處理HTTP請(qǐng)求并返回響應(yīng)的核心載體,它扮演著“中間件”的角色——一邊對(duì)接客戶端的請(qǐng)求,一邊與模型(Model)、模板(Template)協(xié)同工作,最終完成業(yè)務(wù)邏輯的處理。
1.1 視圖的核心職責(zé)
- 接收HTTP請(qǐng)求:獲取客戶端發(fā)送的請(qǐng)求信息(如請(qǐng)求方法、參數(shù)、頭信息等)。
- 與模型交互:從數(shù)據(jù)庫(kù)(通過(guò)模型)查詢或修改數(shù)據(jù),比如獲取一篇文章、篩選分類列表。
- 傳遞數(shù)據(jù)給模板:將模型獲取到的數(shù)據(jù)傳遞給模板,由模板完成HTML渲染。
- 返回HTTP響應(yīng):將渲染后的頁(yè)面或JSON數(shù)據(jù)等響應(yīng)結(jié)果返回給客戶端。
1.2 視圖與模型、模板的關(guān)系
在Django的MVT(Model-View-Template)架構(gòu)中,視圖是“紐帶”:
- 模型(Model)提供數(shù)據(jù)來(lái)源,視圖通過(guò)模型獲取數(shù)據(jù);
- 模板(Template)負(fù)責(zé)頁(yè)面展示,視圖將數(shù)據(jù)注入模板并渲染;
- 客戶端的請(qǐng)求通過(guò)URL路由映射到視圖,視圖處理后返回響應(yīng)。
二、URL路由配置:給請(qǐng)求“指路”的規(guī)則
URL路由的本質(zhì)是“URL地址”與“視圖”的映射關(guān)系——當(dāng)客戶端發(fā)送一個(gè)HTTP請(qǐng)求時(shí),Django通過(guò)路由規(guī)則找到對(duì)應(yīng)的視圖,再由視圖處理請(qǐng)求。
2.1 路由基礎(chǔ):URLconf的配置方式
Django的路由規(guī)則定義在項(xiàng)目或應(yīng)用的urls.py文件中,核心是urlpatterns列表,每個(gè)元素通過(guò)path()函數(shù)映射一個(gè)URL到對(duì)應(yīng)的視圖。
示例(myapp/urls.py):
from django.urls import path
from . import views
# URL與視圖的映射列表
urlpatterns = [
# 首頁(yè):訪問(wèn)http://127.0.0.1:8000/myapp/ 觸發(fā)views.home視圖
path('', views.home, name='home'),
# 文章詳情:訪問(wèn)http://127.0.0.1:8000/myapp/article/1/ 觸發(fā)views.article_detail
path('article/<int:pk>/', views.article_detail, name='article_detail'),
# 分類列表:訪問(wèn)http://127.0.0.1:8000/myapp/category/tech/ 觸發(fā)views.category_articles
path('category/<slug:slug>/', views.category_articles, name='category_articles'),
]其中name參數(shù)是URL的“別名”,用于后續(xù)的反向解析(避免硬編碼URL)。
2.2 Django處理請(qǐng)求的完整流程
- 客戶端發(fā)送HTTP請(qǐng)求(如訪問(wèn)
http://127.0.0.1:8000/myapp/article/1/); - Django解析URL,提取路徑部分(即
/myapp/article/1/,忽略域名、查詢參數(shù)和錨點(diǎn)); - 在
urlpatterns中匹配對(duì)應(yīng)的URL模式(如article/<int:pk>/); - 調(diào)用匹配到的視圖函數(shù)(如
views.article_detail),并傳遞請(qǐng)求對(duì)象和URL參數(shù)(如pk=1); - 視圖處理請(qǐng)求后返回響應(yīng)(如渲染后的文章詳情頁(yè)),Django將響應(yīng)返回給客戶端。
2.3 路徑轉(zhuǎn)換器:靈活捕獲URL參數(shù)
當(dāng)需要從URL中提取參數(shù)(如文章ID、分類別名)時(shí),Django提供了路徑轉(zhuǎn)換器,無(wú)需手動(dòng)解析字符串。常用轉(zhuǎn)換器如下:
| 轉(zhuǎn)換器 | 描述 | 示例 |
|---|---|---|
str | 匹配除斜杠(/)外的任意字符 | path('user/<str:username>/', views.user_profile) |
int | 匹配非負(fù)整數(shù)(用于ID等場(chǎng)景) | path('article/<int:pk>/', views.article_detail) |
slug | 匹配字母、數(shù)字、下劃線、連字符(URL友好的字符串) | path('category/<slug:slug>/', views.category_articles) |
uuid | 匹配UUID格式字符串(用于唯一標(biāo)識(shí)) | path('order/<uuid:order_id>/', views.order_detail) |
path | 匹配包含斜杠的完整路徑(用于文件路徑等) | path('file/<path:file_path>/', views.file_view) |
示例:通過(guò)int:pk獲取文章ID,視圖中接收參數(shù)并查詢文章:
# views.py
from django.shortcuts import render, get_object_or_404
from .models import Article
def article_detail(request, pk):
# 根據(jù)pk(文章ID)查詢文章,不存在則返回404
article = get_object_or_404(Article, pk=pk)
# 渲染模板并傳遞文章數(shù)據(jù)
return render(request, 'article_detail.html', {'article': article})2.4 正則表達(dá)式:處理復(fù)雜URL模式
對(duì)于更靈活的URL匹配(如按年月篩選文章歸檔),可以使用re_path()函數(shù)結(jié)合正則表達(dá)式定義規(guī)則。
示例:匹配/article/2025/08/格式的URL,提取年份和月份:
# urls.py
from django.urls import re_path
from . import views
urlpatterns = [
# 正則表達(dá)式:(?P<year>[0-9]{4}) 表示提取4位數(shù)字作為year參數(shù)
re_path(r'^article/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.article_archive, name='article_archive'),
]
# views.py
def article_archive(request, year, month):
# 篩選指定年月的文章
articles = Article.objects.filter(created_at__year=year, created_at__month=month)
return render(request, 'article_archive.html', {'articles': articles, 'year': year, 'month': month})2.5 反向解析:避免硬編碼URL
在開(kāi)發(fā)中,直接寫(xiě)死URL(如/myapp/article/1/)會(huì)導(dǎo)致后期修改URL時(shí)需要全局替換,而反向解析通過(guò)URL的“別名”(name參數(shù))動(dòng)態(tài)生成URL,解決了硬編碼問(wèn)題。
反向解析的兩種場(chǎng)景:
在視圖中使用:通過(guò)reverse()函數(shù)生成URL。
from django.urls import reverse
def some_view(request):
# 根據(jù)別名'article_detail'和參數(shù)pk=1生成URL:/myapp/article/1/
article_url = reverse('article_detail', args=[1])
# 重定向到該URL
return redirect(article_url)在模板中使用:通過(guò){% url %}模板標(biāo)簽生成URL。
<!-- 模板中生成文章詳情頁(yè)鏈接 -->
<a href="{% url 'article_detail' article.pk %}" rel="external nofollow" >{{ article.title }}</a>2.6 命名空間:解決同名URL沖突
當(dāng)多個(gè)應(yīng)用(如blog和shop)都定義了同名的URL別名(如index)時(shí),反向解析會(huì)無(wú)法區(qū)分。此時(shí)需要通過(guò)命名空間隔離不同應(yīng)用的URL。
配置步驟:
應(yīng)用內(nèi)定義命名空間:在應(yīng)用的urls.py中添加app_name。
# blog/urls.py
app_name = 'blog' # 定義應(yīng)用級(jí)命名空間
urlpatterns = [
path('', views.index, name='index'), # 別名index
]項(xiàng)目中關(guān)聯(lián)命名空間:在項(xiàng)目的urls.py中使用namespace參數(shù)。
# project/urls.py
from django.urls import path, include
urlpatterns = [
path('blog/', include('blog.urls', namespace='blog')), # 關(guān)聯(lián)命名空間
path('shop/', include('shop.urls', namespace='shop')),
]- 反向解析時(shí)指定命名空間:
- 視圖中:
reverse('blog:index')(生成/blog/); - 模板中:
{% url 'blog:index' %}。
三、視圖函數(shù):業(yè)務(wù)邏輯的實(shí)現(xiàn)載體
視圖函數(shù)是處理請(qǐng)求的核心代碼塊,它必須接收request(HTTP請(qǐng)求對(duì)象)作為第一個(gè)參數(shù),并返回HttpResponse(或其子類)對(duì)象。
3.1 簡(jiǎn)單視圖函數(shù)
最基礎(chǔ)的視圖函數(shù)僅返回一段文本響應(yīng):
# views.py
from django.http import HttpResponse
def hello(request):
# 返回文本響應(yīng)
return HttpResponse('Hello, Django!')3.2 錯(cuò)誤視圖處理
在實(shí)際開(kāi)發(fā)中,經(jīng)常需要返回錯(cuò)誤狀態(tài)碼(如404、500)或自定義錯(cuò)誤頁(yè)面。
3.2.1 直接返回錯(cuò)誤狀態(tài)碼
from django.http import HttpResponse, HttpResponseNotFound
# 返回404 Not Found
def page_not_found(request):
return HttpResponseNotFound('頁(yè)面不存在!')
# 返回204 No Content(成功但無(wú)內(nèi)容)
def success_no_content(request):
return HttpResponse(status=204)3.2.2 捕獲404異常(推薦)
使用get_object_or_404()快捷函數(shù),當(dāng)查詢對(duì)象不存在時(shí)自動(dòng)返回404:
from django.shortcuts import get_object_or_404
from .models import Article
def article_detail(request, pk):
# 若Article不存在(pk不存在),自動(dòng)拋出404
article = get_object_or_404(Article, pk=pk)
return render(request, 'article_detail.html', {'article': article})3.2.3 自定義錯(cuò)誤頁(yè)面
在項(xiàng)目的urls.py中配置全局錯(cuò)誤處理器,指定自定義模板:
# project/urls.py
from django.shortcuts import render
# 404頁(yè)面處理器
def handler404(request, exception):
return render(request, '404.html', status=404)
# 500頁(yè)面處理器
def handler500(request):
return render(request, '500.html', status=500)3.3 異步視圖
Django支持異步視圖函數(shù)(需Python 3.7+),適用于IO密集型場(chǎng)景(如調(diào)用外部API、處理大文件):
import asyncio
from django.http import HttpResponse
# 異步視圖:使用async def定義
async def async_view(request):
# 模擬IO等待(如調(diào)用外部API)
await asyncio.sleep(1)
return HttpResponse('這是異步視圖返回的內(nèi)容!')四、快捷函數(shù):簡(jiǎn)化視圖開(kāi)發(fā)的“利器”
Django提供了多個(gè)快捷函數(shù),幫我們減少重復(fù)代碼,提升開(kāi)發(fā)效率。常用的有4個(gè):
4.1render():渲染模板并返回響應(yīng)
無(wú)需手動(dòng)創(chuàng)建HttpResponse,直接將模板與上下文數(shù)據(jù)結(jié)合并返回響應(yīng)。
from django.shortcuts import render
def index(request):
# 上下文數(shù)據(jù):傳遞給模板的變量
context = {'name': 'Django', 'version': '5.0'}
# 渲染index.html模板,傳遞context
return render(request, 'index.html', context)4.2redirect():重定向到其他URL
支持重定向到命名URL、外部鏈接或視圖函數(shù)。
from django.shortcuts import redirect
from django.urls import reverse
def redirect_to_home(request):
# 重定向到別名'home'的URL
return redirect('home')
def redirect_to_article(request, pk):
# 重定向到帶參數(shù)的URL
return redirect('article_detail', pk=pk)
def redirect_to_external(request):
# 重定向到外部鏈接
return redirect('https://example.com')4.3get_object_or_404():查詢對(duì)象或返回404
替代try-except捕獲DoesNotExist異常,簡(jiǎn)化查詢邏輯(前文已示例)。
4.4get_list_or_404():查詢列表或返回404
當(dāng)查詢結(jié)果為空時(shí)返回404,適用于列表頁(yè)(如篩選無(wú)結(jié)果的場(chǎng)景):
from django.shortcuts import get_list_or_404
from .models import Article
def published_articles(request):
# 篩選已發(fā)布的文章,無(wú)結(jié)果則返回404
articles = get_list_or_404(Article, is_published=True)
return render(request, 'article_list.html', {'articles': articles})五、視圖裝飾器:增強(qiáng)視圖功能的“插件”
視圖裝飾器用于給視圖添加額外功能(如限制請(qǐng)求方法、要求登錄、壓縮響應(yīng)),只需在視圖函數(shù)上方添加@裝飾器名即可。
5.1 限制HTTP請(qǐng)求方法
使用require_http_methods、require_GET、require_POST限制視圖接收的請(qǐng)求方法。
from django.views.decorators.http import require_http_methods, require_GET, require_POST
# 僅允許GET和POST請(qǐng)求
@require_http_methods(['GET', 'POST'])
def create_article(request):
if request.method == 'GET':
# 顯示創(chuàng)建表單
return render(request, 'article_form.html')
elif request.method == 'POST':
# 處理表單提交
pass
# 僅允許GET請(qǐng)求
@require_GET
def article_list(request):
pass
# 僅允許POST請(qǐng)求
@require_POST
def delete_article(request):
pass5.2 其他常用裝飾器
@login_required:要求用戶登錄后才能訪問(wèn)視圖(未登錄則跳轉(zhuǎn)登錄頁(yè))。
from django.contrib.auth.decorators import login_required
@login_required
def user_profile(request):
# 僅登錄用戶可訪問(wèn)個(gè)人中心
pass@permission_required:要求用戶擁有指定權(quán)限才能訪問(wèn)。
from django.contrib.auth.decorators import permission_required
# 要求用戶有"修改文章"的權(quán)限
@permission_required('myapp.change_article')
def edit_article(request, pk):
pass@gzip_page:壓縮視圖返回的響應(yīng)內(nèi)容,節(jié)省帶寬。
from django.views.decorators.gzip import gzip_page
@gzip_page
def large_page(request):
# 壓縮大頁(yè)面的響應(yīng)
pass六、請(qǐng)求與響應(yīng)對(duì)象:與客戶端的“對(duì)話”
Django通過(guò)HttpRequest和HttpResponse對(duì)象封裝請(qǐng)求與響應(yīng)的所有信息,是視圖與客戶端交互的核心載體。
6.1 HttpRequest對(duì)象:獲取請(qǐng)求信息
request參數(shù)是HttpRequest的實(shí)例,包含請(qǐng)求的所有信息,常用屬性如下:
request.method:請(qǐng)求方法(如'GET'、'POST')。request.GET:GET請(qǐng)求參數(shù)(類似字典,用get()獲取值)。
# 獲取URL中的查詢參數(shù):?name=Django
name = request.GET.get('name')request.POST:POST請(qǐng)求參數(shù)(表單提交的數(shù)據(jù))。
# 獲取表單中的email字段
email = request.POST.get('email')request.META:請(qǐng)求頭信息(如User-Agent、IP地址)。
# 獲取用戶瀏覽器信息
user_agent = request.META.get('HTTP_USER_AGENT')
# 獲取客戶端IP
ip = request.META.get('REMOTE_ADDR')request.COOKIES:客戶端的Cookie信息。request.FILES:客戶端上傳的文件(需表單enctype="multipart/form-data")。request.user:當(dāng)前登錄的用戶對(duì)象(未登錄則為匿名用戶)。
6.2 HttpResponse對(duì)象:構(gòu)造響應(yīng)內(nèi)容
HttpResponse是所有響應(yīng)的基類,常用子類如下:
HttpResponse:基礎(chǔ)文本響應(yīng)(前文已示例)。JsonResponse:返回JSON數(shù)據(jù)(適用于API接口)。
from django.http import JsonResponse
def api_data(request):
data = {
'name': 'Django',
'features': ['ORM', 'Admin', 'Templates']
}
return JsonResponse(data) # 自動(dòng)設(shè)置Content-Type: application/jsonFileResponse:返回文件下載(StreamingHttpResponse的子類,優(yōu)化大文件傳輸)。
from django.http import FileResponse
import os
def download_pdf(request):
file_path = '/path/to/document.pdf'
# 打開(kāi)文件并返回下載響應(yīng)
response = FileResponse(open(file_path, 'rb'))
# 設(shè)置下載文件名
response['Content-Disposition'] = 'attachment; filename="document.pdf"'
return response七、文件上傳:實(shí)現(xiàn)用戶文件提交
Django處理文件上傳需三步:配置表單、編寫(xiě)視圖、保存文件。
7.1 定義文件上傳表單
需設(shè)置表單的enctype="multipart/form-data"(否則無(wú)法接收文件):
# forms.py
from django import forms
class UploadFileForm(forms.Form):
title = forms.CharField(max_length=50) # 文件標(biāo)題
file = forms.FileField() # 文件上傳字段7.2 編寫(xiě)視圖處理上傳
在視圖中通過(guò)request.FILES獲取上傳的文件,并分塊保存(避免內(nèi)存溢出):
# views.py
from django.shortcuts import render
from .forms import UploadFileForm
import os
def upload_file(request):
if request.method == 'POST':
# 初始化表單并傳遞POST數(shù)據(jù)和文件
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
title = form.cleaned_data['title']
uploaded_file = request.FILES['file'] # 獲取上傳的文件
# 分塊保存文件(適合大文件)
upload_dir = 'uploads/'
os.makedirs(upload_dir, exist_ok=True) # 確保目錄存在
with open(os.path.join(upload_dir, uploaded_file.name), 'wb+') as f:
for chunk in uploaded_file.chunks():
f.write(chunk)
# 上傳成功,跳轉(zhuǎn)成功頁(yè)
return render(request, 'upload_success.html')
else:
# GET請(qǐng)求:顯示空表單
form = UploadFileForm()
return render(request, 'upload.html', {'form': form})7.3 模板渲染表單
<!-- upload.html -->
<form method="post" enctype="multipart/form-data">
{% csrf_token %} <!-- 必須添加,防止CSRF攻擊 -->
{{ form.as_p }} <!-- 渲染表單字段 -->
<button type="submit">上傳</button>
</form>到此這篇關(guān)于Python中的Django視圖與路由的文章就介紹到這了,更多相關(guān)Django視圖與路由內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python實(shí)現(xiàn)批量視頻分幀、保存視頻幀
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)批量視頻分幀、保存視頻幀,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-05-05
Pygame實(shí)戰(zhàn)之實(shí)現(xiàn)經(jīng)典外星人游戲
這篇文章主要介紹了通過(guò)Pygame實(shí)現(xiàn)經(jīng)典的外星人游戲的示例代碼,文中的代碼講解詳細(xì),對(duì)我們了解Pygame有一定的幫助,感興趣的同學(xué)可以試一試2022-01-01
Python 基于http.server模塊實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的代碼舉例
Python http.server模塊通過(guò)繼承BaseHTTPRequestHandler處理HTTP請(qǐng)求,使用ThreadingHTTPServer支持多線程,將其他類實(shí)例設(shè)為RequestHandler屬性實(shí)現(xiàn)跨服務(wù)調(diào)用,本文給大家介紹Python 基于http.server模塊實(shí)現(xiàn)簡(jiǎn)單http服務(wù)的代碼舉例,感興趣的朋友跟隨小編一起看看吧2025-08-08
使用Python求解帶約束的最優(yōu)化問(wèn)題詳解
今天小編就為大家分享一篇使用Python求解帶約束的最優(yōu)化問(wèn)題詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-02-02
python實(shí)現(xiàn)一個(gè)函數(shù)版的名片管理系統(tǒng)過(guò)程解析
這篇文章主要介紹了python實(shí)現(xiàn)一個(gè)函數(shù)版的名片管理系統(tǒng)過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08

