From 9af56803f53a4e41bb826d4e293ef8650ad9f13a Mon Sep 17 00:00:00 2001 From: Gary Wilson Jr Date: Tue, 23 Dec 2008 18:25:24 +0000 Subject: [PATCH] Fixed #8245 -- Added a LOADING flag to autodiscover to prevent an admin.py module with errors from raising a spurious AlreadyRegistered exception in a subsequent call to autodiscover. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9680 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/admin/__init__.py | 18 +++++++++++++++++- tests/regressiontests/bug8245/__init__.py | 0 tests/regressiontests/bug8245/admin.py | 7 +++++++ tests/regressiontests/bug8245/models.py | 4 ++++ tests/regressiontests/bug8245/tests.py | 23 +++++++++++++++++++++++ 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/regressiontests/bug8245/__init__.py create mode 100644 tests/regressiontests/bug8245/admin.py create mode 100644 tests/regressiontests/bug8245/models.py create mode 100644 tests/regressiontests/bug8245/tests.py diff --git a/django/contrib/admin/__init__.py b/django/contrib/admin/__init__.py index 8396ffc6b38..bb856a1241f 100644 --- a/django/contrib/admin/__init__.py +++ b/django/contrib/admin/__init__.py @@ -2,12 +2,26 @@ from django.contrib.admin.options import ModelAdmin, HORIZONTAL, VERTICAL from django.contrib.admin.options import StackedInline, TabularInline from django.contrib.admin.sites import AdminSite, site +# A flag to tell us if autodiscover is running. autodiscover will set this to +# True while running, and False when it finishes. +LOADING = False + def autodiscover(): """ - Auto-discover INSTALLED_APPS admin.py modules and fail silently when + Auto-discover INSTALLED_APPS admin.py modules and fail silently when not present. This forces an import on them to register any admin bits they may want. """ + # Bail out if autodiscover didn't finish loading from a previous call so + # that we avoid running autodiscover again when the URLConf is loaded by + # the exception handler to resolve the handler500 view. This prevents an + # admin.py module with errors from re-registering models and raising a + # spurious AlreadyRegistered exception (see #8245). + global LOADING + if LOADING: + return + LOADING = True + import imp from django.conf import settings @@ -38,3 +52,5 @@ def autodiscover(): # Step 3: import the app's admin file. If this has errors we want them # to bubble up. __import__("%s.admin" % app) + # autodiscover was successful, reset loading flag. + LOADING = False diff --git a/tests/regressiontests/bug8245/__init__.py b/tests/regressiontests/bug8245/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/regressiontests/bug8245/admin.py b/tests/regressiontests/bug8245/admin.py new file mode 100644 index 00000000000..18122696b68 --- /dev/null +++ b/tests/regressiontests/bug8245/admin.py @@ -0,0 +1,7 @@ +from django.contrib import admin + +from models import Story + + +admin.site.register(Story) +raise Exception("Bad admin module") diff --git a/tests/regressiontests/bug8245/models.py b/tests/regressiontests/bug8245/models.py new file mode 100644 index 00000000000..5643955df34 --- /dev/null +++ b/tests/regressiontests/bug8245/models.py @@ -0,0 +1,4 @@ +from django.db import models + +class Story(models.Model): + title = models.CharField(max_length=10) diff --git a/tests/regressiontests/bug8245/tests.py b/tests/regressiontests/bug8245/tests.py new file mode 100644 index 00000000000..c1cc3b595c5 --- /dev/null +++ b/tests/regressiontests/bug8245/tests.py @@ -0,0 +1,23 @@ +from unittest import TestCase + +from django.contrib import admin + + +class Bug8245Test(TestCase): + """ + Test for bug #8245 - don't raise an AlreadyRegistered exception when using + autodiscover() and an admin.py module contains an error. + """ + + def test_bug_8245(self): + # The first time autodiscover is called, we should get our real error. + try: + admin.autodiscover() + except Exception, e: + self.failUnlessEqual(str(e), "Bad admin module") + else: + self.fail( + 'autodiscover should have raised a "Bad admin module" error.') + # Calling autodiscover again should bail out early and not raise an + # AlreadyRegistered error. + admin.autodiscover()