Frameworks · Django

AI code review for Django —
catches the ORM escape-hatch traps.

Django's ORM is safe by default. The bugs happen at the escape hatches: `.raw()` and `.extra()` with f-string interpolation, `mark_safe()` on user input, `DEBUG = True` slipping into prod settings. LGTM's Django hints fire in the bugs + security agents whenever it sees `django` in your requirements or pyproject.

Auto-detected. Zero configuration.

Auto-detected when `django` appears in your `requirements.txt`, `pyproject.toml`, or `Pipfile`. LGTM's Django hint pack loads into the bugs + security + best-practices agents automatically.

Django bugs that hide in plain sight

Four patterns that get past general-purpose code review because they look like idiomatic Django. LGTM knows the shape of each.

ORM escape hatches

`.raw()`, `.extra()`, and `RawSQL()` bypass Django's default parameterization. Team members reach for them when the ORM feels awkward — and f-string a user id into the query. Instant SQL injection on a framework that's normally rock-solid.

mark_safe on user input

Django auto-escapes template variables. `mark_safe()` disables that for the wrapped string. Wrapping user-controlled data in `mark_safe()` is a direct XSS. Easy to write, easy to miss in review.

DEBUG = True in production

Local dev uses `DEBUG = True`. A settings file split (base.py / dev.py / prod.py) is the fix — but until it's set up, one wrong commit ships the debug page + tracebacks to production. Data leakage on every unhandled exception.

Missing CSRF on custom endpoints

Django provides `@csrf_exempt` for cases where a view genuinely can't accept a CSRF token (webhooks, mobile APIs). It's also easy to slap on when tests fail — silently disabling protection on real endpoints.

What LGTM actually catches

Three real examples — the Django-aware bugs + security agents flag these with inline 🎯 Actionable comments and a clear "why" explanation.

criticalsql-injection
def orders_for_user(request):
    user_id = request.GET["user_id"]
    qs = Order.objects.raw(
        f"SELECT * FROM shop_order WHERE user_id = {user_id}"
    )
    return JsonResponse({"orders": [o.id for o in qs]})

What: Django .raw() with f-string interpolation of request.GET data

Why: `request.GET['user_id']` is attacker-controlled. Use parameter binding: `Order.objects.raw('SELECT * FROM shop_order WHERE user_id = %s', [user_id])`.

highxss-reflected
from django.utils.safestring import mark_safe

def profile_view(request, username):
    display = mark_safe(f"Welcome, <b>{username}</b>!")
    return render(request, "profile.html", {"display": display})

What: mark_safe() wrapping a template string that includes user data

Why: Django's auto-escape is bypassed inside mark_safe. A username of `<script>...</script>` executes in the visitor's browser. Use `format_html` with named placeholders instead — it escapes each interpolation.

criticalsensitive-data-exposure
# settings.py
DEBUG = True
ALLOWED_HOSTS = ["*"]
SECRET_KEY = "django-insecure-dev-key-1234"

What: DEBUG=True + wildcard ALLOWED_HOSTS + hardcoded SECRET_KEY

Why: Any of these in a production-facing settings file is a full-severity issue. Use environment-driven configuration via django-environ, and split settings by env (dev/prod).

Django starter .lgtm.yml

Skip migrations (auto-generated), force the django framework slug, bump SQL / XSS / secret-exposure to critical.

version: 1

paths:
  - pattern: "**/migrations/**"
    skip: true
  - pattern: "**/static/**"
    skip: true

frameworks:
  - "django"

severity_overrides:
  sql-injection: "critical"
  xss-reflected: "critical"
  sensitive-data-exposure: "critical"

auto_approve_docs_only: true

Commit as .lgtm.yml at your repo root, flip the Enable .lgtm.yml toggle in Repo Settings. Next PR picks it up. See all recipes →

What ships on every Django review

Same pipeline that reviews everything else on LGTM — the Djangohints just tune each agent's attention.

6 agents in parallel

Bugs, Security, Performance, Readability, Best-practices, Documentation. Each with framework-specific hints when LGTM detects your stack.

16 CI/CD detectors

LGTM Security scans your GitHub Actions, Dockerfiles, and lockfiles alongside the code review. Merge-blocking Check Run on block-level findings.

Adversarial verifier

Every finding is refuted by a skeptic LLM before it posts. Only survivors reach your PR. Kills the confident-hallucination class of false positives.

Try LGTM on your Django repo

Free tier: 20 reviews / month, all 6 agents, all 16 security detectors. BYOK OpenAI or Anthropic. No card required.