django DEBUG=False still runs in debug mode - django

I'm having issues setting my DEBUG = False on my deployed server (on heroku).
I don't believe I've seen this before, but setting debug to false is not getting rid of debug mode for my project. This means that when there are 500 errors it shows the error, and 404 errors are showing all my urls.
What's strange is that when i log into the server and run get the setting value from django.conf import settings settings.DEBUG it shows as False, which is what I set it to for the production server. TEMPLATE_DEBUG is also set to False.
I don't know I've ever seen this before where DEBUG = False but it's still acting in debug mode. Any ideas?
EDIT:
Thought I'd put this little note too because it's very common for people to be getting 500 or 400 errors when switching debug to False. I am not getting any errors, my project is just acting like it's in DEBUG mode.
# settings/dev.py
from .base import *
DEBUG = True
TEMPLATE_DEBUG = DEBUG
if not DEBUG:
ALLOWED_HOSTS = ['localhost']
SECRET_KEY = 'localsecret1234123412341234'
# settings/prod.py
from .base import *
import dj_database_url, os
DEBUG = os.environ.get("DEBUG", False)
TEMPLATE_DEBUG = DEBUG
ALLOWED_HOSTS = ['mydomain.com']
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
STATICFILES_STORAGE = 'whitenoise.django.GzipManifestStaticFilesStorage'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
DATABASES = {}
DATABASES['default'] = dj_database_url.config()

The root cause of issue - False translated to 'False' string not bool.
Used next solution (settings.py):
DEBUG = os.getenv('DEBUG', False) == 'True'
i.e.: in this case DEBUG will set to (bool) True, only if the environment variable is explicitly set to True or 'True'.
Good luck configuring! :)

As a note for others: I had the same problem; I configured my production website on a VM with gunicorn and nginx, following the tutorial for ubuntu 16.04 from the digital ocean documentation.
I wasn't able to turn off the debug mode, even when restarting the nginx systemd's service: the solution was to restart also the gunicorn service:
# systemctl restart nginx gunicorn

If somebody is using python-decouple for env variables and having trouble with DEBUG you have to use this line to retrieve booleans:
from decouple import config
DEBUG = config('DEBUG', default=False, cast=bool)

I'll put this as an actual answer for people that come after.
There are three main areas that this can happen, where 'this' is basically:
I've changed something in my settings, but it doesn't seem to be reflected in the operation of my app!
Server hasn't been reset after code changes made.
Local and Dev settings haven't overridden/or are overriding in unexpected ways
A local Environment Variable is overriding the attempt at hardcoding it
On Heroku, as in this example, Environment Variables are set this way. A more general guide to using them in Linux enviroments is available here.
Using an example from the question, you can see the environment variables being used in:
SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
This uses the os library to go out to the system, and check for an environment variable called DJANGO_SECRET_KEY.
A better example is the:
DEBUG = os.environ.get("DEBUG", False)
This is good because it tries to get it from the environment, and if that fails, uses the second value in the tuple as the default: in this case, False.
During the course of debugging, you can hunt down your settings using printenv from the linux shell, which will print out all of the available EnvVars. If they're not there, you can set them in the format:
export DJANGO_SETTINGS_MODULE=mysite.settings
In this instance, it's probably better to unset the environment variable, rather than typecasting, as per this related answer.

This ended up being an issue with the config variable being "False" instead of False, and so debug wasn't properly set to the boolean value. Shoutout to #WithNail for helping get to the answer

DEBUG takes Boolean value.
The os.environ.get("DEBUG", False) returns string value.
All the string value while typecasting return True.
That's why the DEBUG is True.
print(bool(os.environ.get("DEBUG", False))) # output: True
print(bool("False")) # output: True
print(bool("")) # output: False
To solve issue in heroku don't set any value to config var. it will return null string and after typecasting it will return False:

When you use the module decouple (pip install python-decouple) make sure you cast DEBUG to a bool. Thus settings.py should have the following line:
from decouple import config
DEBUG = config('DEBUG', default=False, cast=bool)
where in the .env file
DEBUG = False # or True

I also experienced this problem as I was loading the debug setting from an environment variable DEBUG = os.environ.get('DEBUG_MODE')).
This set the DEBUG value as a string, not a boolean.
To fix this, I hardcoded DEBUG = False in my prod settings file.

I got the same error that OTREE_PRODUCTION=1 gives error 500 on Heroku. What I did is to make a new app (Note to change Heroku stack to make it compatible with your Python version) , upload codes to this new app, and set OTREE_PRODUCTION=1 for this new app.

I had the same issue & none of the solutions worked. My error stems from the the server configuration. I have multiple apps served by NGINX & GUNICORN. One of the apps is linked with the default server.
This means that any request not matching any of the IP:port listening pair server blocks is served by the default server. While debugging I happened to have set the settings.py of the app linked with the default server block to DEBUG=True & forgot to set it back to DEBUG=False.
So bringing settings.py of the default app's server block back to DEBUG=False, solved the issue.

Related

Implementing production settings in Django

I'm having trouble understanding the switchover from local to production settings for deploying Django projects. I'm using an Ubuntu virtual machine (VM) if it matters.
I understand how to configure my settings. I understand best practices for creating settings files (base.py, local.py, production.py, blah, blah). I know that in local development DEBUG=True, in production DEBUG=False, blah, blah.
But how do I implement this switchover in deployment? Do I get rid of the local.py? Do I create some kind of logic so that my VM only reads base.py and production.py?
What's the best approach?
I'm not sure about the best approach but what I do works...
At the foot of my settings.py, I have:
try:
from local_settings import *
except ImportError, e:
pass
I keep all my local development settings in local_settings.py which overide any production settings. I also make sure not to upload my local_settings.py file!
What you could do is to check in your settings py which environment is used at the moment.
To do this you can set an environment variable on your system that would have diffrent values on your development environment and the production environment.
you can set these environment variables by
sudo -H gedit /etc/environment
and add the following line in the file:
DEBUG="true"
(to make this changes available you will have to log out and log back in into your system)
in the production environment you would then set DEBUG="false".
then you can do this in your settings.py:
DEBUG = os.environ.get('DEBUG', 'true') != 'false'
and then you can set every setting that would be different depending on the environment that is used like this:
if DEBUG:
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
else:
STATICFILES_STORAGE = STATICFILES_STORAGE = 'custom_storages.StaticStorage'
(the setting above uses the local django server to serve staticfiles if it is in the development environment, and amazon s3 with boto if in the production environment (which is defined in the custom_storages module)
This way you can push your updates and always the right settings should be picked up depending on the environment.

Django can't find staticfiles with Debug=False and Allowed_Hosts

Hi all I'm having trouble solving this issue: If I turn DEBUG to False, I can't run manage.py runserver:
CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False
Then, let's say I add something to ALLOWED_HOSTS:
ALLOWED_HOSTS = ['*']
or
ALLOWED_HOSTS = ['localhost']
or
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']
Now, I can do ´manage.py runserver´ but the staticfiles don't work. Weird.
If I turn DEBUG to True, then it works with ALLOWED_HOSTS set to nothing, to localhost or to *. So, I guess the problem has to do with DEBUG. I don't understand it.
In DEBUG mode, the Django development server handles serving static files for you. However, this is not best for production as it's much more inefficient than a true server. See here.
Serving the files
In addition to these configuration steps, you’ll also need to actually serve the static files.
During development, if you use django.contrib.staticfiles, this will be done automatically by runserver when DEBUG is set to True (see django.contrib.staticfiles.views.serve()).
This method is grossly inefficient and probably insecure, so it is unsuitable for production.
See Deploying static files for proper strategies to serve static files in production environments.
Check out here to learn out how to serve static files in production.
EDIT: Adding the following to answer #alejoss question about viewing error pages with DEBUG=True.
I added something like the following to my root urls.py file:
if settings.DEBUG:
urlpatterns += patterns(
'',
url(r'^400/$', TemplateView.as_view(template_name='400.html')),
url(r'^403/$', TemplateView.as_view(template_name='403.html')),
url(r'^404/$', 'django.views.defaults.page_not_found'),
url(r'^500/$', 'django.views.defaults.server_error'),
)
You might need to alter a bit (i.e., the 400 and 403 pages may need to be edited if your template names are different). Basically, this lets you visit http://localhost/400 to see your 400 error page, http://localhost/403 to see your 403 error page, and so on.
If you still need to server static locally (e.g. for testing without debug) you can run devserver in insecure mode:
manage.py runserver --insecure
Okay Here's the very clean solution. you need to use
DEBUG = False
DEBUG_PROPAGATE_EXCEPTIONS = True
This way in your logs you can see what is then problem. Whitenoise returns 500 usually when It is missing some file.
You can see what is missing in you logs. In my case heroku logs were enough.
for more info: https://docs.djangoproject.com/en/2.0/ref/settings/#debug-propagate-exceptions

Heroku Django DEBUG Setting not applied

I currently have a running production Django application on Heroku. Unfortunately, I haven't been able to turn off the DEBUG setting on Heroku. Turning it off locally works fine, but when pushed to Heroku (after heroku config:set DEBUG=False), it doesn't apply.
The error pages are still the default DEBUG ones instead of the 404, 403, and 500 templates in our template root.
I have also tried using a DJANGO_DEBUG setting in case there were any environment conflicts with DEBUG, and casting the result to a boolean in the settings file. heroku config shows the settings in the environment are correct. This is on Django 1.3, Heroku Cedar.
Any tips or solutions?
Does your django settings.py file even look in the environment?
It does not, by default, care about anything you've set in the environment (via "config:set"). If you're "casting" the environment to a boolean, make sure you're casting it correctly. bool('False') is still True.
It's simplest just to detect if the environment variable exists so you don't have to worry about type casting or specific formats of the configuration.
DEBUG = os.environ.get('DEBUG', False)
To disable debug, remove the variable from the environment instead of trying to type cast... it just seems much more reliable and fool proof. config:unset DEBUG
The problem is that the environment variable is not a boolean, rather a string.
So do place below line in settings.py
DEBUG = (os.environ.get('DEBUG_VALUE') == 'True')

Why does setting debug to false in django settings stop Heroku app from loading in development and production?

In my settings i have set DEBUG=False but this instead generated a 500 Error in both dev and production. so i looked around and came across this (Setting DEBUG = False causes 500 Error) and tried it out.
ALLOWED_HOSTS = ['www.heroku.com']
But this did not work, what am i not doing right? Am hosting with heroku
Your app is not hosted on www.heroku.com. Instead, try
ALLOWED_HOSTS = [".herokuapp.com"]
did you try
python manage.py collecstatic
?
you should review files directory becuase in prodhuction static files directory changes. heroku uses whitenouse

Django: Override Debug=True from manage.py runserver command

Is there an easy way to tell Django's runserver to override a single variable in the settings.py file?
I would love to be able to call:
python manage.py runserver 0.0.0.0:8000 Debug=False
Any thoughts?
Motive: have a particular site where there are hundreds of database queries to show or save a particular page, I'd like to be able to turn off debug quickly without having to edit my settings file (which has the possibility of being forgotten).
I think you have two options
The simplest is probably a custom settings override, something like:
# no_debug_settings.py
# pull in the normal settings
from settings import *
# no debug for us
DEBUG = False
Now, when you want to start without debugging, you'd run:
python manage.py runserver --settings=no_debug_settings 0.0.0.0:8000
As an alternative, you could just customise your manage.py file. That imports settings, and passes it to the execute_manager. If you added some code between the import and the call, you could have it check for extra arguments and alter the settings as needed. It's a bit more fiddly and prone to break / be forgotten, so I'd suggest the override settings wrapper is probably your best way to go.
I edited my settings.py file with a conditional block, like this:
import os # If needed.
if os.environ.get('DJANGO_DEBUG'):
print("Debug is enabled.")
DEBUG = True
# When not specified, ALLOW_HOSTS defaults to:
# ALLOWED_HOSTS = ['localhost', '127.0.0.1', '[::1]']
else:
DEBUG = False
ALLOWED_HOSTS = ["*"]
Then, run your server by passing the environmental variable DJANGO_DEBUG=1. You can name the variable anything you want so long as you are consistent:
DJANGO_DEBUG=1 python -Wall manage.py runserver
Omit that environmental variable when calling manage.py to disable debug (because setting it to any value, including 0 will still make it true to the Python code.)
Update: A commenter stated that the ALLOWED_HOSTS directive is ignored when DEBUG is True. This is only true in older versions of Django. The current behavior is to honor ALLOWED_HOSTS or default to localhost addresses if it isn't specified when DEBUG is enabled. My answer is updated to reflect this as a minor correction.
This is sourced from the Django documentation:
When DEBUG is True and ALLOWED_HOSTS is empty, the host is
validated against ['localhost', '127.0.0.1', '[::1]']
Additionally, it states that the behavior your comment on is now outdated in a few major version lines:
In older versions, ALLOWED_HOSTS wasn’t checked if DEBUG=True.
This was also changed in Django 1.10.3, 1.9.11, and 1.8.16 to prevent a
DNS rebinding attack.