How it works...
A module is meant to be under the Python path if you can run Python and import that module. One of the ways to put a module under the Python path is to modify the sys.path variable before importing a module that is in an unusual location. The value of sys.path, as specified by the settings.py file, is a list of directories starting with an empty string for the current directory, followed by the directories in the project, and finally the globally shared directories of the Python installation. You can see the value of sys.path in the Python shell, as follows:
(myproject)$ ./manage.py shell
>>> import sys
>>> sys.path
The same could be done for a Docker project, assuming the container name were django_myproject_app_1, as follows:
myproject_docker/$ docker exec -it django_myproject_app_1 \
> python3 manage.py shell
>>> import sys
>>> sys.path
When trying to import a module, Python searches for the module in this list and returns the first result that is found.
Therefore, we first define the BASE_DIR variable, which is the absolute path to one level higher than the settings.py file. Then, we define the EXTERNAL_LIBS_PATH and EXTERNAL_APPS_PATH variables, which are relative to BASE_DIR. Lastly, we modify the sys.path property, adding new paths to the beginning of the list. Note that we also add an empty string as the first path to search, which means that the current directory of any module should always be checked first before checking other Python paths.