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第三方扩展完成配置,步骤如下:
- 嵌套路由注册配置
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
- 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
相关产品推荐
相关产品推荐

