Django/Heroku Settings injection? - django

I want to be able to change my DATABASES['default'] setting to change automatically when I deploy to heroku. Is there some way to do this?
This looks like what I want
https://devcenter.heroku.com/articles/django-injection, but it seems like it no longer works as of July 1, 2012.

Use dj_database_url, as described here. To wit:
$ pip install dj-database-url
and then in settings.py:
import dj_database_url
DATABASES['default'] = dj_database_url.config()
You can pass config a default argument if you don't want to set DATABASE_URL locally. More info is available here.

Related

Where do I set environment variables for 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

Heroku csv file not getting recognised in settings.py

i am trying to deploy my site using heroku. Being a starter just following the steps given on a website. In settings my csv and database default is not getting recognised.
ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv())
DATABASES = {
'default': dj_database_url.config(
default=config('DATABASE_URL')
)
}
This has nothing to do with Heroku; this wouldn't work locally either. The error message tells you all you need to know: you have not defined Csv. It's not clear what it is supposed to be, but you either need to import that function, or define it yourself.
Install python-decouple pip install python-decouple
ran into the same ordeal.

Getting error with postgis Geodjango on Heroku

Postgis extension is installed:
:DATABASE=> SELECT postgis_version();
postgis_version
2.2 USE_GEOS=1 USE_PROJ=1 USE_STATS=1
I have the following buildpacks:
https://github.com/cyberdelia/heroku-geo-buildpack.git
https://github.com/heroku/heroku-buildpack-python.git
When I run manage.py migrate I get:
AttributeError: 'DatabaseOperations' object has no attribute 'geo_db_type'
I am using the hobby deb postgres which now supports postgis
https://devcenter.heroku.com/changelog-items/792
Do I need to install a different build pack or add some additional configuration? Everything works locally using postgis.
I finally had some time to go back and look at this. It turns out the issue was Heroku was not importing my settings correctly. I was using cookiecutter-django settings scheme that imports common settings into production and for some reason Heroku was not working as expected.
My common settings contained:
DATABASES['default']['ATOMIC_REQUESTS'] = True
DATABASES['default']['ENGINE'] = "django.contrib.gis.db.backends.postgis"
And my production contained:
DATABASES['default'] = env.db("DATABASE_URL")
Heroku did not import those common settings. When I checked in the django shell in heroku the production settings had
'ENGINE': 'django.db.backends.postgresql_psycopg2', 'ATOMIC_REQUESTS': False
After adding DATABASES['default']['ENGINE'] = "django.contrib.gis.db.backends.postgis" to production settings everything is working.
Does anybody know what could be going wrong with importing settings correctly from common.py? It seems to import the rest of the settings correctly, just not the database ones.

Setting django and dj-database-url for local development

Here in comments to the answer, somebody asked this questions. But answer is still unclear for me .
I run my django site in Herouku and it requires dj-database-url module to work with Postgresql. How to run django with DATABASES = dj-database-url() in settings.py on my local computer? Changing code before pushing to Heroku is a pretty ugly way.
There are many ways to handle different production / development environments.
One is to have a local settings file that's imported at the bottom of your settings file that's not in version control, and thus not in heroku.
Another is any way to distinguish heroku environment from your local environment. An arbitrary environment variable, for example.
Another, is the default argument passed to dj_database_url which basically does this simple if statement for you.
import dj_database_url
DATABASES['default'] = dj_database_url.config(
default='sqlite:////path-to-my/database.sqlite')
Remember, this settings file is just python. You could have it use one database on Tuesday for example.. any if statement you can come up with will work.

Modifing settings in Django

I'm trying to get Django's manage.py to run with modified settings files.
I have three settings files
settings.py
preview.py
live.py
settings.py contains my base settings but on live & preview sites I point the ['DJANGO_SETTINGS_MODULE'] to live or preview which in turn load the base file and any settings specific to that environment.
This works fine, until I try to run migrations using manage.py
I updated the manage.py file to import settings.preview but now when I try to run syncdb or migrate I get this error:
django.core.exceptions.ImproperlyConfigured:
You haven't set the DATABASE_ENGINE
setting yet.
My settings file has this in it though:
DATABASE_ENGINE = 'mysql'
How can I get this to work?
Don't modify manage.py if you can help it. Instead pass it the --settings argument to choose an alternate settings module. Setting up a shell script or alias will make it easier to use this.