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;将学习空间拓展至全球乃至虚拟维度…