Video coming soon

The recording for this lesson has not been published yet.

What we cover

  • Cloning the reference blog project
  • Virtual environments with venv
  • requirements.txt and pinned versions
  • Running migrations and the development server

Lesson notes

1. Why we all start from the same code

Your tutorial blog is yours, and you should keep it. But from lesson 1.1 onwards the notes will say things like "open blog/managers.py" - and that only works if we agree on what the project looks like today. The starter repository is that agreement: the Django Girls blog, unchanged in behaviour, with nothing added yet.

Get it running now. Every later lesson assumes you can start this project in under a minute.

2. Clone it

git clone https://github.com/example/more-about-django-starter.git myblog
cd myblog
git log --oneline -3

The last command should show three commits and nothing else. A short history is deliberate: in lesson 0.3 you will add your own commits on top and be able to tell them apart at a glance.

3. A virtual environment, and what it actually is

A virtual environment is a directory with its own python and its own site-packages. Installing into it cannot break another project and cannot break your operating system's Python. One environment per project, always, and never committed to git.

python -m venv .venv

# Linux and macOS
source .venv/bin/activate

# Windows PowerShell
.venv\Scripts\Activate.ps1

# Windows cmd
.venv\Scripts\activate.bat

Your prompt now starts with (.venv). Verify that you are really inside it before installing anything:

which python      # .../myblog/.venv/bin/python   (Windows: where python)
python -V         # Python 3.12.x
pip -V            # pip ... from .../myblog/.venv/lib/...
system python3.12 never install here myblog/.venv Django 5.2, psycopg 3.2 requirements.txt of this course otherproject/.venv Django 3.2, old libraries completely unaffected

4. requirements.txt and pinned versions

python -m pip install --upgrade pip
pip install -r requirements.txt

Open the file. Every line has an exact version, and that is the point.

# requirements.txt
Django==5.2.6
django-environ==0.12.0
Pillow==11.3.0
SpecifierMeansUse it for
Django==5.2.6 Exactly this release Applications, and anything you deploy
Django~=5.2.0 5.2.x, patch releases allowed Security fixes without surprises
Django>=5.2 Anything newer, including 6.0 Libraries, rarely applications
Django Whatever exists today Nothing you care about

Unpinned dependencies mean your laptop, your colleague's laptop and the server can each run a different Django, and the bug only shows up on one of them. Pinning turns "it works on my machine" into a reproducible fact. When you add a package yourself:

pip install django-extensions
pip freeze > requirements.txt   # then read the diff before committing

5. Migrate, create a superuser, run

python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

migrate creates db.sqlite3 and applies every migration in the repository - Django's own tables plus blog. It is safe to run twice; the second time it reports that there is nothing to do.

Now visit both of these and confirm they work:

  • http://127.0.0.1:8000/ - the post list, empty for now
  • http://127.0.0.1:8000/admin/ - log in with the superuser and add two posts, remembering to set published_date

Optional, but it makes the next modules more interesting: load the sample posts that ship with the repository.

python manage.py loaddata blog/fixtures/sample_posts.json

6. A tour of every file

myblog/
├── .git/                   # the repository itself - never edit by hand
├── .gitignore              # what git must ignore (lesson 0.3)
├── .venv/                  # your virtual environment - ignored by git
├── README.md               # how to run the project; keep it true
├── requirements.txt        # pinned runtime dependencies
├── dev-requirements.txt    # linters, pytest - not needed in production
├── manage.py               # thin wrapper that sets DJANGO_SETTINGS_MODULE
├── db.sqlite3              # your local database - ignored by git
├── mysite/                   # the project package
│   ├── __init__.py
│   ├── settings.py         # one file for now; split in lesson 1.3
│   ├── urls.py             # root URLconf: admin + include("blog.urls")
│   ├── wsgi.py             # entry point for Gunicorn (module 14)
│   └── asgi.py             # entry point for async servers (module 12)
├── blog/                   # the only app so far
│   ├── __init__.py
│   ├── admin.py            # admin.site.register(Post)
│   ├── apps.py             # BlogConfig - we use it properly in lesson 1.1
│   ├── forms.py            # PostForm
│   ├── models.py           # Post
│   ├── urls.py             # app_name = "blog" + four routes
│   ├── views.py            # post_list, post_detail, post_new, post_edit
│   ├── tests.py            # empty; replaced by a package in module 8
│   ├── migrations/         # 0001_initial.py - committed, always
│   ├── fixtures/           # sample_posts.json
│   └── templates/blog/     # post_list.html, post_detail.html, post_edit.html
├── templates/              # project-wide templates
│   └── base.html
└── static/                 # your CSS and JS
    └── css/blog.css

Three files are worth opening straight away.

  • manage.py does almost nothing: it points DJANGO_SETTINGS_MODULE at mysite.settings and hands the arguments to Django. When you later have two settings modules, this is the line that decides the default.
  • mysite/settings.py still has DEBUG = True and a hard-coded SECRET_KEY, exactly like the tutorial. That is intentional - lessons 1.2 and 1.3 fix it and you should see the "before" state.
  • blog/migrations/0001_initial.py is code, not a build artefact. It is committed, and it must stay committed, or nobody else can create the database.

7. Things that go wrong on the first run

MessageCauseFix
ModuleNotFoundError: No module named 'django' The environment is not activated, or you installed into a different one Activate .venv, check which python, install again
command not found: python Your system only exposes python3 Use python3 -m venv .venv; inside the venv python works
Activate.ps1 cannot be loaded PowerShell execution policy Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
You have unapplied migrations You skipped migrate Run python manage.py migrate
no such table: blog_post The database file exists but is empty Run migrate; locally you may also delete db.sqlite3 and start over
Error: That port is already in use Another runserver is still alive Stop it, or python manage.py runserver 8001
TemplateDoesNotExist: blog/post_list.html Wrong directory, or the app is missing from INSTALLED_APPS Run from the folder containing manage.py; check the setting

Two commands answer most questions before you start guessing:

python manage.py check          # configuration problems, no server needed
python manage.py showmigrations # which migrations are applied, per app

8. Exercise

  1. Clone the starter repository, create .venv, install the requirements and get the post list rendering in your browser.
  2. Create a superuser and add three posts through the admin, one of them unpublished. Confirm the unpublished one does not appear on the front page, and find the line in blog/views.py that explains why.
  3. Deactivate the environment, run python manage.py runserver again and read the error. Then reactivate it. Recognising this error saves you hours later.
  4. Change one pin in requirements.txt to an older Django patch release, reinstall, and check python -c "import django; print(django.get_version())". Put it back afterwards.
  5. Write the exact commands a new contributor would need, from clone to running server, in README.md. Then follow your own instructions in a fresh folder.

Further reading

After this lesson you will

  • Run the reference blog project on your own machine
  • Understand every file in the starter repository