Fixed #21018 -- Reversed precedence order for management commands.

This commit is contained in:
Aymeric Augustin 2014-01-01 18:05:12 +01:00
parent f17d00278e
commit 0ce945a671
10 changed files with 50 additions and 2 deletions

View File

@ -120,7 +120,7 @@ def get_commands():
# a settings module. # a settings module.
django.setup() django.setup()
app_configs = apps.get_app_configs() app_configs = apps.get_app_configs()
app_names = [app_config.name for app_config in app_configs] app_names = [app_config.name for app_config in reversed(app_configs)]
# Find and load the management module for each installed app. # Find and load the management module for each installed app.
for app_name in app_names: for app_name in app_names:

View File

@ -1319,6 +1319,10 @@ Django installation. Each string should be a dotted Python path to:
These rules apply regardless of whether :setting:`INSTALLED_APPS` These rules apply regardless of whether :setting:`INSTALLED_APPS`
references application configuration classes on application packages. references application configuration classes on application packages.
When several applications provide different versions of the same resource
(template, static file, management command, translation), the application
listed first in :setting:`INSTALLED_APPS` has precedence.
.. setting:: INTERNAL_IPS .. setting:: INTERNAL_IPS
INTERNAL_IPS INTERNAL_IPS

View File

@ -697,6 +697,18 @@ following changes that take effect immediately:
* The ``only_installed`` argument of ``get_model`` and ``get_models`` no * The ``only_installed`` argument of ``get_model`` and ``get_models`` no
longer exists, nor does the ``seed_cache`` argument of ``get_model``. longer exists, nor does the ``seed_cache`` argument of ``get_model``.
Management commands and order of :setting:`INSTALLED_APPS`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When several applications provide management commands with the same name,
Django loads the command from the application that comes first in
:setting:`INSTALLED_APPS`. Previous versions loaded the command from the
applicatino that came last.
This brings discovery of management commands in line with other parts of
Django that rely on the order of :setting:`INSTALLED_APPS`, such as static
files, templates, and translations.
Behavior of ``LocMemCache`` regarding pickle errors Behavior of ``LocMemCache`` regarding pickle errors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,7 @@
from django.core.management.base import NoArgsCommand
class Command(NoArgsCommand):
def handle_noargs(self, **options):
self.stdout.write('complex_app')

View File

@ -0,0 +1,7 @@
from django.core.management.base import NoArgsCommand
class Command(NoArgsCommand):
def handle_noargs(self, **options):
self.stdout.write('simple_app')

View File

@ -25,7 +25,7 @@ from django.test.utils import str_prefix
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils._os import upath from django.utils._os import upath
from django.utils.six import StringIO from django.utils.six import StringIO
from django.test import LiveServerTestCase from django.test import LiveServerTestCase, TestCase
test_dir = os.path.realpath(os.path.join(os.environ['DJANGO_TEST_TEMP_DIR'], 'test_project')) test_dir = os.path.realpath(os.path.join(os.environ['DJANGO_TEST_TEMP_DIR'], 'test_project'))
@ -1469,6 +1469,24 @@ class CommandTypes(AdminScriptTestCase):
self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]")) self.assertOutput(out, str_prefix("EXECUTE:LabelCommand label=anotherlabel, options=[('no_color', False), ('pythonpath', None), ('settings', None), ('traceback', None), ('verbosity', %(_)s'1')]"))
class Discovery(TestCase):
def test_precedence(self):
"""
Apps listed first in INSTALLED_APPS have precendence.
"""
with self.settings(INSTALLED_APPS=['admin_scripts.complex_app',
'admin_scripts.simple_app']):
out = StringIO()
call_command('duplicate', stdout=out)
self.assertEqual(out.getvalue().strip(), 'complex_app')
with self.settings(INSTALLED_APPS=['admin_scripts.simple_app',
'admin_scripts.complex_app']):
out = StringIO()
call_command('duplicate', stdout=out)
self.assertEqual(out.getvalue().strip(), 'simple_app')
class ArgumentOrder(AdminScriptTestCase): class ArgumentOrder(AdminScriptTestCase):
"""Tests for 2-stage argument parsing scheme. """Tests for 2-stage argument parsing scheme.