从django的apps说起

    最近正在重构自己的django项目代码,用的IDE是pycharm。当我在自动创建app时,在每一个app包下自动生成了一个apps.py。我起初是不知道这个模块到底是干什么用的,于是乎就看了官方文档以及django的源代码。

    先简单点说,如果在apps中定义了Appconfig的一个子类,然后定义default_app_config,那么django会在注册应用时,自动加载你定义的配置,否则直接使用默认的APPconfig基类。

    下面深入研究一下工作原理。

    首先得了解一下django的启动流程。当启动django时,会自动注册所有在INSTALLED_APPS中的应用:

  1. django.setup()

        这一步django会导入所有已安装的app,即已添加到INSTALLED_APPS列表中的应用。

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)

    setup函数会配置日志,然后注册settings中定义的INSTALLED_APPS。然后看一下populate实现。

    

populate是django.apps中APPS类的method,具体如下:

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.
        """
       
        # populate() might be called by two threads in parallel on servers
        # that create threads before initializing the WSGI callable.
        with self._lock:
            
            # 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))

上面代码逻辑很简单,如果你在installed_app中定义的是appconfig子类,那直接赋值给app_config;如果你在installed_apps中定义的是一个Python包,那么会创建一个Appconfig实例,AppCOnfig.create(entry);

这里要解释一下,我们在INSTALLED_APPS中可以定义Python包,也可以定义AppConfig的子类,实例如下:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
    #the subclass of AppConfig
    'dashboard.apps.DashConfig',

    总之,不管你是以何种方式在INSTALLED_APPS中添加应用,最终系统都会创建一个AppConfig实例。

    另外还有一点需要注意,就是AppConfig的子类的name不能重复,必须是唯一的,否则会抛出ImproperlyConfigured异常。

    2. 导入Models

    这一步django会导入每个app下的model,默认会搜索app包下的models.py或者models/__init__.py模块。因此我们必须在指定的模块中定义我们的model。

    3. 执行ready方法

    如果你重构了AppConfig的ready方法,那么最后执行该方法。

 

综述:其实一般情况下,如果你没有特殊的要求,没必要单独定义一个AppConfig的子类,Django对此也不是强制要求。

 

 

 

 

 

--------EOF---------
微信分享/微信扫码阅读