You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django REST Framework同一类的不同请求中使用不同lookup字段

DRF 不同请求匹配不同lookup字段实现方案

核心逻辑

默认SimpleRouter只会为ModelViewSet生成统一lookup字段的路由规则,要实现不同请求用不同lookup字段,需要同时修改路由规则和视图动态切换lookup字段两个部分。

第一步:视图层动态切换lookup字段

重写get_object方法,根据请求方法切换对应的lookup字段:

from rest_framework.viewsets import ModelViewSet
from .models import User
from .serializers import UserSerializer

class UserViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    # 默认lookup字段用id,适配更新、查询等请求
    lookup_field = "id"

    def get_object(self):
        # 删除请求时切换为creation_date作为查询字段
        if self.request.method == "DELETE":
            self.lookup_field = "creation_date"
        return super().get_object()

注意:需要保证creation_date字段全局唯一,否则删除时会匹配到多个对象抛出异常,建议给该字段添加唯一约束,若为datetime类型需确保精度足够不会重复。

第二步:自定义SimpleRouter添加专属路由

默认Router的detail路由共用同一个路径参数,需要自定义Router为删除操作单独配置带creation_date参数的路由:

from rest_framework.routers import SimpleRouter, Route, DynamicRoute

class CustomUserRouter(SimpleRouter):
    routes = [
        # 列表路由保持默认
        Route(
            url=r"^{prefix}{trailing_slash}$",
            mapping={"get": "list", "post": "create"},
            name="{basename}-list",
            detail=False,
            initkwargs={"suffix": "List"}
        ),
        # 单独配置删除操作路由,参数为creation_date
        Route(
            url=r"^{prefix}/(?P<creation_date>[^/.]+){trailing_slash}$",
            mapping={"delete": "destroy"},
            name="{basename}-destroy",
            detail=True,
            initkwargs={"suffix": "Destroy"}
        ),
        # 其他详情操作(查询、全量更新、部分更新)用id作为参数
        Route(
            url=r"^{prefix}/(?P<id>[^/.]+){trailing_slash}$",
            mapping={"get": "retrieve", "put": "update", "patch": "partial_update"},
            name="{basename}-detail",
            detail=True,
            initkwargs={"suffix": "Instance"}
        ),
        # 动态路由保持默认配置
        DynamicRoute(
            url=r"^{prefix}/{url_path}{trailing_slash}$",
            name="{basename}-{url_name}",
            detail=False,
            initkwargs={}
        ),
        DynamicRoute(
            url=r"^{prefix}/(?P<id>[^/.]+)/{url_path}{trailing_slash}$",
            name="{basename}-{url_name}",
            detail=True,
            initkwargs={}
        )
    ]

# 注册路由
router = CustomUserRouter()
router.register(r"user", UserViewSet, basename="user")
urlpatterns = router.urls

可选优化

  • 若creation_date为datetime类型,可调整路由正则匹配规则适配ISO时间格式,比如将参数正则改为(?P<creation_date>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?)
  • 若多个视图需要类似逻辑,可将动态切换lookup字段的逻辑抽为公共Mixin,也可以将Router改为通用支持传入不同请求对应的lookup字段配置,减少重复代码。

内容的提问来源于stack exchange,提问作者Rackymuthu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 19:06:09