Django REST framework:SimpleRouter 使用指南

1. SimpleRouter 是什么?

SimpleRouter 是 DRF(Django REST framework)提供的路由器,能根據 ViewSet 自動生成標準的 REST 路由,包括:

  • GET /resources/ → 列表(list
  • POST /resources/ → 新建(create
  • GET /resources/{lookup}/ → 詳情(retrieve
  • PUT /resources/{lookup}/ → 全量更新(update
  • PATCH /resources/{lookup}/ → 局部更新(partial_update
  • DELETE /resources/{lookup}/ → 刪除(destroy

SimpleRouter vs DefaultRouter

  • SimpleRouter:只生成資源路由,不包含“API 根目錄”(api root) 頁面。
  • DefaultRouter:在 SimpleRouter 基礎上多一個“API 根目錄”索引頁(用于瀏覽器友好的入口)。

選擇建議

  • 你需要簡潔、純粹的 REST 路由:SimpleRouter
  • 你希望有一個根索引頁(或給產品/測試同學更友好的瀏覽入口):DefaultRouter

2. 快速上手(完整示例)

2.1 模型與序列化器

# app/models.py
from django.db import modelsclass Book(models.Model):isbn = models.CharField(max_length=20, unique=True)title = models.CharField(max_length=200)author = models.CharField(max_length=100)pub_date = models.DateField(null=True, blank=True)def __str__(self):return f"{self.title}({self.isbn})"
# app/serializers.py
from rest_framework import serializers
from .models import Bookclass BookSerializer(serializers.ModelSerializer):class Meta:model = Bookfields = ["id", "isbn", "title", "author", "pub_date"]

2.2 ViewSet(核心)

# app/views.py
from rest_framework import viewsets, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializerclass BookViewSet(viewsets.ModelViewSet):"""標準 CRUD + 一個自定義動作(按作者聚合數量)"""queryset = Book.objects.all()serializer_class = BookSerializerpermission_classes = [permissions.IsAuthenticatedOrReadOnly]# 將默認主鍵 lookup 切換為 ISBN(可選)lookup_field = "isbn"lookup_url_kwarg = "isbn"  # URL中的參數名(默認與lookup_field相同)@action(detail=False, methods=["GET"], url_path="by-author")def by_author(self, request):"""GET /books/by-author/返回每位作者的圖書數量"""from django.db.models import Countdata = Book.objects.values("author").annotate(count=Count("id")).order_by("-count")return Response(list(data))

2.3 路由

# app/urls.py
from django.urls import path, include
from rest_framework.routers import SimpleRouter
from .views import BookViewSetrouter = SimpleRouter()
# prefix='books' 會得到 /books/ 與 /books/{isbn}/
# basename 用于反向解析名的前綴,若未傳且能從 queryset.model 推斷,則可省略
router.register(r"books", BookViewSet, basename="book")urlpatterns = [path("", include(router.urls)),
]
# project/urls.py(項目根 URL)
from django.contrib import admin
from django.urls import path, includeurlpatterns = [path("admin/", admin.site.urls),path("api/v1/", include("app.urls")),  # 建議加上版本前綴
]

現在可用的路由(示例)

  • GET /api/v1/books/
  • POST /api/v1/books/
  • GET /api/v1/books/{isbn}/
  • PUT /api/v1/books/{isbn}/
  • PATCH /api/v1/books/{isbn}/
  • DELETE /api/v1/books/{isbn}/
  • GET /api/v1/books/by-author/(自定義動作)

3. register() 參數詳解

router.register(prefix, viewset, basename=None)
  • prefix:URL 前綴(復數資源名,建議小寫、用中劃線分詞如 user-profiles)。

  • viewset:繼承了 ViewSet/ModelViewSet 的類。

  • basename:用于生成路由名稱前綴。未提供時,DRF 會嘗試從 viewset.queryset.model 推斷。

    • 反向解析名形如:<basename>-list<basename>-detail<basename>-<action>

何時必須傳 basename:當你的 ViewSet 沒有 queryset(例如動態數據源)或無法從中推斷模型時,必須顯式提供,否則路由注冊會報錯或反向解析名缺失。


4. 路由規則與反向解析

4.1 自動生成的 URL 與名稱

basename="book" 為例:

HTTP路徑對應方法反向解析名
GET/books/listbook-list
POST/books/createbook-list
GET/books/{lookup}/retrievebook-detail
PUT/books/{lookup}/updatebook-detail
PATCH/books/{lookup}/partial_updatebook-detail
DELETE/books/{lookup}/destroybook-detail
GET/books/by-author/(示例)@action(detail=False)book-by-author

反向解析示例:

from django.urls import reversereverse("book-list")               # -> "/api/v1/books/"
reverse("book-detail", kwargs={"isbn": "9787111123456"})
reverse("book-by-author")          # 自定義動作(list 級別)

5. 常用配置與細節

5.1 結尾斜杠(trailing slash)

  • DRF 提供 DEFAULT_ROUTER_TRAILING_SLASH 設置控制結尾斜杠。

    • 常用取值:

      • "/":強制以斜杠結尾(如 /books/)。
      • "":不帶斜杠(如 /books)。
      • "/?":可帶可不帶(兼容兩種風格)。
  • 統一風格非常重要;否則容易出現“有時 301/404、有時匹配不到”的瑕疵。

# settings.py
REST_FRAMEWORK = {"DEFAULT_ROUTER_TRAILING_SLASH": "/",
}

與 Django 的 APPEND_SLASH 行為也有關聯;團隊應統一 API 風格并寫入測試。

5.2 自定義主鍵/查找字段

class BookViewSet(ModelViewSet):lookup_field = "isbn"        # 數據庫字段lookup_url_kwarg = "isbn"    # URL 參數名

如需限制匹配格式(正則),可在 Django 4+ 使用 path converters(推薦)或子類化 Router(高級用法,見 §7.3)。

5.3 命名空間與多應用拆分

# project/urls.py
urlpatterns = [path("api/v1/books/", include(("books.urls", "books"), namespace="books")),path("api/v1/users/", include(("users.urls", "users"), namespace="users")),
]# 反向解析(含命名空間)
reverse("books:book-list")

5.4 過濾、分頁、權限(與路由并列的重要配置)

# settings.py
REST_FRAMEWORK = {"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticatedOrReadOnly"],"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination","PAGE_SIZE": 20,"DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend","rest_framework.filters.SearchFilter","rest_framework.filters.OrderingFilter",],
}
# app/views.py
class BookViewSet(ModelViewSet):...filterset_fields = ["author"]   # /books/?author=xxxsearch_fields = ["title", "author"]  # /books/?search=xxxordering_fields = ["pub_date", "title"]  # /books/?ordering=-pub_date

6. 自定義動作(@action)

@action 能在標準 CRUD 之外添加自定義路由。

  • detail=False(集合級別):/books/top10/
  • detail=True(單資源級別):/books/{lookup}/publish/
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import statusclass BookViewSet(ModelViewSet):queryset = Book.objects.all()serializer_class = BookSerializerlookup_field = "isbn"@action(detail=False, methods=["GET"], url_path="top10")def top10(self, request):qs = Book.objects.order_by("-pub_date")[:10]return Response(BookSerializer(qs, many=True).data)@action(detail=True, methods=["POST"], url_path="publish")def publish(self, request, isbn=None):book = self.get_object()# ... 執行業務邏輯return Response({"isbn": book.isbn, "status": "published"}, status=status.HTTP_200_OK)

反向解析名:

  • book-top10
  • book-publish

7. 進階:定制 Router 與嵌套路由

7.1 統一前綴與版本

# project/urls.py
from rest_framework.routers import SimpleRouter
from books.views import BookViewSet
from users.views import UserViewSetrouter = SimpleRouter()
router.register(r"books", BookViewSet, basename="book")
router.register(r"users", UserViewSet, basename="user")urlpatterns = [path("api/v1/", include(router.urls)),
]

7.2 多個 Router 合并(分應用注冊)

# 每個 app 內部維護自己的 router
# app_a/urls.py -> router_a.urls
# app_b/urls.py -> router_b.urls# project/urls.py
urlpatterns = [path("api/v1/", include("app_a.urls")),path("api/v1/", include("app_b.urls")),
]

7.3 自定義 Router(修改結尾斜杠、lookup 正則……)

from rest_framework.routers import SimpleRouterclass SlashOptionalRouter(SimpleRouter):trailing_slash = "/?"  # 允許有無斜杠都匹配router = SlashOptionalRouter()
router.register(r"books", BookViewSet, basename="book")

更復雜的情況(如在 URL 中匹配特定格式的 lookup),建議用 path converters(Django 原生方案)或第三方 drf-nested-routers 實現嵌套資源(/authors/{id}/books/{isbn}/)。


8. 測試(強烈建議)

# tests/test_books_api.py
import pytest
from django.urls import reverse
from rest_framework.test import APIClient
from app.models import Book@pytest.mark.django_db
def test_book_crud_flow():client = APIClient()# Createresp = client.post(reverse("book-list"), {"isbn": "9787111123456", "title": "DRF 實戰", "author": "Alice"}, format="json")assert resp.status_code == 201# Retrieveurl = reverse("book-detail", kwargs={"isbn": "9787111123456"})resp = client.get(url)assert resp.status_code == 200assert resp.data["title"] == "DRF 實戰"# Custom actionresp = client.get(reverse("book-by-author"))assert resp.status_code == 200

反向解析名(如 book-list / book-detail)寫測試,可避免路徑硬編碼帶來的回歸風險。


9. 常見坑與排錯

  1. 反向解析失敗:多半是忘記傳 basename(且無法從 queryset 推斷),或命名空間未匹配(namespace:name)。
  2. 偶發 301/404:團隊未統一結尾斜杠策略;請用 DEFAULT_ROUTER_TRAILING_SLASH 一次性約定。
  3. lookup_field 不生效:URL 的 kwargs 名與 lookup_url_kwarg 對不上;或某處仍用默認 pk
  4. 接口未出現在路由ViewSet 方法名不規范(必須是 list/retrieve/...@action);或沒有把 router.urls include 進去。
  5. 權限/認證繞過:只在某些方法上聲明 permission_classes,其他方法漏配。建議在 ViewSet 級別統一聲明,特殊再覆蓋。
  6. 前后端聯調“接口名不固定”:團隊成員直接改 prefixbasename。建議寫入規范并加 API 回歸測試。

10. 與文檔/Schema 配合(可選)

  • 如果你要自動生成 OpenAPI / Swagger:
    推薦 drf-spectaculardrf-yasg;選擇 DefaultRouter 可提供一個 root 入口,但不是必須。
  • @action 標注 detailmethodsurl_path 并補充分頁/參數注釋,文檔會更完整。

11. 生產實踐建議(Checklist)

  • 按業務域拆分應用;每個 app 內部維護自己的 router,在項目層統一 api/v{n}/ 前綴。
  • 統一 DEFAULT_ROUTER_TRAILING_SLASH;與 Nginx/網關重寫規則一致。
  • 所有接口用 反向解析名 做測試與內部調用(避免硬編碼路徑)。
  • ViewSet 嚴格用標準方法名(list/retrieve/...)與 @action;自定義動作只做“業務語義上的操作”,避免濫用。
  • 統一權限、限流、分頁、過濾策略;默認安全,按需放開。
  • 如需嵌套資源,優先評估是否真的需要;需要時優先用 drf-nested-routers 或清晰的扁平資源 + 查詢參數。

12. 速查模板

# urls.py
from django.urls import path, include
from rest_framework.routers import SimpleRouter
from .views import FooViewSet, BarViewSetrouter = SimpleRouter()
router.register(r"foos", FooViewSet, basename="foo")
router.register(r"bars", BarViewSet, basename="bar")urlpatterns = [path("", include(router.urls))]
# views.py
from rest_framework import viewsets, permissions
from rest_framework.decorators import action
from rest_framework.response import Responseclass FooViewSet(viewsets.ModelViewSet):queryset = Foo.objects.all()serializer_class = FooSerializerpermission_classes = [permissions.IsAuthenticated]lookup_field = "slug"@action(detail=True, methods=["POST"], url_path="enable")def enable(self, request, slug=None):foo = self.get_object()foo.enable()return Response({"ok": True})
# settings.py
REST_FRAMEWORK = {"DEFAULT_ROUTER_TRAILING_SLASH": "/","DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination","PAGE_SIZE": 20,
}

【完】

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/95486.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/95486.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/95486.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

覆蓋Transformer、GAN:掩碼重建正在重塑時間序列領域!

隨著大數據與深度學習的發展&#xff0c;時間序列分析的建模能力顯著提升&#xff0c;而掩碼重建作為一種自監督學習范式&#xff0c;已成為提升序列表征能力的重要技術。該方法通過隨機掩碼部分數據并重建原始序列&#xff0c;迫使模型挖掘時序依賴性與潛在模式&#xff0c;在…

用AI做TikTok影視解說,全流程全自動成片,不懂外語也能做全球矩陣!

多語種解說&#xff1a; 短劇出海狂吸美金 多語種解說搶先機 TikTok、YouTube等平臺&#xff0c;尤其在非英語市場&#xff0c;內容供給仍遠遠不足&#xff0c;每一個小語種市場都是潛在藍海。 有人用英語講仙俠、西語講爽劇、日語講宮斗、阿語講懸疑&#xff0c;一夜漲粉百…

解密大語言模型推理:輸入處理背后的數學與工程實踐

解密大語言模型推理&#xff1a;輸入處理背后的數學與工程實踐當你向ChatGPT提問時&#xff0c;短短幾秒內就能獲得流暢的回答&#xff0c;這背后隱藏著怎樣的技術魔法&#xff1f;答案在于大語言模型高效推理過程中精妙的輸入處理機制。在現代大語言模型推理中&#xff0c;輸入…

02、連接服務器的幾種方式

02、連接服務器的幾種方式 1、Xshell 適用于Windows https://www.xshell.com/en/free-for-home-school/ 2、Termius 適用于MacOS 直接蘋果商店下載即可 3、IDEA 連接 Tools - Deployment - Browse Remote Host 1、打開Browse Remote Host2、添加服務3、輸入服務器連接信息并測試…

高并發系統設計方案(直播場景)

最近在準備面試&#xff0c;正把平時積累的筆記、項目中遇到的問題與解決方案、對核心原理的理解&#xff0c;以及高頻業務場景的應對策略系統梳理一遍&#xff0c;既能加深記憶&#xff0c;也能讓知識體系更扎實&#xff0c;供大家參考&#xff0c;歡迎討論。 1. 微服務拆分 …

網絡編程基礎:一文搞懂 Socket、HTTP、HTTPS、TCP/IP、SSL 的關系

在日常開發中&#xff0c;我們經常聽到 Socket、HTTP、HTTPS、TCP/IP、SSL 這些術語&#xff0c;這些概念往往容易混淆&#xff0c;且讓人感到困惑。本文將用最通俗易懂的方式來講清這些網絡概念及其相互關系。一、從寄信說起&#xff1a;網絡通信的本質假如你要給遠方的朋友寄…

查看LoRA 哪個適配器處于激活狀態(67)

哪個適配器處于激活狀態 當前哪個適配器處于激活狀態?我們來查看active_adapter屬性就知道了 peft_model.active_adapter輸出 default試試另一個(適配器) 你更想試試另一個(適配器)嗎?只需調用set_adapter()方法即可。 peft_model.set_adapter(yoda) peft_model.act…

??Nginx高性能Web服務器實戰:從協議原理到運維優化??

目錄 前言 一、Web基礎概念 1.1 什么是Web&#xff1f; 1.2 B/S架構模型 1.3 Web請求與響應流程 1.4 靜態資源 vs 動態資源 二、HTTP/HTTPS協議詳解 2.1 HTTP與HTTPS區別 2.2 HTTPS握手流程 2.3 HTTP狀態碼大全 三、Nginx核心知識 3.1 Nginx簡介 3.2 Nginx vs Apache 3.3 Nginx…

【先楫HPM5E00_EVK系列-板卡測評3】hpm5e00evk平臺中斷、定時器、PWM、USART等基礎功能詳解

此文介紹了利用先楫半導體&#xff08;hpm&#xff09;官方hpm5e00_evk開發板使用的主控芯片的一些原理性知識&#xff0c;無實驗內容展示&#xff0c;主要匯總了先楫半導體hpm5e00主控芯片的中斷、定時器、pwm、usart等功能&#xff0c;主要內容來源于B站“HPM_FAE”的視頻和官…

golang 依賴管理

目錄 演進過程 1. GOPATH 階段&#xff08;Go 1.0 - 1.10&#xff0c;2012 - 2018&#xff09; 2. Vendor 機制階段&#xff08;Go 1.5 實驗性引入&#xff0c;1.6 正式支持&#xff0c;2015 - 2018&#xff09; 3. Go Modules 過渡期&#xff08;Go 1.11 - 1.16&#xff0…

概率論—隨機事件與概率

文章目錄考綱術語事件的關系與運算關系運算古典概型概念和性質放入問題——隨機分配取出問題——簡單隨機抽樣問題幾何概型概率的性質與計算性質計算事件的獨立性和獨立的判定事件的獨立性判定定理舉反例的思想獨立試驗序列概型與n重伯努利概型錯題考綱 術語 (隨機)試驗隨機事…

達夢:存儲過程實現多個用戶之間表的授權

一、背景在某項目現場&#xff0c;開發商想實現4個用戶之間能互相擁有表的查詢、刪除、插入、更新權限和存儲過程的執行權限。此過程只要在新增表之后&#xff0c;其他用戶的權限需要授權&#xff0c;如果是手動寫&#xff0c;一張表的授權就要寫至少3次sql語句&#xff0c;如果…

協議分析基礎

0x01 協議分析基礎 網絡安全領域的“基本功”&#xff1a;一切高級攻擊&#xff08;漏洞利用、DDoS、滲透等&#xff09;都體現為網絡流量的異常。 核心價值&#xff1a; 故障排查 &#xff1a; 定位網絡延遲、丟包、無法連接等問題。性能優化 &#xff1a; 分析應用性能瓶頸。…

AI生成內容的版權迷局:GPT-4輸出的“創意”版權風險與規避之道

大型語言模型&#xff08;LLM&#xff09;如 GPT-4&#xff0c;正以前所未有的速度和創造力&#xff0c;改變著內容生產的方式。無論是文章、代碼、圖片還是音樂&#xff0c;AI都能快速生成令人驚嘆的作品。然而&#xff0c;在這股“AI內容創作浪潮”之下&#xff0c;一個嚴肅的…

編程與數學 03-004 數據庫系統概論 19_數據庫的分布式查詢

編程與數學 03-004 數據庫系統概論 19_數據庫的分布式查詢一、分布式查詢的概念&#xff08;一&#xff09;分布式查詢的定義&#xff08;二&#xff09;分布式查詢的特點二、分布式查詢的優化&#xff08;一&#xff09;查詢分解&#xff08;二&#xff09;查詢分配&#xff0…

java--寫在 try 中的創建連接

1. 背景 在 Java 開發中&#xff0c;很多資源&#xff08;數據庫連接、ZooKeeper 連接、Redis 客戶端、文件流等&#xff09;都需要手動關閉。如果忘記關閉&#xff0c;會導致 資源泄漏&#xff08;連接占滿、內存泄漏、文件句柄耗盡等&#xff09;。 為了避免這種問題&#xf…

蔡文勝在香港買了一棟樓,免費給創業者辦公

蔡文勝在香港買了一棟樓&#xff0c;免費給創業者辦公。前段時間&#xff0c;蔡文勝出售美圖公司、套現約8億港幣后&#xff0c;以6.5億港元購入香港天后道上全幢物業&#xff0c;并將其更名為“CAI大廈”。一樓是咖啡廳&#xff0c;二樓做公眾活動&#xff0c;樓上會有兩層會開…

FOC+MCU:重新定義吸塵器電機控制——高效、靜音、智能的終極解決方案

傳統吸塵器電機的“三重困境”當前吸塵器市場&#xff0c;消費者對吸力、噪音、續航的訴求日益嚴苛&#xff0c;但傳統電機控制方案&#xff08;如方波驅動、有感/無感BLDC控制&#xff09;難以兼顧&#xff1a;效率低下&#xff1a;高速運行時電機發熱嚴重&#xff0c;電池能量…

樹形組件,支持搜索展示,自定義展示,支持vue2,vue3,小程序等等

效果圖平臺兼容性Vue2Vue3ChromeSafariapp-vueapp-nvueAndroidiOS鴻蒙√√√√√√---微信小程序支付寶小程序抖音小程序百度小程序快手小程序京東小程序鴻蒙元服務QQ小程序飛書小程序快應用-華為快應用-聯盟√√√√√√-√√√√多語言暗黑模式寬屏模式√屬性屬性名類型默認值…

元宇宙與教育變革:沉浸式學習重構知識獲取與能力培養

1 元宇宙打破傳統教育的核心局限1.1 突破空間限制&#xff1a;從 “固定教室” 到 “全域學習場景”傳統教育受限于物理空間&#xff0c;優質資源集中在少數學校與城市&#xff0c;而元宇宙通過 “虛擬場景復刻 跨地域實時交互”&#xff0c;將學習空間拓展至全球乃至虛擬維度…