Django Interview Questions: Practical and Conceptual

Published · by JOBB GROUP FZE

Django interviews split cleanly into two kinds of question. Conceptual questions check that you know what the framework does for you: the request cycle, the ORM, migrations, security defaults. Practical questions check that you can see what it is doing behind your back, such as a list page that quietly runs a hundred queries. This guide covers both, with short code exercises of the kind used in live interviews. Facts are taken from the Django documentation, checked in November 2026.

Freshers should be solid on the first half. Experienced candidates will be pushed hardest on the second.

Part 1: Conceptual questions

1. What happens between a browser request and a Django response?

A good answer follows the path: the WSGI or ASGI server hands the request to Django; it passes through the middleware stack; the URL resolver matches a pattern in urls.py and calls the view; the view usually talks to models and renders a template or returns JSON; the response travels back out through middleware.

Interviewers often follow up on middleware order. The Django docs describe middleware as “a framework of hooks into Django’s request/response processing”. During the request, middleware runs in the order listed in the MIDDLEWARE setting; on the way out, the response passes through the layers in reverse. If a middleware returns a response without calling the next layer, the inner layers and the view never see the request.

2. What is the difference between a project and an app?

A project is the configuration and deployment unit: settings, root URL configuration, WSGI/ASGI entry points. An app is a reusable package of models, views, templates and migrations that does one job. A project contains several apps. The follow-up is usually “how would you split this system into apps?”, so have an example ready.

3. Explain makemigrations and migrate.

The docs put it plainly: makemigrations “is responsible for packaging up your model changes” into migration files, and migrate “is responsible for applying those to your database”. sqlmigrate shows the SQL a migration will run. Strong candidates add two habits from the docs: commit the model change and its migration together in one commit, and in data migrations written with RunPython, use the historical model from apps.get_model() rather than importing the model directly.

Why the import matters: a data migration runs against the schema as it was at that point in history. Importing today’s model class can reference fields that did not exist yet, and the migration breaks on a fresh database.

4. What does “QuerySets are lazy” mean?

Building a QuerySet with filter() or exclude() does not touch the database. The reference documentation says “no database activity actually occurs until you do something to evaluate the queryset”, for example by iterating over it or calling list() on it. Once evaluated, a QuerySet caches its results, so iterating it twice does not query twice. The catch is that a new QuerySet, such as one created by calling .filter() again, has its own empty cache.

5. How does Django protect against CSRF?

The CSRF middleware checks a secret token on unsafe requests. In templates you place {% csrf_token %} inside forms that post to your own site; the docs warn not to do this for forms that post to external URLs. For JavaScript requests, you send the token in an X-CSRFToken header. The docs recommend exempting individual views with csrf_exempt where truly necessary rather than switching the middleware off.

Expect a follow-up on other defaults: the ORM parameterises queries, which protects against SQL injection unless you build raw SQL with string formatting, and templates auto-escape output, which helps prevent cross-site scripting unless you mark content safe.

6. Function-based or class-based views?

There is no wrong answer, only an unexplained one. Function-based views are explicit and easy to read for one-off logic. Class-based and generic views remove repetition for standard create, list, update and delete pages, at the cost of behaviour hidden in mixins. Say which you prefer and when you would switch.

7. What are signals, and when would you avoid them?

Signals let one part of the code react to events elsewhere, such as post_save on a model. They are handy for decoupled apps but make control flow hard to follow and can fire in surprising places. A thoughtful answer also notes that some operations bypass them: the QuerySet reference states that bulk_create() does not call the model’s save() method and does not send pre_save or post_save signals, and that update() works at the SQL level without calling save().

Part 2: Practical questions

8. Spot the problem: a slow list page

This is the most common practical Django question. Here is an illustrative version.

# models.py
class Author(models.Model):
    name = models.CharField(max_length=100)

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    tags = models.ManyToManyField("Tag")

# views.py
def book_list(request):
    books = Book.objects.all()
    return render(request, "books.html", {"books": books})

# books.html
{% for book in books %}
  {{ book.title }} by {{ book.author.name }}
  {% for tag in book.tags.all %}{{ tag.name }} {% endfor %}
{% endfor %}

The problem: one query fetches the books, then each book.author triggers another query, and each book.tags.all triggers another. With 100 books that is about 201 queries. This is the “N+1” pattern.

The fix:

books = Book.objects.select_related("author").prefetch_related("tags")

The explanation interviewers want: select_related follows single-valued relationships, foreign key and one-to-one, and fetches them in the same query using a join. prefetch_related does a separate lookup for each relationship and joins the results in Python, which is why it handles many-to-many and reverse foreign keys. Then say how you would find the problem in a real codebase: Django’s optimisation guide recommends profiling first, mentioning QuerySet.explain() and tools such as django-debug-toolbar.

9. Spot the problem: a race condition on a counter

def like(request, pk):
    post = Post.objects.get(pk=pk)
    post.likes = post.likes + 1
    post.save()

The problem: two requests can read the same value and both write likes + 1, losing one like.

The fix:

from django.db.models import F
Post.objects.filter(pk=pk).update(likes=F("likes") + 1)

The increment now happens in the database in a single statement. The optimisation guide’s advice to use F expressions and do work in the database applies here. Mention the side effect: because this uses update(), save() is not called and no save signals fire.

10. Fetch only what you need

Interviewers often ask how to make a query cheaper without changing the result. The optimisation guide lists the answers:

  • Use values() or values_list() when you need plain data rather than model objects.
  • Use only() or defer() to skip heavy columns, remembering that accessing a deferred field later costs another query.
  • Use count() rather than len(queryset) when you only need the number, and exists() when you only need to know if there is at least one row.
  • Use iterator() for very large result sets, because the normal QuerySet cache can use a lot of memory.

Add a caution the docs also make about indexes: adding one can help a slow filter, but the overhead of maintaining an index can outweigh the gain, so measure first.

11. Write a data migration

A typical task: “We added a slug field. Fill it for existing rows.”

from django.db import migrations
from django.utils.text import slugify

def fill_slugs(apps, schema_editor):
    Article = apps.get_model("blog", "Article")
    for article in Article.objects.filter(slug=""):
        article.slug = slugify(article.title)
        article.save(update_fields=["slug"])

class Migration(migrations.Migration):
    dependencies = [("blog", "0007_article_slug")]
    operations = [migrations.RunPython(fill_slugs, migrations.RunPython.noop)]

Talking points: the historical model from apps.get_model(); a reverse function so the migration can be rolled back (the docs note a migration with an irreversible operation raises IrreversibleError when reversed); and, for a large table, batching the updates.

12. Two developers added migrations in the same app. Now what?

The docs explain that because migrations record their dependencies, Django detects two new migrations that are not ordered and prompts you with options. Describe how you would resolve it, check that the two migrations do not touch the same fields, and run the test suite before merging.

What changes for experienced candidates

Topic Fresher-level answer Experienced-level answer
ORM performance Knows select_related exists Finds N+1 with profiling, chooses join or prefetch, checks the SQL
Migrations Runs the two commands Writes reversible data migrations, plans changes on large tables to limit locking, squashes old migrations
Security Adds the CSRF tag Explains the token flow, reviews raw SQL and mark_safe usage, sets production settings correctly
Architecture Describes MVT Explains where business logic lives, when to use signals, how to keep views thin
Versions Knows the version used in their project Has upgraded across releases and knows the LTS cycle

On versions: as of November 2026, Django’s download page lists 6.1 as the latest release and 5.2 as the current LTS series, with extended support until April 2028. The next LTS, 6.2, is scheduled for April 2027.

How to practise

  • Install django-debug-toolbar on a personal project and count the queries on each page. Fix every N+1 you find.
  • Write one data migration and one reversible schema change, then roll both back.
  • Read the middleware list in your settings and explain what each item does.
  • Rehearse explaining a past bug out loud in two minutes: symptom, cause, fix, prevention.

Finally, make sure your CV gives the interviewer something concrete to ask about: the apps you built, the queries you sped up, the versions you upgraded. The software engineer resume builder and the web developer resume page have sections for projects and stack. Then run the result through the ATS resume score checker to see whether “Django”, “PostgreSQL” and the other skills in the advert are picked up.

Frequently asked questions

Which Django version should I prepare on?

Whatever the job description names; otherwise the current long-term support release. As of November 2026 the Django download page lists 5.2 as the LTS series, with extended support until April 2028, and 6.1 as the latest release. The fundamentals in this guide apply to both.

Do Django interviews include Django REST Framework?

Often, for API roles. DRF is a separate third-party package, so check the job description. Expect questions on serializers, viewsets, authentication and permissions if it is listed.

How should a fresher prepare for a Django interview?

Build one small project end to end: models with a relationship, a form, authentication, an admin, tests and a deployment. Then be ready to explain every file in it. That covers most fresher questions.

Sources

Ready to build your resume?

Start with a sample or a blank page. No sign-up needed. Free to edit; US$1.00 only if you download a PDF.