Skip to content

django-debug-toolbar conflicts with django test #1035

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mangobowl opened this issue Jan 22, 2018 · 13 comments · Fixed by #1349
Closed

django-debug-toolbar conflicts with django test #1035

mangobowl opened this issue Jan 22, 2018 · 13 comments · Fixed by #1349

Comments

@mangobowl
Copy link

If django-debug-toolbar installed and configured well as the docs, when executing a django project test (eg: python manage.py test), and django reverse function used in the tests(This is very important), it will get these errors as following:

======================================================================
ERROR: test_list (toolbar.tests.MyTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Users\vm\Desktop\test_project\toolbar\tests.py", line 10, in test_li
st
    response = self.client.get(reverse('list'))
  File "C:\Python27\lib\site-packages\django\test\client.py", line 536, in get
    **extra)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 340, in get
    return self.generic('GET', path, secure=secure, **r)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 416, in gener
ic
    return self.request(**r)
  File "C:\Python27\lib\site-packages\django\test\client.py", line 501, in reque
st
    six.reraise(*exc_info)
  File "C:\Python27\lib\site-packages\django\core\handlers\exception.py", line 4
1, in inner
    response = get_response(request)
  File "C:\Python27\lib\site-packages\django\utils\deprecation.py", line 142, in
 __call__
    response = self.process_response(request, response)
  File "C:\Python27\lib\site-packages\debug_toolbar\middleware.py", line 134, in
 process_response
    bits[-2] += toolbar.render_toolbar()
  File "C:\Python27\lib\site-packages\debug_toolbar\toolbar.py", line 64, in ren
der_toolbar
    return render_to_string('debug_toolbar/base.html', context)
  File "C:\Python27\lib\site-packages\django\template\loader.py", line 68, in re
nder_to_string
    return template.render(context, request)
  File "C:\Python27\lib\site-packages\django\template\backends\django.py", line
66, in render
    return self.template.render(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 207, in ren
der
    return self._render(context)
  File "C:\Python27\lib\site-packages\django\test\utils.py", line 107, in instru
mented_test_render
    return self.nodelist.render(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 990, in ren
der
    bit = node.render_annotated(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 957, in ren
der_annotated
    return self.render(context)
  File "C:\Python27\lib\site-packages\django\template\defaulttags.py", line 216,
 in render
    nodelist.append(node.render_annotated(context))
  File "C:\Python27\lib\site-packages\django\template\base.py", line 957, in ren
der_annotated
    return self.render(context)
  File "C:\Python27\lib\site-packages\django\template\defaulttags.py", line 322,
 in render
    return nodelist.render(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 990, in ren
der
    bit = node.render_annotated(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 957, in ren
der_annotated
    return self.render(context)
  File "C:\Python27\lib\site-packages\django\template\defaulttags.py", line 322,
 in render
    return nodelist.render(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 990, in ren
der
    bit = node.render_annotated(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 957, in ren
der_annotated
    return self.render(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 1040, in re
nder
    output = self.filter_expression.resolve(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 708, in res
olve
    obj = self.var.resolve(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 849, in res
olve
    value = self._resolve_lookup(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 890, in _re
solve_lookup
    current = getattr(current, bit)
  File "C:\Python27\lib\site-packages\debug_toolbar\panels\__init__.py", line 96
, in content
    return render_to_string(self.template, self.get_stats())
  File "C:\Python27\lib\site-packages\django\template\loader.py", line 68, in re
nder_to_string
    return template.render(context, request)
  File "C:\Python27\lib\site-packages\django\template\backends\django.py", line
66, in render
    return self.template.render(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 207, in ren
der
    return self._render(context)
  File "C:\Python27\lib\site-packages\django\test\utils.py", line 107, in instru
mented_test_render
    return self.nodelist.render(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 990, in ren
der
    bit = node.render_annotated(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 957, in ren
der_annotated
    return self.render(context)
  File "C:\Python27\lib\site-packages\django\template\defaulttags.py", line 322,
 in render
    return nodelist.render(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 990, in ren
der
    bit = node.render_annotated(context)
  File "C:\Python27\lib\site-packages\django\template\base.py", line 957, in ren
der_annotated
    return self.render(context)
  File "C:\Python27\lib\site-packages\django\template\defaulttags.py", line 216,
 in render
    nodelist.append(node.render_annotated(context))
  File "C:\Python27\lib\site-packages\django\template\base.py", line 957, in ren
der_annotated
    return self.render(context)
  File "C:\Python27\lib\site-packages\django\template\defaulttags.py", line 458,
 in render
    url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
  File "C:\Python27\lib\site-packages\django\urls\base.py", line 87, in reverse
    raise NoReverseMatch("%s is not a registered namespace" % key)
NoReverseMatch: u'djdt' is not a registered namespace

----------------------------------------------------------------------
Ran 1 test in 0.085s

FAILED (errors=1)
Destroying test database for alias 'default'...

Environment

python: 2.7.14
django: 1.11.9
django-debug-toolbar: 1.9.1

Test file sample

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.test import TestCase
from django.core.urlresolvers import reverse

# Create your tests here.
class MyTests(TestCase):
    def test_list(self):
        response = self.client.get(reverse('list'))
        self.assertEqual(response.status_code, 200)
@prince-tanapong
Copy link

Any news on this?

@matthiask
Copy link
Member

The Django test runner forcibly sets DEBUG=False, which means that the debug toolbar's URL patterns are not available.

Try removing the middleware from MIDDLEWARE when running tests. Also, I'd appreciate a documentation patch if the suggestion works well.

@Matchlighter
Copy link

Encountered the same issue. In my case I was overriding SHOW_TOOLBAR_CALLBACK to return the value of DEBUG. Workaround is to import django.conf.settings and return settings.DEBUG instead.

@roffel
Copy link

roffel commented Aug 17, 2018

Are there any updates on this?

@SamMorrowDrums
Copy link

I've had to do this:

settings.py

TESTING_MODE = 'test' in sys.argv

urls.py

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

It is a very frustrating behaviour. I guess maybe there are other workarounds, but this was enough for now.

@rafahuelin
Copy link

rafahuelin commented Oct 27, 2018

I've tried SamMorrowDrums solution and although it hasn't worked for me, this tweaked version based on his idea is working fine:

settings.py

import sys

DEBUG = True
TESTING_MODE = 'test' in sys.argv
DEV_MODE = DEBUG and not TESTING_MODE

if DEV_MODE:
    INSTALLED_APPS += [
        'debug_toolbar'
    ]
    MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]

    # DEBUG TOOLBAR SETTINGS:
    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',
    ]

    def show_toolbar(request):
        return True

    DEBUG_TOOLBAR_CONFIG = {
        'INTERCEPT_REDIRECT': False,
        'SHOW_TOOLBAR_CALLBACK': show_toolbar,
    }

urls.py

from django.conf import settings

if settings.DEV_MODE:
    import debug_toolbar
    urlpatterns += [
        path('__debug__/', include(debug_toolbar.urls)),
    ]

@tezmen
Copy link

tezmen commented May 6, 2019

You can also just override default callback of showing django-debug-toolbar.
Try set like this in your settings.py

INTERNAL_IPS = ['127.0.0.1']
DEBUG_TOOLBAR_CONFIG = {
    'SHOW_TOOLBAR_CALLBACK': lambda r: r.environ.get('SERVER_NAME', None) != 'testserver' and (r.META.get('REMOTE_ADDR', None) in INTERNAL_IPS)
}

... or any other method of check on "is test requests"

@tim-schilling
Copy link
Member

Can someone reproduce this to confirm this is still an issue? I haven't been able to reproduce it.

@shydefoo
Copy link

Can someone reproduce this to confirm this is still an issue? I haven't been able to reproduce it.

Hi, I am still facing this issue as well. Using django-debug-toolbar==2.2 and Django==2.1.8

Could this be because of a slightly older django version?
View works fine when it is called normally, however when calling executing a test python manage.py test it throws

django.request: ERROR: Internal Server Error: /order_platform/photo_import/
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/urls/base.py", line 75, in reverse
    extra, resolver = resolver.namespace_dict[ns]
KeyError: 'djdt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/debug_toolbar/middleware.py", line 99, in __call__
    bits[-2] += toolbar.render_toolbar()
  File "/usr/local/lib/python3.6/site-packages/debug_toolbar/toolbar.py", line 69, in render_toolbar
    return render_to_string("debug_toolbar/base.html", context)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 171, in render
    return self._render(context)
  File "/usr/local/lib/python3.6/site-packages/django/test/utils.py", line 96, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/defaulttags.py", line 309, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 937, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 904, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/defaulttags.py", line 442, in render
    url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
  File "/usr/local/lib/python3.6/site-packages/django/urls/base.py", line 86, in reverse
    raise NoReverseMatch("%s is not a registered namespace" % key)
django.urls.exceptions.NoReverseMatch: 'djdt' is not a registered namespace

This is my settings.py

if DEBUG:
    ...
    INSTALLED_APPS += ["debug_toolbar"]
    # include as early as possible
    MIDDLEWARE = ["debug_toolbar.middleware.DebugToolbarMiddleware"] + MIDDLEWARE
    DEBUG_TOOLBAR_PANELS = [
        "ddt_request_history.panels.request_history.RequestHistoryPanel",
        "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",
    ]
    INSTALLED_APPS += ["django_nose"]
    DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": lambda request: True}
    TEST_RUNNER = "django_nose.NoseTestSuiteRunner"

@tim-schilling
Copy link
Member

@shydefoo You can configure your application to avoid including the toolbar during tests via an environment variable. Another option is to run your tests with DEBUG set to False, though this assumes that you're still excluding the toolbar from being installed.

matthiask pushed a commit that referenced this issue Oct 1, 2020
Remove the "if settings.DEBUG" guard. This guard is not necessary and
leads to several edge cases in local development setups.

This is not necessary as all views are guarded by the
require_show_toolbar decorator which uses the SHOW_TOOLBAR_CALLBACK
setting. This setting is already capable of enabling/disabling across
the application when DEBUG is False. By default, when DEBUG is False,
these views return a 404 response.

By having the URLs always available, the MIDDLEWARE setting also doesn't
need special handling when DEBUG is False, simplifing the overall
configuration. An application should be able to reliably reverse URLs
regardless of the status of DEBUG.

Fixes #1035
Fixes #1043
Fixes #1332
@shydefoo
Copy link

shydefoo commented Oct 3, 2020

@tim-schilling Yeah, that's what I did. Seems like SHOW_TOOLBBAR_CALLBACK was the issue.

@seanick39
Copy link

seanick39 commented Oct 7, 2021

Encountered the same issue. In my case I was overriding SHOW_TOOLBAR_CALLBACK to return the value of DEBUG. Workaround is to import django.conf.settings and return settings.DEBUG instead.

Yep. That did it. django.conf.settings.DEBUG is False while testing, even when the environment variable is True. Docs.
The debug_toolbar middleware is loaded with DEBUG = True from .env, while the __debug__/ urls are skipped due to a falsy django.conf.settings.DEBUG.
So, either synchronise the loading of debug_toolbar urls with .env DEBUG, or use this:

from django.conf import settings
....
DEBUG_TOOLBAR_CONFIG = {
    ...
    "SHOW_TOOLBAR_CALLBACK": lambda x: settings.DEBUG,
}

@KuzenkovAG
Copy link

KuzenkovAG commented Jul 1, 2023

Reason: DEBUG not uploaded from .env

My solution: add environment varibale in pytest.ini

#dependency (version of pytest-env is impotant)
pytest==6.2.5
pytest-django==4.5.2
pytest-env==0.6.2
pytest-pythonpath==0.7.4

#pytest.ini

[pytest]
env =
    DEBUG='True'
python_paths = project_dir/
DJANGO_SETTINGS_MODULE = project_dir.settings
norecursedirs = env/*
addopts = -vv -p no:cacheprovider
testpaths =
    project_dir
python_files = test_*.py

How run test:

pytest

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.