diff --git a/django/apps/registry.py b/django/apps/registry.py index 649ba42d78..7cf5a2637b 100644 --- a/django/apps/registry.py +++ b/django/apps/registry.py @@ -170,16 +170,22 @@ class Apps(object): include_auto_created, include_deferred, include_swapped))) return result - def get_model(self, app_label, model_name): + def get_model(self, app_label, model_name=None): """ Returns the model matching the given app_label and model_name. + As a shortcut, this function also accepts a single argument in the + form .. + model_name is case-insensitive. Raises LookupError if no application exists with this label, or no - model exists with this name in the application. + model exists with this name in the application. Raises ValueError if + called with a single argument that doesn't contain exactly one dot. """ self.check_ready() + if model_name is None: + app_label, model_name = app_label.split('.') return self.get_app_config(app_label).get_model(model_name.lower()) def register_model(self, app_label, model): diff --git a/docs/ref/applications.txt b/docs/ref/applications.txt index 2eff15d708..df105f1237 100644 --- a/docs/ref/applications.txt +++ b/docs/ref/applications.txt @@ -274,5 +274,10 @@ Application registry .. method:: apps.get_model(app_label, model_name) Returns the :class:`~django.db.models.Model` with the given ``app_label`` - and ``model_name``. Raises :exc:`~exceptions.LookupError` if no such - application or model exists. ``model_name`` is case-insensitive. + and ``model_name``. As a shortcut, this method also accepts a single + argument in the form ``app_label.model_name``. ``model_name`` is case- + insensitive. + + Raises :exc:`~exceptions.LookupError` if no such application or model + exists. Raises :exc:`~exceptions.ValueError` when called with a single + argument that doesn't contain exactly one dot. diff --git a/tests/apps/tests.py b/tests/apps/tests.py index 6a345760ee..5ad4ef0b72 100644 --- a/tests/apps/tests.py +++ b/tests/apps/tests.py @@ -6,6 +6,7 @@ from unittest import skipUnless from django.apps import apps from django.apps.registry import Apps +from django.contrib.admin.models import LogEntry from django.core.exceptions import ImproperlyConfigured from django.db import models from django.test import TestCase, override_settings @@ -99,7 +100,7 @@ class AppsTests(TestCase): @override_settings(INSTALLED_APPS=SOME_INSTALLED_APPS) def test_get_app_configs(self): """ - Tests get_app_configs(). + Tests apps.get_app_configs(). """ app_configs = apps.get_app_configs() self.assertListEqual( @@ -109,7 +110,7 @@ class AppsTests(TestCase): @override_settings(INSTALLED_APPS=SOME_INSTALLED_APPS) def test_get_app_config(self): """ - Tests get_app_config(). + Tests apps.get_app_config(). """ app_config = apps.get_app_config('admin') self.assertEqual(app_config.name, 'django.contrib.admin') @@ -122,11 +123,35 @@ class AppsTests(TestCase): @override_settings(INSTALLED_APPS=SOME_INSTALLED_APPS) def test_is_installed(self): + """ + Tests apps.is_installed(). + """ self.assertTrue(apps.is_installed('django.contrib.admin')) self.assertTrue(apps.is_installed('django.contrib.auth')) self.assertTrue(apps.is_installed('django.contrib.staticfiles')) self.assertFalse(apps.is_installed('django.contrib.webdesign')) + @override_settings(INSTALLED_APPS=SOME_INSTALLED_APPS) + def test_get_model(self): + """ + Tests apps.get_model(). + """ + self.assertEqual(apps.get_model('admin', 'LogEntry'), LogEntry) + with self.assertRaises(LookupError): + apps.get_model('admin', 'LogExit') + + # App label is case-sensitive, Model name is case-insensitive. + self.assertEqual(apps.get_model('admin', 'loGentrY'), LogEntry) + with self.assertRaises(LookupError): + apps.get_model('Admin', 'LogEntry') + + # A single argument is accepted. + self.assertEqual(apps.get_model('admin.LogEntry'), LogEntry) + with self.assertRaises(LookupError): + apps.get_model('admin.LogExit') + with self.assertRaises(ValueError): + apps.get_model('admin_LogEntry') + @override_settings(INSTALLED_APPS=['apps.apps.RelabeledAppsConfig']) def test_relabeling(self): self.assertEqual(apps.get_app_config('relabeled').name, 'apps')