def update_contenttypes(app_config, verbosity=2, interactive=True, using=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. """ # TODO: Remove when migration plan / state is passed (#24100). if not is_latest_migration_applied('contenttypes'): return if not app_config.models_module: return try: ContentType = apps.get_model('contenttypes', 'ContentType') except LookupError: return if not router.allow_migrate(using, ContentType): return ContentType.objects.clear_cache() app_label = app_config.label app_models = dict( (model._meta.model_name, model) for model in app_config.get_models()) if not app_models: return # Get all the content types content_types = dict( (ct.model, ct) for ct in ContentType.objects.using(using).filter(app_label=app_label) ) to_remove = [ ct for (model_name, ct) in six.iteritems(content_types) if model_name not in app_models ] cts = [ ContentType( name=smart_text(model._meta.verbose_name_raw), app_label=app_label, model=model_name, ) for (model_name, model) in six.iteritems(app_models) if model_name not in content_types ] ContentType.objects.using(using).bulk_create(cts) if verbosity >= 2: for ct in cts: print("Adding content type '%s | %s'" % (ct.app_label, ct.model)) # Confirm that the content type is stale before deletion. if to_remove: if interactive: content_type_display = '\n'.join( ' %s | %s' % (ct.app_label, ct.model) for ct in to_remove ) ok_to_delete = input("""The following content types are stale and need to be deleted: %s Any objects related to these content types by a foreign key will also be deleted. Are you sure you want to delete these content types? If you're unsure, answer 'no'. Type 'yes' to continue, or 'no' to cancel: """ % content_type_display) else: ok_to_delete = False if ok_to_delete == 'yes': for ct in to_remove: if verbosity >= 2: print("Deleting stale content type '%s | %s'" % (ct.app_label, ct.model)) ct.delete() else: if verbosity >= 2: print("Stale content types remain.")
def create_permissions(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): # TODO: Remove when migration plan / state is passed (#24100). if not is_latest_migration_applied('auth'): return if not app_config.models_module: return try: Permission = apps.get_model('auth', 'Permission') except LookupError: return if not router.allow_migrate(using, Permission): return from django.contrib.contenttypes.models import ContentType # This will hold the permissions we're looking for as # (content_type, (codename, name)) searched_perms = list() # The codenames and ctypes that should exist. ctypes = set() for klass in app_config.get_models(): # Force looking up the content types in the current database # before creating foreign keys to them. ctype = ContentType.objects.db_manager(using).get_for_model(klass) ctypes.add(ctype) for perm in _get_all_permissions(klass._meta, ctype): searched_perms.append((ctype, perm)) # 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(Permission.objects.using(using).filter( content_type__in=ctypes, ).values_list( "content_type", "codename" )) perms = [ Permission(codename=codename, name=name, content_type=ct) for ct, (codename, name) in searched_perms if (ct.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 = 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: raise exceptions.ValidationError( "The verbose_name of %s.%s is longer than %s characters" % ( perm.content_type.app_label, perm.content_type.model, verbose_name_max_length, ) ) Permission.objects.using(using).bulk_create(perms) if verbosity >= 2: for perm in perms: print("Adding permission '%s'" % perm)
def create_permissions(app_config, verbosity=2, interactive=True, using=DEFAULT_DB_ALIAS, **kwargs): # TODO: Remove when migration plan / state is passed (#24100). if not is_latest_migration_applied('auth'): return if not app_config.models_module: return try: Permission = apps.get_model('auth', 'Permission') except LookupError: return if not router.allow_migrate(using, Permission): return from django.contrib.contenttypes.models import ContentType # This will hold the permissions we're looking for as # (content_type, (codename, name)) searched_perms = list() # The codenames and ctypes that should exist. ctypes = set() for klass in app_config.get_models(): # Force looking up the content types in the current database # before creating foreign keys to them. ctype = ContentType.objects.db_manager(using).get_for_model(klass) ctypes.add(ctype) for perm in _get_all_permissions(klass._meta, ctype): searched_perms.append((ctype, perm)) # 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( Permission.objects.using(using).filter( content_type__in=ctypes, ).values_list("content_type", "codename")) perms = [ Permission(codename=codename, name=name, content_type=ct) for ct, (codename, name) in searched_perms if (ct.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 = 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: raise exceptions.ValidationError( "The verbose_name of %s is longer than %s characters" % ( perm.content_type, verbose_name_max_length, )) Permission.objects.using(using).bulk_create(perms) if verbosity >= 2: for perm in perms: print("Adding permission '%s'" % perm)
def update_contenttypes(app_config, verbosity=2, interactive=True, using=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. """ # TODO: Remove when migration plan / state is passed (#24100). if not is_latest_migration_applied('contenttypes'): return if not app_config.models_module: return try: ContentType = apps.get_model('contenttypes', 'ContentType') except LookupError: return if not router.allow_migrate(using, ContentType): return ContentType.objects.clear_cache() app_label = app_config.label app_models = { model._meta.model_name: model for model in app_config.get_models() } if not app_models: return # Get all the content types content_types = { ct.model: ct for ct in ContentType.objects.using(using).filter(app_label=app_label) } to_remove = [ ct for (model_name, ct) in six.iteritems(content_types) if model_name not in app_models ] cts = [ ContentType( app_label=app_label, model=model_name, ) for (model_name, model) in six.iteritems(app_models) if model_name not in content_types ] ContentType.objects.using(using).bulk_create(cts) if verbosity >= 2: for ct in cts: print("Adding content type '%s | %s'" % (ct.app_label, ct.model)) # Confirm that the content type is stale before deletion. if to_remove: if interactive: content_type_display = '\n'.join( ' %s | %s' % (ct.app_label, ct.model) for ct in to_remove) ok_to_delete = input( """The following content types are stale and need to be deleted: %s Any objects related to these content types by a foreign key will also be deleted. Are you sure you want to delete these content types? If you're unsure, answer 'no'. Type 'yes' to continue, or 'no' to cancel: """ % content_type_display) else: ok_to_delete = False if ok_to_delete == 'yes': for ct in to_remove: if verbosity >= 2: print("Deleting stale content type '%s | %s'" % (ct.app_label, ct.model)) ct.delete() else: if verbosity >= 2: print("Stale content types remain.")