James Williams
# Install DRF
pip install djangorestframework
# Add to INSTALLED_APPS in settings.py
INSTALLED_APPS = [
...
'rest_framework',
]
# Add REST Framework settings
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
# serializers.py
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source='author.username', read_only=True)
class Meta:
model = Post
fields = ['id', 'title', 'content', 'author', 'author_name', 'created_at']
read_only_fields = ['id', 'created_at']
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
@api_view(['GET', 'POST'])
def post_list(request):
if request.method == 'GET':
posts = Post.objects.all()
serializer = PostSerializer(posts, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
from rest_framework import generics
class PostListCreate(generics.ListCreateAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
class PostDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Post.objects.all()
serializer_class = PostSerializer
from django.urls import path
from . import views
urlpatterns = [
path('api/posts/', views.PostListCreate.as_view()),
path('api/posts/<int:pk>/', views.PostDetail.as_view()),
]
# views.py
from rest_framework import viewsets
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
# urls.py
from rest_framework.routers import DefaultRouter
from . import views
router = DefaultRouter()
router.register(r'posts', views.PostViewSet)
urlpatterns = [
path('api/', include(router.urls)),
]
Create a complete REST API for your blog
# settings.py
INSTALLED_APPS = [
...
'rest_framework.authtoken',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
]
}
# Generate token for user
from rest_framework.authtoken.models import Token
token = Token.objects.create(user=user)
print(token.key)
from rest_framework import permissions
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(author=self.request.user)
from rest_framework import permissions
class IsAuthorOrReadOnly(permissions.BasePermission):
"""
Custom permission: only author can edit/delete
"""
def has_object_permission(self, request, view, obj):
# Read permissions allowed for any request
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions only for author
return obj.author == request.user
# Usage
class PostViewSet(viewsets.ModelViewSet):
permission_classes = [IsAuthorOrReadOnly]
# Install
pip install django-filter
# Add to INSTALLED_APPS
INSTALLED_APPS = [
...
'django_filters',
]
# ViewSet with filtering
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_fields = ['author', 'published']
search_fields = ['title', 'content']
Add authentication and authorization to your API
Try it:
http://127.0.0.1:8000/api/posts/
GET http://127.0.0.1:8000/api/posts/
Headers:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
POST http://127.0.0.1:8000/api/posts/
Headers:
Content-Type: application/json
Authorization: Token 9944b09...
Body:
{
"title": "New Post",
"content": "Post content here",
"published": true
}
class CommentSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source='author.username', read_only=True)
class Meta:
model = Comment
fields = ['id', 'text', 'author', 'author_name', 'created_at']
class PostSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True, read_only=True, source='comment_set')
comment_count = serializers.SerializerMethodField()
class Meta:
model = Post
fields = ['id', 'title', 'content', 'comments', 'comment_count']
def get_comment_count(self, obj):
return obj.comment_set.count()
Preparation: Install Node.js and create-react-app
Contact: JWilliams@Staff.newman.ac.uk
Office Hours: By appointment
Resources: DRF Documentation, Postman Learning Center
Thank you for your attention!