def test_models_py(self): """ The models in the models.py file were loaded correctly. """ self.assertEqual(apps.get_model("apps", "TotallyNormal"), TotallyNormal) with self.assertRaises(LookupError): apps.get_model("apps", "SoAlternative") with self.assertRaises(LookupError): new_apps.get_model("apps", "TotallyNormal") self.assertEqual(new_apps.get_model("apps", "SoAlternative"), SoAlternative)
def setUpTestData(cls): Site = apps.get_model('sites.Site') current_site = Site.objects.get_current() current_site.flatpage_set.create(url="/foo/", title="foo") current_site.flatpage_set.create(url="/private-foo/", title="private foo", registration_required=True)
def _get_model(model_identifier): """Look up a model from an "app_label.model_name" string.""" try: return apps.get_model(model_identifier) except (LookupError, TypeError): raise base.DeserializationError("Invalid model identifier: '%s'" % model_identifier)
def parse_apps_and_model_labels(labels): """ Parse a list of "app_label.ModelName" or "app_label" strings into actual objects and return a two-element tuple: (set of model classes, set of app_configs). Raise a CommandError if some specified models or apps don't exist. """ apps = set() models = set() for label in labels: if '.' in label: try: model = installed_apps.get_model(label) except LookupError: raise CommandError('Unknown model: %s' % label) models.add(model) else: try: app_config = installed_apps.get_app_config(label) except LookupError as e: raise CommandError(str(e)) apps.add(app_config) return models, apps
def items(self): if not django_apps.is_installed('djmodels.contrib.sites'): raise ImproperlyConfigured( "FlatPageSitemap requires djmodels.contrib.sites, which isn't installed." ) Site = django_apps.get_model('sites.Site') current_site = Site.objects.get_current() return current_site.flatpage_set.filter(registration_required=False)
def test_dynamic_load(self): """ Makes a new model at runtime and ensures it goes into the right place. """ old_models = list(apps.get_app_config("apps").get_models()) # Construct a new model in a new app registry body = {} new_apps = Apps(["apps"]) meta_contents = { 'app_label': "apps", 'apps': new_apps, } meta = type("Meta", (), meta_contents) body['Meta'] = meta body['__module__'] = TotallyNormal.__module__ temp_model = type("SouthPonies", (models.Model,), body) # Make sure it appeared in the right place! self.assertEqual(list(apps.get_app_config("apps").get_models()), old_models) with self.assertRaises(LookupError): apps.get_model("apps", "SouthPonies") self.assertEqual(new_apps.get_model("apps", "SouthPonies"), temp_model)
def kml(request, label, model, field_name=None, compress=False, using=DEFAULT_DB_ALIAS): """ This view generates KML for the given app label, model, and field name. The field name must be that of a geographic field. """ placemarks = [] try: klass = apps.get_model(label, model) except LookupError: raise Http404( 'You must supply a valid app label and module name. Got "%s.%s"' % (label, model)) if field_name: try: field = klass._meta.get_field(field_name) if not isinstance(field, GeometryField): raise FieldDoesNotExist except FieldDoesNotExist: raise Http404('Invalid geometry field.') connection = connections[using] if connection.features.has_AsKML_function: # Database will take care of transformation. placemarks = klass._default_manager.using(using).annotate( kml=AsKML(field_name)) else: # If the database offers no KML method, we use the `kml` # attribute of the lazy geometry instead. placemarks = [] if connection.features.has_Transform_function: qs = klass._default_manager.using(using).annotate( **{'%s_4326' % field_name: Transform(field_name, 4326)}) field_name += '_4326' else: qs = klass._default_manager.using(using).all() for mod in qs: mod.kml = getattr(mod, field_name).kml placemarks.append(mod) # Getting the render function and rendering to the correct. if compress: render = render_to_kmz else: render = render_to_kml return render('gis/kml/placemarks.kml', {'places': placemarks})
def _get_model_from_node(self, node, attr): """ Look up a model from a <object model=...> or a <field rel=... to=...> node. """ model_identifier = node.getAttribute(attr) if not model_identifier: raise base.DeserializationError( "<%s> node is missing the required '%s' attribute" % (node.nodeName, attr)) try: return apps.get_model(model_identifier) except (LookupError, TypeError): raise base.DeserializationError( "<%s> node has invalid model identifier: '%s'" % (node.nodeName, model_identifier))
def shortcut(request, content_type_id, object_id): """ Redirect to an object's page based on a content-type ID and an object ID. """ # Look up the object, making sure it's got a get_absolute_url() function. try: content_type = ContentType.objects.get(pk=content_type_id) if not content_type.model_class(): raise Http404( _("Content type %(ct_id)s object has no associated model") % {'ct_id': content_type_id} ) obj = content_type.get_object_for_this_type(pk=object_id) except (ObjectDoesNotExist, ValueError): raise Http404( _("Content type %(ct_id)s object %(obj_id)s doesn't exist") % {'ct_id': content_type_id, 'obj_id': object_id} ) try: get_absolute_url = obj.get_absolute_url except AttributeError: raise Http404( _("%(ct_name)s objects don't have a get_absolute_url() method") % {'ct_name': content_type.name} ) absurl = get_absolute_url() # Try to figure out the object's domain, so we can do a cross-site redirect # if necessary. # If the object actually defines a domain, we're done. if absurl.startswith(('http://', 'https://', '//')): return HttpResponseRedirect(absurl) # Otherwise, we need to introspect the object's relationships for a # relation to the Site object try: object_domain = get_current_site(request).domain except ObjectDoesNotExist: object_domain = None if apps.is_installed('djmodels.contrib.sites'): Site = apps.get_model('sites.Site') opts = obj._meta for field in opts.many_to_many: # Look for a many-to-many relationship to Site. if field.remote_field.model is Site: site_qs = getattr(obj, field.name).all() if object_domain and site_qs.filter(domain=object_domain).exists(): # The current site's domain matches a site attached to the # object. break # Caveat: In the case of multiple related Sites, this just # selects the *first* one, which is arbitrary. site = site_qs.first() if site: object_domain = site.domain break else: # No many-to-many relationship to Site found. Look for a # many-to-one relationship to Site. for field in obj._meta.fields: if field.remote_field and field.remote_field.model is Site: try: site = getattr(obj, field.name) except Site.DoesNotExist: continue if site is not None: object_domain = site.domain break # If all that malarkey found an object domain, use it. Otherwise, fall back # to whatever get_absolute_url() returned. if object_domain is not None: protocol = request.scheme return HttpResponseRedirect('%s://%s%s' % (protocol, object_domain, absurl)) else: return HttpResponseRedirect(absurl)
def test_get_model(self): """ Tests apps.get_model(). """ self.assertEqual(apps.get_model('admin', 'LogEntry'), LogEntry) with self.assertRaises(LookupError): apps.get_model('admin', 'LogExit') # App label is case-sensitive, Model name is case-insensitive. self.assertEqual(apps.get_model('admin', 'loGentrY'), LogEntry) with self.assertRaises(LookupError): apps.get_model('Admin', 'LogEntry') # A single argument is accepted. self.assertEqual(apps.get_model('admin.LogEntry'), LogEntry) with self.assertRaises(LookupError): apps.get_model('admin.LogExit') with self.assertRaises(ValueError): apps.get_model('admin_LogEntry')
def sort_dependencies(app_list): """Sort a list of (app_config, models) pairs into a single list of models. The single list of models is sorted so that any model with a natural key is serialized before a normal model, and any model with a natural key dependency has it's dependencies serialized first. """ # Process the list of models, and get the list of dependencies model_dependencies = [] models = set() for app_config, model_list in app_list: if model_list is None: model_list = app_config.get_models() for model in model_list: models.add(model) # Add any explicitly defined dependencies if hasattr(model, 'natural_key'): deps = getattr(model.natural_key, 'dependencies', []) if deps: deps = [apps.get_model(dep) for dep in deps] else: deps = [] # Now add a dependency for any FK relation with a model that # defines a natural key for field in model._meta.fields: if field.remote_field: rel_model = field.remote_field.model if hasattr(rel_model, 'natural_key') and rel_model != model: deps.append(rel_model) # Also add a dependency for any simple M2M relation with a model # that defines a natural key. M2M relations with explicit through # models don't count as dependencies. for field in model._meta.many_to_many: if field.remote_field.through._meta.auto_created: rel_model = field.remote_field.model if hasattr(rel_model, 'natural_key') and rel_model != model: deps.append(rel_model) model_dependencies.append((model, deps)) model_dependencies.reverse() # Now sort the models to ensure that dependencies are met. This # is done by repeatedly iterating over the input list of models. # If all the dependencies of a given model are in the final list, # that model is promoted to the end of the final list. This process # continues until the input list is empty, or we do a full iteration # over the input models without promoting a model to the final list. # If we do a full iteration without a promotion, that means there are # circular dependencies in the list. model_list = [] while model_dependencies: skipped = [] changed = False while model_dependencies: model, deps = model_dependencies.pop() # If all of the models in the dependency list are either already # on the final model list, or not on the original serialization list, # then we've found another model with all it's dependencies satisfied. if all(d not in models or d in model_list for d in deps): model_list.append(model) changed = True else: skipped.append((model, deps)) if not changed: raise RuntimeError( "Can't resolve dependencies for %s in serialized app list." % ', '.join('%s.%s' % (model._meta.app_label, model._meta.object_name) for model, deps in sorted( skipped, key=lambda obj: obj[0].__name__))) model_dependencies = skipped return model_list
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 model_class(self): """Return the model class for this type of content.""" try: return apps.get_model(self.app_label, self.model) except LookupError: return None
def test_get_model_only_returns_installed_models(self): with self.assertRaises(LookupError): apps.get_model("not_installed", "NotInstalledModel")