To force a maintenance mode in Django, we need to redirect all traffic to a maintenance page, except for requests from specific IPs (like our own for management purposes). This can be achieved using middleware. Here's a basic approach:
Create a maintenance middleware:
- This middleware will intercept requests and redirect them to a maintenance page if a maintenance mode is active.
Add a Maintenance View and Template:
- Create a simple view and template for the maintenance page that users will see.
Configure the middleware:
- Add the middleware to your Django project settings.
Activate/Deactivate Maintenance Mode:
- We can activate maintenance mode by changing a variable, a file existence, or a database flag.
Here's a simple example to illustrate these steps:
Step 1: Create a Maintenance Middleware
We will create a file namedmaintainence_middleware.py
in one of your apps:
from django.http import HttpResponse
from django.shortcuts import redirect
class MaintenanceMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# Check if maintenance mode is active
# This can be a setting in settings.py, a database flag, or checking for a file
if hasattr(settings, 'MAINTENANCE_MODE') and settings.MAINTENANCE_MODE:
# Allow access to certain IPs
allowed_ips = ['123.456.78.90',] # Your IP here
if request.META.get('REMOTE_ADDR') in allowed_ips:
return self.get_response(request)
else:
return redirect('maintenance_page')
return self.get_response(request)
Step 2: Add a Maintenance View and Template
In our views.py
:
from django.shortcuts import render
def maintenance_page(request):
return render(request, 'maintenance.html')
Create a maintenance.html
template in your templates directory with the appropriate HTML content.
Step 3: Configure the Middleware
In your settings.py
, add the middleware to MIDDLEWARE
:
MIDDLEWARE = [
# ...
'yourapp.maintenance_middleware.MaintenanceMiddleware',
# ...
]
Step 4: Activate/Deactivate Maintenance Mode
In your settings.py
:
# Set this to True to activate maintenance mode
MAINTENANCE_MODE = False
Step 5: You might want to:
Custom Maintenance Page: Customize the
maintenance.html
to inform our users about the maintenance and possibly provide an estimated time for when the service will be back.Dynamic Activation: Instead of manually changing the
settings.py
, we could use an environment variable or a database setting that we can modify without deploying new code.Logging Access Attempts: We might want to log attempts to access the site during maintenance for security and analysis.
Testing: Ensure we test this thoroughly in a staging environment before deploying it to production, especially the IP whitelisting part.
Notify Users in Advance: If possible, notify our users in advance about the planned maintenance.
By following these steps, you can implement a maintenance mode in your Django application that can be easily activated or deactivated as needed.
Step 6: Testing Maintainence Middleware
Set up the test environment: This involves creating a test class that inherits from
TestCase
and setting up any necessary configurations.Test the middleware's behavior: You should test for both when maintenance mode is active and when it is not. Additionally, testing for access from allowed IPs and disallowed IPs is important.
Here's an example of how you might write these test cases:
1. Set Up the Test Environment
First, create a test file in your Django app's tests
directory, e.g., test_
middleware.py
.
from django.test import TestCase, RequestFactory
from django.conf import settings
from yourapp.views import maintenance_page
from yourapp.maintenance_middleware import MaintenanceMiddleware
class MaintenanceMiddlewareTest(TestCase):
def setUp(self):
# The RequestFactory instance is a way to create request instances for use in testing.
self.factory = RequestFactory()
self.middleware = MaintenanceMiddleware(lambda x: x)
2. Test the Middleware's Behavior
Test When Maintenance Mode is Active
def test_maintenance_mode_active(self):
# Set maintenance mode to active
settings.MAINTENANCE_MODE = True
# Create a request instance
request = self.factory.get('/any-page')
request.META['REMOTE_ADDR'] = '111.222.33.44' # Non-allowed IP
# Process the request through the middleware
response = self.middleware(request)
# Check that the response is a redirect to the maintenance page
self.assertEqual(response.status_code, 302)
self.assertEqual(response.url, '/maintenance-page') # URL of your maintenance page
Test When Maintenance Mode is Inactive
def test_maintenance_mode_inactive(self):
# Set maintenance mode to inactive
settings.MAINTENANCE_MODE = False
# Create a request instance
request = self.factory.get('/any-page')
# Process the request through the middleware
response = self.middleware(request)
# Check that the request passes through the middleware unaffected
self.assertEqual(response.status_code, 200)
Test Access from Allowed IPs
def test_access_from_allowed_ip(self):
# Set maintenance mode to active
settings.MAINTENANCE_MODE = True
# Create a request instance with an allowed IP
request = self.factory.get('/any-page')
request.META['REMOTE_ADDR'] = '123.456.78.90' # Allowed IP
# Process the request through the middleware
response = self.middleware(request)
# Check that the request passes through the middleware unaffected
self.assertEqual(response.status_code, 200)
Additional Notes:
Make sure to replace
'yourapp'
with the actual name of your Django app.Modify the
'/maintenance-page'
with the actual URL of your maintenance page.These tests assume that the normal response (when not in maintenance mode) has a status code of 200. Adjust according to your actual app's behavior.
Remember to reset any settings (like
MAINTENANCE_MODE
) after the test to avoid side effects on other tests.
By covering these scenarios, your test case will effectively validate the behavior of your maintenance middleware under different conditions.