How does django manage.py put a project package on sys.path
I read the django doc and some SO posts to know the differences between manage.py and django-admin.py.
They all say:
manage.py is automatically created in each Django project. manage.py is a thin wrapper around django-admin.py that takes care of two things for you before delegating to django-admin.py:
So I checked the scource code of these 2 files(latest version, so it the doc).
Then I am confused. manage.py
does the second thing: sets the DJANGO_SETTINGS_MODULE environment variable. Besides that, I really can not find any differences between these 2 scripts.
[django-admin.py]
#!/usr/bin/env python
from django.core import management
if __name__ == "__main__":
management.execute_from_command_line()
[manage.py]
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
Why? Is the django documentation out of date? Or I missed something here? And where is the code that puts the project's package on sys.path?
The sys.path
is updated here using handle_default_options(options)
statement located here. The execution path is as follows:
execute_from_command_line(argv)
(your manage.py
) utility.execute()
here handle_default_options(options)
here The same method is used by Command
class used as base class for management commands.
From what I can see it's not ./manage.py
who "puts your project's package on sys.path."
The doc says:
sys.path is initialized from these locations:
The installation-dependent default must be what site.py
adds. But it can be disabled with -S
switch. Now then when I run this script ( 1.py
):
import sys
print(sys.path)
I get:
$ python -S ../1.py # to show that it's not current directory that is added
['/path/to/the/script/directory', '/usr/lib/python35.zip', '/usr/lib/python3.5/',
'/usr/lib/python3.5/plat-linux', '/usr/lib/python3.5/lib-dynload']
So, when you run django-admin
, /path/to/env/bin/django-admin
will be the first on the sys.path
. And when ./manage.py
, /path/to/project
.
As such, one can probably say that ./manage.py
"puts your project's package on sys.path," but indirectly, by being at the root of your project.