Django FeatureVault
Feature Flag Framework for Django.
Installation
python -m pip install django-featurevault
First, add django_featurevault to your INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"django_featurevault",
]
Next, add FeatureContextMiddleware to your MIDDLEWARE list:
MIDDLEWARE = [
# ...
"django_featurevault.middleware.FeatureContextMiddleware",
]
Finally, configure your feature flags in settings.py:
FEATURE_FLAGS = {
"default": {
"BACKEND": "django_featurevault.backends.settings.SettingsBackend",
"OPTIONS": {
"FLAGS": {
"GLOBAL_BANNER": True,
"STAFF_DASHBOARD": {
"enabled": True,
"conditions": {
"groups": [
{
"properties": [
{"key": "is_staff", "operator": "exact", "value": True}
]
}
]
},
},
"NEW_CHECKOUT": {
"enabled": True,
"conditions": {
"groups": [
{"rollout_percentage": 50}
]
},
},
}
},
}
}
Backends
Few backends are included by default:
django_featurevault.backends.settings.SettingsBackend: Reads feature flags directly fromsettings.FEATURE_FLAGS.django_featurevault.backends.dummy.DummyBackend: In-memory backend for testing.
Custom Backends
You can create custom storage backends by subclassing BaseFeatureBackend and implementing get_feature and get_all_features:
from typing import Any
from django_featurevault.backends.base import BaseFeatureBackend
class CustomRedisBackend(BaseFeatureBackend):
def __init__(self, alias: str = "default", **options: Any) -> None:
super().__init__(alias=alias, **options)
# Initialize client connections using options passed from settings
self.redis_url = options.get("URL", "redis://localhost:6379/0")
def get_feature(self, feature_name: str, default: Any = False) -> dict[str, Any]:
"""
Fetch feature configuration dictionary by name.
Must return a dict containing at minimum:
{"enabled": bool, "conditions": dict}
"""
# Fetch from your storage engine...
return {
"enabled": True,
"conditions": {},
}
def get_all_features(self) -> dict[str, dict[str, Any]]:
"""Fetch all feature definitions for bulk evaluation."""
return {}
Point to your custom backend in settings.py:
FEATURE_FLAGS = {
"default": {
"BACKEND": "my_app.backends.CustomRedisBackend",
"OPTIONS": {
"URL": "redis://127.0.0.1:6379/1",
},
}
}
Usage
Checking flags in views
Import feature and call is_enabled:
from django.shortcuts import render
from django_featurevault import feature
def home_view(request):
if feature.is_enabled("NEW_CHECKOUT"):
return render(request, "new_checkout.html")
return render(request, "old_checkout.html")
If a flag is not defined, is_enabled returns False by default. You can change this using the default parameter:
feature.is_enabled("UNKNOWN_FLAG", default=True)
Passing explicit context
You can pass a custom context dictionary directly into is_enabled:
feature.is_enabled("BETA_FEATURE", context={"plan": "enterprise", "country": "IN"})
Background tasks and testing context
To evaluate feature flags in Celery workers, cron jobs, or tests where no HTTP request exists, use the context manager:
from django_featurevault import feature
with feature.context(user_id="user_101", is_staff=True):
if feature.is_enabled("STAFF_DASHBOARD"):
...
Conditions and Targeting
Flags defined as dictionaries support targeting rules via conditions.
"FEATURE_NAME": {
"enabled": True,
"conditions": {
"groups": [
# Group 1: Enabled for internal staff
{
"properties": [
{"key": "is_staff", "operator": "exact", "value": True}
],
}
# OR Group 2: Enabled for 20% of beta users in India
{
"properties": [
{"key": "country", "operator": "exact", "value": "IN"},
{"key": "plan", "operator": "exact", "value": "beta"}
],
"rollout_percentage": 20,
}
]
},
}
groups: Evaluated with OR logic (if any group matches, the flag is enabled).propertieswithin a group: Evaluated with AND logic (all properties in the group must match).rollout_percentage: A percentage between 0 and 100 that uses sticky hashing against the user or device ID.
Supported operators
exact: Matches exact equality (==).is_not: Matches inequality (!=).in: Checks values in a list (value in [...]).icontains: Case-insensitive substring match.
Automatically resolved user fields
When evaluating against an authenticated Django user, the following context keys are resolved automatically:
user_id,id,pk: The user's primary key (user.pk).username: The user's username (getattr(user, user.USERNAME_FIELD)).django_group: Group names the user belongs to (user.groups.values_list("name", flat=True)).- Any standard or custom attribute on the user model (like
is_staff,is_superuser,email).
Cookie Configuration
FeatureContextMiddleware automatically sets an anonymous device cookie for sticky rollouts when users are not logged in.
You can customize the cookie name and options in settings.py:
FEATURE_FLAGS = {
"CLIENT_ID_COOKIE": "ff_client_id",
"COOKIE_OPTIONS": {
"max_age": 30 * 24 * 60 * 60,
"httponly": True,
"samesite": "Lax",
},
}
API Endpoint
To expose evaluated feature flags to frontend clients as JSON, include the URLs in your urls.py:
from django.urls import include, path
urlpatterns = [
# ...
path("features/", include("django_featurevault.urls")),
]
This registers GET /features/api/flags/, and returns a JSON map of all evaluated flags:
{
"GLOBAL_BANNER": {"enabled": true},
"STAFF_DASHBOARD": {"enabled": false},
"NEW_CHECKOUT": {"enabled": true}
}
Example Project
An example project is included in the example/ directory.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_featurevault-0.1.0.tar.gz.
File metadata
- Download URL: django_featurevault-0.1.0.tar.gz
- Upload date:
- Size: 14.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c03c5128fec5c68e298c57d79093592d16544bd8bba5940cde27252b03f414c9
|
|
| MD5 |
88ec5675d3a30a80f3cd71e7a49106cb
|
|
| BLAKE2b-256 |
bf7898c861e60e50130fd1648c09b68ce2382e3a3f67d3fa959a0f87611ed680
|
File details
Details for the file django_featurevault-0.1.0-py3-none-any.whl.
File metadata
- Download URL: django_featurevault-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
38f87de89169f94e8c81d79d65de42785b6935045da74c61ede6c10e5fdd3d31
|
|
| MD5 |
5e15e3ab7315d741ca70cb6e8afef155
|
|
| BLAKE2b-256 |
50acbda0d0f54aff42e291979c71b036ddcc40491e28252ee0ea09fbcdcccbd0
|