Skip to content
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

'djdt' is not a registered namespace #1405

Closed
convers39 opened this issue Nov 21, 2020 · 26 comments
Closed

'djdt' is not a registered namespace #1405

convers39 opened this issue Nov 21, 2020 · 26 comments

Comments

@convers39
Copy link

convers39 commented Nov 21, 2020

I got this error when I run django unittest, I have tried all the answers I could find, seems not working.
Here are my settings:

DEBUG_TOOLBAR_PATCH_SETTINGS = False
if DEBUG:
    INSTALLED_APPS += ['debug_toolbar']
    MIDDLEWARE += ['debug_toolbar.middleware.DebugToolbarMiddleware', ]
    DEBUG_TOOLBAR_CONFIG = {
        'SHOW_TOOLBAR_CALLBACK': lambda _request: DEBUG
    }

Project url file:

if settings.DEBUG:
    import debug_toolbar
    urlpatterns += [path('__debug__/', include(debug_toolbar.urls)), ]\
        + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

If I turn off the debug to False manually, then the error is gone, if I just run manage.py test with all those settings above or either same as the official doc , then I get the this error.
Is there any method to avoid this error? Doesn't the debug suppose to be False when running a test?

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 829, in _resolve_lookup
    current = current[bit]
TypeError: 'HistoryPanel' object is not subscriptable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/django/urls/base.py", line 72, 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/src/app/apps/shop/tests/test_views.py", line 63, in test_shop_list_view_sort_GET
    res = self.client.get(reverse('shop:product-list')+'?sorting=sales')
  File "/usr/local/lib/python3.8/site-packages/django/test/client.py", line 733, in get
    response = super().get(path, data=data, secure=secure, **extra)
  File "/usr/local/lib/python3.8/site-packages/django/test/client.py", line 393, in get
    return self.generic('GET', path, secure=secure, **{
  File "/usr/local/lib/python3.8/site-packages/django/test/client.py", line 470, in generic
    return self.request(**r)
  File "/usr/local/lib/python3.8/site-packages/django/test/client.py", line 710, in request
    self.check_exception(response)
  File "/usr/local/lib/python3.8/site-packages/django/test/client.py", line 571, in check_exception
    raise exc_value
  File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.8/site-packages/debug_toolbar/middleware.py", line 94, in __call__
    bits[-2] += toolbar.render_toolbar()
  File "/usr/local/lib/python3.8/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.8/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/usr/local/lib/python3.8/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/local/lib/python3.8/site-packages/django/test/utils.py", line 96, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/defaulttags.py", line 211, in render
    nodelist.append(node.render_annotated(context))
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/loader_tags.py", line 192, in render
    return template.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 172, in render
    return self._render(context)
  File "/usr/local/lib/python3.8/site-packages/django/test/utils.py", line 96, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/defaulttags.py", line 312, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/defaulttags.py", line 312, in render
    return nodelist.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 988, in render
    output = self.filter_expression.resolve(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 671, in resolve
    obj = self.var.resolve(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 796, in resolve
    value = self._resolve_lookup(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 837, in _resolve_lookup
    current = getattr(current, bit)
  File "/usr/local/lib/python3.8/site-packages/debug_toolbar/panels/history/panel.py", line 90, in content
    return render_to_string(
  File "/usr/local/lib/python3.8/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/usr/local/lib/python3.8/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/local/lib/python3.8/site-packages/django/test/utils.py", line 96, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.8/site-packages/django/template/defaulttags.py", line 446, in render
    url = reverse(view_name, args=args, kwargs=kwargs, current_app=current_app)
  File "/usr/local/lib/python3.8/site-packages/django/urls/base.py", line 83, in reverse
    raise NoReverseMatch("%s is not a registered namespace" % key)
django.urls.exceptions.NoReverseMatch: 'djdt' is not a registered namespace
@tim-schilling
Copy link
Contributor

How does DEBUG get set in your settings file? It sounds like it's being set to True when you're running your tests. You can create a new settings file for your tests that specifically sets it to False. Or you can make sure that whatever mechanism is setting the value for DEBUG will set it to False when running the tests.

@convers39
Copy link
Author

How does DEBUG get set in your settings file? It sounds like it's being set to True when you're running your tests. You can create a new settings file for your tests that specifically sets it to False. Or you can make sure that whatever mechanism is setting the value for DEBUG will set it to False when running the tests.

Hi Tim,
Thank you for your help. For the DEBUG setting, I just leave it as DEBUG=True in my settings.py file. I will make another setting file for testing. Just want to clear that, if I am wrong please let me know, DEBUG will not be set to False when we run a test?

@BradleyKirton
Copy link

Hi there, I have recently started working on a large project and have tried adding django-debug-toolbar. The setup works perfectly, however when any unit tests that make use of the django test client to make requests to views run, I receive the 'djdt' is not a registered namespace error.

I read that when running unit tests django explicitly sets DEBUG to false (See here).

I have begun debugging the issue and it seems the following happens when the unit tests are run:

  1. The settings module in our project directory is executed. At this point in time DEBUG is True as it is read from a env variable for local development
  2. The test runner calls setup_test_environment which then sets DEBUG to False and runs the tests
  3. At this point the debug toolbar has been setup however when the tests run the debug-toolbar urls are never added to the project url patterns since DEBUG is now false. This results in the namespace error

Is the use of the django test client a known issue with debug toolbar? As I mentioned above the project is quite large and there may be something else causing the issue.

In the meantime I am going to provide a environment variable specifically for the setup of the debug-toolbar.

@matthiask
Copy link
Member

Here's the way I do it these days. I have a DEBUG and a TESTING setting:
https://github.com/matthiask/workbench/blob/5e3663cb7c28cec707cfe746e9072e4fa6778f30/workbench/settings.py#L16-L17

Then, I initialize DEBUG_TOOLBAR = DEBUG and not TESTING

Now Django (and other packages) can change DEBUG as much as they want, debug toolbar is either activated completely or not at all.

@BradleyKirton
Copy link

Here's the way I do it these days. I have a DEBUG and a TESTING setting:
https://github.com/matthiask/workbench/blob/5e3663cb7c28cec707cfe746e9072e4fa6778f30/workbench/settings.py#L16-L17

Then, I initialize DEBUG_TOOLBAR = DEBUG and not TESTING

Now Django (and other packages) can change DEBUG as much as they want, debug toolbar is either activated completely or not at all.

Awesome! Thanks @matthiask

@tim-schilling
Copy link
Contributor

@matthiask Do you think it's possible and worth us implementing a check that would prevent the toolbar from being instrumented if it's for a test run?

@matthiask
Copy link
Member

@tim-schilling I doubt there is an easy way to achieve this. We'd have to find solutions for pytest, unittest etc. The sys.argv hack definitely would not work for all cases.

@tongclement
Copy link

tongclement commented Dec 17, 2020

Same error. Cannot get it to run.

@tongclement
Copy link

Same error. Cannot get it to run.

Solved - Accidentally uploaded the urls.py of the project to the app directory of the server

@ddhanesha
Copy link

Is this resolved?
I am getting this error as well. I followed installation steps mention here: https://django-debug-toolbar.readthedocs.io/en/latest/installation.html

ddhanesha pushed a commit to climateconnect/climateconnect that referenced this issue Jul 8, 2021
I discovered that there is an issue going on with debug_toolbar app at
the moment. So its better to remove that code for now.

Here is the resource:
jazzband/django-debug-toolbar#1405
@tim-schilling
Copy link
Contributor

tim-schilling commented Jul 8, 2021 via email

@tim-schilling
Copy link
Contributor

tim-schilling commented Jul 8, 2021

@ddhanesha Looking at your code base, you need to inject the toolbar into your pragmatically programatically to add it to your installed apps and middleware on the same condition that you add it to your url patterns.

@martinberoiz
Copy link

Hello, I have the exact same situation as OP and I have the same long error response.

The only workaround I see is to use the flag --debug-mode when running the tests to force django use DEBUG=True.
It'd be nice to have a more fundamental solution to this situation, though.

@tim-schilling
Copy link
Contributor

@martinberoiz have you setup your project to add the toolbar to INSTALLED_APPS, MIDDLEWARE and the urls when running tests / DEBUG = False?

@martinberoiz
Copy link

@tim-schilling yes, that is correct. This is how I configured:

# base.py
if DEBUG:
    MIDDLEWARE.insert(0, 'debug_toolbar.middleware.DebugToolbarMiddleware')
    DEBUG_TOOLBAR_CONFIG = {"SHOW_TOOLBAR_CALLBACK": lambda request: DEBUG}
    INSTALLED_APPS += ('debug_toolbar',)
# urls.py
if settings.DEBUG:
    urlpatterns += (path('__debug__/', include('debug_toolbar.urls')),)

I just noticed that I didn't set DEBUG_TOOLBAR_PATCH_SETTINGS = False like OP. Would that make a difference?

@tim-schilling
Copy link
Contributor

@martinberoiz what's going on is what is explained here #1405 (comment)

DEBUG is actually True when settings load, so MIDDLEWARE and INSTALLED_APPS are setup with the toolbar, then the test runner flips debug to false. However, MIDDLEWARE and INSTALLED_APPS are already populated with the debug settings. The solution is to use Matthias' approach as defined here: #1405 (comment)

See https://github.com/matthiask/workbench/blob/5e3663cb7c28cec707cfe746e9072e4fa6778f30/workbench/settings.py#L16-L17 for an example of how he sets them.

@sklyar61

This comment was marked as off-topic.

@tim-schilling

This comment was marked as off-topic.

@sklyar61

This comment was marked as off-topic.

@VeldaKiara
Copy link
Contributor

Hi @tim-schilling and @matthiask

This is how I am thinking about it

Have a section called "Additional note" right after Troubleshoot section

Then add the following:

Additional Note
In some instances you may experience the following issue
django.urls.exceptions.NoReverseMatch: 'djdt' is not a registered namespace

To debug this issue use the following:
In your settings.py file:

import sys #skip if already existing

DEBUG = env("DEBUG", default=bool({"runserver"}.intersection(sys.argv)))

TESTING = env("TESTING", default="test" in sys.argv)

env- in the above example is where your environment variables are.
sys.argv - is a list containing command-line arguments passed to the Python script.

@matthiask
Copy link
Member

I definitely use env (from speckenv in my case) but we shouldn't presume that people use a particular env utility or library.

I'm not sure if setting DEBUG and TESTING this way helps for this particular issue?

TESTING isn't used in the toolbar at all.

Maybe we could add a system check (here https://github.com/jazzband/django-debug-toolbar/blob/main/debug_toolbar/apps.py ) for DEBUG and a system check which verifies that URLs in the djdt namespace are actually reversible? If debug_toolbar is installed, DEBUG=False could raise a warning (in my opinion an error even, since I don't think there are good use cases for running the toolbar without DEBUG but that wouldn't be backwards compatible) and djdt reversing errors should definitely produce a system check error.

@tim-schilling
Copy link
Contributor

tim-schilling commented Jan 31, 2024

The goal of this issue is to solve how a user configures DDT in the context of runserver and running tests. When tests are run, django does some weird things with DEBUG that results in the toolbar being installed, but DEBUG being set to False. When the tests run, there are errors that seem impossible.

@matthiask
Copy link
Member

Thanks @tim-schilling -- I reacted too quickly without checking the full thread.

@tim-schilling
Copy link
Contributor

I think I'd prefer to see these changes included in the original setup @VeldaKiara. I think the additional note could work, but it would effectively need to redefine how the toolbar would be enabled using the TESTING setting which isn't standard in Django applications.

@VeldaKiara
Copy link
Contributor

I did not move it there on the assumption that it does not happen to everyone that's the perspective I had.

I used the djdt on one of my django apps and I did not get the issue.

I like the idea of putting it on the installation but do I add it as an optional note, with a statement of if the above condition occurs then adjust to these settings?

tim-schilling added a commit that referenced this issue Apr 30, 2024
* updated the change to the changes.rst file

* solution to djdt registered namespace,update docs, system checks and tests

* removing test in the if statements

* Add basic test to example app and example_test to make commands.

* Update check for toolbar and tests.

* update check using with, combine the four tests to one, update default config

* update installation files and remove patch from namespace check

* Clean-up the changelog

* Add docs for the IS_RUNNING_TESTS setting

Co-authored-by: Matthias Kestenholz <mk@feinheit.ch>

* Change the code for the toolbar testing error to E001

* Reduce number of .settings calls and document config update.

---------

Co-authored-by: Tim Schilling <schillingt@better-simple.com>
Co-authored-by: Matthias Kestenholz <mk@feinheit.ch>
@tim-schilling
Copy link
Contributor

Closed in #1889

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

No branches or pull requests

9 participants