Your First Django Project
Introduction
With Django installed in your virtual environment, this chapter creates a project and app, registers the app, wires a Hello Django view to the site root, and runs the development server on http://127.0.0.1:8000/. You will use manage.py for the first time—the CLI entry point for almost all Django work.
Prerequisites
- Django Environment and Installation completed
- Virtual environment activated (
(.venv)in your prompt) - Working directory: e.g.
hello-django/with.venv/inside
Project Layout After This Chapter
We use config as the project package name (common convention). The app is blog.
Step 1: Create the Project
From hello-django/ (only .venv and git files so far):
django-admin startproject config .The trailing . puts manage.py in the current folder instead of a nested config/config/.
Verify:
ls # macOS/Linux
dir # Windows
python manage.py --versionCode explanation:
django-admin— global CLI shipped with Django (uses your venv’s Django)startproject config— creates Python packageconfigwithsettings.py,urls.py, etc.manage.py— project-specific wrapper; prefer it overdjango-adminfor daily tasks
Step 2: Create an Application
python manage.py startapp blogCode explanation:
- A project holds site-wide config; an app is a feature module (blog, users, shop)
blog/getsmodels.py,views.py,admin.py, emptymigrations/
Step 3: Register the App
Edit config/settings.py. Find INSTALLED_APPS and add 'blog':
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"blog", # your app
]Code explanation:
- Django only loads apps listed here (models, admin, templates, static discovery)
- Typo in app name → models/migrations silently missing—double-check spelling
Step 4: Write a View
Edit blog/views.py:
from django.http import HttpResponse
def home(request):
return HttpResponse("Hello Django")Code explanation:
request—HttpRequestwith method, headers, GET/POST dataHttpResponse— plain text or HTML body returned to the browser- Every view accepts
requestas the first argument
Step 5: Wire URLs
App-level URLs
Create blog/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path("", views.home, name="home"),
]Project-level URLs
Edit config/urls.py:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("blog.urls")),
]Code explanation:
include("blog.urls")mounts the app’s URLconf at the site rootname="home"enables{% url 'home' %}andreverse("home")lateradmin/is built-in; you will use it aftercreatesuperuserin a later chapter
Step 6: Run the Development Server
python manage.py runserverDefault: http://127.0.0.1:8000/
Custom port:
python manage.py runserver 8080Verify:
curl http://127.0.0.1:8000/Expected body: Hello Django
Browser: open http://127.0.0.1:8000/ or http://localhost:8000/
Stop the server: Ctrl+C in the terminal.
Warning
Development Server Only
runserver is for local learning. Never expose it to the public internet as production—use Gunicorn + Nginx in deploy chapters.
Step 7: System Check
Before relying on new config, run:
python manage.py checkExpected: System check identified no issues (0 silenced).
Catches common settings.py and URL mistakes early.
manage.py Commands You Will Use Often
| Command | Purpose |
|---|---|
runserver | Start dev server |
check | Validate project configuration |
startapp name | Create a new app |
migrate | Apply database migrations (next chapters) |
makemigrations | Create migration files from models |
createsuperuser | Admin login user |
shell | Django-aware Python REPL |
test | Run tests |
Help:
python manage.py help
python manage.py help migrateDefault Site and Admin (Quick Look)
With server running:
| URL | Expected |
|---|---|
http://127.0.0.1:8000/ | Hello Django |
http://127.0.0.1:8000/admin/ | Admin login (no user yet—setup in Admin chapter) |
Common Problems
| Symptom | Fix |
|---|---|
CommandError: You must set settings.DJANGO_SETTINGS_MODULE | Run commands from folder containing manage.py |
ModuleNotFoundError: No module named 'blog' | Add 'blog' to INSTALLED_APPS |
404 on / | Check config/urls.py includes blog.urls; view wired to "" |
python manage.py uses wrong Django | Activate .venv; check which python |
| Port 8000 in use | runserver 8001 or stop the other process |
| Page shows Django welcome rocket (old tutorial) | You may have a different root view—ensure blog.urls maps "" to home |
Post-Chapter Checklist
-
django-admin startproject config .createdmanage.pyandconfig/ -
blogapp created and listed inINSTALLED_APPS -
blog/views.pyreturns Hello Django -
blog/urls.py+config/urls.pyinclude pattern works -
python manage.py runserver+ browser/curl shows greeting -
python manage.py checkpasses
FAQ
django-admin vs manage.py?
manage.py sets DJANGO_SETTINGS_MODULE for this project. Prefer python manage.py for daily work.
Why project name config?
Avoids clashing with common app names like blog or shop. Any valid Python package name works (mysite, core).
Can I skip creating an app?
Django expects features in apps. Minimal demos can use one app; real projects use several.
Hot reload?
runserver reloads Python code on save. Some settings changes need a manual restart.
SQLite created yet?
Not until you define models and run migrate. No database file required for this Hello view.
Same as Flask app.run()?
Similar developer experience; Django adds manage.py, INSTALLED_APPS, and split project/app layout.