def render(self, include_real=None, ignore_swappable=False, skip_cache=False): "Turns the project state into actual models in a new Apps" if self.apps is None or skip_cache: # Any apps in self.real_apps should have all their models included # in the render. We don't use the original model instances as there # are some variables that refer to the Apps object. # FKs/M2Ms from real apps are also not included as they just # mess things up with partial states (due to lack of dependencies) real_models = [] for app_label in self.real_apps: app = global_apps.get_app_config(app_label) for model in app.get_models(): real_models.append(ModelState.from_model(model, exclude_rels=True)) # Populate the app registry with a stub for each application. app_labels = set(model_state.app_label for model_state in self.models.values()) self.apps = Apps([AppConfigStub(label) for label in sorted(self.real_apps + list(app_labels))]) # We keep trying to render the models in a loop, ignoring invalid # base errors, until the size of the unrendered models doesn't # decrease by at least one, meaning there's a base dependency loop/ # missing base. unrendered_models = list(self.models.values()) + real_models while unrendered_models: new_unrendered_models = [] for model in unrendered_models: try: model.render(self.apps) except InvalidBasesError: new_unrendered_models.append(model) if len(new_unrendered_models) == len(unrendered_models): raise InvalidBasesError( "Cannot resolve bases for %r\nThis can happen if you are inheriting models from an " "app with migrations (e.g. contrib.auth)\n in an app with no migrations; see " "https://docs.djangoproject.com/en/1.7/topics/migrations/#dependencies " "for more" % new_unrendered_models ) unrendered_models = new_unrendered_models # make sure apps has no dangling references if self.apps._pending_lookups: # There's some lookups left. See if we can first resolve them # ourselves - sometimes fields are added after class_prepared is sent for lookup_model, operations in self.apps._pending_lookups.items(): try: model = self.apps.get_model(lookup_model[0], lookup_model[1]) except LookupError: app_label = "%s.%s" % (lookup_model[0], lookup_model[1]) if app_label == settings.AUTH_USER_MODEL and ignore_swappable: continue # Raise an error with a best-effort helpful message # (only for the first issue). Error message should look like: # "ValueError: Lookup failed for model referenced by # field migrations.Book.author: migrations.Author" msg = "Lookup failed for model referenced by field {field}: {model[0]}.{model[1]}" raise ValueError(msg.format(field=operations[0][1], model=lookup_model)) else: do_pending_lookups(model) try: return self.apps finally: if skip_cache: self.apps = None
def __init__(self, real_apps, models, ignore_swappable=False): # Any apps in self.real_apps should have all their models included # in the render. We don't use the original model instances as there # are some variables that refer to the Apps object. # FKs/M2Ms from real apps are also not included as they just # mess things up with partial states (due to lack of dependencies) self.real_models = [] for app_label in real_apps: app = global_apps.get_app_config(app_label) for model in app.get_models(): self.real_models.append(ModelState.from_model(model, exclude_rels=True)) # Populate the app registry with a stub for each application. app_labels = {model_state.app_label for model_state in models.values()} app_configs = [AppConfigStub(label) for label in sorted(real_apps + list(app_labels))] super(StateApps, self).__init__(app_configs) self.render_multiple(list(models.values()) + self.real_models) # If there are some lookups left, see if we can first resolve them # ourselves - sometimes fields are added after class_prepared is sent for lookup_model, operations in self._pending_lookups.items(): try: model = self.get_model(lookup_model[0], lookup_model[1]) except LookupError: app_label = "%s.%s" % (lookup_model[0], lookup_model[1]) if app_label == settings.AUTH_USER_MODEL and ignore_swappable: continue # Raise an error with a best-effort helpful message # (only for the first issue). Error message should look like: # "ValueError: Lookup failed for model referenced by # field migrations.Book.author: migrations.Author" msg = "Lookup failed for model referenced by field {field}: {model[0]}.{model[1]}" raise ValueError(msg.format(field=operations[0][1], model=lookup_model)) else: do_pending_lookups(model)
def render(self, include_real=None): "Turns the project state into actual models in a new Apps" if self.apps is None: # Any apps in self.real_apps should have all their models included # in the render. We don't use the original model instances as there # are some variables that refer to the Apps object. real_models = [] for app_label in self.real_apps: app = global_apps.get_app_config(app_label) for model in app.get_models(): real_models.append(ModelState.from_model(model)) # Populate the app registry with a stub for each application. app_labels = set(model_state.app_label for model_state in self.models.values()) self.apps = Apps([AppConfigStub(label) for label in sorted(self.real_apps + list(app_labels))]) # We keep trying to render the models in a loop, ignoring invalid # base errors, until the size of the unrendered models doesn't # decrease by at least one, meaning there's a base dependency loop/ # missing base. unrendered_models = list(self.models.values()) + real_models while unrendered_models: new_unrendered_models = [] for model in unrendered_models: try: model.render(self.apps) except InvalidBasesError: new_unrendered_models.append(model) if len(new_unrendered_models) == len(unrendered_models): raise InvalidBasesError("Cannot resolve bases for %r" % new_unrendered_models) unrendered_models = new_unrendered_models # make sure apps has no dangling references if self.apps._pending_lookups: # There's some lookups left. See if we can first resolve them # ourselves - sometimes fields are added after class_prepared is sent for lookup_model, operations in self.apps._pending_lookups.items(): try: model = self.apps.get_model(lookup_model[0], lookup_model[1]) except LookupError: # If the lookup failed to something that looks like AUTH_USER_MODEL, # give a better error message about how you can't change it (#22563) extra_message = "" if "%s.%s" % (lookup_model[0], lookup_model[1]) == settings.AUTH_USER_MODEL: extra_message = ( "\nThe missing model matches AUTH_USER_MODEL; if you've changed the value of this" + "\nsetting after making a migration, be aware that this is not supported. If you" + "\nchange AUTH_USER_MODEL you must delete and recreate migrations for its app." ) # Raise an error with a best-effort helpful message # (only for the first issue). Error message should look like: # "ValueError: Lookup failed for model referenced by # field migrations.Book.author: migrations.Author" raise ValueError("Lookup failed for model referenced by field {field}: {model[0]}.{model[1]}{extra_message}".format( field = operations[0][1], model = lookup_model, extra_message = extra_message, )) else: do_pending_lookups(model) return self.apps
def __init__(self, real_apps, models, ignore_swappable=False): # Any apps in self.real_apps should have all their models included # in the render. We don't use the original model instances as there # are some variables that refer to the Apps object. # FKs/M2Ms from real apps are also not included as they just # mess things up with partial states (due to lack of dependencies) real_models = [] for app_label in real_apps: app = global_apps.get_app_config(app_label) for model in app.get_models(): real_models.append( ModelState.from_model(model, exclude_rels=True)) # Populate the app registry with a stub for each application. app_labels = {model_state.app_label for model_state in models.values()} app_configs = [ AppConfigStub(label) for label in sorted(real_apps + list(app_labels)) ] super(StateApps, self).__init__(app_configs) # We keep trying to render the models in a loop, ignoring invalid # base errors, until the size of the unrendered models doesn't # decrease by at least one, meaning there's a base dependency loop/ # missing base. unrendered_models = list(models.values()) + real_models while unrendered_models: new_unrendered_models = [] for model in unrendered_models: try: model.render(self) except InvalidBasesError: new_unrendered_models.append(model) if len(new_unrendered_models) == len(unrendered_models): raise InvalidBasesError( "Cannot resolve bases for %r\nThis can happen if you are inheriting models from an " "app with migrations (e.g. contrib.auth)\n in an app with no migrations; see " "https://docs.djangoproject.com/en/%s/topics/migrations/#dependencies " "for more" % (new_unrendered_models, get_docs_version())) unrendered_models = new_unrendered_models # If there are some lookups left, see if we can first resolve them # ourselves - sometimes fields are added after class_prepared is sent for lookup_model, operations in self._pending_lookups.items(): try: model = self.get_model(lookup_model[0], lookup_model[1]) except LookupError: app_label = "%s.%s" % (lookup_model[0], lookup_model[1]) if app_label == settings.AUTH_USER_MODEL and ignore_swappable: continue # Raise an error with a best-effort helpful message # (only for the first issue). Error message should look like: # "ValueError: Lookup failed for model referenced by # field migrations.Book.author: migrations.Author" msg = "Lookup failed for model referenced by field {field}: {model[0]}.{model[1]}" raise ValueError( msg.format(field=operations[0][1], model=lookup_model)) else: do_pending_lookups(model)
def render(self, include_real=None, ignore_swappable=False, skip_cache=False): "Turns the project state into actual models in a new Apps" if self.apps is None or skip_cache: # Any apps in self.real_apps should have all their models included # in the render. We don't use the original model instances as there # are some variables that refer to the Apps object. # FKs/M2Ms from real apps are also not included as they just # mess things up with partial states (due to lack of dependencies) real_models = [] for app_label in self.real_apps: app = global_apps.get_app_config(app_label) for model in app.get_models(): real_models.append(ModelState.from_model(model, exclude_rels=True)) # Populate the app registry with a stub for each application. app_labels = set(model_state.app_label for model_state in self.models.values()) self.apps = Apps([AppConfigStub(label) for label in sorted(self.real_apps + list(app_labels))]) # We keep trying to render the models in a loop, ignoring invalid # base errors, until the size of the unrendered models doesn't # decrease by at least one, meaning there's a base dependency loop/ # missing base. unrendered_models = list(self.models.values()) + real_models while unrendered_models: new_unrendered_models = [] for model in unrendered_models: try: model.render(self.apps) except InvalidBasesError: new_unrendered_models.append(model) if len(new_unrendered_models) == len(unrendered_models): raise InvalidBasesError("Cannot resolve bases for %r" % new_unrendered_models) unrendered_models = new_unrendered_models # make sure apps has no dangling references if self.apps._pending_lookups: # There's some lookups left. See if we can first resolve them # ourselves - sometimes fields are added after class_prepared is sent for lookup_model, operations in self.apps._pending_lookups.items(): try: model = self.apps.get_model(lookup_model[0], lookup_model[1]) except LookupError: if "%s.%s" % (lookup_model[0], lookup_model[1]) == settings.AUTH_USER_MODEL and ignore_swappable: continue # Raise an error with a best-effort helpful message # (only for the first issue). Error message should look like: # "ValueError: Lookup failed for model referenced by # field migrations.Book.author: migrations.Author" raise ValueError("Lookup failed for model referenced by field {field}: {model[0]}.{model[1]}".format( field=operations[0][1], model=lookup_model, )) else: do_pending_lookups(model) try: return self.apps finally: if skip_cache: self.apps = None