TouchDRF: Django REST Prototyping Kit
TouchDRF provides a suite of intelligent VS Code snippets designed to accelerate the setup and development of Django Rest Framework (DRF) APIs. It focuses on Function-Based Views (FBV) for maximum control over request handling and response structures.
Click a link below to jump straight to the code pattern:
- Setup & Config (Settings.py)
- Standard Imports (Views.py)
- Login View (Manual Auth)
- Create Resource (POST) (Role Checks)
- List Resources (GET) (Filtering)
- Update Resource (PATCH) (Ownership)
- Delete Resource (DELETE) (Ownership)
- Serializer Logic (Foreign Keys)
- URL Routing (urls.py)
🚀 Snippet Trigger List
Type the trigger prefix in any Python file and press Tab to expand.
| Trigger |
Description |
touchdrfset |
Injects required INSTALLED_APPS and REST_FRAMEWORK config. |
touchdrfimp |
Imports all essential DRF decorators, permissions, and models. |
touchdrflogin |
Generates a manual Login View pattern. |
touchdrfcrud |
Generates Create (POST) and List (GET) logic. |
touchdrfid |
Generates Update (PATCH) and Delete (DELETE) logic by ID. |
touchdrfser |
Generates a ModelSerializer with field configurations. |
touchdrfurls |
Generates standard URL patterns for the views above. |
🛠️ Configuration Checklist
When setting up a new project, ensure these steps are completed in settings.py immediately after generating the project:
- Apps: Ensure
rest_framework, rest_framework_simplejwt, and your app_name are in INSTALLED_APPS.
- Auth: Verify
AUTH_USER_MODEL points to your custom model (e.g., 'myapp.User') if you are not using the default.
- Security: Ensure the
REST_FRAMEWORK dictionary sets IsAuthenticated as the default permission class.
(Use touchdrfset to automate this).
💡 Code Patterns & Logic
🔌 Standard Imports
Commonly used modules for views.
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.response import Response
from rest_framework import status
from rest_framework_simplejwt.tokens import RefreshToken
from .models import ItemModel, UserModel
from .serializers import ItemSerializer
🔐 Custom Login Implementation
For scenarios requiring manual credential validation or custom response formats (e.g., returning status 201).
@api_view(['POST'])
@permission_classes([AllowAny])
def login_view(request):
# Manual validation pattern
if not request.data.get('email'):
return Response({"msg": "Validation error"}, status=400)
# User Lookup
try:
user = UserModel.objects.get(email=request.data.get('email'))
except UserModel.DoesNotExist:
return Response({"msg": "Invalid credentials"}, status=400)
# Password Verification (Manual check for non-standard models)
if user.password != request.data.get('password'):
return Response({"msg": "Invalid credentials"}, status=400)
# Token Generation
refresh = RefreshToken.for_user(user)
return Response({
"username": user.username,
"token": str(refresh.access_token)
}, status=201)
### 📦 Serializer Configuration
Use `read_only_fields` to prevent validation errors for fields assigned programmatically in the view (e.g., the author).
```python
from rest_framework import serializers
from .models import ItemModel
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = ItemModel
fields = '__all__'
# Exclude 'author' from input validation, but include in output
read_only_fields = ['author', 'seller']
➕ Create Resource (POST)
Implementation of resource creation with Role-Based Access Control (RBAC).
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def add_item(request):
# Role Verification
if request.user.role.rolename != 'seller':
return Response({"msg": "Permission denied: Seller role required"}, status=403)
if not request.data:
return Response({"msg": "No data provided"}, status=400)
serializer = ItemSerializer(data=request.data)
if serializer.is_valid():
# Programmatically assign the owner
serializer.save(seller=request.user)
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
📋 List Resources (GET)
Fetching lists with query parameter filtering and explicit empty-result handling.
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def get_items(request):
items = ItemModel.objects.all()
# Filtering Logic
cat = request.query_params.get('category')
if cat:
items = items.filter(category=cat)
# Strict Validation: Return 400 if no results found
if not items.exists():
return Response({"msg": "No results found"}, status=400)
serializer = ItemSerializer(items, many=True)
return Response(serializer.data, status=200)
✏️ Update Resource (PATCH)
Partial updates using ID lookup and ownership verification.
@api_view(['PATCH'])
@permission_classes([IsAuthenticated])
def update_item(request, pk):
try:
item = ItemModel.objects.get(pk=pk)
except ItemModel.DoesNotExist:
return Response({"msg": "Resource not found"}, status=404)
# Ownership Verification
if item.seller != request.user:
return Response({"msg": "Permission denied: You do not own this item"}, status=403)
# Partial Update
serializer = ItemSerializer(item, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=200)
return Response(serializer.errors, status=400)
❌ Delete Resource (DELETE)
Resource deletion with ownership verification.
@api_view(['DELETE'])
@permission_classes([IsAuthenticated])
def delete_item(request, pk):
try:
item = ItemModel.objects.get(pk=pk)
except ItemModel.DoesNotExist:
return Response({"msg": "Resource not found"}, status=404)
# Ownership Verification
if item.seller != request.user:
return Response({"msg": "Permission denied: You do not own this item"}, status=403)
item.delete()
return Response(status=204)
🔗 URL Routing
Standard routing pattern for the views above.
from django.urls import path
from . import views
urlpatterns = [
path('api/login/', views.login_view),
path('api/store/items/', views.get_items),
path('api/store/add/', views.add_item),
path('api/store/update/<int:pk>/', views.update_item),
path('api/store/remove/<int:pk>/', views.delete_item),
]
Troubleshooting
- Auth Errors: If requests return unauthorized, check the
REST_FRAMEWORK config in settings.
- Database Errors: Ensure
AUTH_USER_MODEL is set correctly if using a custom user model.
- Import Errors: Use
touchdrfimp to ensure all necessary DRF and SimpleJWT modules are imported.