Registry / web-framework / django-waffle

django-waffle

JSON →
library5.0.0pypypi✓ verified 25d ago

Django Waffle is a feature flipper for Django projects, allowing developers to dynamically toggle features on or off without redeploying code. It supports flags, switches, and samples, enabling use cases like A/B testing, phased rollouts, and granular control based on users, groups, or percentages. The library is actively maintained, with its current version being 5.0.0, and receives fairly steady updates.

pip install django-waffle
INSTALL
IMPORT
SIG · DJANGO-WAFFLE
D
django-waffle
web-frameworkpythonv5.0.0
Install
3.5s avg
Import
724ms
Disk
66MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v5.0.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.95 runs
installs and imports cleanly · install 0.0s · import 0.748s · 66.9MB
glibc
py 3.103.95 runs
installs and imports cleanly · install 3.5s · import 0.700s · 67MB
66MB installed
● package 66MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

flag_is_active, switch_is_active, sample_is_active
from waffle import flag_is_active, switch_is_active, sample_is_active
For checking status programmatically in Python code (e.g., views). `flag_is_active` typically requires the request object.
waffle_flag, waffle_switch, waffle_sample
from waffle.decorators import waffle_flag, waffle_switch, waffle_sample
For decorating Django views to control access based on a flag, switch, or sample.
waffle_tags
{% load waffle_tags %}
For loading Waffle's template tags in Django templates to use `{% flag %}`, `{% switch %}`, or `{% sample %}` blocks.
Flag, Switch, Sample
from waffle.models import Flag, Switch, Sample
For direct interaction with Waffle's database models, typically for advanced customization or custom model swapping.

To get started with Django Waffle, first install the package and add `'waffle'` to your `INSTALLED_APPS` and `'waffle.middleware.WaffleMiddleware'` to your `MIDDLEWARE` settings. Ensure `django.template.context_processors.request` is in your template context processors for template tag functionality. Run migrations (`python manage.py migrate`) to create Waffle's database tables. You can then define flags, switches, and samples via the Django Admin. In your Python code, use `waffle.flag_is_active()` or decorators like `@waffle_flag` to control logic or view access. In templates, load `waffle_tags` and use `{% flag 'name' %}` blocks to conditionally render content.

# settings.py INSTALLED_APPS = [ # ... 'django.contrib.auth', 'django.contrib.messages', 'waffle', # ... ] MIDDLEWARE = [ # ... 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'waffle.middleware.WaffleMiddleware', # ... ] TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] # Terminal # python manage.py migrate # python manage.py createsuperuser # If you don't have one # Then, log into Django Admin to create a Flag named 'my_new_feature' # Set it to active for 'Superusers' or a percentage of users. # views.py from django.shortcuts import render from waffle.decorators import waffle_flag from waffle import flag_is_active @waffle_flag('my_new_feature') def my_feature_view(request): # This view will return a 404 if 'my_new_feature' flag is not active for the request. message = "Welcome to the new feature!" if flag_is_active(request, 'another_flag'): message += " (Another flag is also active.)" return render(request, 'my_app/feature_page.html', {'message': message}) def my_other_view(request): context = {} if flag_is_active(request, 'some_conditional_element'): context['show_element'] = True return render(request, 'my_app/regular_page.html', context) # my_app/feature_page.html {% extends 'base.html' %} {% load waffle_tags %} {% block content %} <h1>{{ message }}</h1> <p>This page is protected by 'my_new_feature' flag.</p> {% endblock %} # my_app/regular_page.html {% extends 'base.html' %} {% load waffle_tags %} {% block content %} <h1>Regular Content</h1> {% flag 'some_conditional_element' %} <p>This element only shows if 'some_conditional_element' is active!</p> {% else %} <p>Conditional element is currently hidden.</p> {% endflag %} {% endblock %}
Debug
Known issues
breakingVersion 5.0.0 dropped support for several End-of-Life Django versions (3.2, 4.0, 4.1) and Python 3.8. Users on these older versions must upgrade their Python/Django environment before updating to django-waffle 5.0.0. Similar breaking changes for Python and Django versions occurred in v4.0.0 and v3.0.0.
fix
Upgrade your Django project to a supported version (e.g., Django 4.2+, 5.0+, 5.2+) and Python to 3.9+ (Python 3.11+ for v4.0.0, Python 3.13+ for v4.2.0).
affects: 5.0.0+
breakingIn v5.0.0, the behavior of `flag.everyone` was corrected. If you relied on the previous, potentially incorrect, behavior of this setting for flags, your application's feature rollout might change.
fix
Review flags that utilize the 'everyone' setting and verify their activation behavior after upgrading to v5.0.0. Adjust flag configurations as needed in the Django admin or via management commands.
affects: 5.0.0+
gotchaDjango Waffle aggressively caches flags, switches, and samples. After upgrading the library or if changing the underlying object structure (e.g., custom models), you may need to clear your cache or change the `WAFFLE_CACHE_PREFIX` setting to avoid stale data. Additionally, in high-traffic, multi-database environments, `WAFFLE_ALWAYS_READ_FROM_DB=True` might be necessary to prevent stale data due to cache misses falling back to potentially old read replicas.
fix
Consider setting `WAFFLE_CACHE_PREFIX` to a new unique value after major upgrades. For critical, real-time consistency, set `WAFFLE_ALWAYS_READ_FROM_DB = True` in settings, but be aware of the performance implications. Implement robust cache invalidation strategies where appropriate.
affects: All versions
gotchaBy default, if Waffle encounters a reference to a flag, switch, or sample that is not defined in the database, it considers it inactive (`False`). This can lead to unexpected behavior if you expect features to be active by default. You can change this behavior via settings like `WAFFLE_CREATE_MISSING_FLAGS` or `WAFFLE_FLAG_DEFAULT`.
fix
Explicitly define all flags, switches, and samples in the Django Admin. Alternatively, set `WAFFLE_CREATE_MISSING_FLAGS = True` (and similar for switches/samples) and define `WAFFLE_FLAG_DEFAULT = True` in your `settings.py` if you want features to be implicitly active upon first access.
affects: All versions
gotchaIf you plan to use custom Flag, Switch, or Sample models, you must define the `WAFFLE_FLAG_MODEL`, `WAFFLE_SWITCH_MODEL`, or `WAFFLE_SAMPLE_MODEL` setting in `settings.py` from the very beginning of your project. Django's migration framework does not support changing swappable models after the initial migration, which can lead to complex migration issues later. Custom models must inherit from their respective `waffle.models.AbstractBase*` classes.
fix
Decide on custom models early in project development. If introducing later, be prepared for manual migration adjustments or database changes. Always ensure custom models inherit from `waffle.models.AbstractBaseFlag`, `AbstractBaseSwitch`, or `AbstractBaseSample`.
affects: All versions
gotchaWhen using `django-waffle`'s `waffle_status` JSON endpoint with Django Rest Framework (DRF), authentication might not be processed correctly by the Waffle middleware, leading to incorrect flag statuses being reported for authenticated users. This is because DRF's authentication typically runs at the start of the view, not in middleware.
fix
Instead of directly using `waffle.urls`, wrap `waffle.views.waffle_json` in a custom DRF view that handles authentication explicitly, or implement custom middleware that ensures `waffle.middleware.WaffleMiddleware` runs after DRF's authentication has processed the request.
affects: All versions (when used with DRF)
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'waffle'
The 'django-waffle' package has not been installed in your Python environment or is not accessible within your project's Python path.
fix
Install the package using pip: `pip install django-waffle`
django.core.exceptions.ImproperlyConfigured: 'waffle' must be in INSTALLED_APPS
The 'waffle' application is not listed in your Django project's `INSTALLED_APPS` setting, or `WaffleMiddleware` is used without 'waffle' being installed.
fix
Add `'waffle'` to your `INSTALLED_APPS` list in `settings.py` and ensure `WaffleMiddleware` is correctly placed in your `MIDDLEWARE` setting.
DatabaseError: no such table: waffle_flag
Django-waffle's database tables have not been created or the database migrations have not been applied after installation.
fix
Run Django migrations to create the necessary database tables: `python manage.py migrate`
AttributeError: 'WSGIRequest' object has no attribute 'waffle'
The `WaffleMiddleware` is not included or incorrectly positioned in your `MIDDLEWARE` setting, preventing the `request.waffle` object from being attached to the request.
fix
Add `'waffle.middleware.WaffleMiddleware'` to your `MIDDLEWARE` list in `settings.py`. It should typically be placed after Django's `AuthenticationMiddleware` if you rely on `request.user` for flag evaluation.
TemplateSyntaxError: 'waffle_tags' is not a registered tag library
The `waffle_tags` template library has not been loaded in your Django template, or the Django template engine context processor for requests is missing.
fix
Add `{% load waffle_tags %}` at the top of your Django template where you intend to use waffle's template tags. Ensure `django.template.context_processors.request` is in your `TEMPLATES` setting's `OPTIONS.context_processors` for flags to work correctly.
Upgrade
Version history
5.0.0latest on PyPI · released Jun 12, 2025
Audit
Dependencies
DjangorequiredCore framework dependency, as it's a Django app. Requires Django's auth system (user model, groups) and the request context processor for template usage.
Agent activity
7 hits · last 30 days
node
6
Resources
django-waffle — pip install django-waffle · libregistry