Django REST Framework
Serializers
from rest_framework import serializers
from .models import Post, User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'bio']
read_only_fields = ['id']
class PostSerializer(serializers.ModelSerializer):
author = UserSerializer(read_only=True)
author_id = serializers.PrimaryKeyRelatedField(
queryset=User.objects.all(), source='author', write_only=True
)
tags = serializers.SlugRelatedField(many=True, slug_field='name', queryset=Tag.objects.all())
class Meta:
model = Post
fields = ['id', 'title', 'slug', 'body', 'status', 'author', 'author_id', 'tags', 'created_at']
read_only_fields = ['id', 'slug', 'created_at']
def validate_title(self, value):
if len(value) < 3:
raise serializers.ValidationError("Title must be at least 3 characters")
return value
def create(self, validated_data):
tags = validated_data.pop('tags', [])
post = Post.objects.create(**validated_data)
post.tags.set(tags)
return postViewSets & Routers
from rest_framework import viewsets, permissions, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.select_related('author').prefetch_related('tags')
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = ['status', 'author']
search_fields = ['title', 'body']
ordering_fields = ['created_at', 'view_count']
ordering = ['-created_at']
def get_queryset(self):
if self.action == 'list':
return self.queryset.filter(status='published')
return self.queryset
def perform_create(self, serializer):
serializer.save(author=self.request.user)
@action(detail=True, methods=['post'])
def publish(self, request, pk=None):
post = self.get_object()
post.status = 'published'
post.save()
return Response({'status': 'published'})
# urls.py
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('posts', PostViewSet, basename='post')
urlpatterns = [path('', include(router.urls))]
# Auto-generates: GET /posts/, POST /posts/, GET /posts/{id}/, PUT, PATCH, DELETE
# Custom: POST /posts/{id}/publish/Authentication & Permissions
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
}
# JWT with SimpleJWT
pip install djangorestframework-simplejwt
# urls.py
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
urlpatterns = [
path('auth/login/', TokenObtainPairView.as_view()),
path('auth/refresh/', TokenRefreshView.as_view()),
]
# Custom permission
from rest_framework.permissions import BasePermission
class IsOwnerOrReadOnly(BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in ['GET', 'HEAD', 'OPTIONS']:
return True
return obj.author == request.userKeep your own version of these notes — editable, searchable, and organised by your stack.
Start free