Where do I set environment variables for Django? - django

everyone!
Django 1.11 + PostgreSQL 9.6 + Gunicorn + Ubuntu 16.04 in AWS
I want to set environment variables for sensitive info.(django secret key, DB password...)
I studied many articles about setting ways.
But when I tried os.environ['env_name'],
.bashrc: Not working
.bash_profile: Not working
.profile: Not working
/etc/environment: Not working
Gunicorn script file.(systemd): I set them in gunicorn systemd script. It work very well.
But because I want to use the environment variables in other program too, I set them among 1~5 configurations. I don't understand why 1~5 configurations didn't work. Is there scope or priority of setting environment variables?
EDIT:
I use Ubuntu 16.04 server. I can't restart terminal session.
I tried 'source .bashrc' and logout/login. But It didn't work.
Of cource, 'echo $some_env_var' is working, I say, django can't read.

.bashrc will work for local development but not for a production environment. I just spent quite a bit of time looking for the answer to this and here's what worked for me:
1) Create a file somewhere on your server titled settings.ini. I did this in /etc/project/settings.ini
2) Add your config data to that file using the following format where the key could be an environmental variable and the value is a string. Note that you don't need to surround the value in quotes.
[section]
secret_key_a=somestringa
secret_key_b=somestringb
3) Access these variables using python's configparser library. The code below could be in your django project's settings file.
from configparser import RawConfigParser
config = RawConfigParser()
config.read('/etc/project/settings.ini')
DJANGO_SECRET = config.get('section', 'secret_key_a')
Source: https://code.djangoproject.com/wiki/SplitSettings (ini-style section)

The simplest solution is as already mentioned using os.environ.get and then set your server environment variables in some way (config stores, bash files, etc.)
Another slightly more sophisticated way is to use python-decouple and .env files. Here's a quick how-to:
1) Install python-decouple (preferably in a venv if not using Docker):
pip install python-decouple
2) Create a .env file in the root of your Django-project, add a key like;
SECRET_KEY=SomeSecretKeyHere
3) In your settings.py, or any other file where you want to use the configuration values:
from decouple import config
...
SECRET_KEY = config('SECRET_KEY')
4) As you probably don't want these secrets to end up in your version control system, add the file to your .gitignore. To make it easier to setup a new project, you could have a .env_default checked into the VCS containing default/dummy-values that's not used in production.

create a file called .bashrc in your server
export('the_name_in_bashrc', some_value)
then in the settings.py
import os
some_variable = os.environ.get('the_name_in_bashrc')

If you're using a virtual ENV you can add the environment variables to that specific environment. You can use export KEY=VALUE in your terminal but that will not persist. If you would like your values to persist you can edit the file:
sudo nano your_environment/bin/activate
Then at the bottom add the values you want e.g.:
export MY_KEY="12345"
And save. Remember to restart your ENV for changes to take effect.

pip install python-dotenv
Go To settings.py
import os
from dotenv import load_dotenv
load_dotenv('.env')
SECRET_KEY = os.getenv('SECRET_KEY')
Go To .env file
SECRET_KEY = your_secret_key

Related

Flask environment variables being ignored (FLASK_ENV and FLASK_APP) WINDOWS 10

After setting the environment variables FLASK_ENV and FLASK_APP running flask run will give me this error:
The snippet shows the command promt.
It says that environment is production and that I didn't provide the FLASK_APP environment variable, even though I typed them in. Did I miss something or can someone explain why this error occurs?
i suggest you this good read https://www.twilio.com/blog/how-run-flask-application on how to run Flask Application (there are 2 approaches)
i also recommend you reading this topic https://flask.palletsprojects.com/en/1.1.x/cli/?highlight=flaskenv#environment-variables-from-dotenv
the better approach is to create .flaskenv file in the root of your project where you set your environment variables like so :
in /.flaskenv file
FLASK_APP=myflaskproject:create_app()
FLASK_ENV=development
FLASK_DEBUG=0
# FLASK_RUN_EXTRA_FILES=
# FLASK_RUN_HOST=
# FLASK_RUN_PORT=8080
# FLASK_RUN_CERT=
# FLASK_RUN_KEY=
in FLASK_APP you call your app but usually it's recommended to use "Application Factory" pattern, see https://flask.palletsprojects.com/en/1.1.x/patterns/appfactories/
then
(.venv) flask run
don't forget to install python-dotenv
At least on Linux you cannot have spaces around the equal sign. Maybe on Windows this is the same.
In the official Flask documentation you can read:
set FLASK_APP=hello
https://flask.palletsprojects.com/en/1.1.x/cli/
set flask<space>=<space>src/app.py
As you can see you are NOT setting flask but flask<space>. Flask may accept that path but it is an illegal windows path.

Python Django set DJANGO_SETTINGS_MODULE when migrating source code

Task: Set up a new running environment by being provided python/Django source code and some additional details.
Problem: Cannot get Django-admin to validate due to missing/incorrect settings configuration
"django.core.exceptions.ImproperlyConfigured Requested setting USE_I18N, but settings are not configured. ..... "
You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings
Env Details: Ubuntu OS, Python 2.7, Django 1.7, PostgreSQL (also Supervisor + gunicorn) Running a venv located **/home/dave/python-env/vas/**bin/activate
Python sys.path
/usr/lib/python2.7/* (multiple defined)
/home/dave/python-env/vas/python2.7/site-packages
So tried several methods (including #export DJANGO_SETTINGS_MODULE=project-name.settings....) with little success.
How can one set the DJANGO_SETTINGS_MODULE variable?
os.environ.setdefault() is set in wsgi (I know this is the next step)
BUT this value is also set in /manage.py ...?
os.environ.setdefault("DJANGO_SETTINGS_MODULE", project_name.settings)
The directory /var/www/app/ (where the python source code is located) has several files, one of them is the project_name where the settings.py sits....
I am new to python/django...
Trying to get django-admin.py validate to validate.
Update: Running #python manage.py runserver runs OK. #python manage.py validate|check returns "System check identified no issues (0 silenced)
Running #django-admin.py check returns the error in question. "You must either define DJANGO_SETTINGS_MODULE ...."
UPDATE 2: Solution
Turns out you don't need django-admin.py as suggested by (Alasdair) and you can use manage.py.
Details - If the 'manage.py check' function returns no issues and #pip install -r requirements.txt completes within your virtual environment THEN one can run #manage.py createsuperuser
I was able to use #manage.py runserver after creating a super user, and using this new user (as the database tables were empty for security reasons) I was able to log into 127.0.0.1:8000/admin. From there the models/tables were visible and using the admin functions I could create a new user + group to access the original system that was being migrated as an admin user.
Also not that a database was required (running postgres) with db/username/pass as per settings files and a git repository (at least empty initialised) for raven...
hope this helps someone coming into python.

How to avoid putting environment variables into multiple places with Django, nginx and uWSGI?

I am trying to configure nginx+uWSGI to serve my Django application.
When I put environment variables into myapp_uwsgi.ini:
uid = username
gid = username
env = DJANGO_SITE_KEY="..."
it works as expected.
However, my app has some management commands which should also have access to the environment variables I have defined.
If I put the environment variables to /home/username/.bashrc:
export DJANGO_SITE_KEY="..."
uWSGI does not load them.
I have tried to put the environment variables into a separate file:
#!/bin/sh
export DJANGO_SITE_KEY="..."
and then call it from both .bashrc:
. /home/username/environment
and myapp_uwsgi.ini:
exec-pre-app = . /home/username/environment
In uWSGI logs I see this line:
running ". /home/username/environment" (pre app)...
But my Django app is unable to access the environment variables with os.environ.
I have also tried putting the export commands to the preactivate hook of virtualenvwrapper and use the virtualenv = setting of uWSGI, but it does not work too (I assume the hooks are only executed when using virtualenvwrapper commands like workon.
Here is the answer from uWSGI developers:
just place each of them (one per line) in a text file in the form
VAR=VALUE
then in uWSGI config
[uwsgi]
for-readline = yourfile
env = %(_)
endfor =
This also works with yml config files:
for-readline: filename
env: %(_)
endfor:
I use django-dotenv. Put your env vars in a file like .env inside your project, and then load it in manage.py and wsgi.py. No other config required. uwsgi and manage.py commands will work as expected, and all your env vars are stored in just one file.
Another approach is using configuration management systems such as Salt or Ansible.
With them one can create Jinja templates for both uWSGI and Django with {{ variables }} defined in one place.

My Django secret key is in an environment variable but I can't do syncdb

I'm setting up a Django project with different files for local and production settings. I can confirm that my Django secret key is successfully in an environment variable in virtualenv and when I do runserver I get no error. However when I try manage.py syncdb I get
django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
I don't understand why I can successfully browse to the site after runserver but I can't sync the database. When I run env I can see that the secret key is there and in my base settings file (imported into local settings) I am doing this:
SECRET_KEY = os.environ.get('MY_SECRET_KEY')
Any help debugging this would be greatly appreciated.
Euan
I'm not sure why the runserver command is working while syncdb isn't, but you can sort it out by adding a environment variable for DJANGO_SETTINGS_MODULE in the same way you did for the SECRET_KEY. The only difference is that you don't need to reference DJANGO_SETTINGS_MODULE within the django code anywhere. I'm running my own setup in exactly that way and the only problem I run into is forgetting to change the settings module when I switch between projects :-)
EDIT: I didn't realise that you were adding --settings=myapp.settings.local to runserver as well as syncdb. The reason you need to do this is that you are using settings on a different path from the default so python can't find them. Also, although you set the DJANGO_SETTINGS_MODULE in the wsgi file, this is only fired when the site is accessed via your webserver. When running a manage command the wsgi file is ignored (AFAIK) so adding DJANGO_SETTINGS_MODULE to your environment variables in the same way as SECRET_KEY makes your settings file available to the manage command.
Hope that helps
Somewhat similar situation here, using virtualenv running an outer script which involves django models.
To make this work please make sure:
Your sys.path list has a path to your virtualenv site-packages. For me it's: sys.path.append('/home/user/.virtualenvs/Project/local/lib/python2.7/site-packages')
Your django settings variable is added to os.environ. Eg: os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Project.settings")

deploying django site (wsgi)

Trying to use 2 different settings file for production and dev.
I set DJANGO_SETTINGS_MODULE='mysite.settings_production'
Works perfectly when running server with runserver
When I run it with apache though, apache doesn't seem to use the setting in the ~/.bash_profile and instead use os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") in the wsgi.py file
I guess it's maybe because apache is running on different user , not mine..
ok.. so it seems it's running as www-data on my ec2 ubuntu.
So I have to create the /home/www-data/.bash_profile and set the env variable?
It seems like so much hassle to use a different settings file.
Is there an obviously easier way to do this?
(I don't want to change the wsgi.py file, because it's source controlled)
Using bash_profile is completely the wrong way to do this.
The correct way is to use the wsgi.py file. However, since you don't want to do this (although I don't understand what it being version-controlled has to do with anything) then you can set environment variables directly in your Apache configuration using SetEnv:
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
Well, it's really wrong way. Common method to have separate settings for different environment is to store environment-dependent in local_settings.py (or whatever you name it) and imprort from settings.py
from local_settings.py import *
don't put local_settings.py under project repository as you will override it with each commit. If you want to keep a sample of local settings, put into a separate file, e.g. local_settings.py.example
You can import local settings at the beginning of settings.py (so settings.py settings would override local settings), or at the end, or have two local settings files for both cases.