Форум сайта python.su
Здравствуйте вот разбираюсь как начиная с файла wsgi.py формируются списки приложений и их моделей, да и вообще как собираются такие данные как *args, **kwds, в простом случае они могут браться при вызове программы из терминала или при формировании url, но тут пока не могу понять как они образуются. Буду прописывать цепочку скрипта до того момента где мне не понятно что происходит.
import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings") from django.core.wsgi import get_wsgi_application application = get_wsgi_application()
def get_wsgi_application(): """ The public interface to Django's WSGI support. Should return a WSGI callable. Allows us to avoid making django.core.handlers.WSGIHandler public API, in case the internal WSGI implementation changes or moves in the future. """ django.setup() return WSGIHandler()
def setup(): """ Configure the settings (this happens as a side effect of accessing the first setting), configure logging and populate the app registry. """ from django.apps import apps from django.conf import settings from django.utils.log import configure_logging configure_logging(settings.LOGGING_CONFIG, settings.LOGGING) apps.populate(settings.INSTALLED_APPS)
class Apps(object): def __init__(self, installed_apps=()): self.all_models = defaultdict(OrderedDict) apps = Apps(installed_apps=None)
class OrderedDict(dict): 'Dictionary that remembers insertion order' # An inherited dict maps keys to values. # The inherited dict provides __getitem__, __len__, __contains__, and get. # The remaining methods are order-aware. # Big-O running times for all methods are the same as regular dictionaries. # The internal self.__map dict maps keys to links in a doubly linked list. # The circular doubly linked list starts and ends with a sentinel element. # The sentinel element never gets deleted (this simplifies the algorithm). # Each link is stored as a list of length three: [PREV, NEXT, KEY]. def __init__(self, *args, **kwds): '''Initialize an ordered dictionary. The signature is the same as regular dictionaries, but keyword arguments are not recommended because their insertion order is arbitrary. ''' if len(args) > 1: raise TypeError('expected at most 1 arguments, got %d' % len(args)) try: self.__root except AttributeError: self.__root = root = [] # sentinel node root[:] = [root, root, None] self.__map = {} self.__update(*args, **kwds)
Офлайн
serrrgggeee
как видно в init используются вот эти саммые данные, но вот не могу понять от куда они берутся
def foo(*args, **kwargs): print(args, kwargs) foo()
Офлайн
ну тогда приложения формируются здесь
if installed_apps is not None: self.populate(installed_apps)
def populate(self, installed_apps=None): """ Loads application configurations and models. This method imports each application module and then each model module. It is thread safe and idempotent, but not reentrant. """ if self.ready: return # populate() might be called by two threads in parallel on servers # that create threads before initializing the WSGI callable. with self._lock: if self.ready: return # app_config should be pristine, otherwise the code below won't # guarantee that the order matches the order in INSTALLED_APPS. if self.app_configs: raise RuntimeError("populate() isn't reentrant") # Load app configs and app modules. for entry in installed_apps: if isinstance(entry, AppConfig): app_config = entry else: app_config = AppConfig.create(entry) if app_config.label in self.app_configs: raise ImproperlyConfigured( "Application labels aren't unique, " "duplicates: %s" % app_config.label) self.app_configs[app_config.label] = app_config # Check for duplicate app names. counts = Counter( app_config.name for app_config in self.app_configs.values()) duplicates = [ name for name, count in counts.most_common() if count > 1] if duplicates: raise ImproperlyConfigured( "Application names aren't unique, " "duplicates: %s" % ", ".join(duplicates)) self.apps_ready = True # Load models. for app_config in self.app_configs.values(): all_models = self.all_models[app_config.label] app_config.import_models(all_models) self.clear_cache() self.models_ready = True for app_config in self.get_app_configs(): app_config.ready() self.ready = True
app_config = AppConfig.create(entry)
class AppConfig(object): """ Class representing a Django application and its configuration. """ def __init__(self, app_name, app_module): # Full Python path to the application eg. 'django.contrib.admin'. self.name = app_name # Root module for the application eg. <module 'django.contrib.admin' # from 'django/contrib/admin/__init__.pyc'>. self.module = app_module # 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 eg. 'admin'. # This value must be unique across a Django project. if not hasattr(self, 'label'): self.label = app_name.rpartition(".")[2] # Human-readable name for the application eg. "Admin". if not hasattr(self, 'verbose_name'): self.verbose_name = self.label.title() # Filesystem path to the application directory eg. # u'/usr/lib/python2.7/dist-packages/django/contrib/admin'. Unicode on # Python 2 and a str on Python 3. if not hasattr(self, 'path'): self.path = self._path_from_module(app_module) # Module containing models eg. <module 'django.contrib.admin.models' # from 'django/contrib/admin/models.pyc'>. Set by import_models(). # None if the application doesn't have a models module. self.models_module = None # Mapping of lower case 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)
@classmethod def create(cls, entry): """ Factory that creates an app config from an entry in INSTALLED_APPS. """ try: # If import_module succeeds, entry is a path to an app module, # which may specify an app config class with default_app_config. # Otherwise, entry is a path to an app config class or an error. module = import_module(entry) except ImportError: # Track that importing as an app module failed. If importing as an # app config class fails too, we'll trigger the ImportError again. module = None mod_path, _, cls_name = entry.rpartition('.') # Raise the original exception when entry cannot be a path to an # app config class. if not mod_path: raise else: try: # If this works, the app module specifies an app config class. entry = module.default_app_config except AttributeError: # Otherwise, it simply uses the default app config class. return cls(entry, module) else: mod_path, _, cls_name = entry.rpartition('.') # If we're reaching this point, we must attempt to load the app config # class located at <mod_path>.<cls_name> # Avoid django.utils.module_loading.import_by_path because it # masks errors -- it reraises ImportError as ImproperlyConfigured. mod = import_module(mod_path) try: cls = getattr(mod, cls_name) except AttributeError: if module is None: # If importing as an app module failed, that error probably # contains the most informative traceback. Trigger it again. import_module(entry) else: raise # Check for obvious errors. (This check prevents duck typing, but # it could be removed if it became a problem in practice.) if not issubclass(cls, 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. try: app_name = cls.name except AttributeError: raise ImproperlyConfigured( "'%s' must supply a name attribute." % entry) # Ensure app_name points to a valid module. app_module = import_module(app_name) # Entry is a path to an app config class. return cls(app_name, app_module)
Офлайн
Вообще не пользуюсь джангой, но все же вставлю свои 5 копеек
О боги, сколько комментариев… По количеству строк их больше чем кода
Отредактировано 4kpt_III (Ноя. 7, 2015 14:57:40)
Офлайн
4kpt_III
Это такой стиль программирования, к Джанге он не относится, я видел такие проекты и на Си. Обычно такой стиль свойственен проектам где много участников, которые чаще всего сосредоточены на своей отдельной тематике, но иногда ходят и дальше нее. Держать все в голове иногда не удается и такие вот комментарии позволяют быстро освежить память.
serrrgggeee
Возьмите отладчик и пройдитесь по выполнению кода, увидите поэтапно что происходит и значения всех необходимых переменных. Debugger можно взять как встроенный pdb , так и воспользоваться IDE типа PyCHarm, Pydev и тп
Офлайн
4kpt_III
ах да, совсем забыл про автоматическую генерацию документации по докстрингам, типа как Sphinx позволяет делать и тп
Офлайн
JOHN_16
Это такой стиль программирования, к Джанге он не относится, я видел такие проекты и на Си. Обычно такой стиль свойственен проектам где много участников, которые чаще всего сосредоточены на своей отдельной тематике, но иногда ходят и дальше нее. Держать все в голове иногда не удается и такие вот комментарии позволяют быстро освежить память.
JOHN_16
ах да, совсем забыл про автоматическую генерацию документации по докстрингам, типа как Sphinx позволяет делать и тп
Офлайн
Вопрос решен.
Офлайн