Django API 開發:視圖設置和路由
theme: devui-blue highlight: monokai-sublime
持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第 17 天,點擊查看活動詳情
前言
視圖集和路由器是 Django REST Framework 中的工具,可以加速 API 開發。 它們是視圖和 URL 之上的附加抽象層。 主要好處是單個視圖集可以替換多個相關視圖。 路由器可以自動為開發人員生成 URL。 在具有許多端點的大型項目中,這意味着開發人員必須編寫更少的代碼。 可以説,與一長串的單個視圖和 URL 相比,對於經驗豐富的開發人員而言,與少量視圖集和路由器組合相比,它更易於理解和推理。
在本章中,我們將向現有項目中添加兩個新的 API 端點,並瞭解如何從視圖和 URL 切換到視圖集和路由器可以用更少的代碼實現相同的功能。
用户終端
當前,我們的項目中具有以下 API 端點。 它們都以 api/v1/
開頭,為簡潔起見,未顯示它們:
前兩個端點是我們創建的,而django-rest-auth提供了另外五個端點。 現在讓我們添加兩個其他端點,以列出所有用户和單個用户。 這是許多 API 中的常見功能,它將使我們更清楚地理解為什麼將我們的視圖和 URL 重構為視圖集和路由器是有意義的。
傳統 Django 具有內置的 User 模型類,我們已經在上一篇文章中使用了該類進行身份驗證。 因此,我們不需要創建新的數據庫模型。 相反,我們只需要連接新的端點即可。 此過程始終涉及以下三個步驟:
- 新增模型序列化器
- 新增每個端點視圖
- 新增每個端點的 URL 路由
從我們的序列化器開始。 我們需要導入 User 模型,然後創建一個使用它的 UserSerializer 類。 然後將其添加到我們現有的 posts/serializers.py
文件中。
```python
posts/serializers.py
from django.contrib.auth import get_user_model # new from rest_framework import serializers from .models import Post
class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ('id', 'author', 'title', 'body', 'created_at',)
class UserSerializer(serializers.ModelSerializer): # new class Meta: model = get_user_model() fields = ('id', 'username',) ```
值得注意的是,雖然我們在這裏使用 get_user_model 來引用 User 模型,但實際上在 Django 中有3種不同的方式來引用 User 模型。
通過使用 get_user_model ,我們確保我們引用的是正確的用户模型,無論是默認用户模型還是新 Django 項目中經常定義的自定義用户模型。
接下來,我們需要為每個端點定義視圖。 首先將 UserSerializer 添加到導入列表中。 然後創建列出所有用户的 UserList 類和提供單個用户詳細視圖的 UserDetail 類。 就像我們的帖子視圖一樣,我們可以在此處使用 ListCreateAPIView 和 RetrieveUpdateDestroyAPIView。
對於每個端點,我們只需要只讀或GET功能。 這意味着我們可以使用 ListAPIView 和 RetrieveUpdateDestroyAPIView 。 我們還需要通過 get_user_model 引用用户模型,以便將其導入第一行。
```python
posts/views.py
from django.contrib.auth import get_user_model # new from rest_framework import generics
from .models import Post from .permissions import IsAuthorOrReadOnly from .serializers import PostSerializer, UserSerializer # new
class PostList(generics.ListCreateAPIView): 0 queryset = Post.objects.all() serializer_class = PostSerializer
class PostDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = (IsAuthorOrReadOnly,) queryset = Post.objects.all() serializer_class = PostSerializer
class UserList(generics.ListCreateAPIView): # new queryset = get_user_model().objects.all() serializer_class = UserSerializer
class UserDetail(generics.RetrieveUpdateDestroyAPIView): # new queryset = get_user_model().objects.all() serializer_class = UserSerializer ```
如果您注意到,這裏有很多重複。 Post 視圖和 User 視圖都具有完全相同的 queryset 和 serializer_class。
最後,我們有了 URL 路由。 確保導入新的 UserList 和 UserDetail 視圖。 然後,我們可以為每個用户使用前綴 users/
。
```python
posts/urls.py
from django.urls import path
from .views import UserList, UserDetail, PostList, PostDetail # new
urlpatterns = [
path('users/', UserList.as_view()), # new
path('users/
我們完成了。 確保本地服務器仍在運行,並跳至可瀏覽的 API 以確認一切正常。
我們的用户列表端點位於 http://127.0.0.1:8000/api/v1/users/
狀態代碼為 200 OK ,表示一切正常。 我們可以看到三個現有用户。
每個用户的主鍵上都有一個用户詳細信息終結點。 因此,我們的超級用户帳户位於:http://127.0.0.1:8000/api/v1/users/1/
。
視圖集
視圖集是一種將多個相關視圖的邏輯組合到單個類中的方法。 換句話説,一個視圖集可以替換多個視圖。 當前,我們有四個視圖:兩個用於博客帖子,兩個用於用户。 相反,我們可以使用兩個視圖集來模仿相同的功能:一個用於博客文章,另一個用於用户。
折衷方案是,對於不十分熟悉視圖集的其他開發人員,可讀性會有所下降。 所以這是一個權衡。當我們交換視圖集時,代碼在更新後的 posts/views.py
文件中是這樣的。
```python
posts/views.py
from django.contrib.auth import get_user_model from rest_framework import viewsets # new
from .models import Post from .permissions import IsAuthorOrReadOnly from .serializers import PostSerializer, UserSerializer
class PostViewSet(viewsets.ModelViewSet): # new permission_classes = (IsAuthorOrReadOnly,) queryset = Post.objects.all() serializer_class = PostSerializer
class UserViewSet(viewsets.ModelViewSet): # new queryset = get_user_model().objects.all() serializer_class = UserSerializer ```
在頂部,而不是從 rest_framework 導入泛型,我們現在在第二行導入視圖集。 然後,我們使用ModelViewSet,它為我們提供了列表視圖和詳細信息視圖。 而且,我們不再需要像以前一樣為每個視圖重複相同的 queryset 和 serializer_class 。
Routers 路由
直接與視圖集一起使用,以自動為我們生成 URL 模式。 我們當前的 posts/urls.py
文件具有四個 URL模式:兩個用於博客文章,兩個用於用户。相反,我們可以為每個視圖集採用一條路由。 因此,使用兩個路由而不是四個 URL 模式。 聽起來更好吧?
Django REST Framework 具有兩個默認路由器:SimpleRouter 和 DefaultRouter 。 我們將使用 SimpleRouter,但也可以為更多高級功能創建自定義路由器。
更新後的代碼如下所示:
```python
posts/urls.py
from django.urls import path from rest_framework.routers import SimpleRouter
from .views import UserViewSet, PostViewSet
router = SimpleRouter() router.register('users', UserViewSet, base_name='users') router.register('', PostViewSet, base_name='posts')
urlpatterns = router.urls ```
在最上面一行,將導入 SimpleRouter 及其視圖。 路由器設置為 SimpleRouter,我們為用户和帖子“註冊”每個視圖集。 最後,我們將 URL 設置為使用新路由器。
繼續並立即檢查我們的四個端點! 用户列表是相同的。
但是,局部視圖有些不同。 現在它被稱為“用户實例”,而不是“用户詳細信息”,並且還有一個附加的“刪除”選項內置於ModelViewSet中。
可以自定義視圖集,但是一個重要的折衷是用視圖集編寫更少的代碼,這是默認設置,它可能需要一些其他配置才能完全匹配您想要的內容。
轉到發佈列表,我們可以看到它是相同的:
重要的是,我們的權限仍然有效。 使用我們的 testuser2 帳户登錄時,Post Instance 為只讀。
但是,如果我們使用超級用户帳户(該日誌是單獨的博客文章的作者)登錄的,那麼我們將具有完整的讀寫-編輯-刪除權限。
總結
視圖集和路由器是一種強大的抽象,可減少開發人員必須編寫的代碼量。 但是,這種簡潔性是以犧牲初始學習曲線為代價的。 最初幾次使用視圖集和路由器而不是視圖和 URL 模式會感到很奇怪。
最終,何時向項目添加視圖集和路由器的決定是相當主觀的。 一個好的經驗法則是從視圖和 URL 開始。 隨着 API 複雜性的增加,如果您發現自己一遍又一遍地重複相同的端點模式,那麼請查看視圖集和路由器。
- 一文帶你瞭解 Python 中的繼承知識點
- 如何使用 HTML 和 CSS 寫一個登錄界面
- 代碼之外:寫作是倒逼成長的最佳方式
- Redis 的快速介紹及其基本數據類型和操作
- 經久不衰的設計定律就是——不要讓我思考的設計
- 一文了解 Python 中的裝飾器
- 聊聊 Go 語言與雲原生技術
- Go Web 編程入門:驗證器
- Golang 的藝術、哲學和科學
- Django API 開發:視圖設置和路由
- Web 編程入門:什麼是Web API?
- Python 實現設計模式之工廠模式
- 好開心我進入了面試環節,那麼我該如何自我介紹?
- 鴻蒙學習筆記:利用鴻蒙JavaUI 框架的 WebView 加載在線網頁
- Go 語言入門很簡單:讀寫鎖