我在使用Django时经常遇到这种情况,因为很多功能都是从manage.py脚本执行的,但我也想让我的一些模块也可以直接作为脚本运行(理想情况下,你可以让它们成为manage.py指令,但我们还没有)。
这是这样一个项目可能看起来的模型;
├── dj_app
│ ├── models.py
│ ├── ops
│ │ ├── bar.py
│ │ └── foo.py
│ ├── script.py
│ ├── tests.py
│ ├── utils.py
│ └── views.py
└── manage.py
这里的重要部分是manage.py、dj_app/script.py和dj_app/tests.py。我们还有子模块dj_app/ops/bar.py和dj_app/ops/foo.py,它们包含了我们希望在整个项目中使用的更多项目。
问题的根源通常是希望您的dj_app/script.py脚本方法在dj_app/tests.py中包含测试用例,当您运行manage.py测试时会调用这些测试用例。
这是我如何设置项目及其导入的;
# dj_app/ops/foo.py
# Foo operation methods and classes
foo_val = "foo123"
.
# dj_app/ops/bar.py
# Bar operations methods and classes
bar_val = "bar123"
.
# dj_app/script.py
# script to run app methods from CLI
# if run directly from command line
if __name__ == '__main__':
from ops.bar import bar_val
from ops.foo import foo_val
# otherwise
else:
from .ops.bar import bar_val
from .ops.foo import foo_val
def script_method1():
print("this is script_method1")
print("bar_val: {}".format(bar_val))
print("foo_val: {}".format(foo_val))
if __name__ == '__main__':
print("running from the script")
script_method1()
.
# dj_app/tests.py
# test cases for the app
# do not run this directly from CLI or the imports will break
from .script import script_method1
from .ops.bar import bar_val
from .ops.foo import foo_val
def main():
print("Running the test case")
print("testing script method")
script_method1()
if __name__ == '__main__':
print("running tests from command line")
main()
.
# manage.py
# just run the test cases for this example
import dj_app.tests
dj_app.tests.main()
.
从manage.py运行测试用例;
$ python3 manage.py
Running the test case
testing script method
this is script_method1
bar_val: bar123
foo_val: foo123
自行运行脚本;
$ python3 dj_app/script.py
running from the script
this is script_method1
bar_val: bar123
foo_val: foo123
请注意,如果尝试直接运行test.py,则会出现错误,因此不要这样做;
$ python3 dj_app/tests.py
Traceback (most recent call last):
File "dj_app/tests.py", line 5, in <module>
from .script import script_method1
ModuleNotFoundError: No module named '__main__.script'; '__main__' is not a package
如果我遇到了更复杂的进口情况,我通常会执行这样的操作来破解它;
import os
import sys
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
sys.path.insert(0, THIS_DIR)
from script import script_method1
sys.path.pop(0)