How do I use .env in Django? - django

My goal is to email using Python Django without having my email password being shown in the actual code. After some research, I guess I can store my password in an .env file and then access the password from the .env file. So, I currently have an .env file in my Django project with this line of code:
export EMAIL_HOST = 'smtp.gmail.com'
And in my settings.py, I have these:
import environ
env = environ.Env()
environ.Env.read_env()
EMAIL_HOST = os.environ.get('EMAIL_HOST')
print(EMAIL_HOST)
But the printed result is None. print(os.environ) spits out something though. How can I get my .env file to work?

Not only in Django, in general use the library python-dotenv.
from dotenv import load_dotenv
import os
load_dotenv()
EMAIL_HOST = os.getenv("EMAIL_HOST")

https://gist.github.com/josuedjh3/38c521c9091b5c268f2a4d5f3166c497
created a file utils.py in your project.
1: Create an .env file to save your environment variables.
file env.
DJANGO_SECRET_KEY=%jjnu7=54g6s%qjfnhbpw0zeoei=$!her*y(p%!&84rs$4l85io
DJANGO_DATABASE_HOST=database
DJANGO_DATABASE_NAME=master
DJANGO_DATABASE_USER=postgres
2: For security purposes, use permissions 600 sudo chmod 600 .env
3: you can now use the varibles settigns.py
from .utils import load_env
get_env = os.environ.get
BASE_DIR = Path(__file__).parent.parent.parent
load_env(BASE_DIR / "../.env") #here you indicate where your .env file is
SECRET_KEY = get_env("DJANGO_SECRET_KEY", "secret")
This way it can handle multiple environments production or stagins

You can do it by importing os and creating a .env file where you will specify all the database details for connection.
settings.py file:
import os
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ.get('DB_NAME'),
"USER": os.environ.get('DB_USER'),
"PASSWORD": os.environ.get('DB_USER_PASSWORD'),
"HOST": os.environ.get('DB_HOST'),
"PORT": os.environ.get('DB_PORT'),
}
}
.env file:
export DB_NAME = dbname
export DB_USER = root
export DB_USER_PASSWORD = root
export DB_HOST = localhost
export DB_DB_PORT = 5432
This example is for PostgreSQL but other DB setup will be exact similar but engine name will need to be changed.

Related

Where to verify the settings during startup

After settings.py executes, I need to check to make sure all the settings were found from the .env variables, and error out if they are not. Where's the appropriate place to put that logic? Right in settings.py? manage.py?
`i would advice you django-environ, check documentation at https://django-environ.readthedocs.io/en/latest/
once put in via pip install django-environ, create .env go into the foundation of your project:
in /.env
After that inside settings.py, you can use your predefined environment variables like:`
import os
# django-environ
# https://django-environ.readthedocs.io/en/latest/
import environ
from django.utils.translation import ugettext_lazy as _
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Load and read .env file
# OS environment variables take precedence over variables from .env
env = environ.Env()
env.read_env(os.path.join(BASE_DIR, '.env'))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env.bool('DEBUG', False)```

Even though django-environ is set up correctly, why does Django give the error The SECRET_KEY setting must not be empty?

The open source project I'm developing uses Docker to use multiple env files, but I need to run the project without Docker.
Although I set django-environ correctly, I get the error "The SECRET_KEY setting must not be empty"
Does anyone have a solution?
I also added this part of the code to the settings
import environ
env = environ.Env(
# set casting, default value
DEBUG=(bool, False)
)
# Take environment variables from .env file
environ.Env.read_env(os.path.join(BASE_DIR, '../docker/dev/docker.env'))
But still it gives the following error
raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")
django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.
django-environ is a good choice for this purpose and you choose a good way to make your variables environment variables.
I think your settings.py module should be like the below code snippet:
import environ
import os
env = environ.Env(
# set casting, default value
DEBUG=(bool, False)
)
# Set the project base directory
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Take environment variables from .env file
environ.Env.read_env(os.path.join(BASE_DIR, '.env'))
# False if not in os.environ because of casting above
DEBUG = env('DEBUG')
# Raises Django's ImproperlyConfigured
# exception if SECRET_KEY not in os.environ
SECRET_KEY = env('SECRET_KEY')
# Parse database connection url strings
# like psql://user:pass#127.0.0.1:8458/db
DATABASES = {
# read os.environ['DATABASE_URL'] and raises
# ImproperlyConfigured exception if not found
#
# The db() method is an alias for db_url().
'default': env.db(),
# read os.environ['SQLITE_URL']
'extra': env.db_url(
'SQLITE_URL',
default='sqlite:////tmp/my-tmp-sqlite.db'
)
}
CACHES = {
# Read os.environ['CACHE_URL'] and raises
# ImproperlyConfigured exception if not found.
#
# The cache() method is an alias for cache_url().
'default': env.cache(),
# read os.environ['REDIS_URL']
'redis': env.cache_url('REDIS_URL')
}
The error you've gotten is about missing SECRET_KEY in your .env file so your .env file for above settings should have below variables:
DEBUG=False
SECRET_KEY=your-secret-key
DATABASE_URL=psql://user:un-githubbedpassword#127.0.0.1:8458/database
SQLITE_URL=sqlite:///my-local-sqlite.db
CACHE_URL=memcache://127.0.0.1:11211,127.0.0.1:11212,127.0.0.1:11213
REDIS_URL=rediscache://127.0.0.1:6379/1?client_class=django_redis.client.DefaultClient&password=ungithubbed-secret

config.py did not send back DATABASE_URL

my config.py:
"""Flask config."""
import os
from dotenv import dotenv_values
basedir = os.path.abspath(os.path.dirname(__file__))
configuration = dotenv_values(".env")
class Config(object):
DEBUG = False
TESTING = False
CSRF_ENABLED = True
SECRET_KEY = os.environ.get('SECRET_KEY')
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
class ProductionConfig(Config):
DEBUG = False
I'm trying to connect to DB with another py file:
import psycopg2
import xlrd
from config import Config
POSTGRES = Config.SQLALCHEMY_DATABASE_URI
connection = psycopg2.connect(POSTGRES)
cursor = connection.cursor()
But POSTRES is None
my .env file is in same directory like this:
FLASK_APP=wsgi.py
FLASK_ENV=development
SECRET_KEY=randomstringofcharacters
DATABASE_URL='postgresql://xxx:xxxxx#127.0.0.1:5432/xxxxx'
All my files are in same directory.
dotenv_values() doesn't side-effect the local environment. You need load_dotenv(), which does.
See https://pypi.org/project/python-dotenv/#load-configuration-without-altering-the-environment

Can't connect .env file of smtp details to django

settings.py
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = os.environ.get('EMAIL_HOST')
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
.env
export EMAIL_HOST_PASSWORD=<>
export EMAIL_HOST_USER = <>
export EMAIL_HOST=<>
3.Termial
(Carealenv) E:\atom data\mywebsite>source .env
'source' is not recognized as an internal or external command,
operable program or batch file.
I am having error of SMTPserverdisconnected .. please run connect first
I want to connect my .env file to django so that SMTPServer get connected and i can send verfication email to users. It will be great help.. Thank you
Further to ruddra's answer, you can alternatively use python-dotenv.
pip install python-dotenv
then in your settings.py
# settings.py
from dotenv import load_dotenv
load_dotenv()
Then you can use the getenv or as you have in your example environ.get function from the built-in os module to grab env variables and provide defaults if they do not exist.
from os import getenv
EMAIL_HOST = getenv('EMAIL_HOST', 'localhost')
Where localhost is whatever you wish to set as default.
You can't use source in Windows machine as described in the Stackoverflow answer.
If you want to use .env file, consider using libraries like django-environ which will read the file directly, no need to load it from ENVIRONMENT Variables.
Sample usage in settings.py:
import environ
env = environ.Env(
# set casting, default value
DEBUG=(bool, False)
)
# reading .env file
environ.Env.read_env()
# False if not in os.environ
EMAIL_HOST = env('EMAIL_HOST')
Another alternative solution is to use Docker with docker-compose, where you can load the environment variables from file.

Heroku Database Settings Injection - How do I setup my dev django database?

I'm trying to get my local dev django app to work after following these instructions on adding env database settings.
https://devcenter.heroku.com/articles/django-injection
I followed the instructions but get the following error when my app tries to access the local database
Request Method: GET
Request URL: http://localhost:8000
Django Version: 1.4
Exception Type: ImproperlyConfigured
Exception Value:
You need to specify NAME in your Django settings file.
My database settings originally,
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'db', # Or path to database file if using sqlite3.
'USER': 'foo', # Not used with sqlite3.
'PASSWORD': 'bar', # Not used with sqlite3.
'HOST': 'localhost',
'PORT': '5432',
}
}
the heroku article says to add the following to the settings file
import dj_database_url
DATABASES = {'default': dj_database_url.config(default='postgres://localhost')}
how do I get dj_database_url.config to use my my dev settings when the DATABASE_URL is not available in dev?
You can just add your dev settings to the default values like this...
import dj_database_url
DATABASES = {'default': dj_database_url.config(default='postgres://foo:bar#localhost:5432/db')}
Use this in your settings.py:
DATABASES = {'default': dj_database_url.config(default=os.environ['DATABASE_URL'])}
and in your .env file have this:
DATABASE_URL=postgres://localhost/yourdbname
when you launch with "foreman start" it will look at the .env file and create all those environment variables, just like running on Heroku itself. Type "heroku config" to confirm that you have a DATABASE_URL set, which you should if you added the postgres database addon.
Just set an environment variable on your operating system and check weither or not it's set. For instance, with a UNIX system:
# In ~/.bash_profile
export LOCAL_DEV=true
# In settings.py
import dj_database_url
DATABASES = {'default': dj_database_url.config(default='postgres://localhost')}
if bool(os.environ.get('LOCAL_DEV', False)):
# Override DATABASES['default'] with your local database configuration
Also, if you need to set an environment variable on your heroku space:
heroku config:add MY_VAR='my_value'
I just tried this and here is my code:
import dj_database_url
local_db = 'postgres://django_login:123456#localhost/django_db'
DATABASES = {'default': dj_database_url.config(default=local_db)}
My database name is "django_db", user name is "django_login", password is "123456".
My code can run both in local machine and heroku.
import dj_database_url
DATABASES = {'default':
dj_database_url.config(default='postgres://yourusername:yourpassword#yourhosturl:5432/yourdbname')}
** Replace bold string with your database settings
if you are using local database then replace yourhosturl by localhost