赞0
摘要
django的project由多个app组成。project的设置由setting指定,而每个app的设置由AppConfig指定。app和project主要由INSTALL_APPS联系,也有url和middleware等等。
AppConfig既然是app的设置类,那么它有哪些属性?
通过__init__方法初始化的属性:
1
2
|
name: app的路径名 比如:django.contrib.admin
module: app的模块
|
通过继承AppConfig,定义类属性:
1
2
3
|
label:唯一的名字,默认是name的最后部分。比如:admin
verbose_name: 别名。默认为label.title( )
path:app的文件路径名。
|
django自动生成的属性:
1
2
|
models_module 对应app下面model模块
models 字典 {model_name: model_class}
|
然后再看看怎么在django中,设置自己的Appconfig:
Appconfig主要由它的类方法create(cls, entry)来实例化。
entry即为setting中的INSTALLED_APPS的元素。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
@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)
|
整个导入流程如图所示:
可以看见有两个方法,一个是指明AppConfig的位置,模块名.类名。
1
2
3
4
5
6
7
|
# settings.py
INSTALLED_APPS
=
(
...,
'rock_n_roll.apps.RockNRollConfig'
,
...
)
|
二是在模块__init__.py文件中,声明default_app_config属性。default_app_config为字符串,指定AppConfig的位置。
引用官网的例子:
rock_n_roll是一个app。这是下面的app.py文件
1
2
3
4
5
6
|
# rock_n_roll/apps.py
from
django.apps
import
AppConfigclass
RockNRollConfig(AppConfig):
name
=
'rock_n_roll'
verbose_name
=
"Rock ’n’ roll"
|
1
2
3
|
# rock_n_roll/__init__.py
default_app_config
=
'rock_n_roll.apps.RockNRollConfig'
|
不过一般使用第二种比较多,因为这样保证了INSTALLED_APPS设置的一致性。