Setting Environment Variables Locally for Django Development

While reading the book “Two Scoops of Django“, I learned many useful things about Django. One of the really useful tips in chapter 5 of the book is the isolation of secrets (e.g. API keys and database passwords) from the source code repository, through the use of environment variables. The concept is great, but I think there is a better way for setting the environment variables on your local development machine.

The book says to put the environment variables in .bashrc, .profile, or .bash_profile, or to put them in the bin/activate script of the virtualenv. This approach is not ideal, for the following reasons:

  1. Using .bashrc and friends means that your API keys and database passwords are always loaded whenever you use the shell, even when you don’t mean to work on your Django project;
  2. In the long run, it contaminates your shell environment with useless environment variables as you work on more and more projects;
  3. At the same time, you will likely be forced to prefix the environment variable names with your project names, to prevent conflicts, making the names longer than necessary;
  4. You have to manually clean up your .bashrc (or its equivalent) after your project’s end-of-life.
  5. You have to use different syntaxes as you migrate between Linux/Unix/Mac and Windows

Even if you go with bin/activate, you are still exposing your API keys and database passwords to the shell, and you have to clean them up in the deactivate function. It’s troublesome and mistake-prone. This is actually a consequence of how virtualenv is doing it wrong.

So here is my approach, which I believe is an improvement:

  1. In the site-packages directory of your virtualenv (something like “lib/python2.7/site-packages/”), define a new mysecrets.py module. The content of this module is like this:
    # `secrets` **must** be a simple dictionary.
    # i.e. no logic to programmatically generate keys or
    # values.
    secrets = {
        'postgresql_username': 'bob',
        'postgresql_password': '132!^a8!#)',
        # etc
    }
  2. Then, in the settings/local.py module of your Django project, import this mysecrets.py module and use the secrets function:
    from .base import *
    import mysecrets
    
    SECRETS = mysecrets.secrets
    
    # The rest of the usual content in local.py…

Now the SECRETS dictionary is even accessible through the django.conf.settings object.

This approach deals with the problems above while still achieving the effect of isolating secrets from the source code repository:

  • It is shell-agnostic because you are using Python to declare environment variables, and you certainly already know Python since you are working on a Django project;
  • You don’t leak your secrets through your shell;
  • You don’t contaminate your shell environment with useless variables;
  • You don’t have to prepend your variable names with your project name;
  • You don’t have to manually edit .bashrc (or its equivalent) in order to clean up, after your project’s end-of-life. You would probably delete your project’s virtualenv anyway.
  • You don’t have to edit the deactivate function in bin/activate to clean up the environment.

Update

@pydanny is concerned that this approach may degenerate into the local_settings.py anti-pattern. While his concern is understandable, I perceive it as a matter of good sense and self-discipline. Like I said in this thread in the Hong Kong Python User Group, anybody who has read @pydanny and @pyaudrey‘s Two Scoops of Django should understand the intention of isolating secrets while keeping all the real logic under version control. The module is purposely named mysecrets.py; anybody who adds anything other than secrets (e.g. API keys and database passwords) into this module simply fails English and should not be programming in any programming language at all. Like the old saying goes: we are all consenting adults.

An even safer approach would involve writing Windows INI-style config files and using Python’s ConfigParser to parse them, as suggested by Jimmy Wong. While this avoids the degeneration into the local_settings.py anti-pattern, it also entails knowing and using an extra syntax (INI-style config file syntax), however trivial it is. It’s a trade-off that I am hesitant to take. I’m lazy this way.

Comments are most welcome.

Update 2

I don’t remember why I originally wrote `secrets` as a function. In retrospec, it should be just a dictionary. It would look more declarative and be less prone to degenerate into the local_settings.py anti-pattern. I’ve updated the code snippets above.

1 thought on “Setting Environment Variables Locally for Django Development”

  1. Interesting idea, but it has the same problem as the local_settings.py anti-pattern: You have executable code outside of version control.

    I suggest instead perhaps an implementation of get_env_variables that accesses a “secrets.cfg” file.

  2. I do accept as true with all the ideas you’ve presented to
    your post. They’re very convincing and will definitely work.
    Nonetheless, the posts are very short for beginners.
    May you please lengthen them a bit from subsequent time?

    Thanks for the post.

  3. Thanks , I’ve recently been looking for information about this subject for ages and yours is the best I have found
    out so far. However, what concerning the bottom line?
    Are you sure about the supply?

  4. When I initially commented I appear to have clicked on the -Notify me when new comments are added- checkbox and now every time a
    comment is added I recieve four emails with the same comment.
    Perhaps there is a way you are able to remove me from that service?

    Thanks!

  5. I am curious to find out what blog platform you happen to be working with?
    I’m having some small security issues with my latest site
    and I would like to find something more risk-free. Do you have any recommendations?

  6. great issues altogether, you just received a new reader. What may you recommend in regards
    to your put up that you just made some days ago?

    Any certain?

  7. I have been exploring for a bit for any high quality articles or weblog posts
    on this kind of space . Exploring in Yahoo I finally stumbled
    upon this web site. Reading this info So i’m satisfied to exhibit that I’ve an incredibly excellent uncanny feeling
    I came upon exactly what I needed. I most indubitably will make certain to do not forget
    this web site and provides it a look on a relentless basis.

  8. Hi there! This post couldn’t be written any better! Reading through this article reminds me of
    my previous roommate! He continually kept preaching about this.
    I’ll forward this post to him. Pretty sure he’ll have a
    good read. Thanks for sharing!

  9. Reading your website gave me a lot of interesting info , it deserves to go viral,
    you need some initial traffic only. How to get initial traffic???
    Search for: masitsu’s effective method

  10. Là encore, mieux vaudra avoir taffé ses personnages dans l’antichambre du solo pour éviter de se faire ruiner illico lors
    des combats face à l’IA ou les équipes d’autres joueurs.

  11. His claim said a thing, yet his actions revealed a much different person than who he dreamed up.– In order to achieve right fat balance, most of the fat supply should come from sources like olive, peanuts, canola, fish, nuts, sun-flower, etc.”My shoulder’s fine, but my swing is long. Kids may also buy bowling balls that are designed specifically for them.Here are the factors to consider when choosing a bowling alley:1.OUCH! And, Ouch! (Yes, I’ll do anything for a good lesson for my fellow law of attraction friends – that would be you!)What I realized was that this little experiment of mine was a lot like many of our everyday creations.com —-Free to reprint with the author’s name and link.2.Bowling TowelsTowels are important and used to wipe the oil residue from the balls. Neal ElAttrache and to return to the team’s spring training facility in Arizona later Monday afternoon.
    Wholesale Jerseys China

  12. I see your page needs some fresh articles. Writing manually is time consuming, but there is tool for this task.

    Just search for: Digitalpoilo’s tools

  13. Whats up are using WordPress ffor your blog platform? I’m new to the blog world but
    I’m trying to get started and set up my own. Do you
    need any coding expertise to make your own blog? Any help would bee greatly appreciated!

  14. Appreciating the dedication you put into your
    blog and in depth information you provide. It’s awesome to come across a
    blog every once in a while that isn’t the same out of
    date rehashed information. Wonderful read! I’ve saved your site and I’m including your RSS
    feeds to my Google account.

  15. Amazing blog! Is your theme custom made or did you download it from somewhere?

    A theme like yours by incorporating simple tweeks would actually make my blog jump out.

    Please inform me that you got your theme. Thanks

  16. I’m gone to say to my little brother, that he should also pay a quick visit this
    website on regular basis to take updated from hottest news.

  17. hello!,I enjoy your writing very a great deal! percentage we maintain contact extra about your
    article on AOL? I require an expert about this house to eliminate my
    problem. Maybe that may be you! Looking forward to look you.

  18. I do trust all the ideas you’ve presented on your post.

    They are very convincing and will certainly work.
    Still, the posts are too short for beginners.
    May just you please lengthen them a little from subsequent time?
    Thank you for the post.

Leave a Reply

Your email address will not be published. Required fields are marked *