django-development

majiayu000's avatarfrom majiayu000

Comprehensive Django development guidelines for Pantas Green emissions tracking platform.Use when: writing Django models, views, serializers, migrations, ORM queries, templates, or any Python backend code.Triggers: django, model, view, serializer, migration, ORM, queryset, endpoint, API, DRF, emission, carbon, python backend, template, admin

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 5, 2026

When & Why to Use This Skill

This Claude skill provides a comprehensive Django development framework and style guide specifically optimized for the Pantas Green emissions tracking platform. It enforces high-standard Python backend practices, including Test-Driven Development (TDD), ORM optimization to prevent N+1 queries, and strict data precision requirements for carbon accounting, ensuring the delivery of scalable, maintainable, and performant enterprise applications.

Use Cases

  • Architecting Django models for emissions tracking with mandatory audit trails and high-precision decimal calculations.
  • Optimizing database performance by implementing advanced ORM patterns like select_related and prefetch_related to eliminate N+1 query issues.
  • Standardizing Python backend code structure, including import organization, class method ordering, and naming conventions for better team collaboration.
  • Implementing robust API endpoints and serializers using Django Rest Framework (DRF) while maintaining strict separation of business logic.
  • Conducting automated code quality reviews using the built-in checklist for Ruff, Mypy, and comprehensive unit testing standards.
namedjango-development
version2.0.0
description|
Use whenwriting Django models, views, serializers, migrations, ORM queries, templates, or any Python backend code.
Triggersdjango, model, view, serializer, migration, ORM, queryset, endpoint, API, DRF, emission, carbon, python backend, template, admin

Django Development Guidelines

Quick Reference

Rule Description
TDD Scaffold stub → write failing test → implement
ORM Use select_related() and prefetch_related() to avoid N+1
Decimals Use DecimalField for financial/emissions, never FloatField
Business Logic Keep in models and services, not views
Constants No hardcoded strings - use constants from */constants/*.py
DRY Templates Don't pass redundant context variables to templates

Before Coding

  • BP-1 (MUST) Ask clarifying questions
  • BP-2 (SHOULD) Draft and confirm approach for complex work
  • BP-3 (SHOULD) List pros/cons if multiple approaches exist

Code Organization & Structure

Import Organization

# Standard library imports
import os
from datetime import datetime

# Third-party imports
from django.db import models
from rest_framework import serializers

# Local imports
from .models import MyModel
from .constants import STATUS_PENDING

Class Method Order

class MyClass:
    # 1. __init__ and constructors
    def __init__(self): ...

    # 2. @classmethod methods
    @classmethod
    def create(cls): ...

    # 3. @staticmethod methods
    @staticmethod
    def validate(): ...

    # 4. @property methods
    @property
    def name(self): ...

    # 5. Public methods
    def process(self): ...

    # 6. Private methods
    def _internal(self): ...

    # 7. Magic methods
    def __str__(self): ...

File Naming

  • Files: snake_case.py
  • Classes: PascalCase
  • Functions: snake_case
  • Constants: UPPER_SNAKE_CASE

Directory Structure

green/
├── static/
│   ├── js/<model_name>/    # JavaScript files by model
│   └── css/<model_name>/   # CSS files by model
└── templates/
    └── <app_name>/

Model Standards

Base Requirements

  • Inherit from CustomModel for common fields
  • Use HistoricalRecords for audit trails
  • Use DecimalField for financial/emissions calculations (never FloatField)

Admin Registration Pattern

@admin.register(MyModel)
class MyModelAdmin(GreenImportExportMixin, LocalDatetimeMixin, SimpleHistoryAdmin):
    change_list_template = 'admin/impexp_change_list.html'
    local_datetimes = ('created_at', 'updated_at')
    list_select_related = ('foreign_key_field',)  # Optimize queries

    class Meta:
        permissions = [
            ('import_mymodel', 'Can import MyModel'),
            ('export_mymodel', 'Can export MyModel'),
        ]

Function Quality Standards

  • Readability: Function purpose should be immediately clear
  • Low Complexity: Minimal nesting, low cyclomatic complexity
  • Early Returns: Exit early instead of deep nesting
  • Positive Checks: Prefer if is_valid over if not is_invalid
  • No Unused Code: Remove unused parameters, variables, and functions
  • Descriptive Names: Consistent with existing codebase vocabulary

Database Query Optimization

N+1 Prevention (CRITICAL)

# ❌ BAD - N+1 query problem
for order in Order.objects.all():
    print(order.customer.name)  # Queries DB for each order

# ✅ GOOD - Single query with JOIN
for order in Order.objects.select_related('customer'):
    print(order.customer.name)  # No additional queries

# ✅ GOOD - Prefetch for ManyToMany and reverse FK
orders = Order.objects.prefetch_related('items', 'tags')

Bulk Operations

# ❌ BAD - Multiple queries
for id in ids:
    obj = Model.objects.get(id=id)

# ✅ GOOD - Single query
objs = Model.objects.filter(id__in=ids)

Circular Join Detection

# ❌ BAD - Circular join pattern (A → B → A)
Model.objects.filter(related__back_to_model__field=value)

# ❌ BAD - Excessive relationship traversal
Model.objects.filter(a__b__c__d__e__field=value)

# ✅ GOOD - Direct path
Model.objects.filter(direct_field=value)

Key indicators of problematic queries:

  • Relationship paths that go A → B → A (circular)
  • More than 3-4 relationship traversals
  • Complex joins when simpler alternatives exist

Constants & String Literals (MANDATORY)

Rule: No Magic Strings

String literals used 3 or more times MUST be defined as constants.

# ❌ BAD - Hardcoded strings
if material_source == 'epd':
    ...
elif material_source == 'pantas':
    ...

# ✅ GOOD - Named constants
from .constants import MATERIAL_SOURCE_EPD, MATERIAL_SOURCE_PANTAS

if material_source == MATERIAL_SOURCE_EPD:
    ...
elif material_source == MATERIAL_SOURCE_PANTAS:
    ...

Constants File Pattern

# app/constants.py
STATUS_PENDING = 'pending'
STATUS_COMPLETED = 'completed'
STATUS_FAILED = 'failed'

STATUS_CHOICES = [
    (STATUS_PENDING, 'Pending'),
    (STATUS_COMPLETED, 'Completed'),
    (STATUS_FAILED, 'Failed'),
]

# Usage in models
class MyModel(models.Model):
    status = models.CharField(choices=STATUS_CHOICES, default=STATUS_PENDING)

Common Patterns to Avoid

Pattern Problem Fix
== 'pending' Magic string Use STATUS_PENDING
== 'epd' Magic string Use MATERIAL_SOURCE_EPD
filter(type='scope1') Magic string Use SCOPE_1 constant
choices=[('a', 'A')] No constants Define choice constants

View-Template DRY (MANDATORY)

Rule: Don't Pass Redundant Context Variables

If an object is already in context, templates can access its properties directly.

# ❌ BAD - Redundant context variables
def my_view(request):
    user = request.user
    return render(request, 'template.html', {
        'user': user,
        'user_name': user.name,        # Redundant!
        'user_email': user.email,      # Redundant!
        'is_active': user.is_active,   # Redundant!
    })

# ✅ GOOD - Let template access properties
def my_view(request):
    return render(request, 'template.html', {
        'user': request.user,
    })

In template:

{{ user.name }}
{{ user.email }}
{{ user.is_active }}

Exceptions (NOT violations)

  • Computed values: "total": calculate_total(items) ✅
  • Method calls with arguments: "filtered": obj.get_items(status='active') ✅
  • Renamed for clarity: "current_user": request.user when template expects specific name ✅

Template Technology Consistency (MANDATORY)

Rule: Use Django Filters, Not JavaScript

Don't duplicate Django template filter functionality in JavaScript.

JS Pattern Django Alternative
new Date().toLocaleString() {{ value|date:"format" }}
toLocaleDateString() {{ value|date:"format" }}
.toLowerCase() {{ value|lower }}
.toUpperCase() {{ value|upper }}
String truncation {{ value|truncatechars:N }}
Number formatting {{ value|floatformat }}

When to Use Django Filters

  • Codebase already uses Django filters for same purpose
  • Django handles it without JavaScript
  • Reduces client-side complexity

Frontend Standards

  • No Inline Styles: Use Bootstrap classes
  • No Inline JavaScript: Place in green/static/js/<model_name>/
  • Consistent Bootstrap: Use Bootstrap framework for styling
  • Template Inheritance: Proper Django template blocks
  • Responsive Design: Works on mobile and desktop

Exception Handling & Logging

Exception Logging

# ✅ CORRECT - exc_info=True ONLY in exception handler
try:
    result = process_data()
except Exception as e:
    logger.error(f"Processing failed: {e}", exc_info=True)

# ✅ CORRECT - No exc_info outside exception block
logger.info(f"Processing started for company {company_id}")
logger.warning(f"Missing optional field: {field_name}")

# ❌ WRONG - exc_info=True outside exception (no stack trace to capture)
logger.info(f"Processing started", exc_info=True)

Log Levels

Level Use For
ERROR Exceptions, failures
WARNING Recoverable issues
INFO Significant events
DEBUG Diagnostic details

Context in Logs

Include relevant IDs: user_id, file_id, company_id

Never log: passwords, tokens, sensitive PII


Testing Standards

Organization

  • Tests in tests/ directory within each app
  • Unit tests: SimpleTestCase (no DB)
  • Integration tests: TestCase (with DB)

Database Mocking

# ✅ Unit tests use Mock, no real DB
from unittest.mock import Mock, patch

class MyTestCase(SimpleTestCase):
    @patch('myapp.services.Model.objects.get')
    def test_something(self, mock_get):
        mock_get.return_value = Mock(name='Test')
        ...

Test Data

# ❌ BAD - Meaningless test data
user = User(name='foo', age=42)

# ✅ GOOD - Realistic test data
user = User(name='John Smith', age=35)

Assertions

# ❌ WEAK - Ambiguous assertion
self.assertGreaterEqual(count, 0)

# ✅ STRONG - Specific assertion
self.assertEqual(count, 5)

Domain-Specific: Emissions

  • Precision: Maintain accuracy in carbon calculations
  • Unit Consistency: Consistent units throughout
  • Financial Fields: Always use DecimalField
  • Audit Trails: Track all calculation changes
  • Validation: Validate emission factors and data sources

Performance & Security

Performance

  • Test query count for performance-critical code
  • Consider memory usage in data processing
  • Use Dramatiq for long-running operations

Security

  • Never log sensitive information
  • Validate file types and sizes for uploads
  • Use Django ORM (avoid raw SQL)

Quality Gates

Gate Command/Requirement
G-1 ruff check passes
G-2 mypy passes
G-3 python manage.py test passes

Code Review Checklist

Before submitting code for review, verify:

Code Quality

  • Import organization correct (stdlib → third-party → local)
  • Class method order follows convention
  • No unused imports, variables, or functions
  • Early return pattern used (no deep nesting)

Database

  • N+1 queries prevented with select_related/prefetch_related
  • No circular join patterns
  • Bulk operations used where appropriate

Constants (MANDATORY)

  • No hardcoded strings used 3+ times
  • Existing constants reused from */constants/*.py
  • New constants created for repeated domain-specific strings

View-Template DRY (MANDATORY)

  • No redundant context variables in render() calls
  • Templates access object properties directly

Template Technology (MANDATORY)

  • No JavaScript duplicating Django filter functionality
  • Consistent with existing codebase patterns

Testing

  • Unit tests use Mock (no DB access)
  • Realistic test data (not "foo" or 42)
  • Strong assertions (assertEqual vs assertGreaterEqual)

Logging

  • exc_info=True only in exception handlers
  • No sensitive data in logs
  • Includes relevant context IDs

Summary of Coding Rules

Rule Level Description
BP-1 MUST Ask clarifying questions
BP-2 SHOULD Confirm approach for complex work
BP-3 SHOULD List pros/cons for multiple approaches
C-1 MUST Follow TDD workflow
C-2 MUST Use existing domain vocabulary
C-3 SHOULD Use Django class-based views
C-4 SHOULD Prefer simple, composable functions
C-6 MUST Follow import conventions and PEP 8
C-10 MUST Use constants for repeated strings
C-11 MUST No local imports inside functions
D-1 MUST Avoid N+1 queries
D-2 SHOULD Use transactions for atomic operations
D-3 MUST Create migrations for model changes
D-4 SHOULD Use Decimal for financial/emissions
T-1 MUST Tests in tests/ directory
T-3 MUST Separate unit from integration tests
T-7 MUST Realistic test data
L-1 MUST exc_info=True in exception handlers
L-4 MUST No sensitive data in logs
G-1 MUST ruff check passes
G-2 MUST mypy passes
G-3 MUST Django tests pass

Version: 2.0.0 - Enhanced with lessons from django-reviewer agent