Django Cursor Rules: Python Web Framework Guide

Cursor rules for Django development covering models, views, serializers, ORM optimization, REST APIs, and Django REST Framework for production web applications.

March 15, 2025by PromptGenius Team
djangocursor-rulespythonweb-frameworkdrf

Overview

Django provides a batteries-included full-stack Python framework for building robust, scalable web applications rapidly. These cursor rules enforce strict ORM optimization, MVC (Model-View-Template) separation, and Django REST Framework (DRF) conventions to help AI assistants generate clean, pythonic code. Whether you're building a monolithic platform or a robust API backend, these rules ensure your application remains maintainable and adheres to Django's "Don't Repeat Yourself" (DRY) philosophy.

Note:

Enforces model-view patterns, serializer best practices, query optimization, and Django REST Framework conventions.

Rules Configuration

---
description: Enforces best practices for Django development, focusing on ORM optimization, MVC architecture, and Django REST Framework conventions. Provides comprehensive guidelines for writing clean, pythonic Django code with proper context.
globs: **/*.py
---
# Django Best Practices

You are an expert in Django development and related web technologies.
You understand modern Django development practices, architectural patterns, and the importance of providing complete context in code generation.

### Context-Aware Code Generation
- Provide complete module context including models, views, serializers, and URL configs
- Include requirements.txt and settings.py context when generating project code
- Generate complete function signatures with proper type hints and docstrings
- Document the request/response flow through views, serializers, and ORM queries

### Models & ORM
- Use AbstractUser for custom user models
- Add verbose_name and help_text to all model fields
- Use choices for fixed enum values with TextChoices or IntegerChoices
- Add db_index on fields used in filter(), exclude(), and order_by()
- Use class-based views (ListView, DetailView, CreateView) over function views
- Use ModelForm for CRUD operations with built-in validation

### DRF & Serializers
- Use ModelSerializer for model-backed API endpoints
- Use SerializerMethodField for computed read-only fields
- Apply permission classes (IsAuthenticated, IsAdminUser) at the view or viewset level
- Use ViewSets with ModelViewSet for standard CRUD endpoints
- Implement pagination (PageNumberPagination) for list endpoints

### Security
- Use Django's built-in CSRF protection for all session-based views
- Apply @login_required or LoginRequiredMixin to protected views
- Validate file uploads with proper content-type checking and size limits
- Use django-cors-headers with explicit allowed origins for API access
- Never use @staff_member_required or is_staff checks alone for sensitive operations

### Testing & Quality
- Write tests with pytest-django for faster test execution
- Use Django TestCase for database-backed integration tests
- Mock external API calls with responses or mocker for reliable unit tests
- Test model methods, view responses, serializer validation, and signal handlers
- Run flake8 and isort for consistent code style

### Build & Deployment
- Use Django 5.0+ for latest features and security patches
- Generate and run migrations with makemigrations and migrate
- Collect static files with collectstatic before deployment
- Use environment variables for settings (SECRET_KEY, DATABASE_URL)
- Configure gunicorn + nginx for production serving

Installation

Create django.mdc in your project's .cursor/rules/ directory and paste the configuration above. Cursor and Windsurf both read .cursor/rules/ — Copilot users place it in .github/copilot-instructions.md instead.

Examples

# models.py — User model with AbstractUser and verbose fields
from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    email = models.EmailField(unique=True, verbose_name="email address")
    bio = models.TextField(blank=True, verbose_name="biography")
    role = models.CharField(max_length=20, choices=UserRole.choices, default=UserRole.USER)

    class Meta:
        indexes = [models.Index(fields=["email"])]

# views.py — Class-based view with ModelForm
from django.views.generic import CreateView
from django.contrib.auth.mixins import LoginRequiredMixin

class ProfileCreateView(LoginRequiredMixin, CreateView):
    model = Profile
    form_class = ProfileForm
    success_url = "/profile/"
# serializers.py — DRF serializer with validation
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    full_name = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ["id", "email", "full_name", "role"]
        read_only_fields = ["id"]

    def get_full_name(self, obj):
        return f"{obj.first_name} {obj.last_name}".strip()