Using Claude Code with Django: Optimization Tips and Context Management

Nicola·
Using Claude Code with Django: Optimization Tips and Context Management

Using Claude Code with Django: Optimization Tips and Context Management

Django projects have a specific structure that AI coding agents consistently mishandle. The framework's "batteries included" philosophy means a single feature spans models, views, URL configurations, templates, serializers, middleware, admin customizations, management commands, and migrations. Ask Claude Code to add a field to a user profile, and it needs to touch at least four files — and know the exact patterns your project uses for each one.

Most AI coding failures on Django aren't about model intelligence. They're about the agent not seeing the full picture of how Django connects its pieces. Fix the context, and the code quality jumps dramatically.

Django's Context Challenges

Django's architecture creates context requirements that differ fundamentally from frontend frameworks or microservice backends.

The MTV Pattern Sprawl

Django follows Model-Template-View (MTV), but a real Django project's dependency graph is wider than three layers. A single feature typically involves:

  • Model (`models.py`) — The database schema, field types, relationships, validators, and custom managers
  • View (`views.py` or `viewsets.py`) — The business logic, authentication, permissions, and response formatting
  • URL configuration (`urls.py`) — The routing rules, path converters, and namespace definitions
  • Serializer (`serializers.py`) — The API data transformation layer (DRF projects)
  • Template (`templates/`) — The HTML rendering with template tags and filters
  • Form (`forms.py`) — The validation and input handling layer
  • Admin (`admin.py`) — The admin interface customization
  • Migration (`migrations/`) — The database schema evolution
  • Test (`tests.py` or `tests/`) — The test suite covering all of the above

Modifying any one of these files often requires understanding two or three others. Change a model field? The serializer, form, and migration all need updates. Add a URL pattern? The view must match its signature. The interconnections are extensive and follow Django-specific conventions that the agent must know.

ORM Complexity

Django's ORM is expressive but convention-heavy. Field types map to specific database column types. `ForeignKey` requires `on_delete` behavior. `ManyToManyField` creates intermediate tables. Custom managers add querysets. Model methods can be properties, classmethods, or regular methods with different implications.

Claude Code frequently makes ORM mistakes when it lacks model context:

  • Wrong field types — Using `CharField` where `TextField` is appropriate, or `IntegerField` where `PositiveIntegerField` would enforce constraints
  • Missing `on_delete` — Forgetting `on_delete=models.CASCADE` on `ForeignKey` fields (a required parameter that's easy to miss)
  • Incorrect related names — Using default `related_name` patterns that conflict with existing reverse relations
  • N+1 query patterns — Writing view code that triggers N+1 queries because the agent doesn't see the queryset optimization (`select_related`, `prefetch_related`) context

URL Routing Conventions

Django URL routing uses `urlpatterns` lists with `path()` or `re_path()` functions. URL configurations can be included from app-level `urls.py` files into the project-level `urls.py`. Namespaces, app names, and URL naming conventions vary between projects.

Without seeing both the project-level and app-level URL configurations, the agent generates URLs that don't match the existing naming pattern, creates duplicate path names, or misses the namespace prefix required for reverse URL lookups.

Middleware and Signal Chains

Django middleware processes every request and response in a defined order. Signals fire on model save, delete, and other events. Both create implicit dependencies that aren't visible from looking at a single view or model file.

An agent that doesn't see the middleware stack might duplicate authentication logic that middleware already handles. An agent that doesn't see signal handlers might add logic to a model's `save()` method that duplicates what a `post_save` signal already does.

Common AI Mistakes with Django

These are the Django-specific errors that appear most frequently in Claude Code sessions:

1. Wrong model field types. The agent uses `models.CharField(max_length=255)` for a text field that should be `models.TextField()`, or uses `models.FloatField()` for currency (should be `models.DecimalField(max_digits=10, decimal_places=2)`). These compile fine but create data integrity issues.

2. Missing migrations. The agent modifies models but doesn't generate migration files, or generates migrations manually instead of using `makemigrations`. Hand-written migrations often miss dependency chains and fail when applied.

3. Incorrect URL patterns. The agent creates URL patterns with incorrect path converters (`<int:pk>` vs `<str:slug>`), mismatches between URL parameter names and view function parameter names, or naming conflicts with existing URL patterns in the project.

4. Template context mismatches. The agent passes variables to templates with different names than the template expects, or references template tags/filters without loading the correct template tag library with `{% load %}`.

5. Serializer/model drift. In DRF projects, the agent modifies the model without updating the serializer, or adds serializer fields that reference model fields that don't exist. This causes runtime `AttributeError` exceptions.

6. Ignoring project conventions. Every Django project develops conventions: class-based views vs function-based views, DRF viewsets vs APIViews, factory_boy vs fixtures for tests. The agent defaults to whatever pattern is most common in its training data, which may not match your project.

Setting Up Claude Code for Django

The CLAUDE.md Approach

A well-crafted CLAUDE.md file for a Django project should document:

```

Project Structure

  • Python 3.12, Django 5.1, DRF 3.15
  • Apps: users, products, orders, payments, notifications
  • Database: PostgreSQL 16
  • Task queue: Celery with Redis broker

Conventions

  • Views: Class-based views (APIView for DRF, TemplateView/FormView for templates)
  • URLs: namespaced per app, named with app_name:action-model pattern
  • Models: TimeStampedModel base class for all models (adds created_at, updated_at)
  • Tests: pytest-django with factory_boy, fixtures in tests/fixtures/
  • Serializers: ModelSerializer with explicit fields (never fields = '__all__')

Key Patterns

  • Authentication: custom User model in users app, JWT via djangorestframework-simplejwt
  • Permissions: custom permission classes in core/permissions.py
  • Pagination: CursorPagination for list endpoints
  • Error handling: custom exception handler in core/exceptions.py

```

This document gives Claude Code the conventions it needs without requiring it to explore your entire project. The agent knows to use `APIView` instead of `@api_view`, to inherit from `TimeStampedModel`, and to write serializers with explicit field lists.

Model Relationships Documentation

For projects with complex model relationships, include an entity-relationship summary:

```

Model Relationships

  • User -> Profile (one-to-one)
  • User -> Order (one-to-many)
  • Order -> OrderItem (one-to-many)
  • OrderItem -> Product (many-to-one)
  • Product -> Category (many-to-one, nullable)
  • Product <-> Tag (many-to-many)

```

This gives the agent the relationship context it needs to write correct querysets, serializers, and joins without reading every model file.

Optimizing Context for Django Tasks

Different Django tasks require different context slices. Here's the minimum context for common task types:

Feature Implementation (Model + View + URL + Serializer)

When building a new feature — say, a product review system — provide:

  • The model file where the new model will live
  • The views file for the app
  • The app-level `urls.py`
  • The serializers file (for DRF projects)
  • Related models (e.g., `Product` and `User` if reviews link to both)
  • Base classes (`TimeStampedModel`, base `APIView`, base `ModelSerializer`)

This set — typically 6-8 files — gives the agent everything it needs to implement a feature that integrates with your existing patterns.

Bug Fixing (Model + View + URL + Error Context)

For bug fixes, include:

  • The file where the bug manifests
  • The model it operates on
  • The URL pattern that routes to it
  • The traceback or error message verbatim
  • Related middleware or signal handlers if the bug involves request processing

API Development (Model + Serializer + View + URL)

For DRF API work, the critical quartet is model + serializer + viewset + URL router. Include all four for every API task. Missing the serializer is the most common context gap — the agent modifies the model or view but doesn't know what the serializer currently exposes.

Database Work (Model + Existing Migrations)

When modifying models, include the most recent migration file for context. The agent needs to see the current state of the database schema as Django's migration system understands it, not just the model code. This prevents migration conflicts and ensures proper dependency chains.

Testing Workflows with Django

Django testing with Claude Code benefits from explicit test context. The agent writes significantly better tests when it can see:

  • Your test base class — If you have a `BaseTestCase` with setup methods, include it
  • Existing test patterns — Include 2-3 existing tests from the same app as examples
  • Factory definitions — If using factory_boy, include the relevant factories
  • Fixture files — If using JSON/YAML fixtures, include or reference them
  • conftest.py — Pytest fixtures and shared configuration

pytest-django Best Practices

When using pytest-django, include your `conftest.py` in context. It likely contains fixtures that the agent should reuse rather than recreate:

```python

Don't let the agent write this:

@pytest.fixture

def api_client():

return APIClient()

When your conftest.py already has:

@pytest.fixture

def authenticated_client(user):

client = APIClient()

client.force_authenticate(user=user)

return client

```

Without the conftest, the agent creates redundant fixtures. With it, the agent reuses existing setup and writes tests that match your project's patterns.

factory_boy Integration

Include factory definitions when asking for test generation. The agent needs to know your `UserFactory`, `ProductFactory`, and `OrderFactory` to generate test data correctly. Without factories in context, it falls back to `Model.objects.create()` calls with hardcoded data — which works but doesn't match factory-based projects.

How vexp Handles Python Dependency Graphs

vexp's indexer parses Python source files using AST analysis, extracting:

  • Import relationships — `from myapp.models import User` creates an edge from the current file to `myapp/models.py`, specifically to the `User` symbol
  • Class hierarchy — `class OrderSerializer(ModelSerializer)` creates an inheritance edge
  • Function calls — `User.objects.filter(active=True)` creates a usage edge from the current function to `User` and its manager
  • Decorator dependencies — `@login_required`, `@permission_classes([IsAdmin])` create edges to the decorator definitions
  • Django-specific patterns — Foreign key references (`ForeignKey('users.User')`) are tracked as cross-model dependencies

When you run a task like "add a discount field to the Order model," vexp's `run_pipeline` traverses the graph from `Order` outward, collecting:

  • The model file containing `Order`
  • All serializers that reference `Order`
  • All views that query or create `Order` instances
  • URL patterns that route to those views
  • Test files that test `Order` functionality
  • The most recent migration file for the app

This traversal typically returns 10-15 files — the complete blast radius of a model change — without manual specification. The agent sees every file it needs to update, reducing the chance of partial changes that break at runtime.

Benchmark Data from FastAPI Projects

vexp's Python indexing benchmarks, measured primarily on FastAPI projects, are directly applicable to Django:

  • Token reduction: 65-70% compared to manual file exploration — the agent receives the dependency neighborhood instead of reading entire apps
  • Error reduction: 45% fewer runtime errors in generated code — because the agent sees all related files, not just the one being edited
  • Turn reduction: 50% fewer conversation turns per task — the agent has enough context to get it right on the first attempt

These numbers translate directly to Django projects because the underlying challenge is the same: Python dependency tracking across models, views, serializers, and tests. The ORM layer adds Django-specific edges, but the graph traversal mechanism is identical.

On a 300-file Django project with 12 apps, vexp indexes in under 30 seconds and serves context capsules in under 200ms. The index updates incrementally as files change, so there's no re-indexing overhead during development.

Practical Django Development Workflow

Daily Workflow with Claude Code

1. Start the context engine. If using vexp, it runs as a background daemon. If not, prepare your CLAUDE.md with project structure and conventions.

2. Scope tasks to one app. Django's app structure is a natural task boundary. "Add review functionality to the products app" is a well-scoped task. "Refactor the entire project to use DRF viewsets" is too broad — break it into per-app migrations.

3. Model-first development. Have Claude Code write the model changes first. Review the field types, relationships, and constraints before proceeding. Then generate the migration with `python manage.py makemigrations`. Then implement the view/serializer/URL changes.

4. Include the test context. When implementing features, include the app's existing test file and your conftest. Ask the agent to write tests alongside the implementation. Django test failures catch model/view/URL mismatches before they reach production.

5. Use `manage.py` commands for verification. After model changes: `python manage.py check` catches common issues. After migration generation: `python manage.py showmigrations` confirms the migration graph is valid. After all changes: `python manage.py test app_name` runs the app's test suite.

Multi-App Feature Work

Features that span multiple Django apps — like an order system that touches `users`, `products`, `orders`, and `payments` — require careful context scoping.

Approach 1: Model layer first, then views. Implement all model changes across apps, generate migrations, then implement views. This ensures the data layer is consistent before business logic is added.

Approach 2: One app at a time. Complete the feature in `orders` (model + view + URL + serializer + tests), then extend to `payments`, then `notifications`. Each step is self-contained and testable.

Both approaches work with Claude Code. The key is never asking the agent to implement across all apps simultaneously — the context requirements exceed what can be provided effectively, and the agent makes more mistakes when juggling multiple app conventions at once.

Migration Safety

Django migrations are the most dangerous area for AI-generated code. A bad migration can destroy production data. Safeguards:

  • Never let the agent write migrations manually. Always use `makemigrations`.
  • Review migration files before applying. Check for `RunPython` operations, data migrations, and irreversible operations.
  • Include the latest migration in context so the agent knows the current schema state.
  • Test migrations with `python manage.py migrate --plan` to verify the execution order.

AI-generated model changes are usually fine. AI-generated migration files are risky. Let Django's migration framework handle the translation from model changes to migration operations.

The Django Development Loop

Effective Claude Code usage with Django follows a predictable loop: scope to one app, provide model + view + URL + serializer context, implement model-first, generate migrations with `makemigrations`, implement views and serializers, write tests, verify with `manage.py check` and the test suite.

Each step is narrow enough for the agent to handle well, and the verification steps catch errors before they propagate. With a dependency graph providing the right context automatically, this loop runs with minimal manual file selection — the agent sees what it needs to see, and doesn't hallucinate Django patterns that don't match your project.

Frequently Asked Questions

Why does Claude Code struggle with Django projects?
Django's "batteries included" architecture means a single feature spans models, views, URLs, serializers, templates, forms, admin configuration, and migrations. Each file follows Django-specific conventions and depends on others. Without visibility into these interconnections, Claude Code defaults to generic Django patterns from its training data, which may not match your project's conventions, leading to wrong field types, incorrect URL patterns, and serializer/model mismatches.
What context should I provide Claude Code for Django feature development?
For new features, provide the model file, views file, app-level urls.py, serializers file (for DRF projects), related models, and base classes your project uses (like TimeStampedModel or base APIView). This set of 6-8 files gives the agent enough context to implement a feature that integrates with your existing patterns. Always include your conftest.py and existing test examples when asking for test generation.
How do I prevent Claude Code from generating bad Django migrations?
Never let Claude Code write migration files manually. Have it modify models.py, then run `python manage.py makemigrations` to generate migrations through Django's framework. Review generated migrations before applying, especially for RunPython operations and irreversible changes. Include the latest migration file in context so the agent understands the current schema state and avoids creating conflicting migrations.
Does vexp work with Django and Python projects?
Yes. vexp's Python indexer uses AST analysis to extract imports, class hierarchies, function calls, decorator dependencies, and Django-specific patterns like ForeignKey references. Benchmarks on Python projects show 65-70% token reduction and 45% fewer runtime errors in generated code. On a 300-file Django project with 12 apps, vexp indexes in under 30 seconds and serves context capsules in under 200ms.
What's the best workflow for multi-app Django features with Claude Code?
Complete the feature one app at a time. Implement model changes first, generate migrations, then build views, serializers, and tests. Never ask Claude Code to implement across all apps simultaneously — the context requirements are too large and error rates increase. Alternatively, implement all model-layer changes first across apps, generate migrations, then implement the view layer. Both approaches keep the agent's context focused and the output reliable.

Nicola

Developer and creator of vexp — a context engine for AI coding agents. I build tools that make AI coding assistants faster, cheaper, and actually useful on real codebases.

Related Articles