Django - Minimal App (Python Tutorial)
How to create a minimal Django application.
Updated Aug 24, 2023

Tested With

  • Django==4.2.4

Create A New Project

One-liner (Windows):

mkdir mysite && cd mysite && python -m venv venv && venv\Scripts\activate.bat && pip install django pillow && django-admin startproject mysite . && python manage.py migrate && set "DJANGO_SUPERUSER_PASSWORD=admin" && python manage.py createsuperuser --noinput --username admin --email admin@example.org && python manage.py startapp pages && python manage.py startapp blog && python manage.py runserver

One-liner (macOS, Linux):

mkdir mysite && cd mysite && python -m venv venv && source venv/bin/activate && pip install django pillow && django-admin startproject mysite . && python manage.py migrate && export DJANGO_SUPERUSER_PASSWORD=admin && python manage.py createsuperuser --noinput --username admin --email admin@example.org && python manage.py startapp page && python manage.py startapp blog && python manage.py runserver

OR do it manually:

mkdir mysite
cd mysite
python -m venv venv
venv\Scripts\activate.bat (Windows)
source venv/bin/activate (macOS, Linux)
pip install django pillow
django-admin startproject mysite .
python manage.py migrate
python manage.py createsuperuser
python manage.py startapp pages
python manage.py startapp blog
python manage.py runserver

Edit mysite/settings.py

Add these lines to the project settings file:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pages', # here
    'blog',  # here
]

# ...

TEMPLATES = [
    {
        'BACKEND': 'django.template.backen...',
        'DIRS': [BASE_DIR / 'templates'], # here
        'APP_DIRS': True,
        # ..
    },
]

# ...

STATIC_URL = 'static/'
STATICFILES_DIRS = [BASE_DIR / 'static'] # here

MEDIA_URL = 'media/'                     # here
MEDIA_ROOT = BASE_DIR / 'media'          # here

Edit mysite/urls.py

Edit the main urls.py file and make these changes:

from django.contrib import admin

from django.urls import include, path      # import include
from django.conf.urls.static import static # here
from django.conf import settings           # here

urlpatterns = [
    path('', include('pages.urls')),      # here
    path('blog/', include('blog.urls')),  # here
    path('admin/', admin.site.urls),
] 
# here
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Add Base Template

Create a file called base.html in the templates directory and add these lines to it:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>{% block title %}MySite{% endblock %}</title>
</head>
<body>
    {% block content %}{% endblock %}
</body>
</html>

Pages App

Create pages/urls.py

from django.urls import path
from . import views

app_name = 'pages'

urlpatterns = [
    path('', views.home, name='home'),
    path('about/', views.about, name='about'),
]

Edit pages/views.py

from django.shortcuts import render

# As an example, this app uses function-based views.
# The blog app uses class-based views.

def home(request):
    return render(request, 'pages/home.html')

def about(request):
    return render(request, 'pages/about.html')

Create templates/pages/home.html

{% extends 'base.html' %}
{% block content %}
<h1>Home</h1>
{% endblock %}

Create templates/pages/about.html

{% extends 'base.html' %}
{% block title %}About{% endblock %}
{% block content %}
<h1>About</h1>
{% endblock %}

Visit / and /about/ URLs to observe the respective pages:

Blog App

Edit blog/models.py

Add these lines to the blog app models.py file:

from django.db import models


class Post(models.Model):
    title = models.CharField(max_length=255, default='', blank=False)
    body = models.TextField(default='')
    slug = models.SlugField(max_length=255, unique=True)
    image = models.ImageField(upload_to='images')

    def __str__(self):
        return self.title

Create blog/urls.py

Create urls.py file in the blog app folder and add these lines to it:

from django.contrib import admin
from django.urls import path
from blog.views import PostDetailView
  
urlpatterns = [
    path('<slug:slug>/', PostDetailView.as_view(), name='post_detail'),
] 

Edit blog/views.py

Edit blog app views.py file and add these lines to it:

from django.views.generic import DetailView
from myapp.models import Post


class PostDetailView(DetailView):
    model = Post

Create templates/blog/post_detail.html

Create a template for the blog detail page:

{% extends 'base.html' %}
{% block title %}{{ post.title }}{% endblock %}

{% block content %}
<h1>{{ post.title }}</h1>
{% if post.image %}
    <img width="300" src="{{ post.image.url }}">
{% endif %}
<p>{{ post.body }}</p>
{% endblock %}

Edit blog/admin.py

Register the Post model so we can create blog posts using the admin:

from django.contrib import admin
from . import models

admin.site.register(models.Post)

Run migrations

python manage.py makemigrations
python manage.py migrate

Visit /admin/ and create a blog post with the slug django-tutorial.

Visit /blog/django-tutorial/ and you should see something like this:

Theming

Edit templates/base.html and add these lines:

<head>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;1,500&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="/static/css/styles.css">
    <title>{% block title %}MySite{% endblock %}</title>
</head>

Create static/css folder structure and put styles.css in it:

* {
    margin: 0;
    padding: 0;
}

body {
    font-family: 'Open Sans', sans-serif;
}

TODO

  • static files
  • basic theme