1

I am working on a project where we use feature toggles to hide features until they are ready to be released.

The pattern we have followed is to simply not route certain endpoints if the feature toggle is off. I.e in urls.py, we only include URLs in the urlconf if the toggle is on. But this means feature toggles only have an effect if the server is restarted. We'd like to be able to dynamically turn feature toggles on and off on a running server. It seems that the urlconf is only parsed at startup time so changes to it are not reflected without a reboot.

I've tried making a middleware to block certain URLs based on the value of a feature toggle and that works but doesn't play nicely with the Swagger docs, which I also would like to reflect the state of the feature toggles.

In general, it feels like I am fighting the system, which is usually a sign that I'm not approaching it from the right angle.

So, how do people advise me to implement dynamic feature toggles of behaviour in Django?

EDIT: I meant to say that I have looked at a few posts, such as this one: Django dynamic urlpatterns but there wasn't really any resolution.

Some even older posts talk about forcing a refresh of urlconf by reloading the module and I've tried that but, although I can see the code getting executed again, it doesn't seem to affect the URLs. It's like they are being cached but I can't find out any way to clear that cache (all posts on I've found on that subject are obsolete)

dh7892
  • 26
  • 3
  • You shouldn't have to restart the server to parse a new urls.py. It should be enough to restart Apache. – user984003 Apr 30 '20 at 12:00
  • 1
    For dynamic changes, I add variables to a database table. Maye you could do a query for each request and see which set of urls to use. Or add a db lookup in your middleware. – user984003 Apr 30 '20 at 12:03
  • I guess the point is to avoid restarting any service. When I said "restart the server" I meant the webserver process (e.g. apache, daphne or gunicorn or whatever) rather than restarting the whole machine. But I don't feel like this should be necessary. – dh7892 Apr 30 '20 at 12:33
  • On the issue of actually how to store the toggles, I've been using `Constance` To do this https://github.com/jazzband/django-constance This works very well. It's more about how I use the toggles to dynamically enable or disable URLs from the applicaiton – dh7892 Apr 30 '20 at 12:35

1 Answers1

0

Include all urls in urls.py. Then add the if-else redirect to the middleware.

It's not clear to me if there are many toggle/url options or just one, but it sounds like you already have a way to store and look up that info.

class BeforeViewMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):

        path = request.path

        # look up toggle option, urls in dynamic place. I use a DB table; you said in comments you use Constance 

        if <toggle is off and url is in toggle-on options only>: # depends on how you store this info
             return HttpResponseRedirect("<other url or some error page, whatever>")
user984003
  • 23,717
  • 51
  • 158
  • 250
  • Yes, this is exactly the sort thing I did with the middleware that I tried. But, as I mention in the question, this doesn't play nicely with Swagger so I think Swagger will still show the documentation for URLS that are toggled off. – dh7892 Apr 30 '20 at 16:08
  • I don't know Swagger so can't help you there. – user984003 Apr 30 '20 at 16:10