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

Django REST Framework如何定义嵌套Viewset及自定义lookup_field名称

问题1:自定义URL参数名实现方案

完全可以实现,不需要修改模型原有字段命名。
DRF的ViewSet单独提供了lookup_url_kwarg参数用来定义URL路径中的参数名,和负责指定模型查询字段的lookup_field是互相独立的配置项,你只需要在ModelAViewset中新增该配置即可:

class ModelAViewset(viewsets.ModelViewSet):
    queryset = ModelA.objects.all()
    serializer_class = ModelASerializer
    # 原配置保留,对应模型的slug字段,不需要修改
    lookup_field = "slug"
    # 新增配置,指定URL中显示的参数名
    lookup_url_kwarg = "model_a_slug"

如果需要给多个ViewSet统一实现动态基于模型名生成参数名,可以写一个通用混入类复用逻辑:

class AutoLookupUrlKwargMixin:
    @property
    def lookup_url_kwarg(self):
        # 自动获取当前模型的小写名,拼接lookup_field生成参数名
        model_name = self.queryset.model._meta.model_name
        return f"{model_name}_{self.lookup_field}"

# 所有需要该逻辑的ViewSet继承该混入类即可
class ModelAViewset(AutoLookupUrlKwargMixin, viewsets.ModelViewSet):
    queryset = ModelA.objects.all()
    serializer_class = ModelASerializer
    lookup_field = "slug"

配置完成后自动生成的路径即为{root_url}/model-a/<model_a_slug>。


问题2:嵌套路由实现方案

可以实现,DRF官方原生路由不直接支持嵌套结构,通用方案是使用drf-nested-routers第三方扩展完成配置,步骤如下:

  1. 嵌套路由注册配置
from rest_framework import routers
from rest_framework_nested.routers import NestedDefaultRouter

# 注册根路由
root_router = routers.DefaultRouter()
root_router.register("model-a", ModelAViewset, basename="model-a")

# 注册model-a下的嵌套model-b路由,lookup参数对应父资源的参数前缀
model_a_nested_router = NestedDefaultRouter(
    root_router, 
    "model-a", 
    lookup="model_a"
)
model_a_nested_router.register(
    "model-b", 
    ModelBViewset, 
    basename="model-a-model-b"
)

# 合并路由到全局urlpatterns
urlpatterns = [
    # 其他全局路由配置
] + root_router.urls + model_a_nested_router.urls
  1. ModelBViewset配套配置
class ModelBViewset(viewsets.ModelViewSet):
    queryset = ModelB.objects.all()
    serializer_class = ModelBSerializer
    # 配置子资源的URL参数名
    lookup_field = "pk"
    lookup_url_kwarg = "model_b_pk"

    # 可选:如果需要自动过滤出属于当前父级ModelA的ModelB实例,重写get_queryset即可
    def get_queryset(self):
        model_a_slug = self.kwargs["model_a_slug"]
        return super().get_queryset().filter(model_a__slug=model_a_slug)

配置完成后即可通过{root_url}/model-a/<model_a_slug>/model-b/<model_b_pk>访问ModelB的详情页。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 01:30:00