How can I make a trailing slash optional on a Django Rest Framework SimpleRouter

22k Views Asked by At

The docs say you can set trailing_slash=False but how can you allow both endpoints to work, with or without a trailing slash?

7

There are 7 best solutions below

6
On BEST ANSWER

You can override the __init__ method of the SimpleRouter class:

from rest_framework.routers import SimpleRouter


class OptionalSlashRouter(SimpleRouter):

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

The ? character will make the slash optional for all available routes.

0
On

I found the easiest way to do this is just to set up your URLs individually to handle the optional trailing slash, e.g.

from django.urls import re_path

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

Not a DRY solution, but then it's only an extra two characters for each URL. And it doesn't involve overriding the router.

0
On

For the DefaultRouter class, it's the same as Ryan Allen's answer:

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
On

If you're using DRF's routers and viewsets, you can include /? in your prefix.

from rest_framework import routers

from .views import ClientViewSet

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

For DefaultrRoter class, it can be done in a simpler way

from djoser import views

from rest_framework.routers import DefaultRouter


router = DefaultRouter(trailing_slash=False)
router.register(r'users', views.UserViewSet)
4
On

You can also override this setting by passing a trailing_slash argument to the SimpleRouter constructor as follows:

from rest_framework import routers

router = routers.SimpleRouter(trailing_slash=False)
0
On

For anyone using ExtendedSimpleRouter in rest_framework_extensions, the accepted solution needs a small modification. The self.trailling_slash has to be after the super().__init__() like this.

from rest_framework_extensions.routers import ExtendedSimpleRouter

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