From 6feb75129f42fdac751d0b79a2a005b4c0ad5c2d Mon Sep 17 00:00:00 2001 From: Juan Catalano Date: Fri, 6 Sep 2013 20:23:25 -0300 Subject: Fixed #21060 -- Refactored admin's autodiscover method to make it reusable. We want to be able to use it for instance for discovering `tasks.py` modules inside the INSTALLED_APPS. This commit therefore moves the logic to `autodiscover_modules` method in django.utils.module_loading. --- django/utils/module_loading.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'django/utils/module_loading.py') diff --git a/django/utils/module_loading.py b/django/utils/module_loading.py index 9c8ea98d50..8868a2d3ab 100644 --- a/django/utils/module_loading.py +++ b/django/utils/module_loading.py @@ -1,5 +1,6 @@ from __future__ import absolute_import # Avoid importing `importlib` from this package. +import copy import imp from importlib import import_module import os @@ -34,6 +35,43 @@ def import_by_path(dotted_path, error_prefix=''): return attr +def autodiscover_modules(*args, **kwargs): + """ + Auto-discover INSTALLED_APPS modules and fail silently when + not present. This forces an import on them to register any admin bits they + may want. + + You may provide a register_to keyword parameter as a way to access a + registry. This register_to object must have a _registry instance variable + to access it. + """ + from django.conf import settings + + register_to = kwargs.get('register_to') + for app in settings.INSTALLED_APPS: + mod = import_module(app) + # Attempt to import the app's module. + try: + if register_to: + before_import_registry = copy.copy(register_to._registry) + + for module_to_search in args: + import_module('%s.%s' % (app, module_to_search)) + except: + # Reset the model registry to the state before the last import as + # this import will have to reoccur on the next request and this + # could raise NotRegistered and AlreadyRegistered exceptions + # (see #8245). + if register_to: + register_to._registry = before_import_registry + + # Decide whether to bubble up this error. If the app just + # doesn't have an admin module, we can ignore the error + # attempting to import it, otherwise we want it to bubble up. + if module_has_submodule(mod, module_to_search): + raise + + def module_has_submodule(package, module_name): """See if 'module' is in 'package'.""" name = ".".join([package.__name__, module_name]) -- cgit v1.3