2017-05-01

Adding Feature Switches to your Django Project in 10 Minutes

The first time I heard about feature switches was at a Winnipeg Agile Group meeting a year or two ago.  They peaked my interest immediately and seemed like a must when trying to practice DevOps.

I wanted to try them out on my own, so I did some investigating.  I have a Django hobby project and figured it would be a perfect target for trying out feature switches.  I started by writing down some of the features I though would be useful:

  • Stored in a database
  • Support changes on-the-fly
  • Global enable/disable
  • Must support multiple conditions
    • client IP address
    • user
    • group
    • date/time
  • Use them in several scenarios:
    • code (models.py, views.py in Django)
    • templates (Django)
    • entire projects (urls.py in Django)
Since Django has a lot of open source projects, I decided to do a Google search to see what's available.  I found a comparison with a bunch of old projects (+1 years since updated) that I avoided because they're likely not being maintained anymore, and decided to try out gargoyle since it had most (if not all) of the features I thought would be useful.  The original project is deprecated, however Yplan forked it and is actively maintaining the project.  So I downloaded the latest release and manually added it to my project.  I followed their suggestion and also added nexus, then later found I needed to add the dependencies modeldict and jsonfield (link to the project that worked).

However, when I logged in using my admin user and tried to add my first feature switch in the nexus UI, I repeatedly got the error "Enter valid JSON".  I tried a couple of different syntaxes thinking maybe it's expecting quotes, or doesn't support certain characters.  No luck.

Then I found a compatibility post, and figured maybe my jsonfield project is incompatible.  So I searched for a different version.  Fortunately the next version I tried fixed the problem, and I was off to the races.  I had my first feature switch saved in the database.

Next up, add some code that uses it.  Based on the really good gargoyle documentation, I made a slight modification to one of my views and the corresponding template.  Loading the page I found my feature switch looked like it was working.  To verify I toggled the feature switch back and forth in the nexus UI and refreshed the page each time.

Done.  That was too easy.

Please contact me if you have any questions, or are interested in the post and what I do.  


Below are most of the technical details:

def index(request):
    if (gargoyle.is_active('feature_key', request)):
        switched_variable = 'enabled'
    else:
        switched_variable = 'disabled'
    return render(request, 'project/index.html', {'switched_variable': switched_variable })
  • template additions:
   {% load gargoyle_tags %}
    {% ifswitch feature_key %}
        <DIV>SWITCH: ENABLED</DIV>
    {% else %}
        <DIV>SWITCH: DISABLED</DIV>
    {% endifswitch %}
    <DIV>Switch:{{ switched_variable }}</DIV>