home / skills / physics91 / claude-vibe / django-reviewer

django-reviewer skill

/skills/django-reviewer

This skill reviews Django projects for ORM optimization, view patterns, security, and admin practices to improve performance, safety, and maintainability.

npx playbooks add skill physics91/claude-vibe --skill django-reviewer

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
7.6 KB
---
name: django-reviewer
description: |
  WHEN: Django project review, ORM queries, views/templates, admin customization
  WHAT: ORM optimization + View patterns + Template security + Admin config + Migration safety
  WHEN NOT: FastAPI → fastapi-reviewer, Flask → flask-reviewer, DRF API only → consider api-expert
---

# Django Reviewer Skill

## Purpose
Reviews Django projects for ORM usage, view patterns, security, and best practices.

## When to Use
- Django project code review
- ORM query optimization
- View/template review
- Admin customization review
- Migration safety check

## Project Detection
- `django` in requirements.txt/pyproject.toml
- `manage.py` in project root
- `settings.py` with INSTALLED_APPS
- `urls.py`, `views.py`, `models.py` files

## Workflow

### Step 1: Analyze Project
```
**Django**: 4.2+ / 5.0+
**Database**: PostgreSQL/MySQL/SQLite
**Template Engine**: Django Templates/Jinja2
**REST**: Django REST Framework
**Admin**: Django Admin / Unfold
```

### Step 2: Select Review Areas
**AskUserQuestion:**
```
"Which areas to review?"
Options:
- Full Django review (recommended)
- ORM and query optimization
- Views and URL patterns
- Templates and security
- Admin customization
multiSelect: true
```

## Detection Rules

### ORM Optimization
| Check | Recommendation | Severity |
|-------|----------------|----------|
| N+1 query | Use select_related/prefetch_related | CRITICAL |
| .all() in template | Prefetch in view | HIGH |
| filter().first() | Use .filter().first() or get_or_none | LOW |
| Multiple .save() | Use bulk_update/bulk_create | MEDIUM |

```python
# BAD: N+1 query
def get_orders(request):
    orders = Order.objects.all()
    # Each order.customer triggers a query!
    return render(request, "orders.html", {"orders": orders})

# GOOD: select_related for ForeignKey
def get_orders(request):
    orders = Order.objects.select_related("customer").all()
    return render(request, "orders.html", {"orders": orders})

# GOOD: prefetch_related for ManyToMany/reverse FK
def get_orders(request):
    orders = Order.objects.prefetch_related("items").all()
    return render(request, "orders.html", {"orders": orders})

# BAD: Multiple saves
for item in items:
    item.status = "processed"
    item.save()

# GOOD: Bulk update
Item.objects.filter(id__in=item_ids).update(status="processed")
```

### View Patterns
| Check | Recommendation | Severity |
|-------|----------------|----------|
| Function view for CRUD | Use Class-Based Views | LOW |
| No permission check | Add @login_required or PermissionMixin | HIGH |
| Business logic in view | Move to service/manager | MEDIUM |
| No pagination | Add Paginator | MEDIUM |

```python
# BAD: Logic in view
def create_order(request):
    if request.method == "POST":
        # Too much logic here
        user = request.user
        cart = Cart.objects.get(user=user)
        order = Order.objects.create(user=user, total=cart.total)
        for item in cart.items.all():
            OrderItem.objects.create(order=order, product=item.product)
        cart.items.all().delete()
        send_confirmation_email(user, order)
        return redirect("order_detail", order.id)

# GOOD: Service layer
# services/order_service.py
class OrderService:
    @staticmethod
    def create_from_cart(user: User) -> Order:
        cart = Cart.objects.get(user=user)
        order = Order.objects.create(user=user, total=cart.total)
        OrderItem.objects.bulk_create([
            OrderItem(order=order, product=item.product)
            for item in cart.items.all()
        ])
        cart.items.all().delete()
        send_confirmation_email.delay(user.id, order.id)  # Celery task
        return order

# views.py
class CreateOrderView(LoginRequiredMixin, View):
    def post(self, request):
        order = OrderService.create_from_cart(request.user)
        return redirect("order_detail", order.id)
```

### Template Security
| Check | Recommendation | Severity |
|-------|----------------|----------|
| \|safe filter misuse | Only use for trusted content | CRITICAL |
| {% autoescape off %} | Avoid, use mark_safe in Python | HIGH |
| User input in JS | Use json_script filter | HIGH |
| No CSRF token | Add {% csrf_token %} | CRITICAL |

```html
<!-- BAD: XSS vulnerability -->
<div>{{ user_content|safe }}</div>

<!-- GOOD: Auto-escaped (default) -->
<div>{{ user_content }}</div>

<!-- BAD: User data in JS -->
<script>
var data = "{{ user_data }}";  // XSS risk!
</script>

<!-- GOOD: json_script filter -->
{{ user_data|json_script:"user-data" }}
<script>
const data = JSON.parse(
    document.getElementById("user-data").textContent
);
</script>
```

### Model Design
| Check | Recommendation | Severity |
|-------|----------------|----------|
| No indexes on filter fields | Add db_index=True | HIGH |
| CharField without max_length | Always specify max_length | MEDIUM |
| No __str__ method | Add for admin display | LOW |
| No Meta ordering | Add default ordering | LOW |

```python
# GOOD: Well-designed model
class Order(models.Model):
    user = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name="orders",
    )
    status = models.CharField(
        max_length=20,
        choices=OrderStatus.choices,
        default=OrderStatus.PENDING,
        db_index=True,  # Frequently filtered
    )
    created_at = models.DateTimeField(auto_now_add=True, db_index=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ["-created_at"]
        indexes = [
            models.Index(fields=["user", "status"]),
        ]

    def __str__(self):
        return f"Order {self.id} - {self.user.email}"
```

### Migration Safety
| Check | Recommendation | Severity |
|-------|----------------|----------|
| Non-nullable field without default | Add default or null=True first | CRITICAL |
| Large table ALTER | Use RunSQL with concurrent index | HIGH |
| Data migration in schema migration | Separate into data migration | MEDIUM |

```python
# BAD: Adding non-nullable field
class Migration(migrations.Migration):
    operations = [
        migrations.AddField(
            model_name="order",
            name="tracking_number",
            field=models.CharField(max_length=100),  # Will fail!
        ),
    ]

# GOOD: Safe migration strategy
# Step 1: Add nullable field
migrations.AddField(
    model_name="order",
    name="tracking_number",
    field=models.CharField(max_length=100, null=True),
),
# Step 2: Data migration to populate
# Step 3: Make non-nullable with default
```

## Response Template
```
## Django Code Review Results

**Project**: [name]
**Django**: 5.0 | **DB**: PostgreSQL | **DRF**: 3.14

### ORM Optimization
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | views.py:45 | N+1 query - missing select_related |

### View Patterns
| Status | File | Issue |
|--------|------|-------|
| HIGH | views.py:23 | Missing LoginRequiredMixin |

### Template Security
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | templates/user.html:12 | Unsafe |safe filter usage |

### Migrations
| Status | File | Issue |
|--------|------|-------|
| CRITICAL | 0015_add_field.py | Non-nullable field without default |

### Recommended Actions
1. [ ] Add select_related to order queries
2. [ ] Add permission mixins to views
3. [ ] Remove |safe from user content
4. [ ] Fix migration for tracking_number field
```

## Best Practices
1. **ORM**: Always prefetch related objects
2. **Views**: Use CBV, service layer for logic
3. **Security**: CSRF, XSS prevention, permissions
4. **Migrations**: Zero-downtime strategies
5. **Testing**: Factory Boy, pytest-django

## Integration
- `python-reviewer`: General Python patterns
- `security-scanner`: Django security audit
- `sql-optimizer`: Query analysis

Overview

This skill reviews Django projects to find performance issues, security risks, and maintenance problems across ORM usage, views, templates, admin, and migrations. It produces actionable recommendations to optimize queries, restructure business logic, secure templates, and make migrations safe. The output highlights severity and file locations so you can prioritize fixes quickly.

How this skill works

It scans project indicators (requirements, manage.py, settings.py, urls.py, views.py, models.py) to detect a Django codebase and inspects ORM patterns, view structure, template usage, model design, admin configuration, and migrations. For each finding it reports severity (CRITICAL/HIGH/MEDIUM/LOW), explains the issue, and gives concrete code-level remediation such as select_related/prefetch_related, service extraction, CSRF/JSON encoding fixes, and safe migration sequences. Recommendations are framed to be actionable and prioritized.

When to use it

  • Before releases to catch N+1 queries, unindexed filters, and heavy migrations
  • During code review for new views or refactors to enforce patterns and permissions
  • When you suspect template XSS, unsafe |safe usage, or missing CSRF tokens
  • When preparing schema changes to ensure zero-downtime migrations
  • When hardening admin customizations and model representations in the admin UI

Best practices

  • Detect and fix N+1 queries with select_related for FK and prefetch_related for M2M/reverse FK
  • Keep business logic out of views—use service/manager layers and Class-Based Views with Mixins
  • Treat templates as untrusted: avoid |safe, prefer json_script for JS, and always include {% csrf_token %}
  • Design models with explicit max_length, db_index for filtered fields, and useful __str__ and Meta ordering
  • Split schema and data migrations: add nullable fields first, populate data, then make fields non-nullable

Example use cases

  • A pull request contains new list views that may cause N+1 queries; run the skill to get select_related suggestions
  • A team plans a large schema change; run migration safety checks to recommend a zero-downtime strategy
  • An admin customization shows slow pages; detect missing indexes and poor queryset usage
  • A template injects user content into JavaScript; get json_script and escaping fixes to prevent XSS
  • Hardening a legacy app: identify views missing permission checks and recommend LoginRequired/PermissionMixins

FAQ

Does this skill run against non-Django frameworks?

No. It targets Django projects. For FastAPI, Flask, or DRF-only APIs, use the appropriate reviewer (fastapi-reviewer, flask-reviewer, or api-expert).

How does it detect a Django project?

It looks for indicators like django in requirements/pyproject, presence of manage.py, settings.py with INSTALLED_APPS, and common Django files such as urls.py, views.py, and models.py.

Will it modify my code or migrations?

No. It only analyzes and reports findings with suggested code changes and safe migration steps for you to apply manually.