I am attempting to run a Django server as part of a project which, so far, has another package. If only for learning purposes, I'd like to keep it that way for the moment instead of merging both the core and web packages. I have looked at similar questions, but have not found a solution to my specific problem
The tree listed below is the result of running the following command in the root project folder:
django-admin startproject web
.
├── __init__.py
├── core
│ ├── __init__.py
│ ├── __pycache__
│ │ └── __init__.cpython-38.pyc
│ ├── server.py
│ └── task_manager
│ ├── __init__.py
│ ├── __pycache__
│ └── main.py
├── test
├── venv
│ ├...
│ └── pyvenv.cfg
└── web
├── __init__.py
├── __pycache__
│ ...
├── db.sqlite3
├── manage.py
└── web
├── __init__.py
├── __pycache__
├── asgi.py
├── settings.py
├── urls.py
└── wsgi.py
As I want the Django server to be able to access the outer package, my understanding is that I have to cd into the base project directory, and run the web server as such:
python -m web.manage runserver
Since by default the files created by the django-admin createproject contain absolute package references, I changed the "web.XYZ" to "web.web.XYZ" references.
My issue: if I simply run the above command to execute the runserver, I get the following import error:
ModuleNotFoundError: No module named 'web.web'
After some investigation, I found that I could import both files from the sibling package and the current package using the core.XYZ and web.web.XYZ just fine. In fact, modifying the default manage.py code like such:
import os
import sys
import web.web.settings
print('This prints just fine')
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'web.web.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
Yields the following output:
...:ProjectMgmt ...$ python -m web.manage runserver
This prints just fine
Traceback (most recent call last):
File "/Volumes/ProjectMgmt/web/manage.py", line 6, in <module>
import web.web.settings
ModuleNotFoundError: No module named 'web.web'
This leads me to think that "something" is reloading the manage.py module and "something" happened in-between that leads the script to not be able to find the proper package structure. Digging in the Django code, I found the following in the code executed by execute_from_command_line (note the call to autoreload.check_errors), itself called within manage.py:
if settings.configured:
# Start the auto-reloading dev server even if the code is broken.
# The hardcoded condition is a code smell but we can't rely on a
# flag on the command class because we haven't located it yet.
if subcommand == 'runserver' and '--noreload' not in self.argv:
try:
autoreload.check_errors(django.setup)()
except Exception:
# The exception will be raised later in the child process
# started by the autoreloader. Pretend it didn't happen by
# loading an empty list of applications.
apps.all_models = defaultdict(OrderedDict)
apps.app_configs = OrderedDict()
apps.apps_ready = apps.models_ready = apps.ready = True
# In all other cases, django.setup() is required to succeed.
else:
django.setup()
Adding the --noreload argument to my runserver command and executing it from the base project folder actually starts the server just fine and there are no more import errors.
python -m web.manage runserver --noreload
My question: why does this happen and is there anyway to avoid using --noreload ? This feels hacky.