Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Django/Python-specific code review overlay. Extends the universal code-reviewer skill with Django and Python version-aware rules. Trigger when reviewing Django views, models, serializers, forms, URLs, settings, migrations, Celery tasks, or any .py file in a Django project. Keywords: Django, DRF, ORM, QuerySet, serializer, viewset, model, migration, WSGI, ASGI, Celery, pytest-django. Do NOT trigger for pure Python scripts unrelated to Django, or for frontend code in the same project (use code-rev
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✓→✓ | = Same ✓ | 81% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 157% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 132% | 0% |
| case-06 | ✓→✓ | = Same ✓ | 207% | 0% |
| case-07 | ✓→✓ | = Same ✓ | 78% | 0% |
This skill extends code-reviewer (the universal skill). Always apply the universal skill's full checklist first, then apply the Django-specific rules in this file on top.
Composition order:
code-reviewer (universal pillars: correctness, security, performance, DRY, tests, docs)Run these commands before touching any code. Version determines which rules apply.
bash# Python version python --version cat .python-version 2>/dev/null # Django version python -c "import django; print(django.get_version())" # Key package versions pip show djangorestframework celery | grep -E "^(Name|Version)" # Check if project uses ASGI or WSGI grep -r "application = " */asgi.py */wsgi.py 2>/dev/null | head -5
Report at the top of your review:
🔍 Environment: Python X.Y | Django X.Y | DRF X.Y (if present) | WSGI/ASGIThen apply the version-specific rules below that match.
async def views with ORM calls without sync_to_async(). Flag SynchronousOnlyOperation risk.acreate(), aget(), afilter() — these don't exist yet; flag if used.X_FRAME_OPTIONS defaults to DENY since 3.0 — flag any override that weakens it.acreate, aget, asave, adelete, aiterator) — prefer these in async views over sync_to_async() wrapping.async def get() / async def post() handlers are used correctly.async views that use transaction.atomic() without sync wrapping.Signal.asend() / Signal.asend_robust() not yet available — flag async signal dispatch attempts.GeneratedField and db_default are available — flag Python-side computed defaults that could be db_default=Now() or a GeneratedField.sync_to_async(decorator) workarounds that are now unnecessary.asyncio.CancelledError available for async disconnect cleanup — flag missing cleanup in async views with long-held connections.mysql-connector or settings targeting MySQL < 8.0.acheck_password, async permissions) — flag sync auth calls in async views.match/case, no X | Y union types, no dict | dict merge operator. Flag if used on these versions.match/case available — flag verbose if/elif chains on Django model state that could be a match.target-version = "py312" or "py313" in ruff.toml.Work through each section. Skip if not relevant to the files being reviewed.
select_related() or prefetch_related().python # ❌ N+1 for order in Order.objects.all(): print(order.user.email) # query per order
# ✅ Fixed for order in Order.objects.select_related('user'): print(order.user.email)
cursor.execute() or Model.objects.raw() with f-strings or string concatenation. Must use parameterized queries: cursor.execute("... WHERE id = %s", [user_input])..save() inside that could use bulk_create() or bulk_update().list() on a queryset before filtering is complete).only() / defer() — flag queries that load all fields when only a subset is needed.values() / values_list() — suggest for read-only, non-model use cases to reduce memory overhead.exists() vs count() — flag count() > 0 checks; use exists() instead.get() without try/except — flag bare Model.objects.get() without catching DoesNotExist.sync_to_async() or not using a-prefixed methods.CharField and TextField — flag null=True on string fields; Django convention is blank=True only (empty string, not NULL).ForeignKey — flag missing on_delete argument (required since Django 2.0).ForeignKey — flag missing related_name on fields that will be reverse-accessed.get_queryset() without calling super().Meta.ordering — flag models with ordering set that also use .order_by() everywhere (redundant).__str__ — flag models missing a __str__ method.makemigrations skipped after model changes (check if migration files match model state).GeneratedField (5.0+) — suggest replacing @property fields that only read other model fields.get_object_or_404 — flag bare Model.objects.get() in views where get_object_or_404 is more appropriate.@login_required, permission_required, or IsAuthenticated (DRF).@csrf_exempt) without documented justification.dispatch() for logic that belongs in get() / post().reverse() or {% url %}.validate_<field>() or validate() methods for business rules.SerializerMethodField — flag methods that hit the database (N+1 risk in list views).ViewSet vs APIView — flag APIView used where a ViewSet + router would reduce boilerplate.DEFAULT_THROTTLE_CLASSES for anonymous endpoints.depth on serializers — flag depth > 1; prefer explicit nested serializers for control.permission_classes = [] — flag explicitly empty permissions (open endpoint) without comment.DEBUG = True in any non-development settings file — critical, must flag.SECRET_KEY hardcoded in settings — must come from environment variable.ALLOWED_HOSTS = ['*'] in production settings — flag.python SECURE_SSL_REDIRECT = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SECURE_HSTS_SECONDS = 31536000 X_FRAME_OPTIONS = 'DENY' SECURE_CONTENT_TYPE_NOSNIFF = True
|safe in templates — flag any use; verify it's intentional and the value is truly safe.settings.py that mixes dev and production config — suggest settings/base.py, settings/dev.py, settings/production.py.INSTALLED_APPS containing debug tools (debug_toolbar, django_extensions) in production settings.DEFAULT_AUTO_FIELD (causes warnings in Django 3.2+).DATABASES with hardcoded credentials — must use os.environ.get() or django-environ.pytest-django or TestCase from django.test.@pytest.mark.django_db or TransactionTestCase.setUpTestData() for expensive setup shared across test methods.assertRaisesMessage / assertFormError where appropriate.sync_to_async() (all versions).transaction.atomic() inside async views without sync wrapping (all versions — transactions are not async-safe).await on a-prefixed ORM methods (await Model.objects.acreate(...)) — 4.1+.sync_to_async(decorator) workarounds for decorators that natively support async (5.0+).@shared_task or @app.task.bind=True on tasks that need self.retry().transaction.on_commit() wrapper (risk of operating on uncommitted data).CELERY_BROKER_URL — must come from environment.ruff configuration (pyproject.toml or ruff.toml) in new projects.print() statements left in production code — use logging.except: clauses — must be except Exception at minimum, with logging.isort or ruff handles this.logger.info(f"...") → use logger.info("...", extra={...}).Use the same format as code-reviewer (universal). Add a Django context line:
🔍 Environment: Python 3.12 | Django 5.2 LTS | DRF 3.15 | ASGI
## Code Review Summary
[... standard universal format ...]
### 🐍 Django-Specific Issues
[Issues found by this overlay, using the same severity/format as universal]settings/production.py as security-critical scope.security-auditor skill if available.Other measured skills in the registry, with their headline benchmark lift.