Django · Lesson 5 of 5
Building a JSON API
Return JSON from views and expose a REST API with Django REST framework.
- Intermediate
- 15 min read
- 3 objectives
Before this lessonLesson 4: Forms and the Admin
What you will learn
- Return JsonResponse
- Write a serializer
- Use a ModelViewSet
Modern apps often serve JSON to a React front end or a mobile app instead of HTML pages. Django can do that natively, and the Django REST framework (DRF) makes it fast to build a full API.
A plain JSON view
from django.http import JsonResponse
from .models import Post
def api_posts(request):
data = list(Post.objects.filter(published=True).values("id", "title", "created"))
return JsonResponse({"posts": data})Django REST framework
pip install djangorestframeworkAdd "rest_framework" to INSTALLED_APPS. DRF has three main pieces: serializers, viewsets and routers.
Serializers
A serializer converts model instances to JSON and validates incoming JSON, much like a form.
# blog/serializers.py
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
author_name = serializers.CharField(source="author.name", read_only=True)
class Meta:
model = Post
fields = ["id", "title", "body", "published", "author", "author_name", "created"]
read_only_fields = ["created"]ViewSets and routers
A ModelViewSet provides list, create, retrieve, update and delete in a few lines.
# blog/api.py
from rest_framework import viewsets, permissions
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.select_related("author")
serializer_class = PostSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
# mysite/urls.py
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register("posts", PostViewSet)
urlpatterns += [path("api/", include(router.urls))]That gives you GET /api/posts/, POST /api/posts/, GET /api/posts/1/, PUT, PATCH and DELETE, plus a browsable HTML interface for testing.
Trying it
curl http://127.0.0.1:8000/api/posts/
curl -X POST http://127.0.0.1:8000/api/posts/ \
-H "Content-Type: application/json" \
-d '{"title": "Hello API", "body": "text", "author": 1}'Pagination, filtering and auth
# settings.py
REST_FRAMEWORK = {
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
"PAGE_SIZE": 20,
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
],
}# Write your solution here
