Django integration
This guide targets Django 4.2+ running on Python 3.11 or later. By the end your Django application will initialise the A vs B SDK once on startup, expose a per-request helper on every HttpRequest object via middleware, and cleanly shut down when the process exits.
Install
1pip install avsb-pythonObtain your SDK key
Open your A vs B project, go to Settings → Environments, and copy the Server SDK key for the target environment. Add it to your environment — never hardcode it in settings.py.
1AVSB_SDK_KEY=sdk_production_...Configure Django settings
Add the A vs B middleware to MIDDLEWARE and set your SDK key. The middleware must appear early enough that downstream middleware and views can access request.avsb.
1import os2
3MIDDLEWARE = [4 'django.middleware.security.SecurityMiddleware',5 'avsb.contrib.wsgi.AvsbMiddleware', # <-- add this6 'django.contrib.sessions.middleware.SessionMiddleware',7 # ... rest of your middleware8]9
10AVSB_SDK_KEY = os.environ['AVSB_SDK_KEY']Create an initialiser (AppConfig)
Initialise the SDK singleton once when Django starts using an AppConfig.ready() hook. This avoids re-connecting on every request and ensures the datafile is available before the first request is served.
1from django.apps import AppConfig2
3
4class MyAppConfig(AppConfig):5 default_auto_field = 'django.db.models.BigAutoField'6 name = 'myapp'7
8 def ready(self) -> None:9 from django.conf import settings10 from avsb import AvsbServer11
12 # Store on the config so other modules can import it13 self.__class__.avsb_server = AvsbServer(sdk_key=settings.AVSB_SDK_KEY)14 self.__class__.avsb_server.on_ready_sync() # blocks briefly on first booton_ready_sync() is a convenience wrapper for the synchronous Django context. If you run Django with an ASGI server (e.g. Daphne or Uvicorn) and want fully async startup, use await server.on_ready() inside an async ready() or an ASGI lifespan handler instead.Read a flag in a view
The middleware attaches a scoped helper to request.avsbusing the context it builds from the request (see the middleware's context_from option). The helper exposes typed flag methods.
1from django.http import JsonResponse2from django.views import View3
4
5class CheckoutView(View):6 def get(self, request):7 # request.avsb is pre-scoped to the current user context8 show_new = request.avsb.get_bool_flag('checkout-v2', False)9 theme = request.avsb.get_string_flag('ui-theme', 'default')10 return JsonResponse({'showNewCheckout': show_new, 'theme': theme})Configure context_from (optional)
By default the middleware builds an anonymous context. Pass a context_from callable in AVSB_MIDDLEWARE_OPTIONS to build a richer targeting context from the request.
1AVSB_MIDDLEWARE_OPTIONS = {2 'context_from': lambda request: {3 'kind': 'user',4 'key': str(request.user.id) if request.user.is_authenticated else 'anon',5 'plan': getattr(request.user, 'plan', 'free'),6 }7}Track an event
1request.avsb.track('purchase', value=149.99, properties={'currency': 'usd'})Identify a user
If the user logs in during the request lifecycle and you need to re-evaluate flags against the authenticated identity, build a new scoped client directly from the server singleton:
1from myapp.apps import MyAppConfig2
3server = MyAppConfig.avsb_server4scoped = server.for_user({'kind': 'user', 'key': str(user.id), 'plan': user.plan})5show_new = scoped.get_bool_flag('checkout-v2', False)Graceful shutdown
Register a Django AppConfig shutdown signal or a plain atexit hook to flush and close the SDK before the process exits:
1import atexit2
3class MyAppConfig(AppConfig):4 # ...5 def ready(self) -> None:6 # ... init as above ...7 atexit.register(self.__class__.avsb_server.close_sync)Testing
1import pytest2from avsb.test_utils import MockAvsbServer, TestData3
4@pytest.fixture5def mock_server():6 td = (7 TestData.flag('checkout-v2')8 .boolean_flag()9 .variation_for_user('u_1', True)10 .fallthrough_variation(False)11 )12 return MockAvsbServer(flags=[td.build()])13
14def test_returns_true_for_u1(mock_server):15 scoped = mock_server.for_user({'kind': 'user', 'key': 'u_1'})16 assert scoped.get_bool_flag('checkout-v2', False) is True17
18def test_returns_default_false(mock_server):19 scoped = mock_server.for_user({'kind': 'user', 'key': 'other'})20 assert scoped.get_bool_flag('checkout-v2', False) is FalseWhat's next
- FastAPI integration — async Python with ASGI middleware; Flask usage is covered in the same guide.
- Python SDK reference — full
AvsbServerandAsyncAvsbServerAPI. - Multi-context targeting — combine user and organisation attributes in one evaluation.