Jim
Jim

Reputation: 14270

django-debug-toolbar won't display from production server

I'd like to view the Django Debug Toolbar when accessing my production website which is running Django 1.6. My server is running Debian 7.8, Nginx 1.2.1, and Gunicorn 19.1.1. However, when I try to access the site after adding DDT to my installed apps, I get the following error:

NoReverseMatch at /
u'djdt' is not a registered namespace
Exception Location: /home/mysite/venv/mysite/local/lib/python2.7/site-packages/django/core/urlresolvers.py in reverse, line 505

Error during template rendering
In template /home/mysite/venv/mysite/local/lib/python2.7/site-packages/debug_toolbar/templates/debug_toolbar/base.html, error at line 12

data-store-id="{{ toolbar.store_id }}" data-render-panel-url="{% url 'djdt:render_panel' %}"

I know it's not recommended that you run the toolbar in production but I just want to run it while I do some testing on my production server prior to opening it up for public use. As you might expect, it works just fine in my development environment on my laptop. I did some research and have ensured that I'm using the "explicit" setup as recommended here. I also ran the command "django-admin.py collectstatic" to ensure the toolbar's static files were collected into my STATIC_ROOT.

Since I'm running behind a proxy server, I also added some middleware to ensure that the client's IP address is being passed to the toolbar's middleware instead of my proxy's IP address. That didn't fix the problem either.

I'm showing all the settings which seem pertinent to this problem below. Is there something else I'm missing?

Thanks!

These are the pertinent base settings:

SETTINGS_ROOT = os.path.abspath(os.path.dirname(__file__).decode('utf-8'))
STATIC_ROOT = '/var/www/mysite/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(SETTINGS_ROOT, "../../static"),
)
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
)
MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.middleware.common.BrokenLinkEmailsMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
TEMPLATE_DIRS = (
    os.path.join(SETTINGS_ROOT, "../../templates"),
)
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Django management commands in 'scripts'
    'scripts',
    'apps.account',
)

These production-only settings get added to base settings in production:

DEBUG = True  # DDT needs this to be True
TEMPLATE_DEBUG = DEBUG
INSTALLED_APPS += (
    'django_extensions',
    # I'm using Django 1.6
    'debug_toolbar',  
)
if 'debug_toolbar' in INSTALLED_APPS:
MIDDLEWARE_CLASSES += ('conf.middleware.DjangoDebugToolbarFix', 
                       'debug_toolbar.middleware.DebugToolbarMiddleware', )

    # I had to add this next setting after upgrading my OS to Mavericks
    DEBUG_TOOLBAR_PATCH_SETTINGS = False
    # IP for laptop and external IP needed by DDT
    INTERNAL_IPS = ('76.123.67.152', )
    DEBUG_TOOLBAR_CONFIG = {
       'DISABLE_PANELS': [
           'debug_toolbar.panels.redirects.RedirectsPanel',
        ],
       'SHOW_TEMPLATE_CONTEXT': True,
       'INTERCEPT_REDIRECTS': False
    }

This is in my urls.py:

if 'debug_toolbar' in dev.INSTALLED_APPS:
    import debug_toolbar
    urlpatterns += patterns('',
        url(r'^__debug__/', include(debug_toolbar.urls)),
    )

Here is the additional middleware:

class DjangoDebugToolbarFix(object):
    """Sets 'REMOTE_ADDR' based on 'HTTP_X_FORWARDED_FOR', if the latter is
    set."""
    def process_request(self, request):
        if 'HTTP_X_FORWARDED_FOR' in request.META:
            ip = request.META['HTTP_X_FORWARDED_FOR'].split(",")[0].strip()
            request.META['REMOTE_ADDR'] = ip

Upvotes: 7

Views: 7711

Answers (5)

Daniel Butler
Daniel Butler

Reputation: 3736

If you are on docker the following code helped me get the internal ip.

# Debug Toolbar
if DEBUG:
    import os
    import socket
    hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
    INTERNAL_IPS = [ip[:-1] + '1' for ip in ips] + ['127.0.0.1', '10.0.2.2', ]

credit goes here https://gist.github.com/douglasmiranda/9de51aaba14543851ca3#file-option2-py

And this answer has additional options: https://stackoverflow.com/a/49818040/317346

Upvotes: 1

Stryker
Stryker

Reputation: 6120

I had to add the following to the project url.py file to fix the issue. After that debug tool bar is displayed.

 from django.conf.urls import include
 from django.conf.urls import patterns
 from django.conf import settings


  if settings.DEBUG:
      import debug_toolbar
      urlpatterns += patterns('',
              url(r'^__debug__/', include(debug_toolbar.urls)),
              )

Upvotes: 0

Erik Telepovský
Erik Telepovský

Reputation: 543

Actually, you shouldn't set DEBUG to True on your production server, keep it False and check my solution below:

The default DDT callback (debug_toolbar.middleware.show_toolbar) checks are that DEBUG must be set to True, the IP of the request must be in INTERNAL_IPS, and the request must not be an AJAX request.

We can provide our own callback which excludes the DEBUG setting condition:

settings:

INTERNAL_IPS = ['YOUR.IP.ADDRESS.HERE']  # put your client IP address here (not server IP!)

DEBUG_TOOLBAR_CONFIG = {
    'SHOW_TOOLBAR_CALLBACK': lambda request: not request.is_ajax() and request.META.get('REMOTE_ADDR', None) in INTERNAL_IPS
}

You can check HTTP_X_FORWARDED_FOR if you wish too, it is up to you.

urls:

if 'debug_toolbar' in settings.INSTALLED_APPS:
    import debug_toolbar

    urlpatterns += [
        url(r'^__debug__/', include(debug_toolbar.urls)),
    ]

Upvotes: 10

Hans Kristian
Hans Kristian

Reputation: 1806

I am using the exact same setup as OP describes, with the noticeable exception of running everything in a separate Docker container which make the IP of each service hard to predict.

This is how you force Django Debug Toolbar to always show (only use this locally, never in production):

def custom_show_toolbar(request):
    return True # Always show toolbar, for example purposes only.

DEBUG_TOOLBAR_CONFIG = {
    'SHOW_TOOLBAR_CALLBACK': custom_show_toolbar,
}

Upvotes: 11

nicorellius
nicorellius

Reputation: 4043

So django-debug-toolbar uses JavaScript to run as well. have you confirmed you have n conflicting JS scripts affecting your setup? I had a hell of a time with one project using DjDT and it was a back-to-top script that was interfering...

Also, I know you have lots of extra code to handle your proxy situation, but have you uan it straight out of the box to see if that works on your server? I might create a new virtualenv, start from scratch and make sure it works on your server and then proceed to add apps and additional configuration.

These are probably thing you have thought of but I thought I'd add them anyway since your question hasn't received much action.

Good luck.

Upvotes: 0

Related Questions