Toggle Django Views with Cookies

Published June 19, 2018 by wamberg

What are we trying to do

Let's toggle the code we deliver to the user. We'll change the delivery path based on a cookie. Our fork in the path will come at the view level. We mean "view" in Django's Model-Template-View sense of the word. The cookie we're using for this tutorial could be set through code (like in our previous tutorial). But there are more simple ways to set cookies. The most simple may be to open a browser console and type:

document.cookie="features.new-home-page=true"

In our example we'll toggle the home page. Users coming to our site receive the current home page by default. If the user has the feature flag cookie set then they will receive the new home page.

Specify a feature

First, let's review the code that makes checking for a feature flag cookie easy:

# flags/views.py

from django.views.generic import TemplateView
from django.views.generic.base import View

FEATURES = {"new-home-page": False}


class FeatureFlagException(Exception):
    pass


class FeatureFlags:
    """ Cookie-based feature flag toggler """

    def __init__(self, request):
        self.request = request

    def is_active(self, name):
        if name not in FEATURES:
            raise FeatureFlagException(f"'{name}' is not a valid feature flag")

        cookie_name = f"features.{name}"
        cookie_flag = self.request.COOKIES.get(cookie_name)
        if cookie_flag is not None:
            return cookie_flag == "true"

        default_flag = FEATURES[name]
        return default_flag

If the global variable, FEATURES, looks familiar, it should! We introduced this dictionary of <flag name>:<default state> items in a previous post: Setting Cookies for Feature Flags in Django. class FeatureFlags is initialized with a Django request instance. Then you can check a particular feature flag at any point in your code. We'll show what it looks like to toggle the home page view.

Switch the view

Next we can use class FeatureFlags from above to toggle between two views: the current home page and a new home page:

# flags/views.py (continued)
class HomePageView(TemplateView):
    """ This is the view for our current home page. """
    template_name = "home.html"


class NewHomePageView(TemplateView):
    """ This is the view for our new, experimental home page. """
    template_name = "new-home.html"


class HomePageSwitchView(View):
    """
    This is the view that controls our delivery path
    and toggles between the current and new home pages.
    """
    def get(self, *args, **kwargs):
        request = self.request
        feature_flags = FeatureFlags(request)

        view_cls = HomePageView
        if feature_flags.is_active("new-home-page"):
            view_cls = NewHomePageView

        return view_cls.as_view(request, *args, **kwargs)

The keystone of the switch is feature_flags.is_active("new-home-page"). Here we final see our cookie-based feature toggler in action. The utility it provides is simple. Given a request and a feature name it returns True or False if the feature should activate. The feature_flags.is_active method checks cookies in this case. If a cookie is set with a name we're expecting then the feature is available to the user.

Use the following URL code to make the switcher view accessible:

# flags/urls.py
from django.urls import path

from .views import HomePageSwitchView

path("/", HomePageSwitchView.as_view())

Experiment! 👩‍🔬

You can imagine using a SwitchView-like class for any new view code you want to experiment with. For this example switching the entire home page at once is a big change. We recommend making changes as small as possible. If there were some way to code, deploy, and measure changes on the home page at a component level, do that first! Sometimes there aren't smaller components though. Sometimes the view is the component. Other times business needs dictate a large, sweeping change. In these cases switching at the view is necessary. Hopefully this tutorial makes those cases easier and less error-prone.

Twitter avatar
Contact me on Twitter!
@AccelDelivery
Want to share a link about software delivery?
Have feedback on what you read?
I'd love to hear from you.