Quickstart

pip install pillow django-imagekit

Add these fields to a model:

from django.db import models

# START
from imagekit.models import ImageSpecField
from pilkit.processors import ResizeToFill
# END

class Post(models.Model):
    # START
    image = models.ImageField(default='',
                              blank=True,
                              upload_to='images')
    image_medium = ImageSpecField(source='image',
                                     processors=[ResizeToFill(250, 150)],
                                     format='JPEG',
                                     options={'quality': 60})
    image_small = ImageSpecField(source='image',
                                     processors=[ResizeToFill(100, 50)],
                                     format='JPEG',
                                     options={'quality': 60})
    # END

Edit the project settings.py file and add imagekit to the INSTALLED_APPS list. Add MEDIA_URL and MEDIA_ROOT variables:

INSTALLED_APPS = [
    # ...
    'imagekit'
]

# START
MEDIA_URL = '/media/' 
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# END

Output image URLs in templates like this:

<img src="{{ post.image.url }}">
<img src="{{ post.image_medium.url }}">
<img src="{{ post.image_small.url }}">

Full Tutorial

Run these commands to setup a base project:

python3 -m venv venv
source venv/bin/activate
pip install django
django-admin startproject mysite .
python manage.py startapp blog
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver

Install the following packages:

pip install pillow django-imagekit

Edit the blog app models.py file and add a new class called Post. Add these image fields to it:

from django.db import models

# START
from imagekit.models import ImageSpecField
from pilkit.processors import ResizeToFill
# END

class Post(models.Model):
    # START
    image = models.ImageField(default='',
                              blank=True,
                              upload_to='images')
    image_medium = ImageSpecField(source='image',
                                     processors=[ResizeToFill(250, 150)],
                                     format='JPEG',
                                     options={'quality': 60})
    image_small = ImageSpecField(source='image',
                                     processors=[ResizeToFill(100, 50)],
                                     format='JPEG',
                                     options={'quality': 60})
    # END

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

from django.contrib import admin

from blog.models import Post

admin.site.register(Post)

Edit the blog/views.py file and add a new view function called detail to it:

from django.shortcuts import render, get_object_or_404

from blog.models import Post


def detail(request, pk=None):
    post = get_object_or_404(Post, pk=pk)

    return render(request,
                  'blog/detail.html',
                  {'post': post})

Edit the mysite/urls.py file and make the following changes:

from django.conf.urls.static import static # HERE
from django.contrib import admin
from django.urls import path

import blog.views # HERE
from mysite import settings # HERE

urlpatterns = [
    # HERE
    path('blog/<int:pk>/',
         blog.views.detail,
         name='blog_detail'),
    path('admin/', admin.site.urls),
    # HERE
] + static(settings.MEDIA_URL,
           document_root=settings.MEDIA_ROOT)

Edit the mysite/settings.py file and add the following lines:

INSTALLED_APPS = [
    # HERE
    'blog.apps.BlogConfig',
    # ...
    'django.contrib.admin',
    # ...
    # HERE
    'imagekit'
]

# START
MEDIA_URL = '/media/' 
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# END

Create a file called detail.html in the blog/templates/blog directory:

{% if post.image %}
    <img src="{{ post.image.url }}">
    <br><br>
    <img src="{{ post.image_medium.url }}">
    <img src="{{ post.image_small.url }}">
{% endif %}

Run migrations:

python manage.py makemigrations && \
python manage.py migrate

Visit /admin/ and create a post.

Visit /blog/1/ and you should see the original image and resized smaller images below it.