Django Debug Tools
Bugs happen in every project - even for experienced developers. Debugging is not a sign that you’re doing something wrong. It’s just a normal part of building things. Good developers are not the ones who never get bugs. They’re the ones who can find what went wrong quickly and fix it properly.
Debugging Mindset
Section titled “Debugging Mindset”Follow these steps every time something breaks. Don’t skip steps - it saves time in the long run:
- Make the bug happen again so you know exactly what triggers it.
- Read the full error message from top to bottom.
- Find the exact file and line number where the error happened.
- Understand why it broke, not just where.
- Make a small, focused fix.
- Test the same thing again to confirm it’s fixed.
The most important rule: fix the actual cause, not just the error message. If you just hide the error without understanding it, it will come back.
Common Django Debug Tools
Section titled “Common Django Debug Tools”You don’t need just one tool - different tools answer different questions. Use them together:
- Django traceback - the error page in your browser or terminal that shows what went wrong.
- Temporary print statements - quick and dirty way to check values in your code locally.
- Breakpoints in VS Code - pause your running code and look inside it like a microscope.
- Django shell - a Python terminal connected to your project, great for testing database queries.
- Application logs - a record of what your app did during each request, useful for finding issues in production.
Read Tracebacks Like a Professional
Section titled “Read Tracebacks Like a Professional”When Django shows you an error, don’t panic. Read it from the bottom up.
The bottom lines tell you:
- What type of error it is (e.g.
AttributeError,KeyError,DoesNotExist) - A message explaining what went wrong
- The exact line of code that caused it
Then read upward to understand the chain of code that led to that point.
Don’t start changing code before you understand the full picture. Guessing and changing random things makes debugging take much longer.
Quick Checks in Django Shell
Section titled “Quick Checks in Django Shell”The Django shell is a Python terminal that’s already connected to your project and database. It’s great when you want to test a query or check your data without having to click through pages in the browser.
Open the shell:
uv run python manage.py shellExample - check your database data:
from core.models import Product
Product.objects.count()Product.objects.first()Use the shell for:
- Checking what’s actually in the database
- Testing ORM queries before putting them in your views
- Trying out small bits of logic quickly
Logging Basics for Real Projects
Section titled “Logging Basics for Real Projects”print() is fine for quick checks on your own computer, but once you’re working with a team or on a real server, logs are much better. They stay recorded even after the request is done, and you can filter them by how serious the message is.
Here’s a simple logging setup in settings.py that sends logs to the terminal:
LOGGING = { "version": 1, "disable_existing_loggers": False, "handlers": { "console": { "class": "logging.StreamHandler", }, }, "root": { "handlers": ["console"], "level": "INFO", }, "loggers": { "django.request": { "handlers": ["console"], "level": "ERROR", "propagate": False, }, },}Things to keep in mind when logging in production:
- Never log passwords, tokens, or private user data. Logs can be read by many people.
- Use the right level for each message -
DEBUG,INFO,WARNING, orERROR- so it’s easy to filter later. - If your project gets a lot of traffic, add request IDs to logs so you can trace one user’s journey through many log lines.
Django Debug Toolbar
Section titled “Django Debug Toolbar”Django Debug Toolbar is a panel that appears on the side of your web pages while you’re developing. It shows you useful information about what Django did to build that page.
You can use it to see:
- Every SQL query that ran for that page, and how long each one took
- Which templates were used and how long rendering took
- Request headers and current Django settings
- Cache and middleware activity
This is really useful for catching slow database queries before they become a problem on a live site.
Install
Section titled “Install”uv add django-debug-toolbarConfigure settings.py
Section titled “Configure settings.py”INSTALLED_APPS = [ # other apps...]
if ENVIRONMENT != PRODUCTION: INSTALLED_APPS += [ # ... "debug_toolbar", ]
MIDDLEWARE = [ # other middleware...]
if ENVIRONMENT != PRODUCTION: MIDDLEWARE += [ # ... "debug_toolbar.middleware.DebugToolbarMiddleware", ]
INTERNAL_IPS = [ "127.0.0.1",]The if ENVIRONMENT != PRODUCTION checks make sure the toolbar only runs on your local machine, never on the real server.
Configure urls.py
Section titled “Configure urls.py”from django.conf import settingsfrom django.urls import include, path
urlpatterns = [ # your URLs...]
if settings.ENVIRONMENT != settings.PRODUCTION: urlpatterns += [ path("__debug__/", include("debug_toolbar.urls")), ]Safe Usage Rules
Section titled “Safe Usage Rules”- Only use the Debug Toolbar in development - never on a live site.
- Always keep it behind
settings.DEBUGor environment checks. - Never expose the
__debug__/URL in production - it leaks internal details about your app.
A good way to describe this tool in interviews:
“I use Django Debug Toolbar to find slow database queries and catch N+1 problems before the site goes live.”
VS Code Debug Setup for Django
Section titled “VS Code Debug Setup for Django”Sometimes print() and logs aren’t enough. When a bug is really tricky, you can use VS Code’s debugger to pause your running Django server at any line of code and look at exactly what’s happening at that moment - variable values, what function called what, etc.
Prerequisites
Section titled “Prerequisites”- VS Code Python extension installed.
- Your Django project folder open at the root (the folder where
manage.pylives).
Create .vscode/launch.json
Section titled “Create .vscode/launch.json”This file tells VS Code how to start Django in debug mode:
{ "version": "0.2.0", "configurations": [ { "name": "Django: Runserver", "type": "debugpy", "request": "launch", "program": "${workspaceFolder}/manage.py", "args": ["runserver"], "django": true, "justMyCode": true, "console": "integratedTerminal", "env": { "DJANGO_SETTINGS_MODULE": "myproject.settings" } } ]}Replace myproject.settings with your actual project name and settings file path.
Optional .vscode/settings.json
Section titled “Optional .vscode/settings.json”{ "python.testing.pytestEnabled": true, "python.testing.unittestEnabled": false, "python.analysis.typeCheckingMode": "basic"}How to Use the Debugger
Section titled “How to Use the Debugger”- Click on the line number in a view, serializer, or any function where you want to pause - this sets a breakpoint (a red dot appears).
- Go to the Run and Debug panel in VS Code and start
Django: Runserver. - Open your browser and trigger the page or action that calls that code.
- VS Code will pause the code right at your breakpoint.
- You can now look at the current value of every variable, step through the code one line at a time, and understand exactly what’s happening.
If the Breakpoint Is Not Being Hit
Section titled “If the Breakpoint Is Not Being Hit”- Make sure you started Django using the Django debug config, not a regular terminal command.
- Check that the request is actually reaching the file and function where you put the breakpoint.
- Restart the debug session after making any code or config changes.