Buckets:
| import inspect | |
| import os | |
| from importlib import import_module | |
| from django.core.exceptions import ImproperlyConfigured | |
| from django.utils.functional import cached_property | |
| from django.utils.module_loading import import_string, module_has_submodule | |
| APPS_MODULE_NAME = "apps" | |
| MODELS_MODULE_NAME = "models" | |
| class AppConfig: | |
| """Class representing a Django application and its configuration.""" | |
| def __init__(self, app_name, app_module): | |
| # Full Python path to the application e.g. 'django.contrib.admin'. | |
| self.name = app_name | |
| # Root module for the application e.g. <module 'django.contrib.admin' | |
| # from 'django/contrib/admin/__init__.py'>. | |
| self.module = app_module | |
| # Reference to the Apps registry that holds this AppConfig. Set by the | |
| # registry when it registers the AppConfig instance. | |
| self.apps = None | |
| # The following attributes could be defined at the class level in a | |
| # subclass, hence the test-and-set pattern. | |
| # Last component of the Python path to the application e.g. 'admin'. | |
| # This value must be unique across a Django project. | |
| if not hasattr(self, "label"): | |
| self.label = app_name.rpartition(".")[2] | |
| if not self.label.isidentifier(): | |
| raise ImproperlyConfigured( | |
| "The app label '%s' is not a valid Python identifier." % self.label | |
| ) | |
| # Human-readable name for the application e.g. "Admin". | |
| if not hasattr(self, "verbose_name"): | |
| self.verbose_name = self.label.title() | |
| # Filesystem path to the application directory e.g. | |
| # '/path/to/django/contrib/admin'. | |
| if not hasattr(self, "path"): | |
| self.path = self._path_from_module(app_module) | |
| # Module containing models e.g. <module 'django.contrib.admin.models' | |
| # from 'django/contrib/admin/models.py'>. Set by import_models(). | |
| # None if the application doesn't have a models module. | |
| self.models_module = None | |
| # Mapping of lowercase model names to model classes. Initially set to | |
| # None to prevent accidental access before import_models() runs. | |
| self.models = None | |
| def __repr__(self): | |
| return "<%s: %s>" % (self.__class__.__name__, self.label) | |
| def default_auto_field(self): | |
| from django.conf import settings | |
| return settings.DEFAULT_AUTO_FIELD | |
| def _is_default_auto_field_overridden(self): | |
| return self.__class__.default_auto_field is not AppConfig.default_auto_field | |
| def _path_from_module(self, module): | |
| """Attempt to determine app's filesystem path from its module.""" | |
| # See #21874 for extended discussion of the behavior of this method in | |
| # various cases. | |
| # Convert to list because __path__ may not support indexing. | |
| paths = list(getattr(module, "__path__", [])) | |
| if len(paths) != 1: | |
| filename = getattr(module, "__file__", None) | |
| if filename is not None: | |
| paths = [os.path.dirname(filename)] | |
| else: | |
| # For unknown reasons, sometimes the list returned by __path__ | |
| # contains duplicates that must be removed (#25246). | |
| paths = list(set(paths)) | |
| if len(paths) > 1: | |
| raise ImproperlyConfigured( | |
| "The app module %r has multiple filesystem locations (%r); " | |
| "you must configure this app with an AppConfig subclass " | |
| "with a 'path' class attribute." % (module, paths) | |
| ) | |
| elif not paths: | |
| raise ImproperlyConfigured( | |
| "The app module %r has no filesystem location, " | |
| "you must configure this app with an AppConfig subclass " | |
| "with a 'path' class attribute." % module | |
| ) | |
| return paths[0] | |
| def create(cls, entry): | |
| """ | |
| Factory that creates an app config from an entry in INSTALLED_APPS. | |
| """ | |
| # create() eventually returns app_config_class(app_name, app_module). | |
| app_config_class = None | |
| app_name = None | |
| app_module = None | |
| # If import_module succeeds, entry points to the app module. | |
| try: | |
| app_module = import_module(entry) | |
| except Exception: | |
| pass | |
| else: | |
| # If app_module has an apps submodule that defines a single | |
| # AppConfig subclass, use it automatically. | |
| # To prevent this, an AppConfig subclass can declare a class | |
| # variable default = False. | |
| # If the apps module defines more than one AppConfig subclass, | |
| # the default one can declare default = True. | |
| if module_has_submodule(app_module, APPS_MODULE_NAME): | |
| mod_path = "%s.%s" % (entry, APPS_MODULE_NAME) | |
| mod = import_module(mod_path) | |
| # Check if there's exactly one AppConfig candidate, | |
| # excluding those that explicitly define default = False. | |
| app_configs = [ | |
| (name, candidate) | |
| for name, candidate in inspect.getmembers(mod, inspect.isclass) | |
| if ( | |
| issubclass(candidate, cls) | |
| and candidate is not cls | |
| and getattr(candidate, "default", True) | |
| ) | |
| ] | |
| if len(app_configs) == 1: | |
| app_config_class = app_configs[0][1] | |
| else: | |
| # Check if there's exactly one AppConfig subclass, | |
| # among those that explicitly define default = True. | |
| app_configs = [ | |
| (name, candidate) | |
| for name, candidate in app_configs | |
| if getattr(candidate, "default", False) | |
| ] | |
| if len(app_configs) > 1: | |
| candidates = [repr(name) for name, _ in app_configs] | |
| raise RuntimeError( | |
| "%r declares more than one default AppConfig: " | |
| "%s." % (mod_path, ", ".join(candidates)) | |
| ) | |
| elif len(app_configs) == 1: | |
| app_config_class = app_configs[0][1] | |
| # Use the default app config class if we didn't find anything. | |
| if app_config_class is None: | |
| app_config_class = cls | |
| app_name = entry | |
| # If import_string succeeds, entry is an app config class. | |
| if app_config_class is None: | |
| try: | |
| app_config_class = import_string(entry) | |
| except Exception: | |
| pass | |
| # If both import_module and import_string failed, it means that entry | |
| # doesn't have a valid value. | |
| if app_module is None and app_config_class is None: | |
| # If the last component of entry starts with an uppercase letter, | |
| # then it was likely intended to be an app config class; if not, | |
| # an app module. Provide a nice error message in both cases. | |
| mod_path, _, cls_name = entry.rpartition(".") | |
| if mod_path and cls_name[0].isupper(): | |
| # We could simply re-trigger the string import exception, but | |
| # we're going the extra mile and providing a better error | |
| # message for typos in INSTALLED_APPS. | |
| # This may raise ImportError, which is the best exception | |
| # possible if the module at mod_path cannot be imported. | |
| mod = import_module(mod_path) | |
| candidates = [ | |
| repr(name) | |
| for name, candidate in inspect.getmembers(mod, inspect.isclass) | |
| if issubclass(candidate, cls) and candidate is not cls | |
| ] | |
| msg = "Module '%s' does not contain a '%s' class." % ( | |
| mod_path, | |
| cls_name, | |
| ) | |
| if candidates: | |
| msg += " Choices are: %s." % ", ".join(candidates) | |
| raise ImportError(msg) | |
| else: | |
| # Re-trigger the module import exception. | |
| import_module(entry) | |
| # Check for obvious errors. (This check prevents duck typing, but | |
| # it could be removed if it became a problem in practice.) | |
| if not issubclass(app_config_class, AppConfig): | |
| raise ImproperlyConfigured("'%s' isn't a subclass of AppConfig." % entry) | |
| # Obtain app name here rather than in AppClass.__init__ to keep | |
| # all error checking for entries in INSTALLED_APPS in one place. | |
| if app_name is None: | |
| try: | |
| app_name = app_config_class.name | |
| except AttributeError: | |
| raise ImproperlyConfigured("'%s' must supply a name attribute." % entry) | |
| # Ensure app_name points to a valid module. | |
| try: | |
| app_module = import_module(app_name) | |
| except ImportError: | |
| raise ImproperlyConfigured( | |
| "Cannot import '%s'. Check that '%s.%s.name' is correct." | |
| % ( | |
| app_name, | |
| app_config_class.__module__, | |
| app_config_class.__qualname__, | |
| ) | |
| ) | |
| # Entry is a path to an app config class. | |
| return app_config_class(app_name, app_module) | |
| def get_model(self, model_name, require_ready=True): | |
| """ | |
| Return the model with the given case-insensitive model_name. | |
| Raise LookupError if no model exists with this name. | |
| """ | |
| if require_ready: | |
| self.apps.check_models_ready() | |
| else: | |
| self.apps.check_apps_ready() | |
| try: | |
| return self.models[model_name.lower()] | |
| except KeyError: | |
| raise LookupError( | |
| "App '%s' doesn't have a '%s' model." % (self.label, model_name) | |
| ) | |
| def get_models(self, include_auto_created=False, include_swapped=False): | |
| """ | |
| Return an iterable of models. | |
| By default, the following models aren't included: | |
| - auto-created models for many-to-many relations without | |
| an explicit intermediate table, | |
| - models that have been swapped out. | |
| Set the corresponding keyword argument to True to include such models. | |
| Keyword arguments aren't documented; they're a private API. | |
| """ | |
| self.apps.check_models_ready() | |
| for model in self.models.values(): | |
| if model._meta.auto_created and not include_auto_created: | |
| continue | |
| if model._meta.swapped and not include_swapped: | |
| continue | |
| yield model | |
| def import_models(self): | |
| # Dictionary of models for this app, primarily maintained in the | |
| # 'all_models' attribute of the Apps this AppConfig is attached to. | |
| self.models = self.apps.all_models[self.label] | |
| if module_has_submodule(self.module, MODELS_MODULE_NAME): | |
| models_module_name = "%s.%s" % (self.name, MODELS_MODULE_NAME) | |
| self.models_module = import_module(models_module_name) | |
| def ready(self): | |
| """ | |
| Override this method in subclasses to run code when Django starts. | |
| """ | |
Xet Storage Details
- Size:
- 11.5 kB
- Xet hash:
- f11b3c0628dd988aeb78ce63255676c887463d4dbf4894f47e77307281805279
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.