54👍
Indeed, you can use the same function that generates a new key when you call startproject
, which is django.core.management.utils.get_random_secret_key()
.
Note however it’s not very different from your version.
107👍
Note that this may not be safe to use for production, as S Ghosh
is pointing out in a post below. But copy and paste this after running django-admin shell
for example to quickly get a key.
from django.core.management.utils import get_random_secret_key
get_random_secret_key()
- [Django]-Django contrib admin default admin and password
- [Django]-How to expire Django session in 5minutes?
- [Django]-Django Multiple Authentication Backend for one project
44👍
Run this command below on the Terminal.
$ python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
output:
2x$e%!k_u_0*gq0s4!_u(2(^lpy&gir0hg)q&5nurj0-sseuav
- [Django]-Django storages: Import Error – no module named storages
- [Django]-Assign variables to child template in {% include %} tag Django
- [Django]-Embed YouTube video – Refused to display in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'
20👍
I would like to add that as per the commit Fixed #31757 — Adjusted system check for SECRET_KEY to warn about autogenerated default keys, the method get_random_secret_key()
is considred to be insecure.
If you are using python 3.6+ then you can use the secrets.token_hex([nbytes=None])
function
python3 -c 'import secrets; print(secrets.token_hex(100))'
- [Django]-Manager isn't available; User has been swapped for 'pet.Person'
- [Django]-Use Python standard logging in Celery
- [Django]-How to upgrade django?
10👍
The post referenced by S Ghosh TLDR: Generate Django Secret Key indicates that as of version 3.1.3, Django is actually using the Python secrets
module behind the scenes. Looking at this blob for get_random_secret_key
and this other blob for get_random_string
, I can see it is so:
def get_random_secret_key():
"""
Return a 50 character random string usable as a SECRET_KEY setting value.
"""
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
return get_random_string(50, chars)
def get_random_string(length, allowed_chars=RANDOM_STRING_CHARS):
"""
Return a securely generated random string.
The bit length of the returned value can be calculated with the formula:
log_2(len(allowed_chars)^length)
For example, with default `allowed_chars` (26+26+10), this gives:
* length: 12, bit length =~ 71 bits
* length: 22, bit length =~ 131 bits
"""
return ''.join(secrets.choice(allowed_chars) for i in range(length))
The only issue with the get_random_secret_key
function as I see it in the code is that the allowed characters does not include capital letters, so the number of possible bits for the same size key is smaller than it would be if capitals were included, but not by much:
from math import log2
lower_plus_numbers = (list(chr(o) for o in range(0x61, 0x7B))
+ list(chr(o) for o in range(0x30, 0x3A)))
punctuation = list('!@#$%^&*(-_=+)')
upper_alpha = list(chr(o) for o in range(0x41, 0x5B))
shorter = log2((len(lower_plus_numbers) + len(punctuation)) ** 50)
longer = log2((len(lower_plus_numbers) + len(punctuation) + len(upper_alpha)) ** 50)
print(f'longer: {int(longer + 0.5)}; shorter: {int(shorter + 0.5)} '
f'difference: {int(longer - shorter + 0.5)}; ratio: {longer/shorter}')
The output of the above code:
longer: 312; shorter: 282; difference: 30; ratio: 1.1070316647619918
So, if you have a recent enough Django and Python, the biggest question is whether you want to generate your SECRET_KEY
with a dependency on Dango, or just Python. If you don’t mind the Django dependency, but want to include upper case letters, or want to have a longer key, you can easily do something like:
from django.utils.crypto import get_random_string
key_length = 60
get_random_string(
key_length,
allowed_chars=lower_plus_numbers + punctuation + upper_alpha,
)
Sample output:
'gW(VDtylhoAuZNcLbIC=ai5=2*tPZ=Gmf4D1^4T!NxX3tB0%_w7pYY2+FgDx'
If you don’t want the Django dependency, you could use S Ghosh’s answer. Or if you want more than hex characters, you could do something like:
allowed_chars = [chr(i) for i in range(0x21, 0x7F)]
key_length = 60
key = ''.join(secrets.choice(allowed_chars) for i in range(key_length))
Value of key
(as a python string):
'DN7tbWid#q6R^=%i"[1AA>$@AZg=XD+p|[aB?:#V`:kKWL77P6dC,~(\\9O\'j'
- [Django]-Why won't Django use IPython?
- [Django]-How do I reuse HTML snippets in a django view
- [Django]-DRF: Simple foreign key assignment with nested serializers?