def remove_migasfree_play_user(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) UserProfile = apps.get_model('server', 'UserProfile') user = UserProfile.objects.using(db_alias).get(username='******') user.delete()
def handle(self, **options): database = options['database'] connection = connections[database] verbosity = options['verbosity'] interactive = options['interactive'] # The following are stealth options used by Django's internals. reset_sequences = options.get('reset_sequences', True) allow_cascade = options.get('allow_cascade', False) inhibit_post_migrate = options.get('inhibit_post_migrate', False) self.style = no_style() # Import the 'management' module within each installed app, to register # dispatcher events. for app_config in apps.get_app_configs(): try: import_module('.management', app_config.name) except ImportError: pass sql_list = sql_flush(self.style, connection, only_django=True, reset_sequences=reset_sequences, allow_cascade=allow_cascade) if interactive: confirm = input("""You have requested a flush of the database. This will IRREVERSIBLY DESTROY all data currently in the %r database, and return each table to an empty state. Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: """ % connection.settings_dict['NAME']) else: confirm = 'yes' if confirm == 'yes': try: with transaction.atomic(using=database, savepoint=connection.features.can_rollback_ddl): with connection.cursor() as cursor: for sql in sql_list: cursor.execute(sql) except Exception as exc: raise CommandError( "Database %s couldn't be flushed. Possible reasons:\n" " * The database isn't running or isn't configured correctly.\n" " * At least one of the expected database tables doesn't exist.\n" " * The SQL was invalid.\n" "Hint: Look at the output of 'django-admin sqlflush'. " "That's the SQL this command wasn't able to run.\n" % ( connection.settings_dict['NAME'], ) ) from exc # Empty sql_list may signify an empty database and post_migrate would then crash if sql_list and not inhibit_post_migrate: # Emit the post migrate signal. This allows individual applications to # respond as if the database had been migrated from scratch. emit_post_migrate_signal(verbosity, interactive, database) else: self.stdout.write("Flush cancelled.\n")
def emit_post_migrate(verbosity, interactive, database): # Emit the post migrate signal. This allows individual applications to # respond as if the database had been migrated from scratch. all_models = [] for app_config in apps.get_app_configs(): all_models.extend(router.get_migratable_models(app_config, database, include_auto_created=True)) emit_post_migrate_signal(set(all_models), verbosity, interactive, database)
def _migrate_from_old_targets(self, tmp_path): if "sqlite3" in self.databases['default']['ENGINE']: try: delete_path(self.databases['default']['NAME']) except Exception: self.clear(False) setup_from_none() self.read() else: self.clear(False) from django.db import DEFAULT_DB_ALIAS, connections from django.apps import apps from django.utils.module_loading import module_has_submodule from django.db.migrations.executor import MigrationExecutor from django.core.management.sql import emit_pre_migrate_signal, emit_post_migrate_signal for app_config in apps.get_app_configs(): if module_has_submodule(app_config.module, "management"): import_module('.management', app_config.name) connection = connections[DEFAULT_DB_ALIAS] connection.prepare_database() executor = MigrationExecutor(connection) emit_pre_migrate_signal(0, None, connection.alias) executor.migrate(executor.loader.graph.leaf_nodes()) emit_post_migrate_signal(0, None, connection.alias) self.clear(True, ['django_migrations'])
def unmigrate_preprint_service_permissions(state, schema): emit_post_migrate_signal(2, False, 'default') # New permission groups Permission.objects.filter(codename='add_preprint').update(codename='add_preprintservice', name='Can add preprint service') Permission.objects.filter(codename='change_preprint').update(codename='change_preprintservice', name='Can change preprint service') Permission.objects.filter(codename='delete_preprint').update(codename='delete_preprintservice', name='Can delete preprint service') Permission.objects.filter(codename='view_preprint').update(codename='view_preprintservice', name='Can view preprint service details in the admin app.')
def test_only_called_once(self, mocked_load_constants_to_database): """ Test that load_constants_to_database is only called once. """ emit_post_migrate_signal(verbosity=1, interactive=False, db=DEFAULT_DB_ALIAS) mocked_load_constants_to_database.assert_called_once()
def apply(self, project_state, schema_editor, collect_sql=False): # we need current content types and migrations # therefore we need to emit a post migrate signal BEFORE we access those # https://code.djangoproject.com/ticket/23422 db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) return super(PermissionContentTypeApplyMigration, self).apply(project_state, schema_editor, collect_sql)
def handle(self, app_label, migration_name, *args, **options): self.verbosity = options.get('verbosity') interactive = options.get('interactive') record = options.get('record') connection = connections[DEFAULT_DB_ALIAS] connection.prepare_database() executor = MigrationExecutor(connection, None) # before anything else, see if there's conflicting apps and drop out hard if there are any conflicts = executor.loader.detect_conflicts() if conflicts: name_str = "; ".join("%s in %s" % (", ".join(names), app) for app, names in conflicts.items()) raise CommandError( "Conflicting migrations detected (%s).\nTo fix them run " "'python manage.py makemigrations --merge'" % name_str ) if app_label not in executor.loader.migrated_apps: raise CommandError( "App '%s' does not have migrations (you cannot selectively sync unmigrated apps)" % app_label ) try: migration = executor.loader.get_migration_by_prefix(app_label, migration_name) except AmbiguityError: raise CommandError( "More than one migration matches '%s' in app '%s'. Please be more specific." % (migration_name, app_label) ) except KeyError: raise CommandError("Cannot find a migration matching '%s' from app '%s'." % (migration_name, app_label)) migration_module = import_module(migration.__module__) # check migration can be run offline apply_function = getattr(migration_module, APPLY_FUNCTION, None) if not apply_function or not callable(apply_function): raise CommandError("Migration %s does not contain function named '%s'" % (migration, APPLY_FUNCTION)) plan = executor.migration_plan([(app_label, migration.name)]) if record and not plan: raise CommandError("Migration %s has already been applied" % migration) emit_pre_migrate_signal(self.verbosity, interactive, connection.alias) self.stdout.write(self.style.MIGRATE_HEADING("Operations to perform:")) self.stdout.write(" Manually apply migration %s" % migration) if record: self.stdout.write(" Record migration %s as applied" % migration) self.stdout.write(self.style.MIGRATE_HEADING("Manual migration:")) self.apply_migration(migration, apply_function) if record: self.record_migration(migration, executor) # send the post_migrate signal, so individual apps can do whatever they need to do at this point. emit_post_migrate_signal(self.verbosity, interactive, connection.alias)
def handle(self, **options): database = options['database'] connection = connections[database] verbosity = options['verbosity'] interactive = options['interactive'] # The following are stealth options used by Django's internals. reset_sequences = options.get('reset_sequences', True) allow_cascade = options.get('allow_cascade', False) inhibit_post_migrate = options.get('inhibit_post_migrate', False) self.style = no_style() # Import the 'management' module within each installed app, to register # dispatcher events. for app_config in apps.get_app_configs(): try: import_module('.management', app_config.name) except ImportError: pass sql_list = sql_flush(self.style, connection, only_django=True, reset_sequences=reset_sequences, allow_cascade=allow_cascade) if interactive: confirm = input("""You have requested a flush of the database. This will IRREVERSIBLY DESTROY all data currently in the %r database, and return each table to an empty state. Are you sure you want to do this? Type 'yes' to continue, or 'no' to cancel: """ % connection.settings_dict['NAME']) else: confirm = 'yes' if confirm == 'yes': try: connection.ops.execute_sql_flush(database, sql_list) except Exception as exc: raise CommandError( "Database %s couldn't be flushed. Possible reasons:\n" " * The database isn't running or isn't configured correctly.\n" " * At least one of the expected database tables doesn't exist.\n" " * The SQL was invalid.\n" "Hint: Look at the output of 'django-admin sqlflush'. " "That's the SQL this command wasn't able to run.\n" % (connection.settings_dict['NAME'], )) from exc # Empty sql_list may signify an empty database and post_migrate would then crash if sql_list and not inhibit_post_migrate: # Emit the post migrate signal. This allows individual applications to # respond as if the database had been migrated from scratch. emit_post_migrate_signal(verbosity, interactive, database) else: self.stdout.write("Flush cancelled.\n")
def add_administrators_group(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') administrators_group, created = Group.objects.get_or_create(name='administrators') if created: is_admin_perm = Permission.objects.get(codename='is_administrator') administrators_group.permissions.add(is_admin_perm)
def remove_reaction_question_index(apps, schema_editor): """ Search for the Reaction Question Index then delete it """ db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) ReactionQuestionIndexPage = apps.get_model('core', 'ReactionQuestionIndexPage') ReactionQuestionIndexPage.objects.using(db_alias).all().delete()
def assing_permissions(apps, schema_editor): # force post signal as permissions are created in post migrate signals # related Django issue https://code.djangoproject.com/ticket/23422 emit_post_migrate_signal(2, False, "default") Group = apps.get_model("auth", "Group") Permission = apps.get_model("auth", "Permission") manage_channels = Permission.objects.filter( codename="manage_channels", content_type__app_label="channel").first() for group in Group.objects.iterator(): group.permissions.add(manage_channels)
def emit_post_migrate(verbosity, interactive, database): # Emit the post migrate signal. This allows individual applications to # respond as if the database had been migrated from scratch. all_models = [] for app_config in apps.get_app_configs(): all_models.extend( router.get_migratable_models(app_config, database, include_auto_created=True)) emit_post_migrate_signal(verbosity, interactive, database)
def add_administrators_group(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') administrators_group, created = Group.objects.get_or_create( name='administrators') if created: is_admin_perm = Permission.objects.get(codename='is_administrator') administrators_group.permissions.add(is_admin_perm)
def create_group(apps, schema_editor): # Workaround for a Django bug: https://code.djangoproject.com/ticket/23422 emit_post_migrate_signal(verbosity=0, interactive=False, db='default') Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') for group_name, permission_codenames in settings.GROUPS_PERMISSIONS.items(): group, created = Group.objects.get_or_create(name=group_name) group.permissions.add(*[Permission.objects.get(codename=c) for c in permission_codenames])
def apply_migration(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') managers_group = Group.objects.create(name=u'Managers') item_change_perm = Permission.objects.get(name='Can change item') item_delete_perm = Permission.objects.get(name='Can delete item') managers_group.permissions.add(item_change_perm) managers_group.permissions.add(item_delete_perm)
def populate_permissions(apps, schema_editor): ''' Add term permissions for archival staff ''' emit_post_migrate_signal(1, False, 'default') group = Group.objects.get(name='archivist_user') existing_permissions = group.permissions.all() for codename in ('add_sourcetype', 'change_sourcetype', 'view_sourcetype', 'add_sourcerole', 'change_sourcerole', 'view_sourcerole'): permission = Permission.objects.get(codename=codename) if permission not in existing_permissions: group.permissions.add(permission)
def add_banner_perms_to_groups(*args, **kwargs): # this is to make sure that the permissions created in an earlier migration exist! emit_post_migrate_signal(2, False, 'default') edit_permission = Permission.objects.get(codename='change_maintenancestate') delete_permission = Permission.objects.get(codename='delete_maintenancestate') osf_admin = Group.objects.get(name='osf_admin') [osf_admin.permissions.add(perm) for perm in [edit_permission, delete_permission]] osf_admin.save()
def add_init_institution_administration_group(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') inst_administrators_group, created = Group.objects.get_or_create(name='institution_administration') if created: is_inst_admin_perm = Permission.objects.get(codename='is_institution_administrator') organisation_perm = Permission.objects.get(codename='can_access_organization') structure_perm = Permission.objects.get(codename='can_access_structure') inst_administrators_group.permissions.add(is_inst_admin_perm, organisation_perm, structure_perm)
def add_executive_group(apps, schema_editor): # create group db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') executive_group, created = Group.objects.get_or_create(name='executive') if created: # Learning unit can_access_learningunit = Permission.objects.get(codename='can_access_learningunit') executive_group.permissions.add(can_access_learningunit)
def add_students_group(apps, schema_editor): # create group db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') student_group, created = Group.objects.get_or_create(name='students') if created: # Add permissions to group student_path_perm = Permission.objects.get(codename='can_access_student_path') student_group.permissions.add(student_path_perm)
def add_domain_admin_group(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') group, _ = Group.objects.get_or_create(name='Domain Admin') permissions = Permission.objects.filter(codename__in=[ 'add_computer', ]) group.permissions.add(*permissions)
def emit_post_migrate(verbosity, interactive, database): # Emit the post migrate signal. This allows individual applications to # respond as if the database had been migrated from scratch. all_models = [] for app in models.get_apps(): all_models.extend([ m for m in models.get_models(app, include_auto_created=True) if router.allow_migrate(database, m) ]) emit_post_migrate_signal(set(all_models), verbosity, interactive, database)
def add_executive_group(apps, schema_editor): # create group db_alias = schema_editor.connection.alias emit_post_migrate_signal(1, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') executive_group, created = Group.objects.get_or_create(name='executive') if created: # Learning unit can_access_learningunit = Permission.objects.get( codename='can_access_learningunit') executive_group.permissions.add(can_access_learningunit)
def add_students_group(apps, schema_editor): # create group db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') student_group, created = Group.objects.get_or_create(name='students') if created: # Add permissions to group student_path_perm = Permission.objects.get( codename='can_access_student_path') student_group.permissions.add(student_path_perm)
def add_preprintservice_permissions(*args): # this is to make sure that the permissions created earlier exist! emit_post_migrate_signal(2, False, 'default') osf_admin = Group.objects.get(name='osf_admin') [osf_admin.permissions.add(perm) for perm in get_preprintservice_permissions()] osf_admin.save() view_preprintservice = Permission.objects.get(codename='view_preprintservice') read_only = Group.objects.get(name='read_only') read_only.permissions.add(view_preprintservice) read_only.save()
def add_turkle_user_admin_group(apps, schema_editor): """Create custom group that has CRU (but not D) access to User/Group models """ # Force Django to create permissions before all migrations are run # # When running the migrations creates the database tables from # scratch (such as when running 'python manage.py test', but not # when running 'python manage.py migrate' to update an existing # database), Django will not add database rows with permissions # for the User and Group models until *after* all migrations have # been run. We need these rows with permission data to be added # to the database now, so that we can grant the permissions to the # new Group instance we are creating. # # This is a known issue with Django that was identified in Django # bug #23422, "Cannot add Permission to Group in data migration" # back in 2014: # https://code.djangoproject.com/ticket/23422 # # The bug report was closed as "wontfix" in 2014. The use of # emit_post_migrate_signal() - which supposedly works in Django # 2.2+ - was suggested in a comment on the bug report made on # 2020-05-07: # https://code.djangoproject.com/ticket/23422#comment:28 emit_post_migrate_signal(1, False, 'default') batch_ctype = ContentType.objects.get_for_model(Batch) group_ctype = ContentType.objects.get_for_model(Group) project_ctype = ContentType.objects.get_for_model(Project) user_ctype = ContentType.objects.get_for_model(User) batch_perms = [ Permission.objects.get(codename='view_batch', content_type=batch_ctype) ] group_perms = [ Permission.objects.get(codename=codename, content_type=group_ctype) for codename in ['add_group', 'change_group', 'view_group'] ] project_perms = [ Permission.objects.get(codename='view_project', content_type=project_ctype) ] user_perms = [ Permission.objects.get(codename=codename, content_type=user_ctype) for codename in ['add_user', 'change_user', 'view_user'] ] # Because we use get_or_create(), if an existing Turkle installation already # has a "Turkle User Admin" group, we will overwrite the existing permissions. (uag, _) = Group.objects.get_or_create(name='Turkle User Admin') uag.permissions.set(batch_perms + group_perms + project_perms + user_perms)
def unmigrate_preprint_service_permissions(state, schema): emit_post_migrate_signal(2, False, 'default') # New permission groups Permission.objects.filter(codename='add_preprint').update( codename='add_preprintservice', name='Can add preprint service') Permission.objects.filter(codename='change_preprint').update( codename='change_preprintservice', name='Can change preprint service') Permission.objects.filter(codename='delete_preprint').update( codename='delete_preprintservice', name='Can delete preprint service') Permission.objects.filter(codename='view_preprint').update( codename='view_preprintservice', name='Can view preprint service details in the admin app.')
def emit_post_migrate_or_sync(verbosity, interactive, database_name, created_models, post_migrate_state, plan): """Emit the post_migrate and/or post_sync signals. This will emit the :py:data:`~django.db.models.signals.post_migrate` and/or :py:data:`~django.db.models.signals.post_sync` signals, providing the appropriate arguments for the current version of Django. Args: verbosity (int): The verbosity level for output. interactive (bool): Whether handlers of the signal can prompt on the terminal for input. database_name (unicode): The name of the database that was migrated. created_models (list of django.db.models.Model): The list of models created outside of any migrations. post_migrate_state (django.db.migrations.state.ProjectState): The project state after applying migrations. plan (list): The full migration plan that was applied. """ emit_kwargs = { 'db': database_name, 'interactive': interactive, 'verbosity': verbosity, } if django_version <= (1, 8): emit_kwargs['created_models'] = created_models elif django_version >= (1, 10): if post_migrate_state: apps = post_migrate_state.apps else: apps = None emit_kwargs.update({ 'apps': apps, 'plan': plan, }) if emit_post_sync_signal: emit_post_sync_signal(**emit_kwargs) else: emit_post_migrate_signal(**emit_kwargs)
def populate_permissions(apps, schema_editor): ''' Add permissions to edit rights to archivist staff ''' emit_post_migrate_signal(1, False, 'default') group = Group.objects.get(name='archivist_user') existing_permissions = group.permissions.all() for codename in ( # Rights 'add_right', 'change_right', 'view_right'): permission = Permission.objects.get(codename=codename) if permission not in existing_permissions: group.permissions.add(permission)
def insertData(apps, schema_editor): group = Group(name="Key cobblers") group.save() # We need to call function below manually so that permissions # are correctly set up in the Django database before we attempt # to assign the permissions to the group. Note that this signal is # fired automatically by Django after each migration cycle, but it's # too late for us by then. emit_post_migrate_signal(2, False, "default") permissions = Permission.objects.filter(content_type_id=12) group.permissions.set(permissions) group.save()
def add_view_yourwords_entry_to_groups(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth.Group') Permission = apps.get_model('auth.Permission') view_yourwords_entry = Permission.objects.get( codename='can_view_yourwords_entry') group_names = ('product_admin', 'data_admin', 'data_viewer', 'content_editor', 'content_admin') for group_name in group_names: group = Group.objects.get(name=group_name) group.permissions.add(view_yourwords_entry)
def remove_content_editor_survey_permissions(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth.Group') content_editor_group = get_group(Group, 'content_editor') SurveysIndexPage = apps.get_model('surveys.SurveysIndexPage') # Wagtail Page permission GroupPagePermission = apps.get_model('wagtailcore.GroupPagePermission') page_permission_types = ('add', 'edit', 'publish', 'bulk_delete', 'lock') surveys = SurveysIndexPage.objects.all() remove_page_permission(GroupPagePermission, content_editor_group, surveys, page_permission_types)
def add_tutors_group(apps, schema_editor): # create group db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') tutors_group, created = Group.objects.get_or_create(name='tutors') if created: # Add permissions to group catalog_perm = Permission.objects.get(codename='can_access_catalog') offer_perm = Permission.objects.get(codename='can_access_offer') student_path_perm = Permission.objects.get(codename='can_access_student_path') evaluation_perm = Permission.objects.get(codename='can_access_evaluation') score_encoding_perm = Permission.objects.get(codename='can_access_scoreencoding') tutors_group.permissions.add(catalog_perm, student_path_perm,offer_perm, evaluation_perm, score_encoding_perm)
def add_subject_perms_to_groups(*args, **kwargs): # this is to make sure that the permissions created in an earlier migration exist! emit_post_migrate_signal(2, False, 'default') view_permission = Permission.objects.get(codename='view_subject') edit_permission = Permission.objects.get(codename='change_subject') osf_admin = Group.objects.get(name='osf_admin') read_only = Group.objects.get(name='read_only') [osf_admin.permissions.add(perm) for perm in [view_permission, edit_permission]] osf_admin.save() read_only.permissions.add(view_permission) read_only.save()
def add_groups(apps, schema_editor): # Workaround for https://code.djangoproject.com/ticket/23422 db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth.Group') Permission = apps.get_model('auth.Permission') for group_data in GROUPS: group, created = Group.objects.get_or_create(name=group_data['name']) for permission in group_data['permissions']: try: group.permissions.add(Permission.objects.get(codename=permission)) except ObjectDoesNotExist: print("Could not find the '%s' permission" % permission)
def add_registrationprovider_perms(*args): # this is to make sure that the permissions created in an earlier migration exist! emit_post_migrate_signal(2, False, 'default') # Add permissions for the read only group read_only_group = Group.objects.get(name='read_only') [ read_only_group.permissions.add(perm) for perm in get_new_permissions(read_only=True) ] read_only_group.save() # Add permissions for new OSF Admin group - can perform actions admin_group = Group.objects.get(name='osf_admin') [admin_group.permissions.add(perm) for perm in get_new_permissions()] admin_group.save()
def add_preprintservice_permissions(*args): # this is to make sure that the permissions created earlier exist! emit_post_migrate_signal(2, False, 'default') osf_admin = Group.objects.get(name='osf_admin') [ osf_admin.permissions.add(perm) for perm in get_preprintservice_permissions() ] osf_admin.save() view_preprintservice = Permission.objects.get( codename='view_preprintservice') read_only = Group.objects.get(name='read_only') read_only.permissions.add(view_preprintservice) read_only.save()
def add_group_permissions(*args): # this is to make sure that the permissions created in an earlier migration exist! emit_post_migrate_signal(2, False, 'default') # Add permissions for the read only group read_only_group = Group.objects.get(name='read_only') [read_only_group.permissions.add(perm) for perm in get_new_read_only_permissions()] read_only_group.save() logger.info('Institution and Preprint Provider permissions added to read only group') # Add permissions for new OSF Admin group - can perform actions admin_group = Group.objects.get(name='osf_admin') [admin_group.permissions.add(perm) for perm in get_new_read_only_permissions()] [admin_group.permissions.add(perm) for perm in get_new_admin_permissions()] admin_group.save() logger.info('Administrator permissions for Institutions and Preprint Providers added to admin group')
def add_banner_perms_to_groups(*args, **kwargs): # this is to make sure that the permissions created in an earlier migration exist! emit_post_migrate_signal(2, False, 'default') edit_permission = Permission.objects.get( codename='change_maintenancestate') delete_permission = Permission.objects.get( codename='delete_maintenancestate') osf_admin = Group.objects.get(name='osf_admin') [ osf_admin.permissions.add(perm) for perm in [edit_permission, delete_permission] ] osf_admin.save()
def run(self, **options): database = options.get("database", DEFAULT_DB_ALIAS) connection = connections[database] verbosity = options["verbosity"] interactive = False # The following are stealth options used by Django's internals. reset_sequences = options.get("reset_sequences", True) allow_cascade = options.get("allow_cascade", False) inhibit_post_migrate = options.get("inhibit_post_migrate", False) self.style = no_style() # Import the 'management' module within each installed app, to register # dispatcher events. for app_config in apps.get_app_configs(): try: import_module(".management", app_config.name) except ImportError: pass sql_list = sql_flush( self.style, connection, only_django=True, reset_sequences=reset_sequences, allow_cascade=allow_cascade, ) print("Flushing database!") connection.ops.execute_sql_flush(database, sql_list) if sql_list and not inhibit_post_migrate: # Emit the post migrate signal. This allows individual applications to # respond as if the database had been migrated from scratch. emit_post_migrate_signal(verbosity, interactive, database) corpora_file = os.path.abspath(settings.CORPORA_FILE) print(f"Done. Loading from {corpora_file}") # see https://code.djangoproject.com/ticket/8085 if os.environ.get("RUN_MAIN", False): load_explorer_app() for corpus in Corpus.objects.all(): if corpus.pdfs and not corpus.disabled: os.environ["TESSDATA_PREFIX"] = settings.TESSDATA_PREFIX load_tif_pdf_plaintext(corpus)
def migrate_preprint_service_permissions(state, schema): """ Django permissions on the preprint model have new names. """ # this is to make sure that the permissions created earlier exist! emit_post_migrate_signal(2, False, 'default') Permission.objects.filter(codename='add_preprint').delete() Permission.objects.filter(codename='change_preprint').delete() Permission.objects.filter(codename='delete_preprint').delete() Permission.objects.filter(codename='view_preprint').delete() # Old permission groups Permission.objects.filter(codename='add_preprintservice').update(codename='add_preprint', name='Can add preprint') Permission.objects.filter(codename='change_preprintservice').update(codename='change_preprint', name='Can change preprint') Permission.objects.filter(codename='delete_preprintservice').update(codename='delete_preprint', name='Can delete preprint') Permission.objects.filter(codename='view_preprintservice').update(codename='view_preprint', name='Can view preprint details in the admin app')
def add_perm(apps, schema_editor): # Workaround to ensure the permission added in 0084_auto_20170406_0858 # is actually created, see https://code.djangoproject.com/ticket/23422 emit_post_migrate_signal(0, False, schema_editor.connection.alias) GroupACL = apps.get_model('permissions', 'GroupACL') Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') permission = Permission.objects.get(codename='mass_add_translation') groupacls = GroupACL.objects.filter(language=None, subproject=None).exclude(project=None) for acl in groupacls.iterator(): acl.permissions.add(permission) for group in Group.objects.filter(name__endswith='@Administration'): group.permissions.add(permission) for group in Group.objects.filter(name__in=('Owners', 'Managers')): group.permissions.add(permission)
def create_subject_matter_expert_group(app, schema_editor): # Trigger post-migrate steps, which will create custom model permissions # that otherwise might not be created if this migration runs in the same # migration group as the one which adds the permissions. # https://code.djangoproject.com/ticket/23422 db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = app.get_model('auth', 'Group') Permission = app.get_model('auth', 'Permission') sme = Group.objects.get_or_create(name="Subject Matter Experts")[0] perms = Permission.objects.filter(codename__in=[ 'manage_unpublished_master_datasets', 'manage_unpublished_datacut_datasets', ]) sme.permissions.add(*perms) sme.save()
def add_init_institution_administration_group(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') inst_administrators_group, created = Group.objects.get_or_create( name='institution_administration') if created: is_inst_admin_perm = Permission.objects.get( codename='is_institution_administrator') organisation_perm = Permission.objects.get( codename='can_access_organization') structure_perm = Permission.objects.get( codename='can_access_structure') inst_administrators_group.permissions.add(is_inst_admin_perm, organisation_perm, structure_perm)
def add_migasfree_play_user(apps, schema_editor): db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) UserProfile = apps.get_model('server', 'UserProfile') Permission = apps.get_model('auth', 'Permission') name = 'migasfree-play' user, _ = UserProfile.objects.using(db_alias).get_or_create(username=name) user.is_active = True user.password = make_password(name) user.save() permissions = Permission.objects.using(db_alias).filter( codename__in=['change_devicelogical', 'can_save_devicelogical'], content_type__app_label='server' ) user.user_permissions.add(*permissions)
def add_perm(apps, schema_editor): # Workaround to ensure the permission added in 0084_auto_20170406_0858 # is actually created, see https://code.djangoproject.com/ticket/23422 emit_post_migrate_signal(0, False, schema_editor.connection.alias) GroupACL = apps.get_model('permissions', 'GroupACL') Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') permission = Permission.objects.get(codename='mass_add_translation') groupacls = GroupACL.objects.filter( language=None, subproject=None ).exclude( project=None ) for acl in groupacls.iterator(): acl.permissions.add(permission) for group in Group.objects.filter(name__endswith='@Administration'): group.permissions.add(permission) for group in Group.objects.filter(name__in=('Owners', 'Managers')): group.permissions.add(permission)
def add_faculty_manager_group(apps, schema_editor): # create group db_alias = schema_editor.connection.alias emit_post_migrate_signal(2, False, db_alias) Group = apps.get_model('auth', 'Group') Permission = apps.get_model('auth', 'Permission') faculty_managers_group, created = Group.objects.get_or_create(name='faculty_managers') if created: # Learning unit can_access_learningunit = Permission.objects.get(codename='can_access_learningunit') faculty_managers_group.permissions.add(can_access_learningunit) can_edit_learningunit_specification = Permission.objects.get(codename='can_edit_learningunit_specification') faculty_managers_group.permissions.add(can_edit_learningunit_specification) can_change_learningcomponentyear = Permission.objects.get(codename='change_learningcomponentyear') faculty_managers_group.permissions.add(can_change_learningcomponentyear) can_edit_learningunit_pedagogy = Permission.objects.get(codename='can_edit_learningunit_pedagogy') faculty_managers_group.permissions.add(can_edit_learningunit_pedagogy) change_learningclassyear = Permission.objects.get(codename='change_learningclassyear') faculty_managers_group.permissions.add(change_learningclassyear) # Offer can_access_offer = Permission.objects.get(codename='can_access_offer') faculty_managers_group.permissions.add(can_access_offer)
def create_page_creators_group(apps, schema_editor): # Ensure wiki.add_document permission is created in a fresh database # https://code.djangoproject.com/ticket/23422#comment:20 db_alias = schema_editor.connection.alias emit_post_migrate_signal(verbosity=1, interactive=False, db=db_alias, created_models=[]) # Grab the wiki.add_document permission Permission = apps.get_model('auth', 'Permission') add_perm = Permission.objects.get(codename='add_document', content_type__app_label='wiki') # Create the Page Creators group, if needed Group = apps.get_model('auth', 'Group') group, created = Group.objects.get_or_create(name='Page Creators') group.permissions.add(add_perm) # Add existing unbanned users to Page Creators User = apps.get_model('users', 'User') for user in User.objects.only('id'): if not user.bans.exists(): user.groups.add(group)
def add_surveys_permissions_to_groups(apps, schema_editor): db_alias = schema_editor.connection.alias try: # Django 1.9 emit_post_migrate_signal(2, False, db_alias) except TypeError: # Django < 1.9 try: # Django 1.8 emit_post_migrate_signal(2, False, 'default', db_alias) except TypeError: # Django < 1.8 emit_post_migrate_signal([], 2, False, 'default', db_alias) Group = apps.get_model('auth.Group') GroupPagePermission = apps.get_model('wagtailcore.GroupPagePermission') SurveysIndexPage = apps.get_model('surveys.SurveysIndexPage') # Create groups # <- Editors -> editor_group = Group.objects.get(name='Editors') surveys = SurveysIndexPage.objects.first() GroupPagePermission.objects.get_or_create( group=editor_group, page=surveys, permission_type='add', ) GroupPagePermission.objects.get_or_create( group=editor_group, page=surveys, permission_type='edit', ) # <- Moderator -> moderator_group = Group.objects.get(name='Moderators') surveys = SurveysIndexPage.objects.first() GroupPagePermission.objects.get_or_create( group=moderator_group, page=surveys, permission_type='add', ) GroupPagePermission.objects.get_or_create( group=moderator_group, page=surveys, permission_type='edit', ) GroupPagePermission.objects.get_or_create( group=moderator_group, page=surveys, permission_type='publish', )
def emit_post_migrate_to_avoid_breaking_continuity(schema_editor): """ This is so that running migrations together doesn't break, because Django adds Permissions in post_migrate signal """ db_alias = schema_editor.connection.alias try: emit_post_migrate_signal(0, False, db_alias) except TypeError: # Django < 1.9 try: emit_post_migrate_signal(2, False, 'default', db_alias) except TypeError: # Django < 1.8 emit_post_migrate_signal([], 2, False, 'default', db_alias)
def update_permissions_for_group(apps, schema_editor): ''' Update permissions for some users. Give bulk-delete permissions to moderators. Give edit permission to moderators and editors in order to display 'Main' page in the explorer. ''' db_alias = schema_editor.connection.alias try: # Django 1.9 emit_post_migrate_signal(2, False, db_alias) except TypeError: # Django < 1.9 try: # Django 1.8 emit_post_migrate_signal(2, False, 'default', db_alias) except TypeError: # Django < 1.8 emit_post_migrate_signal([], 2, False, 'default', db_alias) Group = apps.get_model('auth.Group') Permission = apps.get_model('auth.Permission') GroupPagePermission = apps.get_model('wagtailcore.GroupPagePermission') SectionIndexPage = apps.get_model('core.SectionIndexPage') MainPage = apps.get_model('core.Main') moderator_group = Group.objects.filter(name='Moderators').first() editor_group = Group.objects.filter(name='Editors').first() if moderator_group: sections = SectionIndexPage.objects.first() GroupPagePermission.objects.get_or_create( group_id=moderator_group.id, page_id=sections.id, permission_type='bulk_delete' ) main = MainPage.objects.first() GroupPagePermission.objects.get_or_create( group_id=moderator_group.id, page_id=main.id, permission_type='edit' ) if editor_group: main = MainPage.objects.first() GroupPagePermission.objects.get_or_create( group_id=editor_group.id, page_id=main.id, permission_type='edit' )
def remove_user_permission_for_moderator_group(apps, schema_editor): db_alias = schema_editor.connection.alias try: # Django 1.9 emit_post_migrate_signal(2, False, db_alias) except TypeError: # Django < 1.9 try: # Django 1.8 emit_post_migrate_signal(2, False, 'default', db_alias) except TypeError: # Django < 1.8 emit_post_migrate_signal([], 2, False, 'default', db_alias) Group = apps.get_model('auth.Group') Permission = apps.get_model('auth.Permission') # <- Moderator -> moderator_group = Group.objects.filter(name='Moderators').first() if moderator_group: change_user = Permission.objects.get(codename='change_user') moderator_group.permissions.remove(change_user)
def handle(self, *args, **options): self.verbosity = options.get('verbosity') self.interactive = options.get('interactive') self.show_traceback = options.get('traceback') self.load_initial_data = options.get('load_initial_data') # Import the 'management' module within each installed app, to register # dispatcher events. for app_config in apps.get_app_configs(): if module_has_submodule(app_config.module, "management"): import_module('.management', app_config.name) # Get the database we're operating from db = options.get('database') connection = connections[db] # If they asked for a migration listing, quit main execution flow and show it if options.get("list", False): return self.show_migration_list(connection, [options['app_label']] if options['app_label'] else None) # Work out which apps have migrations and which do not executor = MigrationExecutor(connection, self.migration_progress_callback) # Before anything else, see if there's conflicting apps and drop out # hard if there are any conflicts = executor.loader.detect_conflicts() if conflicts: name_str = "; ".join( "%s in %s" % (", ".join(names), app) for app, names in conflicts.items() ) raise CommandError( "Conflicting migrations detected (%s).\nTo fix them run " "'python manage.py makemigrations --merge'" % name_str ) # If they supplied command line arguments, work out what they mean. run_syncdb = False target_app_labels_only = True if options['app_label'] and options['migration_name']: app_label, migration_name = options['app_label'], options['migration_name'] if app_label not in executor.loader.migrated_apps: raise CommandError( "App '%s' does not have migrations (you cannot selectively " "sync unmigrated apps)" % app_label ) if migration_name == "zero": targets = [(app_label, None)] else: try: migration = executor.loader.get_migration_by_prefix(app_label, migration_name) except AmbiguityError: raise CommandError( "More than one migration matches '%s' in app '%s'. " "Please be more specific." % (migration_name, app_label) ) except KeyError: raise CommandError("Cannot find a migration matching '%s' from app '%s'." % ( migration_name, app_label)) targets = [(app_label, migration.name)] target_app_labels_only = False elif options['app_label']: app_label = options['app_label'] if app_label not in executor.loader.migrated_apps: raise CommandError( "App '%s' does not have migrations (you cannot selectively " "sync unmigrated apps)" % app_label ) targets = [key for key in executor.loader.graph.leaf_nodes() if key[0] == app_label] else: targets = executor.loader.graph.leaf_nodes() run_syncdb = True plan = executor.migration_plan(targets) # Print some useful info if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Operations to perform:")) if run_syncdb and executor.loader.unmigrated_apps: self.stdout.write( self.style.MIGRATE_LABEL(" Synchronize unmigrated apps: ") + (", ".join(executor.loader.unmigrated_apps)) ) if target_app_labels_only: self.stdout.write( self.style.MIGRATE_LABEL(" Apply all migrations: ") + (", ".join(set(a for a, n in targets)) or "(none)") ) else: if targets[0][1] is None: self.stdout.write(self.style.MIGRATE_LABEL( " Unapply all migrations: ") + "%s" % (targets[0][0], ) ) else: self.stdout.write(self.style.MIGRATE_LABEL( " Target specific migration: ") + "%s, from %s" % (targets[0][1], targets[0][0]) ) # Run the syncdb phase. # If you ever manage to get rid of this, I owe you many, many drinks. # Note that pre_migrate is called from inside here, as it needs # the list of models about to be installed. if run_syncdb and executor.loader.unmigrated_apps: if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:")) created_models = self.sync_apps(connection, executor.loader.unmigrated_apps) else: created_models = [] # The test runner requires us to flush after a syncdb but before migrations, # so do that here. if options.get("test_flush", False): call_command( 'flush', verbosity=max(self.verbosity - 1, 0), interactive=False, database=db, reset_sequences=False, inhibit_post_migrate=True, ) # Migrate! if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Running migrations:")) if not plan: if self.verbosity >= 1: self.stdout.write(" No migrations to apply.") # If there's changes that aren't in migrations yet, tell them how to fix it. autodetector = MigrationAutodetector( executor.loader.project_state(), ProjectState.from_apps(apps), ) changes = autodetector.changes(graph=executor.loader.graph) if changes: self.stdout.write(self.style.NOTICE( " Your models have changes that are not yet reflected " "in a migration, and so won't be applied." )) self.stdout.write(self.style.NOTICE( " Run 'manage.py makemigrations' to make new " "migrations, and then re-run 'manage.py migrate' to " "apply them." )) else: executor.migrate(targets, plan, fake=options.get("fake", False)) # Send the post_migrate signal, so individual apps can do whatever they need # to do at this point. emit_post_migrate_signal(created_models, self.verbosity, self.interactive, connection.alias)
def create_provider_auth_groups(apps, schema_editor): # this is to make sure that the permissions created in an earlier migration exist! emit_post_migrate_signal(2, False, 'default') PreprintProvider = apps.get_model('osf', 'PreprintProvider') for provider in PreprintProvider.objects.all(): GroupHelper(provider).update_provider_auth_groups()
def handle(self, *args, **options): self.verbosity = verbosity = options.get('verbosity') self.interactive = interactive = options.get('interactive') migrations_dir = options.get('input_dir') try: default_input_dir = os.path.join( settings.BASE_DIR, DEFAULT_PENDING_MIGRATIONS_DIRECTORY) except AttributeError: default_input_dir = None if migrations_dir is None: if not default_input_dir: raise CommandError( "No input directory to read migrations from. Either set " "BASE_DIR in your settings or provide a directory path " "via the --input-dir option.") else: migrations_dir = default_input_dir elif not migrations_dir: raise CommandError( "Provide a real directory path via the --input-dir option.") if not (os.path.exists(migrations_dir) and os.listdir(migrations_dir)): raise CommandError("Input directory (%s) doesn't exist or is " "empty." % migrations_dir) # Get the database we're operating from db = options.get('database') connection = connections[db] # Hook for backends needing any database preparation try: connection.prepare_database() except AttributeError: # pragma: no cover pass executor = MigrationExecutor(connection, self.migration_progress_callback) # Replace the loader with a pending migration one executor.loader = PendingMigrationLoader( connection, pending_migrations_dir=migrations_dir) targets = executor.loader.graph.leaf_nodes() pending_migration_keys = executor.loader.pending_migrations.keys() if options.get('unapply'): targets = [] # We only want to unapply the collected migrations for key, migration in executor.loader.pending_migrations.items(): app_label, migration_name = key migration_found = False for dependency in migration.dependencies: pending = dependency in pending_migration_keys if dependency[0] == app_label and not pending: result = executor.loader.check_key(dependency, app_label) dependency = result or dependency targets.append(dependency) migration_found = True if not migration_found: targets.append((app_label, None)) else: # Trim non-collected migrations for migration_key in list(targets): if migration_key not in pending_migration_keys: targets.remove(migration_key) plan = executor.migration_plan(targets) MIGRATE_HEADING = self.style.MIGRATE_HEADING MIGRATE_LABEL = self.style.MIGRATE_LABEL # Print some useful info if verbosity > 0: self.stdout.write(MIGRATE_HEADING("Operations to perform:")) for target in targets: if target[1] is None: self.stdout.write(MIGRATE_LABEL( " Unapply all migrations: ") + "%s" % (target[0],) ) else: self.stdout.write(MIGRATE_LABEL( " Target specific migration: ") + "%s, from %s" % (target[1], target[0]) ) try: # pragma: no cover emit_pre_migrate_signal([], verbosity, interactive, connection.alias) except TypeError: # pragma: no cover emit_pre_migrate_signal(verbosity, interactive, connection.alias) # Migrate! if verbosity > 0: self.stdout.write(MIGRATE_HEADING("Running migrations:")) if not plan: if verbosity > 0: self.stdout.write(" No migrations to apply.") # If there's changes not in migrations, tell them how to fix it autodetector = MigrationAutodetector( executor.loader.project_state(), ProjectState.from_apps(apps), ) changes = autodetector.changes(graph=executor.loader.graph) if changes: self.stdout.write(self.style.NOTICE( " Your models have changes that are not yet reflected" " in a migration, and so won't be applied." )) self.stdout.write(self.style.NOTICE( " Run 'manage.py makeprojectmigrations' to make new " "migrations, and then run 'manage.py migrateproject' " "to apply them." )) else: executor.migrate(targets, plan, fake=options.get("fake", False)) # A little database clean-up for app_label, migration_name in pending_migration_keys: executor.recorder.record_unapplied(app_label, migration_name) # Send the post_migrate signal, so individual apps can do whatever they # need to do at this point. try: # pragma: no cover emit_post_migrate_signal([], verbosity, interactive, connection.alias) except TypeError: # pragma: no cover emit_post_migrate_signal(verbosity, interactive, connection.alias)
def handle(self, *args, **options): self.verbosity = options['verbosity'] self.interactive = options['interactive'] # Import the 'management' module within each installed app, to register # dispatcher events. for app_config in apps.get_app_configs(): if module_has_submodule(app_config.module, "management"): import_module('.management', app_config.name) # Get the database we're operating from db = options['database'] connection = connections[db] # Hook for backends needing any database preparation connection.prepare_database() # Work out which apps have migrations and which do not executor = MigrationExecutor(connection, self.migration_progress_callback) # Raise an error if any migrations are applied before their dependencies. executor.loader.check_consistent_history(connection) # Before anything else, see if there's conflicting apps and drop out # hard if there are any conflicts = executor.loader.detect_conflicts() if conflicts: name_str = "; ".join( "%s in %s" % (", ".join(names), app) for app, names in conflicts.items() ) raise CommandError( "Conflicting migrations detected; multiple leaf nodes in the " "migration graph: (%s).\nTo fix them run " "'python manage.py makemigrations --merge'" % name_str ) # If they supplied command line arguments, work out what they mean. target_app_labels_only = True if options['app_label']: # Validate app_label. app_label = options['app_label'] try: apps.get_app_config(app_label) except LookupError as err: raise CommandError(str(err)) if app_label not in executor.loader.migrated_apps: raise CommandError("App '%s' does not have migrations." % app_label) if options['app_label'] and options['migration_name']: migration_name = options['migration_name'] if migration_name == "zero": targets = [(app_label, None)] else: try: migration = executor.loader.get_migration_by_prefix(app_label, migration_name) except AmbiguityError: raise CommandError( "More than one migration matches '%s' in app '%s'. " "Please be more specific." % (migration_name, app_label) ) except KeyError: raise CommandError("Cannot find a migration matching '%s' from app '%s'." % ( migration_name, app_label)) targets = [(app_label, migration.name)] target_app_labels_only = False elif options['app_label']: targets = [key for key in executor.loader.graph.leaf_nodes() if key[0] == app_label] else: targets = executor.loader.graph.leaf_nodes() plan = executor.migration_plan(targets) if options['plan']: self.stdout.write('Planned operations:', self.style.MIGRATE_LABEL) if not plan: self.stdout.write(' No planned migration operations.') for migration, backwards in plan: self.stdout.write(str(migration), self.style.MIGRATE_HEADING) for operation in migration.operations: message, is_error = self.describe_operation(operation, backwards) style = self.style.WARNING if is_error else None self.stdout.write(' ' + message, style) return run_syncdb = options['run_syncdb'] and executor.loader.unmigrated_apps # Print some useful info if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Operations to perform:")) if run_syncdb: self.stdout.write( self.style.MIGRATE_LABEL(" Synchronize unmigrated apps: ") + (", ".join(sorted(executor.loader.unmigrated_apps))) ) if target_app_labels_only: self.stdout.write( self.style.MIGRATE_LABEL(" Apply all migrations: ") + (", ".join(sorted({a for a, n in targets})) or "(none)") ) else: if targets[0][1] is None: self.stdout.write(self.style.MIGRATE_LABEL( " Unapply all migrations: ") + "%s" % (targets[0][0],) ) else: self.stdout.write(self.style.MIGRATE_LABEL( " Target specific migration: ") + "%s, from %s" % (targets[0][1], targets[0][0]) ) pre_migrate_state = executor._create_project_state(with_applied_migrations=True) pre_migrate_apps = pre_migrate_state.apps emit_pre_migrate_signal( self.verbosity, self.interactive, connection.alias, apps=pre_migrate_apps, plan=plan, ) # Run the syncdb phase. if run_syncdb: if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:")) self.sync_apps(connection, executor.loader.unmigrated_apps) # Migrate! if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Running migrations:")) if not plan: if self.verbosity >= 1: self.stdout.write(" No migrations to apply.") # If there's changes that aren't in migrations yet, tell them how to fix it. autodetector = MigrationAutodetector( executor.loader.project_state(), ProjectState.from_apps(apps), ) changes = autodetector.changes(graph=executor.loader.graph) if changes: self.stdout.write(self.style.NOTICE( " Your models have changes that are not yet reflected " "in a migration, and so won't be applied." )) self.stdout.write(self.style.NOTICE( " Run 'manage.py makemigrations' to make new " "migrations, and then re-run 'manage.py migrate' to " "apply them." )) fake = False fake_initial = False else: fake = options['fake'] fake_initial = options['fake_initial'] post_migrate_state = executor.migrate( targets, plan=plan, state=pre_migrate_state.clone(), fake=fake, fake_initial=fake_initial, ) # post_migrate signals have access to all models. Ensure that all models # are reloaded in case any are delayed. post_migrate_state.clear_delayed_apps_cache() post_migrate_apps = post_migrate_state.apps # Re-render models of real apps to include relationships now that # we've got a final state. This wouldn't be necessary if real apps # models were rendered with relationships in the first place. with post_migrate_apps.bulk_update(): model_keys = [] for model_state in post_migrate_apps.real_models: model_key = model_state.app_label, model_state.name_lower model_keys.append(model_key) post_migrate_apps.unregister_model(*model_key) post_migrate_apps.render_multiple([ ModelState.from_model(apps.get_model(*model)) for model in model_keys ]) # Send the post_migrate signal, so individual apps can do whatever they need # to do at this point. emit_post_migrate_signal( self.verbosity, self.interactive, connection.alias, apps=post_migrate_apps, plan=plan, )
def handle(self, *args, **options): self.verbosity = options.get('verbosity') self.interactive = options.get('interactive') # Import the 'management' module within each installed app, to register # dispatcher events. for app_config in apps.get_app_configs(): if module_has_submodule(app_config.module, "management"): import_module('.management', app_config.name) # Get the database we're operating from db = options.get('database') connection = connections[db] # If they asked for a migration listing, quit main execution flow and show it if options.get("list", False): warnings.warn( "The 'migrate --list' command is deprecated. Use 'showmigrations' instead.", RemovedInDjango110Warning, stacklevel=2) self.stdout.ending = None # Remove when #21429 is fixed return call_command( 'showmigrations', '--list', app_labels=[options['app_label']] if options['app_label'] else None, database=db, no_color=options.get('no_color'), settings=options.get('settings'), stdout=self.stdout, traceback=options.get('traceback'), verbosity=self.verbosity, ) # Hook for backends needing any database preparation connection.prepare_database() # Work out which apps have migrations and which do not executor = MigrationExecutor(connection, self.migration_progress_callback) # Before anything else, see if there's conflicting apps and drop out # hard if there are any conflicts = executor.loader.detect_conflicts() if conflicts: name_str = "; ".join( "%s in %s" % (", ".join(names), app) for app, names in conflicts.items() ) raise CommandError( "Conflicting migrations detected; multiple leaf nodes in the " "migration graph: (%s).\nTo fix them run " "'python manage.py makemigrations --merge'" % name_str ) # If they supplied command line arguments, work out what they mean. target_app_labels_only = True if options['app_label'] and options['migration_name']: app_label, migration_name = options['app_label'], options['migration_name'] if app_label not in executor.loader.migrated_apps: raise CommandError( "App '%s' does not have migrations." % app_label ) if migration_name == "zero": targets = [(app_label, None)] else: try: migration = executor.loader.get_migration_by_prefix(app_label, migration_name) except AmbiguityError: raise CommandError( "More than one migration matches '%s' in app '%s'. " "Please be more specific." % (migration_name, app_label) ) except KeyError: raise CommandError("Cannot find a migration matching '%s' from app '%s'." % ( migration_name, app_label)) targets = [(app_label, migration.name)] target_app_labels_only = False elif options['app_label']: app_label = options['app_label'] if app_label not in executor.loader.migrated_apps: raise CommandError( "App '%s' does not have migrations." % app_label ) targets = [key for key in executor.loader.graph.leaf_nodes() if key[0] == app_label] else: targets = executor.loader.graph.leaf_nodes() plan = executor.migration_plan(targets) run_syncdb = options.get('run_syncdb') and executor.loader.unmigrated_apps # Print some useful info if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Operations to perform:")) if run_syncdb: self.stdout.write( self.style.MIGRATE_LABEL(" Synchronize unmigrated apps: ") + (", ".join(executor.loader.unmigrated_apps)) ) if target_app_labels_only: self.stdout.write( self.style.MIGRATE_LABEL(" Apply all migrations: ") + (", ".join(set(a for a, n in targets)) or "(none)") ) else: if targets[0][1] is None: self.stdout.write(self.style.MIGRATE_LABEL( " Unapply all migrations: ") + "%s" % (targets[0][0], ) ) else: self.stdout.write(self.style.MIGRATE_LABEL( " Target specific migration: ") + "%s, from %s" % (targets[0][1], targets[0][0]) ) emit_pre_migrate_signal(self.verbosity, self.interactive, connection.alias) # Run the syncdb phase. if run_syncdb: if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Synchronizing apps without migrations:")) self.sync_apps(connection, executor.loader.unmigrated_apps) # Migrate! if self.verbosity >= 1: self.stdout.write(self.style.MIGRATE_HEADING("Running migrations:")) if not plan: executor.check_replacements() if self.verbosity >= 1: self.stdout.write(" No migrations to apply.") # If there's changes that aren't in migrations yet, tell them how to fix it. autodetector = MigrationAutodetector( executor.loader.project_state(), ProjectState.from_apps(apps), ) changes = autodetector.changes(graph=executor.loader.graph) if changes: self.stdout.write(self.style.NOTICE( " Your models have changes that are not yet reflected " "in a migration, and so won't be applied." )) self.stdout.write(self.style.NOTICE( " Run 'manage.py makemigrations' to make new " "migrations, and then re-run 'manage.py migrate' to " "apply them." )) else: fake = options.get("fake") fake_initial = options.get("fake_initial") executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial) # Send the post_migrate signal, so individual apps can do whatever they need # to do at this point. emit_post_migrate_signal(self.verbosity, self.interactive, connection.alias)