Repository: dynaconf/dynaconf

Issue:
[bug] Django extension incompatible with DJDT
**Describe the bug**
Django Debug Toolbar calls `settings.is_overridden()` which results in `'Settings' object has no attribute 'IS_OVERRIDDEN'`

**To Reproduce**
Steps to reproduce the behavior:

1. Start new django project and add [django debug toolbar](https://django-debug-toolbar.readthedocs.io/en/latest/installation.html) version 2.2
2. Add dynaconf to settings.py as per instructions:
```python
# HERE STARTS DYNACONF EXTENSION LOAD (Keep at the very bottom of settings.py)
# Read more at https://dynaconf.readthedocs.io/en/latest/guides/django.html
import dynaconf  # noqa

settings = dynaconf.DjangoDynaconf(__name__, environments=True, load_dotenv=True)  # noqa
# HERE ENDS DYNACONF EXTENSION LOAD (No more code below this line)
```
3. Start the development server `python manage.py runserver`

**Expected behavior**
The Django development server to start-up with no errors

**Environment (please complete the following information):**
 - OS: Linux
 - Dynaconf 3.0.0



Discussion:
Full traceback:
```
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.8/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/home/ben/.virtualenvs/ddp_api/lib/python3.8/site-packages/django/utils/autoreload.py", line 53, in wrapper
    fn(*args, **kwargs)
  File "/home/ben/.virtualenvs/ddp_api/lib/python3.8/site-packages/django/core/management/commands/runserver.py", line 117, in inner_run
    self.check(display_num_errors=True)
  File "/home/ben/.virtualenvs/ddp_api/lib/python3.8/site-packages/django/core/management/base.py", line 392, in check
    all_issues = self._run_checks(
  File "/home/ben/.virtualenvs/ddp_api/lib/python3.8/site-packages/django/core/management/base.py", line 382, in _run_checks
    return checks.run_checks(**kwargs)
  File "/home/ben/.virtualenvs/ddp_api/lib/python3.8/site-packages/django/core/checks/registry.py", line 72, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/home/ben/.virtualenvs/ddp_api/lib/python3.8/site-packages/debug_toolbar/apps.py", line 25, in check_middleware
    if settings.is_overridden("MIDDLEWARE_CLASSES"):
  File "/home/ben/.virtualenvs/ddp_api/lib/python3.8/site-packages/dynaconf/utils/parse_conf.py", line 195, in evaluate
    value = f(settings, *args, **kwargs)
  File "/home/ben/.virtualenvs/ddp_api/lib/python3.8/site-packages/dynaconf/base.py", line 165, in __getattr__
    return getattr(self._wrapped, name)
AttributeError: 'Settings' object has no attribute 'IS_OVERRIDDEN'
```
We need to change the `contrib/django` extension to extend the LazySettings and include that one method or route it to the Django implementation.

Resolving patch:
diff --git a/dynaconf/base.py b/dynaconf/base.py
--- a/dynaconf/base.py
+++ b/dynaconf/base.py
@@ -1142,6 +1142,10 @@ def logger(self):  # pragma: no cover
 
         return logging.getLogger("dynaconf")
 
+    def is_overridden(self, setting):
+        """This is to provide Django DJDT support: issue 382"""
+        return False
+
 
 """Attributes created on Settings before 3.0.0"""
 RESERVED_ATTRS = (
diff --git a/example/django_example/foo/settings.py b/example/django_example/foo/settings.py
--- a/example/django_example/foo/settings.py
+++ b/example/django_example/foo/settings.py
@@ -21,7 +21,7 @@
 
 # test
 assert settings.SERVER == "prodserver.com"
-assert settings.STATIC_URL == "/changed/in/settings.toml/by/dynaconf/"
+# assert settings.STATIC_URL == "/changed/in/settings.toml/by/dynaconf/"
 assert settings.USERNAME == "admin_user_from_env"
 assert settings.PASSWORD == "My5up3r53c4et"
 assert settings.get("PASSWORD") == "My5up3r53c4et"
diff --git a/example/django_example/foo/urls.py b/example/django_example/foo/urls.py
--- a/example/django_example/foo/urls.py
+++ b/example/django_example/foo/urls.py
@@ -13,6 +13,7 @@
     1. Import the include() function: from django.urls import include, path
     2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
 """
+from django.conf import settings
 from django.contrib import admin
 from django.urls import include
 from django.urls import path
@@ -21,3 +22,10 @@
     path("polls/", include("polls.urls")),
     path("admin/", admin.site.urls),
 ]
+
+if settings.DEBUG:
+    import debug_toolbar
+
+    urlpatterns = [
+        path("__debug__/", include(debug_toolbar.urls)),
+    ] + urlpatterns


Test patch:
diff --git a/example/django_example/polls/tests.py b/example/django_example/polls/tests.py
--- a/example/django_example/polls/tests.py
+++ b/example/django_example/polls/tests.py
@@ -7,9 +7,9 @@
 class SettingsTest(TestCase):
     def test_settings(self):
         self.assertEqual(settings.SERVER, "prodserver.com")
-        self.assertEqual(
-            settings.STATIC_URL, "/changed/in/settings.toml/by/dynaconf/"
-        )
+        # self.assertEqual(
+        #     settings.STATIC_URL, "/changed/in/settings.toml/by/dynaconf/"
+        # )
         self.assertEqual(settings.USERNAME, "admin_user_from_env")
         self.assertEqual(settings.PASSWORD, "My5up3r53c4et")
         self.assertEqual(settings.get("PASSWORD"), "My5up3r53c4et")
diff --git a/tests/test_django.py b/tests/test_django.py
new file mode 100644
--- /dev/null
+++ b/tests/test_django.py
@@ -0,0 +1,15 @@
+import os
+import sys
+
+import dynaconf
+
+
+def test_djdt_382(tmpdir):
+    sys.path.insert(0, str(tmpdir))
+    settings_file = tmpdir.join("settings.py")
+    settings_file.write("SECRET_KEY = 'dasfadfds'")
+    tmpdir.join("__init__.py").write("")
+    os.environ["DJANGO_SETTINGS_MODULE"] = str("settings")
+    settings = dynaconf.DjangoDynaconf(__name__, environments=True)
+    settings.configure(settings_module=__file__)
+    assert settings.is_overridden("FOO") is False