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

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

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,
}

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)),
]

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

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.

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)),
)

Related

Using PUBLIC_SCHEMA_URLCONF in django-tenant-schemas

I am trying to have django-tenant-schemas re-route users if they visit the base domain using the optional setting PUBLIC_SCHEMA_URLCONF. Whenever I visit the
base url I get this response:
I'm hoping someone can tell me what the value of PUBLIC_SCHEMA_URLCONF should be based on my project structure or if anything else might be wrong. I want to use the urls from public_website when people try to access the base domain.
My project directory looks like this:
website
├──approvals
├──batches
├──customauth
├──email_portal
├──exports
├──file_downloads
├──password_reset
├──payroll
├──payroll_codes
├──reports
├──scheduling
├──shifts
├──static
├──templates
├──website
| ├──migrations
| ├──static
| ├──templates
| └──settings
| ├──__init__.py
| ├──base.py
| ├──prod.py
| └──dev.py
├──scheduling
├──public_website
| ├──__init__.py
| └──urls.py
└──manage.py
And I want PUBLIC_SCHEMA_URLCONF to refer to the urls in public_website, which look like:
from django.conf.urls import include, url
import website.views as website_views
from django.contrib import admin
from django.http import HttpResponse
url_patterns = [
url(r'^$', lambda request: HttpResponse('ok')),
url(r'^admin/login/', website_views.Login.as_view()),
url(r'^admin/', include(admin.site.urls)) # user authentication urls
]
Here are the relevant bits in my settings:
DJANGO_APPS = (
'jet',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'django.contrib.admin',
'django_user_agents',
'django_ses',
# 'admin_reorder'
)
MY_APPS_WITH_MODELS = (
'customauth',
'payroll_codes',
'scheduling',
'payroll',
'shifts',
'email_portal',
'tutor_training_tracker'
)
MY_APPS_WITHOUT_MODELS = (
'exports',
'reports',
'file_downloads',
'batches',
'approvals'
)
SHARED_APPS = (
'tenant_schemas',
'website',
'public_website'
)
TENANT_APPS = DJANGO_APPS + MY_APPS_WITH_MODELS
INSTALLED_APPS = list(OrderedDict.fromkeys(SHARED_APPS + DJANGO_APPS + MY_APPS_WITHOUT_MODELS + MY_APPS_WITH_MODELS))
ROOT_URLCONF = 'website.urls'
PUBLIC_SCHEMA_URLCONF = 'public_website.urls'
TENANT_MODEL = "website.Client"
DEFAULT_FILE_STORAGE = "tenant_schemas.storage.TenantFileSystemStorage"
Any help would be greatly appreciated.
Solution:
(Thanks to Thomas for writing the middleware for me)
Add custom middleware class:
from django.conf import settings
from django.db import connection
from tenant_schemas.middleware import MIDDLEWARE_MIXIN
from tenant_schemas.utils import remove_www, get_tenant_model, get_public_schema_name
class CustomTenantMiddleware(MIDDLEWARE_MIXIN):
def get_tenant(self, model, hostname, request):
return model.objects.get(domain_url=hostname)
def hostname_from_request(self, request):
""" Extracts hostname from request. Used for custom requests filtering.
By default removes the request's port and common prefixes.
"""
return remove_www(request.get_host().split(':')[0]).lower()
def process_request(self, request):
# Connection needs first to be at the public schema, as this is where
# the tenant metadata is stored.
connection.set_schema_to_public()
hostname = self.hostname_from_request(request)
TenantModel = get_tenant_model()
try:
# get_tenant must be implemented by extending this class.
tenant = self.get_tenant(TenantModel, hostname, request)
assert isinstance(tenant, TenantModel)
request.tenant = tenant
connection.set_tenant(request.tenant)
except (TenantModel.DoesNotExist, AssertionError):
request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
request.public_tenant = True
return
if hasattr(settings, 'PUBLIC_SCHEMA_URLCONF') and request.tenant.schema_name == get_public_schema_name():
request.urlconf = settings.PUBLIC_SCHEMA_URLCONF
and reference it in settings:
MIDDLEWARE_CLASSES = (
# 'tenant_schemas.middleware.TenantMiddleware',
'website.middleware.CustomTenantMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'django_user_agents.middleware.UserAgentMiddleware',
'admin_reorder.middleware.ModelAdminReorder',
'website.middleware.CustomTenantMiddleware',
# 'djadmin.middleware.DJMiddleware',
)
I maintain Django-Tenants which is a fork of django-tenant-schemas. The public url file gets called when the domain doesn't match a tenant. However depending on the middleware you have this can result in this not working. If this is the case write custom middleware for the tenant. You may also want edit you host file as it hard to test with out editing. What middleware are you using?
Make sure you have installed latest version of django-tenants and these settings are set in settings.py:
SHOW_PUBLIC_IF_NO_TENANT_FOUND = True # I wonder why this setting is not meintioned in docs.
PUBLIC_SCHEMA_URLCONF = 'project_name.urls_public'

Debugging django-channels

I'm trying to incorporate django-channels into my next project but I am having issues debugging. I have tried pycharms debugger and also pdb but it does not hit the breakpoints.
Take a look into django channels panel. It is a plugin to django debug toolbar. You can add django-channels-panel to this to add channel debug functionality to your project. This ensures that you can channel details when your app is in development mode.
https://github.com/Krukov/django-channels-panel
Installation [ Django debug toolbar ]
pip install django-debug-toolbar
In settings.py
INSTALLED_APPS = [
# ...
'django.contrib.staticfiles',
# ...
'debug_toolbar',
]
MIDDLEWARE = [
# ...
'debug_toolbar.middleware.DebugToolbarMiddleware',
# ...
]
In urls.py
from django.conf import settings
from django.conf.urls import include, url
if settings.DEBUG:
import debug_toolbar
urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)),
]
Configuration
DEBUG_TOOLBAR_PANELS = [
'debug_toolbar.panels.versions.VersionsPanel',
'debug_toolbar.panels.timer.TimerPanel',
'debug_toolbar.panels.settings.SettingsPanel',
'debug_toolbar.panels.headers.HeadersPanel',
'debug_toolbar.panels.request.RequestPanel',
'debug_toolbar.panels.sql.SQLPanel',
'debug_toolbar.panels.staticfiles.StaticFilesPanel',
'debug_toolbar.panels.templates.TemplatesPanel',
'debug_toolbar.panels.cache.CachePanel',
'debug_toolbar.panels.signals.SignalsPanel',
'debug_toolbar.panels.logging.LoggingPanel',
'debug_toolbar.panels.redirects.RedirectsPanel',
]
Installation [ Django channels panel ]
pip install django-channels-panel
add 'channels_panel' to your INSTALLED_APPS in settings.py
add 'channels_panel.panel.ChannelsDebugPanel' to your DEBUG_TOOLBAR_PANELS
Adding PYCHARM_DEBUG=True to the environment variables solved this for me.
This adds a lot of extra logging to be outputted when running the debugger, but it seems that the problem remains fixed even after removing the PYCHARM_DEBUG value from the config.
This is what works for me currently:
In the Python debugging settings, make sure Gevent-compatible is unticked
I don't think anything else is necessary. My breakpoints are hit after this setting is changed, and they are not hit when Gevent-compatible is ticked.

django-axes lockout not working

Has anyone here successfully configured django-axes? Axes is a module which provides you with the ability to lock out a user after a specified number of unsuccessful login attempts. I'm having three problems which I haven't been able to solve. First, my application continues to allow me to try to login even if I've exceeded the failure limit, second my site isn't displaying the lockout template if I exceed the failure limit, and third my administrative site isn't showing any login failures. I've read the docs on Github but I still don't see what I'm doing wrong. My files are shown below. Thanks for your help.
# Relevant settings in settings.py
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'login',
'axes',
)
# MIDDLEWARE_CLASSES contains usual classes
MIDDLEWARE_CLASSES += (
'axes.middleware.FailedLoginMiddleware',
)
AXES_LOGIN_FAILURE_LIMIT = 1
import datetime as dt
delta = dt.timedelta(minutes=1)
AXES_COOLOFF_TIME = delta
AXES_LOCKOUT_URL = '/accounts/locked_out/'
AXES_LOCKOUT_TEMPLATE = 'registration/locked_out.html'
# Relevant routes in urls.py
urlpatterns = patterns('',
# This is my login view, nothing special there
url(r'^$', 'login.views.firewall_login'),
# The view for Axes lockout
url(r'^accounts/locked_out/$',
'login.views.locked_out',
{'template': 'registration/locked_out.html'}),
url(r'^admin/', include(admin.site.urls)),
)
# views.py
def locked_out(request, template):
"""User is redirected here after they're locked out."""
return render(request, template)
Add this to your setting.py:
AUTHENTICATION_BACKENDS = [
# AxesBackend should be the first backend in the AUTHENTICATION_BACKENDS list.
'axes.backends.AxesBackend',
# Django ModelBackend is the default authentication backend.
'django.contrib.auth.backends.ModelBackend',
]
All I can help with is that you need to add
AXES_ENABLE_ACCESS_FAILURE_LOG = True # log access failures to the database.
Not sure about the other questions myself, unfortunately

Why is Django ignoring my ROOT_URLCONF setting?

I tried setting ROOT_URLCONF in settings.py in my project (called registration) to a variety of strings: ROOT_URLCONF = 'registration.urls', ROOT_URLCONF = 'foo.urls', ROOT_URLCONF = 'monkey.urls', ROOT_URLCONF = 'registration.registration.urls'.
Regardless, I get this output on my home page:
Page not found (404)
Request Method: GET
Request URL: http://78.198.124.245/
Directory indexes are not allowed here.
You're seeing this error because you have DEBUG = True in your Django settings file.
Why is that? Here is the file I am using to configure Passenger (passenger_wsgi.py). This file is located in "/home/david/registration/registration/."
import os, sys
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "registration.settings")
# This application object is used by any WSGI server configured to use this
# file. This includes Django's development server, if the WSGI_APPLICATION
# setting points here.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
sys.path.append(os.getcwd())
sys.path.append("/home/david/registration/registration")
sys.path.append("/home/david/registration/registration/app")
/home/david/registration/registration/urls.py looks like this.
from django.conf.urls import patterns, include, url, http
def myFunction(request):
return http.HttpResponse("A mapped URL")
urlpatterns = patterns('',
(r'^$', 'myFunction')
)
Why is my Django application completely ignoring my ROOT_URLCONF setting and returning the same output every time I access my home page?
Nothing of your tries actually resides in python path. If the path is /home/david/registration/registration and the urls are in /home/david/registration/registration/urls.py then what should be the relative path from first to second?

Django Admin: Path to file uploaded is wrong. Missing "static"?

I have a simple model and the default admin in django. Everything works as expected and I can upload files.
I've read the django docs regarding upload paths.
My MEDIA URL and MEDIA ROOT are set and the uploading works.
Lets say I login into the default admin, place an order with an uploaded jpg, the I go to edit the order and I see the current upload file.
If I hover the current file link, the complete url is some.url.com/uploads/myfile.jpg, when it should be some.url.com/static/uploads/myfile.jpg ???
My MEDIA URL is set at some.url.com/static/ and MEDIA ROOT at the absolute path to "static".
Since the upload works fine and goes where it should, maybe something is missing...
I'd like to be able to, inside default django admin, go to order edit, hover the current uploaded file, click it and it would open in a new window, Obviously, currently it goes 404...
The relevant part from the model:
ficheiro = models.FileField(upload_to='uploads')
Heres a screenshot:
screenshot http://anibalcascais.com/exemplo.jpg
Thank You
# Django settings for ensanis project.
import os.path
DEBUG = False
TEMPLATE_DEBUG = DEBUG
ADMINS = (
# ('Anibal Santos', 'anibalcascais#gmail.com'),
)
MANAGERS = ADMINS
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# If running in a Windows environment this must be set to the same as your
# system time zone.
TIME_ZONE = 'Europe/Lisbon'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'pt_PT'
SITE_ID = 1
# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True
# Absolute path to the directory that holds media.
# Example: "/home/media/media.lawrence.com/"
MEDIA_ROOT = '/home/anibal/sites/ensanis/static/'
# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash if there is a path component (optional in other cases).
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = 'http://cl10.anibalcascais.com/static/'
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
# Examples: "http://foo.com/media/", "/media/".
ADMIN_MEDIA_PREFIX = 'http://cl10.anibalcascais.com/media/'
# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.load_template_source',
'django.template.loaders.app_directories.load_template_source',
# 'django.template.loaders.eggs.load_template_source',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)
ROOT_URLCONF = 'ensanis.urls'
TEMPLATE_DIRS = (
'templates',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'ensanis.encomendas',
'django.contrib.admin',
'ensanis.django_evolution',
)
ok, I'm sorry to bother you all, but it turns out it was something obvious:
I've restarted fcgi and the paths are now correct. (duhhh!)
Sorry all for your trouble :)