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),
]
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),
]
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),
]))
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)