如何在Django Rest Framework SimpleRouter中使尾随斜杠可选

48

文档中提到可以设置trailing_slash=False,但是如何允许带斜杠或不带斜杠的两个端点都能正常工作呢?

6个回答

55
您可以重写SimpleRouter类的__init__方法:__init__ method
from rest_framework.routers import SimpleRouter


class OptionalSlashRouter(SimpleRouter):

    def __init__(self):
        super().__init__()
        self.trailing_slash = '/?'

?字符会使所有可用的路由中斜杠成为可选项。


有趣的是,我今天也在考虑这个问题。但我正在使用URL路由器。会尝试一下看看会发生什么。+1 - Bernard 'Beta Berlin' Parah
12
我使用了DefaultRouter,并且需要这样做:`class OptionalSlashRouter(DefaultRouter):def __init__(self, *args, **kwargs): super(DefaultRouter, self).__init__(*args, **kwargs) self.trailing_slash = '/?' ` - Def_Os
2
你可以将 /? 传递给 构造函数 - x-yuri
3
__init__ 方法的真值为真时,会覆盖 trailing_slash 以始终为 /。该方法位于 此处 - Ryan Allen
5
把超级初始化方法调用放在 self.trailing_slash = '/?' 之前。 - Mcmil
获取 - django.core.exceptions.ImproperlyConfigured: "^?$" 不是一个有效的正则表达式:在位置1没有可重复的内容。 解决方案如下。 - Vikram Ray

36

您也可以通过向SimpleRouter构造函数传递trailing_slash参数来覆盖此设置,如下所示:

from rest_framework import routers

router = routers.SimpleRouter(trailing_slash=False)

10
带有尾部斜杠的网址无法正常工作。 - Ryan Allen
那就是关键所在,但在这种情况下,您可能需要在HTTP服务器级别上配置以支持两者。例如:Apache有mod_rewrite模块,您可以对没有尾随斜杠的URL进行简单的重定向。 - OzzyTheGiant
1
如果我设置了 trailing_slash=False,并且在注册URL时在末尾添加斜杠,同时没有将APPEND_SLASH设置为False,则带或不带斜杠的URL都可以正常工作,因为没有带斜杠的URL会重定向到带斜杠的URL。 - mic
问题在于,DRF 的子页面 URL(例如 my_model/1/)会变成 my_model//1。因此,最好保持默认的 trailing_slash=True,注册不带尾随斜杠的 URL,并将 APPEND_SLASH 设置为 True。 - mic

14

如果你正在使用DRF的路由器和视图集,你可以在你的前缀中包含/?

from rest_framework import routers

from .views import ClientViewSet

router = routers.SimpleRouter(trailing_slash=False)
router.register(r"clients/?", ClientViewSet)

我更喜欢这个解决方案,它可以给你更多的控制。 - imns

5

我发现最简单的方法就是单独设置URL以处理可选的尾随斜杠,例如:

from django.urls import re_path

urlpatterns = [
    re_path('api/end-point/?$', api.endPointView),
    ...

虽然这不是DRY(Don't Repeat Yourself)的解决方案,但对于每个URL只需要额外增加两个字符就可以了。而且它并不涉及覆盖路由器。


1
对于DefaultRouter类,与Ryan Allen的答案相同:
from rest_framework.routers import DefaultRouter


class OptionalSlashRouter(DefaultRouter):
    """Make all trailing slashes optional in the URLs used by the viewsets
    """
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.trailing_slash = '/?'


router = OptionalSlashRouter()
...

1
对于使用rest_framework_extensions中的ExtendedSimpleRouter的任何人,接受的解决方案需要进行小修改。 self.trailing_slash必须在super().__init__()之后,如下所示。
from rest_framework_extensions.routers import ExtendedSimpleRouter

class OptionalSlashRouter(ExtendedSimpleRouter):
    def __init__(self):
        super(ExtendedSimpleRouter, self).__init__()
        self.trailing_slash = "/?"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接