PYTHON / DJANGO
Installing Django and starting a project
Install Django into a virtual environment, generate a project skeleton with startproject, and run the development server with confidence about what each command does.
What you will learn
- Create an isolated virtual environment and install a pinned Django version into it
- Generate a project with django-admin startproject, with or without the trailing dot
- Explain why manage.py exists instead of calling django-admin inside a project
- Verify an installation from Python using django.get_version() and call_command
Understanding Installing Django and starting a project
Django is distributed as an ordinary Python package on PyPI, so installing it is just pip install. The complication is which Python it lands in: if you install into the system interpreter and later run a different one, import django fails even though pip reported success. A virtual environment removes that ambiguity by giving the project its own interpreter and its own site-packages, so python, pip, and django-admin on your PATH all belong to the same environment.
Once installed, Django adds a console script called django-admin. Its only job that matters at this stage is startproject, which copies a small template of Python files onto disk and substitutes your project name and a freshly generated SECRET_KEY. Nothing is compiled, nothing is registered globally, and no database is touched; the result is plain source code you own and can edit or delete freely.
The generated manage.py is a thin wrapper that sets the DJANGO_SETTINGS_MODULE environment variable to your project's settings module before handing control to Django's command runner. That is why django-admin works fine for startproject, which needs no settings, but you use python manage.py for runserver, migrate, or shell: those commands need to know which settings file to load, and manage.py answers that question for them.
import os
import tempfile
from django.core.management import call_command
os.chdir(tempfile.mkdtemp())
call_command("startproject", "mysite")
for root, dirs, files in os.walk("mysite"):
dirs[:] = [d for d in dirs if d != "__pycache__"]
for name in sorted(files):
print(os.path.join(root, name))Django is a normal pip-installed package; startproject only writes plain Python files, and manage.py is the entry point that tells Django which settings module to load.
Worked examples
Booting Django without a project
Shows that Django refuses to do anything until a settings object exists, which is exactly what manage.py arranges for you.
import django
from django.conf import settings
settings.configure(
DEBUG=True,
INSTALLED_APPS=["django.contrib.contenttypes", "django.contrib.auth"],
)
django.setup()
from django.apps import apps
print(settings.DEBUG)
for config in apps.get_app_configs():
print(config.label)Example explained
Line 1settings.configure() supplies settings in code instead of from a settings.py module.
Line 2django.setup() populates the app registry; without it, apps.get_app_configs() raises AppRegistryNotReady.
Line 3The import of django.apps is placed after setup() because touching the registry too early is what causes that error.
Line 4manage.py performs the same two steps for you by pointing DJANGO_SETTINGS_MODULE at your project.
Project names startproject rejects
Demonstrates the two validation rules applied to a project name before any files are written.
from django.core.management import call_command
from django.core.management.base import CommandError
for name in ["my-site", "django"]:
try:
call_command("startproject", name)
except CommandError as exc:
print(exc)Example explained
Line 1The project name becomes a package name, so it must satisfy str.isidentifier(): no hyphens, no spaces, no leading digit.
Line 2Django also tries to import the name; if the import succeeds, the name is already taken and would shadow that module.
Line 3Both checks run before anything is created, so a rejected name leaves no half-written directory behind.
Line 4Names like test, json, or email fail the second check for the same reason as django.
Important notes
runserver is a single-process development server with autoreload; it is not meant to serve real traffic and will refuse to be treated as a production server.
The yellow "You have N unapplied migration(s)" warning on first run is expected: the default apps ship with migrations that have not been applied to your empty database yet.
Common mistakes
Installing Django with sudo pip or into the system Python while the editor's terminal runs a different interpreter; import django then raises ModuleNotFoundError even though the install succeeded.
Forgetting the trailing dot in startproject and then running commands one level too high, producing "can't open file 'manage.py': No such file or directory" because manage.py sits inside the outer mysite/ directory.
Naming the project after a module you plan to import, such as django or test; startproject aborts with a CommandError, and forcing a similar name later causes confusing import shadowing.
Try it yourself
Change, predict, then run
Using call_command("startproject", "shopsite") in a temporary directory, generate a project and then print every line of shopsite/manage.py that mentions DJANGO_SETTINGS_MODULE.
Open the Python workspaceCheck your understanding
Why does startproject work with django-admin, while runserver is normally invoked as python manage.py runserver?
- startproject needs no settings, whereas runserver does, and manage.py is what points Django at your project's settings module
- django-admin can only create files, so any command that reads files must go through manage.py
- manage.py contains its own copy of Django, so commands run faster through it
- django-admin is installed globally and cannot see a virtual environment, so it fails inside a project
Show answer
startproject just copies a template, so it has nothing to configure; runserver must load your settings, and manage.py sets DJANGO_SETTINGS_MODULE before delegating to the same command runner django-admin uses. The virtual environment option is wrong because django-admin is installed into the environment alongside Django, and django-admin runserver would in fact work if DJANGO_SETTINGS_MODULE were exported manually.