DEV Community

Tyler Smith
Tyler Smith

Posted on

Development-only routes in Django

When you adopt a continuous integration approach to software development, all of your code gets committed to the main branch of your repository, and that branch must always be in a deployable state. This means you must have a way of hiding incomplete features that aren't ready for your users.

One way to hide incomplete features is to completely omit routes that aren't ready for public viewing on the production site.

Step 1: Checking if the site is in development

Let's pretend that we're building a project where we are actively working on an incomplete "Blog" feature. The {project_name}/urls.py file currently looks like this:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('events/', include('events.urls')),
    path('blog/', include('blog.urls')),
    path('admin/', admin.site.urls),
]
Enter fullscreen mode Exit fullscreen mode

We need a way to identify if the site is in development environment. If it's not, then we don't want to include the route.

Django doesn't offer an explicit way of checking development vs production environments, but we know that the DEBUG setting in {project_name}/settings.py should be set to False in production. We'll assume that if DEBUG is True that we're in development:

from django.contrib import admin
from django.urls import include, path
from django.conf import settings

urlpatterns = [
    path('events/', include('events.urls')), 
    path('blog/', include('blog.urls')
         ) if settings.DEBUG == True else None,
    path('admin/', admin.site.urls),
]
Enter fullscreen mode Exit fullscreen mode

Now the blog/ routes will be accessible in development environments, but they will not be accessible in production.

Step 2: Filtering out "None" routes (optional)

Surprisingly, Django 3.2 handles items with a value of None in the urlpatterns list just fine: the code above works as-is. However, my gut tells me this will break something in the future, so I'd prefer to filter all of the None values out, leaving only items that have non-None values.

We'll wrap the entire urlpatterns list in a filter function:

# {project_name}/urls.py

urlpatterns = list(filter(lambda route: route is not None, [
    path('events/', include('events.urls')), 
    path('blog/', include('blog.urls')
         ) if settings.DEBUG == True else None,
    path('admin/', admin.site.urls),
]))
Enter fullscreen mode Exit fullscreen mode

The filter function must be wrapped in a list function, otherwise it will return a filter object. You could also do something similar to this with a list comprehension, but I prefer using filter in this case. Alternatively, you could skip this step and everything should still work.

Next steps

If you wanted to take this further, you could create a reusable is_development() function, or use environment variables to check if the app is in production. In my projects, I pass an APP_ENV variable into the project on startup, then check it with os.environ.get('APP_ENV') == "production".

Hopefully you found this post helpful. If you did, feel free to leave a like or a comment.

Top comments (0)