Loading django/contrib/auth/management/__init__.py +16 −11 Original line number Diff line number Diff line Loading @@ -60,18 +60,21 @@ def _check_permission_clashing(custom, builtin, ctype): pool.add(codename) def create_permissions(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kwargs): def create_permissions(app_config, verbosity=22, interactive=True, db=DEFAULT_DB_ALIAS, **kwargs): if not app_config.models_module: return try: apps.get_model('auth', 'Permission') Permission = apps.get_model('auth', 'Permission') except LookupError: return if not router.allow_migrate(db, auth_app.Permission): if not router.allow_migrate(db, Permission): return from django.contrib.contenttypes.models import ContentType app_models = apps.get_models(app) app_models = apps.get_models(app_config.models_module) # This will hold the permissions we're looking for as # (content_type, (codename, name)) Loading @@ -89,20 +92,20 @@ def create_permissions(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kw # Find all the Permissions that have a content_type for a model we're # looking for. We don't need to check for codenames since we already have # a list of the ones we're going to create. all_perms = set(auth_app.Permission.objects.using(db).filter( all_perms = set(Permission.objects.using(db).filter( content_type__in=ctypes, ).values_list( "content_type", "codename" )) perms = [ auth_app.Permission(codename=codename, name=name, content_type=ctype) Permission(codename=codename, name=name, content_type=ctype) for ctype, (codename, name) in searched_perms if (ctype.pk, codename) not in all_perms ] # Validate the permissions before bulk_creation to avoid cryptic # database error when the verbose_name is longer than 50 characters permission_name_max_length = auth_app.Permission._meta.get_field('name').max_length permission_name_max_length = Permission._meta.get_field('name').max_length verbose_name_max_length = permission_name_max_length - 11 # len('Can change ') prefix for perm in perms: if len(perm.name) > permission_name_max_length: Loading @@ -112,13 +115,13 @@ def create_permissions(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kw verbose_name_max_length, ) ) auth_app.Permission.objects.using(db).bulk_create(perms) Permission.objects.using(db).bulk_create(perms) if verbosity >= 2: for perm in perms: print("Adding permission '%s'" % perm) def create_superuser(app, created_models, verbosity, db, **kwargs): def create_superuser(app_config, verbosity=22, interactive=True, db=DEFAULT_DB_ALIAS, **kwargs): try: apps.get_model('auth', 'Permission') except LookupError: Loading @@ -128,7 +131,7 @@ def create_superuser(app, created_models, verbosity, db, **kwargs): from django.core.management import call_command if UserModel in created_models and kwargs.get('interactive', True): if not UserModel.objects.exists() and interactive: msg = ("\nYou just installed Django's auth system, which means you " "don't have any superusers defined.\nWould you like to create one " "now? (yes/no): ") Loading Loading @@ -203,7 +206,9 @@ def get_default_username(check_db=True): return '' return default_username signals.post_migrate.connect(create_permissions, dispatch_uid="django.contrib.auth.management.create_permissions") signals.post_migrate.connect(create_superuser, sender=auth_app, dispatch_uid="django.contrib.auth.management.create_superuser") sender=apps.get_app_config('auth'), dispatch_uid="django.contrib.auth.management.create_superuser") django/contrib/auth/tests/test_management.py +12 −6 Original line number Diff line number Diff line Loading @@ -232,13 +232,15 @@ class PermissionTestCase(TestCase): Test that we show proper error message if we are trying to create duplicate permissions. """ auth_app_config = apps.get_app_config('auth') # check duplicated default permission models.Permission._meta.permissions = [ ('change_permission', 'Can edit permission (duplicate)')] six.assertRaisesRegex(self, CommandError, "The permission codename 'change_permission' clashes with a " "builtin permission for model 'auth.Permission'.", create_permissions, models, [], verbosity=0) create_permissions, auth_app_config, verbosity=0) # check duplicated custom permissions models.Permission._meta.permissions = [ Loading @@ -249,21 +251,23 @@ class PermissionTestCase(TestCase): six.assertRaisesRegex(self, CommandError, "The permission codename 'my_custom_permission' is duplicated for model " "'auth.Permission'.", create_permissions, models, [], verbosity=0) create_permissions, auth_app_config, verbosity=0) # should not raise anything models.Permission._meta.permissions = [ ('my_custom_permission', 'Some permission'), ('other_one', 'Some other permission'), ] create_permissions(models, [], verbosity=0) create_permissions(auth_app_config, verbosity=0) def test_default_permissions(self): auth_app_config = apps.get_app_config('auth') permission_content_type = ContentType.objects.get_by_natural_key('auth', 'permission') models.Permission._meta.permissions = [ ('my_custom_permission', 'Some permission'), ] create_permissions(models, [], verbosity=0) create_permissions(auth_app_config, verbosity=0) # add/change/delete permission by default + custom permission self.assertEqual(models.Permission.objects.filter( Loading @@ -272,7 +276,7 @@ class PermissionTestCase(TestCase): models.Permission.objects.filter(content_type=permission_content_type).delete() models.Permission._meta.default_permissions = [] create_permissions(models, [], verbosity=0) create_permissions(auth_app_config, verbosity=0) # custom permission only since default permissions is empty self.assertEqual(models.Permission.objects.filter( Loading @@ -280,10 +284,12 @@ class PermissionTestCase(TestCase): ).count(), 1) def test_verbose_name_length(self): auth_app_config = apps.get_app_config('auth') permission_content_type = ContentType.objects.get_by_natural_key('auth', 'permission') models.Permission.objects.filter(content_type=permission_content_type).delete() models.Permission._meta.verbose_name = "some ridiculously long verbose name that is out of control" six.assertRaisesRegex(self, exceptions.ValidationError, "The verbose_name of permission is longer than 39 characters", create_permissions, models, [], verbosity=0) create_permissions, auth_app_config, verbosity=0) django/contrib/contenttypes/management.py +10 −6 Original line number Diff line number Diff line from django.apps import apps from django.contrib.contenttypes.models import ContentType from django.db import DEFAULT_DB_ALIAS, router from django.db.models import signals from django.utils.encoding import smart_text Loading @@ -7,13 +6,16 @@ from django.utils import six from django.utils.six.moves import input def update_contenttypes(app, created_models, verbosity=2, db=DEFAULT_DB_ALIAS, **kwargs): def update_contenttypes(app_config, verbosity=2, interactive=True, db=DEFAULT_DB_ALIAS, **kwargs): """ Creates content types for models in the given app, removing any model entries that no longer have a matching model class. """ if not app_config.models_module: return try: apps.get_model('contenttypes', 'ContentType') ContentType = apps.get_model('contenttypes', 'ContentType') except LookupError: return Loading @@ -21,7 +23,7 @@ def update_contenttypes(app, created_models, verbosity=2, db=DEFAULT_DB_ALIAS, * return ContentType.objects.clear_cache() app_models = apps.get_models(app) app_models = apps.get_models(app_config.models_module) if not app_models: return # They all have the same app_label, get the first one. Loading Loading @@ -85,11 +87,13 @@ If you're unsure, answer 'no'. print("Stale content types remain.") def update_all_contenttypes(verbosity=2, **kwargs): def update_all_contenttypes(**kwargs): for app_config in apps.get_app_configs(only_with_models_module=True): update_contenttypes(app_config.models_module, None, verbosity, **kwargs) update_contenttypes(app_config, **kwargs) signals.post_migrate.connect(update_contenttypes) if __name__ == "__main__": update_all_contenttypes() django/contrib/sites/management.py +16 −10 Original line number Diff line number Diff line Loading @@ -2,17 +2,22 @@ Creates the default Site object. """ from django.db.models import signals from django.db import connections from django.db import router from django.contrib.sites.models import Site from django.contrib.sites import models as site_app from django.apps import apps from django.core.management.color import no_style from django.db import DEFAULT_DB_ALIAS, connections, router from django.db.models import signals def create_default_site(app_config, verbosity=22, interactive=True, db=DEFAULT_DB_ALIAS, **kwargs): try: Site = apps.get_model('sites', 'Site') except LookupError: return def create_default_site(app, created_models, verbosity, db, **kwargs): # Only create the default sites in databases where Django created the table if Site in created_models and router.allow_migrate(db, Site): if not router.allow_migrate(db, Site): return if not Site.objects.exists(): # The default settings set SITE_ID = 1, and some tests in Django's test # suite rely on this value. However, if database sequences are reused # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that Loading @@ -34,4 +39,5 @@ def create_default_site(app, created_models, verbosity, db, **kwargs): Site.objects.clear_cache() signals.post_migrate.connect(create_default_site, sender=site_app) signals.post_migrate.connect(create_default_site, sender=apps.get_app_config('sites')) django/core/management/sql.py +14 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,13 @@ def emit_pre_migrate_signal(create_models, verbosity, interactive, db): if verbosity >= 2: print("Running pre-migrate handlers for application %s" % app_config.label) models.signals.pre_migrate.send( sender=app_config, app_config=app_config, verbosity=verbosity, interactive=interactive, db=db) # For backwards-compatibility -- remove in Django 1.9. models.signals.pre_syncdb.send( sender=app_config.models_module, app=app_config.models_module, create_models=create_models, Loading @@ -225,6 +232,13 @@ def emit_post_migrate_signal(created_models, verbosity, interactive, db): if verbosity >= 2: print("Running post-migrate handlers for application %s" % app_config.label) models.signals.post_migrate.send( sender=app_config, app_config=app_config, verbosity=verbosity, interactive=interactive, db=db) # For backwards-compatibility -- remove in Django 1.9. models.signals.post_syncdb.send( sender=app_config.models_module, app=app_config.models_module, created_models=created_models, Loading Loading
django/contrib/auth/management/__init__.py +16 −11 Original line number Diff line number Diff line Loading @@ -60,18 +60,21 @@ def _check_permission_clashing(custom, builtin, ctype): pool.add(codename) def create_permissions(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kwargs): def create_permissions(app_config, verbosity=22, interactive=True, db=DEFAULT_DB_ALIAS, **kwargs): if not app_config.models_module: return try: apps.get_model('auth', 'Permission') Permission = apps.get_model('auth', 'Permission') except LookupError: return if not router.allow_migrate(db, auth_app.Permission): if not router.allow_migrate(db, Permission): return from django.contrib.contenttypes.models import ContentType app_models = apps.get_models(app) app_models = apps.get_models(app_config.models_module) # This will hold the permissions we're looking for as # (content_type, (codename, name)) Loading @@ -89,20 +92,20 @@ def create_permissions(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kw # Find all the Permissions that have a content_type for a model we're # looking for. We don't need to check for codenames since we already have # a list of the ones we're going to create. all_perms = set(auth_app.Permission.objects.using(db).filter( all_perms = set(Permission.objects.using(db).filter( content_type__in=ctypes, ).values_list( "content_type", "codename" )) perms = [ auth_app.Permission(codename=codename, name=name, content_type=ctype) Permission(codename=codename, name=name, content_type=ctype) for ctype, (codename, name) in searched_perms if (ctype.pk, codename) not in all_perms ] # Validate the permissions before bulk_creation to avoid cryptic # database error when the verbose_name is longer than 50 characters permission_name_max_length = auth_app.Permission._meta.get_field('name').max_length permission_name_max_length = Permission._meta.get_field('name').max_length verbose_name_max_length = permission_name_max_length - 11 # len('Can change ') prefix for perm in perms: if len(perm.name) > permission_name_max_length: Loading @@ -112,13 +115,13 @@ def create_permissions(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kw verbose_name_max_length, ) ) auth_app.Permission.objects.using(db).bulk_create(perms) Permission.objects.using(db).bulk_create(perms) if verbosity >= 2: for perm in perms: print("Adding permission '%s'" % perm) def create_superuser(app, created_models, verbosity, db, **kwargs): def create_superuser(app_config, verbosity=22, interactive=True, db=DEFAULT_DB_ALIAS, **kwargs): try: apps.get_model('auth', 'Permission') except LookupError: Loading @@ -128,7 +131,7 @@ def create_superuser(app, created_models, verbosity, db, **kwargs): from django.core.management import call_command if UserModel in created_models and kwargs.get('interactive', True): if not UserModel.objects.exists() and interactive: msg = ("\nYou just installed Django's auth system, which means you " "don't have any superusers defined.\nWould you like to create one " "now? (yes/no): ") Loading Loading @@ -203,7 +206,9 @@ def get_default_username(check_db=True): return '' return default_username signals.post_migrate.connect(create_permissions, dispatch_uid="django.contrib.auth.management.create_permissions") signals.post_migrate.connect(create_superuser, sender=auth_app, dispatch_uid="django.contrib.auth.management.create_superuser") sender=apps.get_app_config('auth'), dispatch_uid="django.contrib.auth.management.create_superuser")
django/contrib/auth/tests/test_management.py +12 −6 Original line number Diff line number Diff line Loading @@ -232,13 +232,15 @@ class PermissionTestCase(TestCase): Test that we show proper error message if we are trying to create duplicate permissions. """ auth_app_config = apps.get_app_config('auth') # check duplicated default permission models.Permission._meta.permissions = [ ('change_permission', 'Can edit permission (duplicate)')] six.assertRaisesRegex(self, CommandError, "The permission codename 'change_permission' clashes with a " "builtin permission for model 'auth.Permission'.", create_permissions, models, [], verbosity=0) create_permissions, auth_app_config, verbosity=0) # check duplicated custom permissions models.Permission._meta.permissions = [ Loading @@ -249,21 +251,23 @@ class PermissionTestCase(TestCase): six.assertRaisesRegex(self, CommandError, "The permission codename 'my_custom_permission' is duplicated for model " "'auth.Permission'.", create_permissions, models, [], verbosity=0) create_permissions, auth_app_config, verbosity=0) # should not raise anything models.Permission._meta.permissions = [ ('my_custom_permission', 'Some permission'), ('other_one', 'Some other permission'), ] create_permissions(models, [], verbosity=0) create_permissions(auth_app_config, verbosity=0) def test_default_permissions(self): auth_app_config = apps.get_app_config('auth') permission_content_type = ContentType.objects.get_by_natural_key('auth', 'permission') models.Permission._meta.permissions = [ ('my_custom_permission', 'Some permission'), ] create_permissions(models, [], verbosity=0) create_permissions(auth_app_config, verbosity=0) # add/change/delete permission by default + custom permission self.assertEqual(models.Permission.objects.filter( Loading @@ -272,7 +276,7 @@ class PermissionTestCase(TestCase): models.Permission.objects.filter(content_type=permission_content_type).delete() models.Permission._meta.default_permissions = [] create_permissions(models, [], verbosity=0) create_permissions(auth_app_config, verbosity=0) # custom permission only since default permissions is empty self.assertEqual(models.Permission.objects.filter( Loading @@ -280,10 +284,12 @@ class PermissionTestCase(TestCase): ).count(), 1) def test_verbose_name_length(self): auth_app_config = apps.get_app_config('auth') permission_content_type = ContentType.objects.get_by_natural_key('auth', 'permission') models.Permission.objects.filter(content_type=permission_content_type).delete() models.Permission._meta.verbose_name = "some ridiculously long verbose name that is out of control" six.assertRaisesRegex(self, exceptions.ValidationError, "The verbose_name of permission is longer than 39 characters", create_permissions, models, [], verbosity=0) create_permissions, auth_app_config, verbosity=0)
django/contrib/contenttypes/management.py +10 −6 Original line number Diff line number Diff line from django.apps import apps from django.contrib.contenttypes.models import ContentType from django.db import DEFAULT_DB_ALIAS, router from django.db.models import signals from django.utils.encoding import smart_text Loading @@ -7,13 +6,16 @@ from django.utils import six from django.utils.six.moves import input def update_contenttypes(app, created_models, verbosity=2, db=DEFAULT_DB_ALIAS, **kwargs): def update_contenttypes(app_config, verbosity=2, interactive=True, db=DEFAULT_DB_ALIAS, **kwargs): """ Creates content types for models in the given app, removing any model entries that no longer have a matching model class. """ if not app_config.models_module: return try: apps.get_model('contenttypes', 'ContentType') ContentType = apps.get_model('contenttypes', 'ContentType') except LookupError: return Loading @@ -21,7 +23,7 @@ def update_contenttypes(app, created_models, verbosity=2, db=DEFAULT_DB_ALIAS, * return ContentType.objects.clear_cache() app_models = apps.get_models(app) app_models = apps.get_models(app_config.models_module) if not app_models: return # They all have the same app_label, get the first one. Loading Loading @@ -85,11 +87,13 @@ If you're unsure, answer 'no'. print("Stale content types remain.") def update_all_contenttypes(verbosity=2, **kwargs): def update_all_contenttypes(**kwargs): for app_config in apps.get_app_configs(only_with_models_module=True): update_contenttypes(app_config.models_module, None, verbosity, **kwargs) update_contenttypes(app_config, **kwargs) signals.post_migrate.connect(update_contenttypes) if __name__ == "__main__": update_all_contenttypes()
django/contrib/sites/management.py +16 −10 Original line number Diff line number Diff line Loading @@ -2,17 +2,22 @@ Creates the default Site object. """ from django.db.models import signals from django.db import connections from django.db import router from django.contrib.sites.models import Site from django.contrib.sites import models as site_app from django.apps import apps from django.core.management.color import no_style from django.db import DEFAULT_DB_ALIAS, connections, router from django.db.models import signals def create_default_site(app_config, verbosity=22, interactive=True, db=DEFAULT_DB_ALIAS, **kwargs): try: Site = apps.get_model('sites', 'Site') except LookupError: return def create_default_site(app, created_models, verbosity, db, **kwargs): # Only create the default sites in databases where Django created the table if Site in created_models and router.allow_migrate(db, Site): if not router.allow_migrate(db, Site): return if not Site.objects.exists(): # The default settings set SITE_ID = 1, and some tests in Django's test # suite rely on this value. However, if database sequences are reused # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that Loading @@ -34,4 +39,5 @@ def create_default_site(app, created_models, verbosity, db, **kwargs): Site.objects.clear_cache() signals.post_migrate.connect(create_default_site, sender=site_app) signals.post_migrate.connect(create_default_site, sender=apps.get_app_config('sites'))
django/core/management/sql.py +14 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,13 @@ def emit_pre_migrate_signal(create_models, verbosity, interactive, db): if verbosity >= 2: print("Running pre-migrate handlers for application %s" % app_config.label) models.signals.pre_migrate.send( sender=app_config, app_config=app_config, verbosity=verbosity, interactive=interactive, db=db) # For backwards-compatibility -- remove in Django 1.9. models.signals.pre_syncdb.send( sender=app_config.models_module, app=app_config.models_module, create_models=create_models, Loading @@ -225,6 +232,13 @@ def emit_post_migrate_signal(created_models, verbosity, interactive, db): if verbosity >= 2: print("Running post-migrate handlers for application %s" % app_config.label) models.signals.post_migrate.send( sender=app_config, app_config=app_config, verbosity=verbosity, interactive=interactive, db=db) # For backwards-compatibility -- remove in Django 1.9. models.signals.post_syncdb.send( sender=app_config.models_module, app=app_config.models_module, created_models=created_models, Loading