52👍
I’d go about it this way:
Have the secret key in a separate file “secret_key.py”. This file does not exist for a pristine installation. In your settings.py include something like:
try:
from .secret_key import SECRET_KEY
except ImportError:
SETTINGS_DIR = os.path.abspath(os.path.dirname(__file__))
generate_secret_key(os.path.join(SETTINGS_DIR, 'secret_key.py'))
from .secret_key import SECRET_KEY
The function generate_secret_key(filename)
that you will write generates a file called filename
(which, as we call it, will be secret_key.py
in the same dir as settings.py
) with the contents:
SECRET_KEY = '....random string....'
Where random string is the generated key based on a random number.
For key generation you can use Umang’s suggestion https://stackoverflow.com/a/16630719/166761.
119👍
To add to what Carles Barrobés said, you can generate a new key using the method that Django uses in startproject
:
from django.utils.crypto import get_random_string
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
get_random_string(50, chars)
For Django 1.10 and above, the above code snippet is nicely wrapped up in a function.
from django.core.management.utils import get_random_secret_key
get_random_secret_key()
- [Django]-How do I clone a Django model instance object and save it to the database?
- [Django]-What does error mean? : "Forbidden (Referer checking failed – no Referer.):"
- [Django]-How to change a django QueryDict to Python Dict?
39👍
Open a Django shell with python manage.py shell
and do the following to create a secure random secret key in Django 2.1:
>>> from django.core.management.utils import get_random_secret_key
>>> get_random_secret_key()
'[GENERATED KEY]'
>>>
Note: The >>>
represents the shell prompt, and should not be typed.
Edit: Some answers here suggest automatically generating a file with a secret key in it from within the Django settings file itself. This is unsuitable for a production environment for a couple reasons. First of all, future deployments to new machines will create mismatching keys. Secondly, you’ll need to take extra care to ensure there is no read access to that file from other programs or users. For these reasons it is generally advisable and common practice to store secrets on production machines as environment variables.
- [Django]-Create custom buttons in admin change_form in Django
- [Django]-Using Python's os.path, how do I go up one directory?
- [Django]-Is it secure to store passwords as environment variables (rather than as plain text) in config files?
5👍
Generally speaking, you can divide Django configuration into things that are app-specific and things that are server-specific. This falls into the latter category.
There are a number of ways you can tackle the problem of server-specific configuration, it is discussed more in this question.
For this particular instance, using the approach I outline in my answer to the other question, I’d put a placeholder in settings_local.py.sample
for distribution, and during installation, I’d copy that over to settings_local.py
and edit to suit.
- [Django]-Django: signal when user logs in?
- [Django]-Where are the Assertion Methods list from Django TestCase?
- [Django]-Django – Rotating File Handler stuck when file is equal to maxBytes
3👍
Carles Barrobés made an excellent answer but it is incomplete, here is my version for python 3 with the missing function to work.
from django.core.management.utils import get_random_secret_key
def generate_secret_key (filepath):
secret_file = open(filepath, "w")
secret = "SECRET_KEY= " + "\""+ get_random_secret_key() + "\"" + "\n"
secret_file.write(secret)
secret_file.close()
try:
from .secret_key import SECRET_KEY
except ModuleNotFoundError:
SETTINGS_DIR = os.path.abspath(os.path.dirname(__file__))
generate_secret_key(os.path.join(SETTINGS_DIR, 'secret_key.py'))
from .secret_key import SECRET_KEY
Take notice that I changed the ImportError
for ModuleNotFoundError
and creates the python file secret_key.py
to gather the SECRET_KEY like a variable instead to parse a txt file.
- [Django]-How to get an ImageField URL within a template?
- [Django]-Django request to find previous referrer
- [Django]-Programmatically saving image to Django ImageField
2👍
I would solve the problem like this:
- Provide a dummy secret key like:
I_AM_A_DUMMY_KEY_CHANGE_ME
- Create a manage command to generate a new one:
./manage.py gen_secret_key
- In the documentation, STRONGLY advise users to run the command as soon as possible
- [Django]-Django model "doesn't declare an explicit app_label"
- [Django]-How to pass information using an HTTP redirect (in Django)
- [Django]-List_display – boolean icons for methods
1👍
In my code I have three levels of settings file inspired by Two Scoops of Django, so a middle one goes like this where BASE_PRIVATE_DIR is set up in the base template. In my case this is from the django directory ../../mysite_private but somewhere ouside the normal files under the application git.:
from .base import *
ALLOWED_HOSTS = ['staging.django.site']
#Allow local override which is per deployment instance. There should probably then be
# an instance git for version control of the production data
try:
import sys
private_path = BASE_PRIVATE_DIR.child('production')
sys.path.append(private_path)
from private_settings import *
except ImportError:
print(" No production overide private_settings.py found. This is probably an error = {}".format(private_path))
# If it doesnt' exist that is fine and just use system and environment defaults
- [Django]-Annotating a Sum results in None rather than zero
- [Django]-Using {% url ??? %} in django templates
- [Django]-How do I match the question mark character in a Django URL?
1👍
If you create a new project using template, like django-admin.py startproject --template=path_to_template project_name
just put {{ secret_key }}
into your project template settings file (e.g. settings.py) like SECRET_KEY = '{{ secret_key }}'
and Django will generate it for you.
- [Django]-Manager isn't accessible via model instances
- [Django]-What does on_delete do on Django models?
- [Django]-Different db for testing in Django?
1👍
In this solution I use django-dotenv, which is one of the dependencies of my project, as listed in requirements.txt
like django-dotenv==1.4.1
. The advantage of this approach is you have a different .env
file for each environment where the application is installed.
Create the file utils.py
in the same directory of settings.py
with the following content:
from django.utils.crypto import get_random_string
def generate_secret_key(env_file_name):
env_file = open(env_file_name, "w+")
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
generated_secret_key = get_random_string(50, chars)
env_file.write("SECRET_KEY = '{}'\n".format(generated_secret_key))
env_file.close()
Then modify the settings.py
file as follows:
import dotenv
from [project-folder-name] import utils
...
try:
SECRET_KEY = os.environ['SECRET_KEY']
except KeyError:
path_env = os.path.join(BASE_DIR, '.env')
utils.generate_secret_key(path_env)
dotenv.read_dotenv(path_env)
SECRET_KEY = os.environ['SECRET_KEY']
For those who don’t use django-dotenv
, all you have to do it to add it as a dependency and change the manage.py
to load it at startup:
import dotenv
if __name__ == "__main__":
dotenv.read_dotenv()
- [Django]-Django abstract models versus regular inheritance
- [Django]-Django multiprocessing and database connections
- [Django]-Unable to find a locale path to store translations for file __init__.py
1👍
I found this block of code on pypi.org which almost works like Umang’s answer.
Right in your project directory run
python manage.py generate_secret_key [--replace] [secretkey.txt]
This will generate a new file secretkey.txt
containing a random Django secret key. In your production settings file go and replace the secret key with the generated key.
Or in order to avoid hard coding the secret key. Add the following code snippet so that when you always run the program a new secret key will generate an updated key for you.
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# Use a separate file for the secret key
with open(os.path.join(BASE_DIR, 'secretkey.txt')) as f:
SECRET_KEY = f.read().strip()
OR
# Use a separate file for the secret key
with open('/path/to/the/secretkey.txt') as f:
SECRET_KEY = f.read().strip()
- [Django]-How to obtain a QuerySet of all rows, with specific fields for each one of them?
- [Django]-Django's self.client.login(…) does not work in unit tests
- [Django]-How can I call a custom Django manage.py command directly from a test driver?