django 使用drf-nested-routers在嵌套路由中指定lookup_url_kwarg

57hvy0tb  于 2023-11-20  发布在  Go
关注(0)|答案(1)|浏览(139)

使用drf-nested-routers,我们实现了许多嵌套的路由,这些路由的深度为两个级别。
就像在文档中的示例一样:

/clients/
/clients/{pk}/
/clients/{client_pk}/maildrops/
/clients/{client_pk}/maildrops/{pk}/
/clients/{client_pk}/maildrops/{maildrop_pk}/recipients/
/clients/{client_pk}/maildrops/{maildrop_pk}/recipients/{pk}/

字符串
但是,我不喜欢第四行的不一致。我怎么才能让lookup_url_kwarg也成为maildrop_pk呢?

/clients/{client_pk}/maildrops/{maildrop_pk}/


urls.py看起来是这样的:

# urls.py
router = DefaultRouter()
router.register(r'clients', ClientViewSet, basename='clients')
## generates:
# /clients/
# /clients/{pk}/

client_router = routers.NestedSimpleRouter(router, r'clients', lookup='client')
client_router.register(r'maildrops', MailDropViewSet, basename='maildrops')
## generates:
# /clients/{client_pk}/maildrops/
# /clients/{client_pk}/maildrops/{pk}/

maildrops_router = routers.NestedSimpleRouter(client_router, r'maildrops', lookup='maildrop')
maildrops_router.register(r'recipients', MailRecipientViewSet, basename='recipients')
## generates:
# /clients/{client_pk}/maildrops/{maildrop_pk}/recipients/
# /clients/{client_pk}/maildrops/{maildrop_pk}/recipients/{pk}/

urlpatterns = [
    path(r'', include(router.urls)),
    path(r'', include(client_router.urls)),
    path(r'', include(maildrops_router.urls)),
]


如果我将MailDropViewSet中的lookup_url_kwarg设置为maildrop_pk

class MailDropViewSet(viewsets.ViewSet):
    serializer_class = MailDropSerializer
    lookup_url_kwarg = "maildrop_pk"


那么路由看起来像这样:

/clients/{client_pk}/maildrops/{maildrop_pk}/
/clients/{client_pk}/maildrops/{maildrop_maildrop_pk}/recipients/
/clients/{client_pk}/maildrops/{maildrop_maildrop_pk}/recipients/{pk}/


我希望在路由中对URL查找kwargs进行一致的命名,例如:

/clients/{client_pk}/maildrops/{maildrop_pk}/
/clients/{client_pk}/maildrops/{maildrop_pk}/recipients/
/clients/{client_pk}/maildrops/{maildrop_pk}/recipients/{pk}/


但我看不出这是怎么配置的

ctzwtxfj

ctzwtxfj1#

虽然不理想,但一个想法可能是制作我们自己的NestedSimpleRouter,使用:

from rest_framework_nested.routers import NestedMixin

class OurNestedMixin(NestedMixin):
    def __init__(self, parent_router, parent_prefix, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.nest_prefix = kwargs.get('lookup', 'nested_%i' % self.nest_count)

字符串
并将其混合成NestedSimpleRouter

from rest_framework_nested.routers import NestedMixin

class OurNestedSimpleRouter(OurNestedMixin, NestedSimpleRouter):
    pass


因此,我们可以将其用作:

# urls.py
router = DefaultRouter()
router.register(r'clients', ClientViewSet, basename='clients')

client_router = OurNestedSimpleRouter(router, r'clients', lookup='')
client_router.register(r'maildrops', MailDropViewSet, basename='maildrops')

maildrops_router = OurNestedSimpleRouter(client_router, r'maildrops', lookup='')
maildrops_router.register(
    r'recipients', MailRecipientViewSet, basename='recipients'
)


所以ViewSet s的lookup_url_kwarg s决定了参数的名称,这将定义URL模式。
当然,结果是lookup_url_kwarg应该在所有ViewSet上定义,对于它们生成的所有路径,永远不会有两个同名的路径参数。

相关问题