Найти - Пользователи
Полная версия: создание списка приложений и их моделей
Начало » Python для экспертов » создание списка приложений и их моделей
1
serrrgggeee
Здравствуйте вот разбираюсь как начиная с файла 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()
Здесь все начинается и весь результат попадает в переменную application формирование этих значений *args, **kwds пока не вижу двигаемся дальше

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()
здесь меня интересует только django.setup() в которой
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)
формирование apps тоесть from django.apps import apps

class Apps(object):                                                                                                                                
    def __init__(self, installed_apps=()):                                      
      
       self.all_models = defaultdict(OrderedDict)       
apps = Apps(installed_apps=None)                        

довольно большой класс но тут меня интересует только вот эта строка self.all_models = defaultdict(OrderedDict) здесь как можно предположить формируется объект моделей. Да при вызове этого файла сразу формируется объект apps = Apps(installed_apps=None) но опять порядковых и именнованых переменных я не встречаю которые нужны будут при создании объекта OrderedDict который будет нужен при создании объекта используя класс defaultdict(OrderedDict)
вот сам класс OrderedDict. Вот час кода
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)
как видно в init используются вот эти саммые данные, но вот не могу понять от куда они берутся
FishHook
serrrgggeee
как видно в init используются вот эти саммые данные, но вот не могу понять от куда они берутся

Наличие *args и **kwargs в объявлении функции вовсе не обязывает в эту функцию что-либо передавать.
def foo(*args, **kwargs):
   print(args, kwargs)
foo()
serrrgggeee
ну тогда приложения формируются здесь
if installed_apps is not None:    
    self.populate(installed_apps) 
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                                                               
                                                                                        
теперь здесь installed_apps = none
вот тут формируется
 app_config = AppConfig.create(entry) 
так как installed_apps = none то entry тоже none
вот класс AppConfig c с которого получается объект но здесь конкретно идет обращение к методу create, но все равно должна как я понимаю отработать эта часть

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)

но опять же здесь def __init__(self, app_name, app_module):
я не вижу где определяются app_name и app_module, а уже после этого должен сработать метод

 @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)
или я чтото опять не улавливаю в python?
4kpt_III
Вообще не пользуюсь джангой, но все же вставлю свои 5 копеек
О боги, сколько комментариев… По количеству строк их больше чем кода
JOHN_16
4kpt_III
Это такой стиль программирования, к Джанге он не относится, я видел такие проекты и на Си. Обычно такой стиль свойственен проектам где много участников, которые чаще всего сосредоточены на своей отдельной тематике, но иногда ходят и дальше нее. Держать все в голове иногда не удается и такие вот комментарии позволяют быстро освежить память.
serrrgggeee
Возьмите отладчик и пройдитесь по выполнению кода, увидите поэтапно что происходит и значения всех необходимых переменных. Debugger можно взять как встроенный pdb , так и воспользоваться IDE типа PyCHarm, Pydev и тп
JOHN_16
4kpt_III
ах да, совсем забыл про автоматическую генерацию документации по докстрингам, типа как Sphinx позволяет делать и тп
4kpt_III
JOHN_16
Это такой стиль программирования, к Джанге он не относится, я видел такие проекты и на Си. Обычно такой стиль свойственен проектам где много участников, которые чаще всего сосредоточены на своей отдельной тематике, но иногда ходят и дальше нее. Держать все в голове иногда не удается и такие вот комментарии позволяют быстро освежить память.

А я где-то сказал, что это именно джанга? Я имел ввиду, что помочь не смогу, потому, что не использую джангу. Ну а стиль кода я такой видел даже когда люди делали простой гуй.

JOHN_16
ах да, совсем забыл про автоматическую генерацию документации по докстрингам, типа как Sphinx позволяет делать и тп

Пробовал? Там докстринги и они должны специальным образом форматироваться.
serrrgggeee
Вопрос решен.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB