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 app_cache.get_app_configs(only_with_models_module=True): all_models.extend(router.get_migratable_models(app_config.models_module, database, include_auto_created=True)) emit_post_migrate_signal(set(all_models), verbosity, interactive, database)
def load_disk(self): """ Loads the migrations from all INSTALLED_APPS from disk. """ self.disk_migrations = {} self.unmigrated_apps = set() self.migrated_apps = set() for app_config in app_cache.get_app_configs(only_with_models_module=True): # Get the migrations module directory module_name = self.migrations_module(app_config.label) was_loaded = module_name in sys.modules try: module = import_module(module_name) except ImportError as e: # I hate doing this, but I don't want to squash other import errors. # Might be better to try a directory check directly. if "No module named" in str(e) and "migrations" in str(e): self.unmigrated_apps.add(app_config.label) continue raise else: # PY3 will happily import empty dirs as namespaces. if not hasattr(module, '__file__'): continue # Module is not a package (e.g. migrations.py). if not hasattr(module, '__path__'): continue # Force a reload if it's already loaded (tests need this) if was_loaded: six.moves.reload_module(module) self.migrated_apps.add(app_config.label) directory = os.path.dirname(module.__file__) # Scan for .py[c|o] files migration_names = set() for name in os.listdir(directory): if name.endswith(".py") or name.endswith(".pyc") or name.endswith(".pyo"): import_name = name.rsplit(".", 1)[0] if import_name[0] not in "_.~": migration_names.add(import_name) # Load them south_style_migrations = False for migration_name in migration_names: try: migration_module = import_module("%s.%s" % (module_name, migration_name)) except ImportError as e: # Ignore South import errors, as we're triggering them if "south" in str(e).lower(): south_style_migrations = True break raise if not hasattr(migration_module, "Migration"): raise BadMigrationError("Migration %s in app %s has no Migration class" % (migration_name, app_config.label)) # Ignore South-style migrations if hasattr(migration_module.Migration, "forwards"): south_style_migrations = True break self.disk_migrations[app_config.label, migration_name] = migration_module.Migration(migration_name, app_config.label) if south_style_migrations: self.unmigrated_apps.add(app_config.label)
def emit_post_migrate_signal(created_models, verbosity, interactive, db): # Emit the post_migrate signal for every application. for app_config in app_cache.get_app_configs(only_with_models_module=True): if verbosity >= 2: print("Running post-migrate handlers for application %s" % app_config.label) models.signals.post_migrate.send( sender=app_config.models_module, app=app_config.models_module, created_models=created_models, verbosity=verbosity, interactive=interactive, db=db)
def fixture_dirs(self): """ Return a list of fixture directories. The list contains the 'fixtures' subdirectory of each installed application, if it exists, the directories in FIXTURE_DIRS, and the current directory. """ dirs = [] for app_config in app_cache.get_app_configs(): d = os.path.join(app_config.path, 'fixtures') if os.path.isdir(d): dirs.append(d) dirs.extend(list(settings.FIXTURE_DIRS)) dirs.append('') dirs = [upath(os.path.abspath(os.path.realpath(d))) for d in dirs] return dirs
def build_suite(self, test_labels, extra_tests=None, **kwargs): suite = unittest.TestSuite() if test_labels: for label in test_labels: if '.' in label: suite.addTest(build_test(label)) else: app_config = app_cache.get_app_config(label) suite.addTest(build_suite(app_config)) else: for app_config in app_cache.get_app_configs(): suite.addTest(build_suite(app_config)) if extra_tests: for test in extra_tests: suite.addTest(test) return runner.reorder_suite(suite, (unittest.TestCase,))
def handle(self, *app_labels, **options): from django.core.apps import app_cache format = options.get('format') indent = options.get('indent') using = options.get('database') excludes = options.get('exclude') show_traceback = options.get('traceback') use_natural_keys = options.get('use_natural_keys') if use_natural_keys: warnings.warn("``--natural`` is deprecated; use ``--natural-foreign`` instead.", PendingDeprecationWarning) use_natural_foreign_keys = options.get('use_natural_foreign_keys') or use_natural_keys use_natural_primary_keys = options.get('use_natural_primary_keys') use_base_manager = options.get('use_base_manager') pks = options.get('primary_keys') if pks: primary_keys = pks.split(',') else: primary_keys = [] excluded_apps = set() excluded_models = set() for exclude in excludes: if '.' in exclude: app_label, model_name = exclude.split('.', 1) model_obj = app_cache.get_model(app_label, model_name) if not model_obj: raise CommandError('Unknown model in excludes: %s' % exclude) excluded_models.add(model_obj) else: try: app_obj = app_cache.get_app_config(exclude).models_module if app_obj is not None: excluded_apps.add(app_obj) except LookupError: raise CommandError('Unknown app in excludes: %s' % exclude) if len(app_labels) == 0: if primary_keys: raise CommandError("You can only use --pks option with one model") app_list = OrderedDict((app_config.models_module, None) for app_config in app_cache.get_app_configs(only_with_models_module=True) if app_config.models_module not in excluded_apps) else: if len(app_labels) > 1 and primary_keys: raise CommandError("You can only use --pks option with one model") app_list = OrderedDict() for label in app_labels: try: app_label, model_label = label.split('.') try: app = app_cache.get_app_config(app_label).models_module except LookupError: raise CommandError("Unknown application: %s" % app_label) if app is None or app in excluded_apps: continue model = app_cache.get_model(app_label, model_label) if model is None: raise CommandError("Unknown model: %s.%s" % (app_label, model_label)) if app in app_list.keys(): if app_list[app] and model not in app_list[app]: app_list[app].append(model) else: app_list[app] = [model] except ValueError: if primary_keys: raise CommandError("You can only use --pks option with one model") # This is just an app - no model qualifier app_label = label try: app = app_cache.get_app_config(app_label).models_module except LookupError: raise CommandError("Unknown application: %s" % app_label) if app is None or app in excluded_apps: continue app_list[app] = None # Check that the serialization format exists; this is a shortcut to # avoid collating all the objects and _then_ failing. if format not in serializers.get_public_serializer_formats(): try: serializers.get_serializer(format) except serializers.SerializerDoesNotExist: pass raise CommandError("Unknown serialization format: %s" % format) def get_objects(): # Collate the objects to be serialized. for model in sort_dependencies(app_list.items()): if model in excluded_models: continue if not model._meta.proxy and router.allow_migrate(using, model): if use_base_manager: objects = model._base_manager else: objects = model._default_manager queryset = objects.using(using).order_by(model._meta.pk.name) if primary_keys: queryset = queryset.filter(pk__in=primary_keys) for obj in queryset.iterator(): yield obj try: self.stdout.ending = None serializers.serialize(format, get_objects(), indent=indent, use_natural_foreign_keys=use_natural_foreign_keys, use_natural_primary_keys=use_natural_primary_keys, stream=self.stdout) except Exception as e: if show_traceback: raise raise CommandError("Unable to serialize database: %s" % e)
def get_installed(): from django.core.apps import app_cache return [app_config.name for app_config in app_cache.get_app_configs()]
def update_all_contenttypes(verbosity=2, **kwargs): for app_config in app_cache.get_app_configs(only_with_models_module=True): update_contenttypes(app_config.models_module, None, verbosity, **kwargs)
def sync_apps(self, connection, apps): "Runs the old syncdb-style operation on a list of apps." cursor = connection.cursor() # Get a list of already installed *models* so that references work right. tables = connection.introspection.table_names() seen_models = connection.introspection.installed_models(tables) created_models = set() pending_references = {} # Build the manifest of apps and models that are to be synchronized all_models = [ (app_config.label, router.get_migratable_models(app_config.models_module, connection.alias, include_auto_created=True)) for app_config in app_cache.get_app_configs(only_with_models_module=True) if app_config.label in apps ] def model_installed(model): opts = model._meta converter = connection.introspection.table_name_converter # Note that if a model is unmanaged we short-circuit and never try to install it return not ((converter(opts.db_table) in tables) or (opts.auto_created and converter(opts.auto_created._meta.db_table) in tables)) manifest = OrderedDict( (app_name, list(filter(model_installed, model_list))) for app_name, model_list in all_models ) create_models = set(itertools.chain(*manifest.values())) emit_pre_migrate_signal(create_models, self.verbosity, self.interactive, connection.alias) # Create the tables for each model if self.verbosity >= 1: self.stdout.write(" Creating tables...\n") with transaction.atomic(using=connection.alias, savepoint=False): for app_name, model_list in manifest.items(): for model in model_list: # Create the model's database table, if it doesn't already exist. if self.verbosity >= 3: self.stdout.write(" Processing %s.%s model\n" % (app_name, model._meta.object_name)) sql, references = connection.creation.sql_create_model(model, no_style(), seen_models) seen_models.add(model) created_models.add(model) for refto, refs in references.items(): pending_references.setdefault(refto, []).extend(refs) if refto in seen_models: sql.extend(connection.creation.sql_for_pending_references(refto, no_style(), pending_references)) sql.extend(connection.creation.sql_for_pending_references(model, no_style(), pending_references)) if self.verbosity >= 1 and sql: self.stdout.write(" Creating table %s\n" % model._meta.db_table) for statement in sql: cursor.execute(statement) tables.append(connection.introspection.table_name_converter(model._meta.db_table)) # We force a commit here, as that was the previous behaviour. # If you can prove we don't need this, remove it. transaction.set_dirty(using=connection.alias) # The connection may have been closed by a syncdb handler. cursor = connection.cursor() # Install custom SQL for the app (but only if this # is a model we've just created) if self.verbosity >= 1: self.stdout.write(" Installing custom SQL...\n") for app_name, model_list in manifest.items(): for model in model_list: if model in created_models: custom_sql = custom_sql_for_model(model, no_style(), connection) if custom_sql: if self.verbosity >= 2: self.stdout.write(" Installing custom SQL for %s.%s model\n" % (app_name, model._meta.object_name)) try: with transaction.commit_on_success_unless_managed(using=connection.alias): for sql in custom_sql: cursor.execute(sql) except Exception as e: self.stderr.write(" Failed to install custom SQL for %s.%s model: %s\n" % (app_name, model._meta.object_name, e)) if self.show_traceback: traceback.print_exc() else: if self.verbosity >= 3: self.stdout.write(" No custom SQL for %s.%s model\n" % (app_name, model._meta.object_name)) if self.verbosity >= 1: self.stdout.write(" Installing indexes...\n") # Install SQL indices for all newly created models for app_name, model_list in manifest.items(): for model in model_list: if model in created_models: index_sql = connection.creation.sql_indexes_for_model(model, no_style()) if index_sql: if self.verbosity >= 2: self.stdout.write(" Installing index for %s.%s model\n" % (app_name, model._meta.object_name)) try: with transaction.commit_on_success_unless_managed(using=connection.alias): for sql in index_sql: cursor.execute(sql) except Exception as e: self.stderr.write(" Failed to install index for %s.%s model: %s\n" % (app_name, model._meta.object_name, e)) # Load initial_data fixtures (unless that has been disabled) if self.load_initial_data: call_command('loaddata', 'initial_data', verbosity=self.verbosity, database=connection.alias, skip_validation=True) return created_models