从django的apps说起
最近正在重构自己的django项目代码,用的IDE是pycharm。当我在自动创建app时,在每一个app包下自动生成了一个apps.py。我起初是不知道这个模块到底是干什么用的,于是乎就看了官方文档以及django的源代码。
先简单点说,如果在apps中定义了Appconfig的一个子类,然后定义default_app_config,那么django会在注册应用时,自动加载你定义的配置,否则直接使用默认的APPconfig基类。
下面深入研究一下工作原理。
首先得了解一下django的启动流程。当启动django时,会自动注册所有在INSTALLED_APPS中的应用:
- 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对此也不是强制要求。
微信分享/微信扫码阅读