skills/django-5/SKILL.md
# Django 5 Code Review Skill ## Overview This skill provides code review guidelines for Django 5 applications, focusing on async views, Django REST Framework, security best practices, and modern patterns. ## Key Review Areas ### 1. Async Views and ORM **Check for proper async usage:** - Use async views for I/O-bound operations - Use `sync_to_async` for ORM operations in async views - Consider `aiterator()` for large querysets - Be aware of connection pool exhaustion ```python # Good: Async
npx skillsauth add danieldeusing/reviewr-templates skills/django-5Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill provides code review guidelines for Django 5 applications, focusing on async views, Django REST Framework, security best practices, and modern patterns.
Check for proper async usage:
sync_to_async for ORM operations in async viewsaiterator() for large querysets# Good: Async view with proper ORM handling
from asgiref.sync import sync_to_async
async def user_list(request):
users = await sync_to_async(list)(
User.objects.filter(is_active=True).select_related('profile')
)
return JsonResponse({'users': [u.to_dict() for u in users]})
# Good: Async iteration for large datasets
async def export_data(request):
async for item in Item.objects.filter(active=True).aiterator():
yield process_item(item)
# Avoid: Direct ORM calls in async context
async def bad_view(request):
users = User.objects.all() # SynchronousOnlyOperation error
Verify security patterns:
# Good: Parameterized queries
User.objects.filter(email=user_input) # Safe
User.objects.raw('SELECT * FROM users WHERE email = %s', [user_input]) # Safe
# Avoid: String interpolation in queries
User.objects.raw(f'SELECT * FROM users WHERE email = "{user_input}"') # SQL injection!
# Good: Permission checks
from django.contrib.auth.decorators import permission_required
@permission_required('app.change_item', raise_exception=True)
def edit_item(request, pk):
item = get_object_or_404(Item, pk=pk)
# ...
# Good: Object-level permissions
def update_item(request, pk):
item = get_object_or_404(Item, pk=pk)
if item.owner != request.user:
raise PermissionDenied
Review DRF patterns:
# Good: Serializer with validation
class UserSerializer(serializers.ModelSerializer):
email = serializers.EmailField(validators=[UniqueValidator(queryset=User.objects.all())])
class Meta:
model = User
fields = ['id', 'email', 'first_name', 'last_name']
read_only_fields = ['id']
def validate_email(self, value):
if 'spam' in value:
raise serializers.ValidationError("Invalid email domain")
return value.lower()
# Good: ViewSet with permissions
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
pagination_class = StandardResultsSetPagination
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ['status', 'category']
search_fields = ['name', 'description']
ordering_fields = ['created_at', 'name']
Check for database performance:
select_related for ForeignKey fieldsprefetch_related for reverse relations and M2Monly() or defer() for large models# Good: Optimized queries
articles = Article.objects.select_related('author').prefetch_related(
'tags',
Prefetch('comments', queryset=Comment.objects.select_related('user'))
).filter(published=True)
# Avoid: N+1 queries
articles = Article.objects.all()
for article in articles:
print(article.author.name) # Separate query for each article!
# Good: Efficient bulk operations
Item.objects.bulk_create([Item(name=n) for n in names])
Item.objects.filter(status='draft').update(status='published')
Review model patterns:
# Good: Well-designed model
class Article(models.Model):
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(unique=True)
content = models.TextField()
author = models.ForeignKey(User, on_delete=models.PROTECT, related_name='articles')
status = models.CharField(max_length=20, choices=Status.choices, default=Status.DRAFT)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = ArticleManager()
published = PublishedManager()
class Meta:
ordering = ['-created_at']
indexes = [
models.Index(fields=['status', '-created_at']),
]
def clean(self):
if self.status == Status.PUBLISHED and not self.content:
raise ValidationError("Published articles must have content")
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super().save(*args, **kwargs)
Verify form handling:
# Good: Form with validation
class RegistrationForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
password_confirm = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email', 'first_name', 'last_name']
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
if password and password_confirm and password != password_confirm:
raise forms.ValidationError("Passwords don't match")
return cleaned_data
Verify testing practices:
# Good: Comprehensive test
import pytest
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APIClient
@pytest.mark.django_db
class TestArticleAPI:
def test_list_articles_authenticated(self, api_client, user):
api_client.force_authenticate(user=user)
response = api_client.get(reverse('article-list'))
assert response.status_code == status.HTTP_200_OK
def test_create_article_requires_auth(self, api_client):
response = api_client.post(reverse('article-list'), {'title': 'Test'})
assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_user_can_only_edit_own_articles(self, api_client, user, other_user_article):
api_client.force_authenticate(user=user)
response = api_client.patch(
reverse('article-detail', args=[other_user_article.id]),
{'title': 'Hacked'}
)
assert response.status_code == status.HTTP_403_FORBIDDEN
development
# React 18 Code Review Skill ## Overview This skill provides code review guidelines for React 18 applications, focusing on hooks, concurrent features, Suspense, and modern patterns. ## Key Review Areas ### 1. Hooks Best Practices **Check for proper hook usage:** - Follow the Rules of Hooks (only call at top level, only in React functions) - Use appropriate hooks for the use case - Ensure custom hooks start with `use` prefix - Check dependency arrays for completeness and correctness ```type
development
# FastAPI Code Review Skill ## Overview This skill provides code review guidelines for FastAPI applications, focusing on async patterns, Pydantic v2 models, dependency injection, and API best practices. ## Key Review Areas ### 1. Pydantic Models **Check for proper model usage:** - Use Pydantic v2 syntax and features - Define proper validation rules - Use appropriate field types - Separate request/response models when needed ```python # Good: Pydantic v2 model with validation from pydantic
development
# Angular 19 Code Review Skill ## Overview This skill provides code review guidelines for Angular 19 applications, focusing on modern patterns including signals, standalone components, and the new control flow syntax. ## Key Review Areas ### 1. Signal-Based Reactivity **Check for proper signal usage:** - Use `signal()` for reactive state instead of BehaviorSubject where appropriate - Use `computed()` for derived values - Use `effect()` sparingly and only for side effects - Prefer `input()`
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.