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.
django.setup()
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.
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`
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
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
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
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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._os import upath
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'))
@ -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')]"))
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):
"""Tests for 2-stage argument parsing scheme.