Django REST Framework JSON:API
DRF JSON:API is a Django REST framework API adapter for the JSON:API specification. It simplifies building APIs that adhere to the JSON:API standard, providing serializers, parsers, and renderers. The current version is 8.1.0, and new major versions are released roughly every 3-6 months, with patch releases as needed.
Common errors
-
ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "some-view-name". Ensure that the view name is correct and that URL exists for the given parameters.
cause The `view_name` specified in `ResourceRelatedField` or `HyperlinkedIdentityField` does not match an existing URL pattern, or the `lookup_field` (pre-v6.0.0) or `kwargs_map` (v6.0.0+) is incorrect.fixVerify that the `view_name` corresponds to a valid DRF viewset registered in your `urls.py`. For versions >= 6.0.0, ensure `kwargs_map` in the `(view_name, kwargs_map)` tuple correctly maps serializer fields to URL kwargs (e.g., `{'pk': '<pk>'}`). For older versions, check `lookup_field`. -
AttributeError: 'YourSerializer' object has no attribute 'get_resource_type' or 'Meta.resource_name' is missing.
cause The JSON:API serializer needs to define a `json_api_type` in its `Meta` class or have a custom `get_resource_type` method if the default auto-detection fails.fixAdd `json_api_type = 'your-resource-name'` to the `Meta` class of your serializer. For example, `class Meta: model = Post; fields = '__all__'; json_api_type = 'posts'`. -
TypeError: __init__() got an unexpected keyword argument 'related_link_lookup_field'
cause The keyword argument `related_link_lookup_field` (and `self_link_lookup_field`) were removed in v6.0.0.fixRemove the `related_link_lookup_field` and `self_link_lookup_field` arguments. For `ResourceRelatedField`, pass a tuple `(view_name, kwargs_map)` to `related_link_view_name` and `self_link_view_name` to define how the lookup is performed.
Warnings
- breaking In v8.0.0, `rest_framework_json_api.settings.resource_name_conversion_func` was removed. The setting `RESOURCE_NAME_CONVERSION_FUNC` no longer exists. Also, `rest_framework_json_api.utils.get_resource_name` now requires either `serializer_class` or `model` as an argument, not `queryset`.
- breaking With v7.0.0, `RelatedField` and `HyperlinkedRelatedField` from `rest_framework.relations` are no longer supported. The custom `LinkageSerializer` was also removed. The default filter backend changed to `django_filters`.
- breaking In v6.0.0, the `related_link_view_name` and `self_link_view_name` arguments in `ResourceRelatedField` and `HyperlinkedIdentityField` now require a tuple `(view_name, kwargs_map)` or `(view_name, None)`. Direct string `view_name` is no longer sufficient. Also, `related_link_lookup_field` and `self_link_lookup_field` were removed.
- gotcha Incorrect `Content-Type` header (e.g., `application/json` instead of `application/vnd.api+json`) can lead to parser errors or incorrect rendering, especially if `REST_FRAMEWORK_JSON_API['JSON_API_CONTENT_TYPE']` is `None` (which is the default).
Install
-
pip install djangorestframework-jsonapi
Imports
- JSONRenderer
from rest_framework_json_api.renderers import JSONRenderer
- JSONParser
from rest_framework_json_api.parsers import JSONParser
- ModelSerializer
from rest_framework.serializers import ModelSerializer
from rest_framework_json_api.serializers import ModelSerializer
- ResourceRelatedField
from rest_framework.relations import RelatedField
from rest_framework_json_api.relations import ResourceRelatedField
- ReadOnlyModelViewSet
from rest_framework.viewsets import ReadOnlyModelViewSet
from rest_framework_json_api.views import ReadOnlyModelViewSet
Quickstart
import os
from django.db import models
from rest_framework_json_api import serializers, views
from rest_framework import routers
from django.urls import path, include
from django.conf import settings
# Minimal Django settings for quickstart
if not settings.configured:
settings.configure(
DEBUG=True,
INSTALLED_APPS=[
'django.contrib.auth',
'django.contrib.contenttypes',
'rest_framework',
'rest_framework_json_api',
'quickstart_app' # A dummy app for models/serializers
],
ROOT_URLCONF=__name__,
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework_json_api.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer', # Optional for browsable API
),
'DEFAULT_PARSER_CLASSES': (
'rest_framework_json_api.parsers.JSONParser',
),
'DEFAULT_METADATA_CLASS': 'rest_framework_json_api.metadata.JSONAPIMetadata',
'DEFAULT_FILTER_BACKENDS': (
'rest_framework_json_api.filters.QueryParameterValidationFilter',
'rest_framework_json_api.filters.OrderingFilter',
'rest_framework_json_api.django_filters.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
),
'SEARCH_PARAM': 'filter[search]',
'TEST_REQUEST_RENDERER_CLASSES': (
'rest_framework_json_api.renderers.JSONRenderer',
),
'TEST_REQUEST_PARSER_CLASSES': (
'rest_framework_json_api.parsers.JSONParser',
)
}
)
# 1. Define a simple Django Model
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
# 2. Define a JSON:API Serializer for the Model
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ('id', 'title', 'content', 'created_at')
json_api_type = 'posts'
# 3. Define a JSON:API ViewSet
class PostViewSet(views.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
# Filtering, ordering, search can be enabled via DRF settings and filter backends
# 4. Register the ViewSet with a Router
router = routers.DefaultRouter()
router.register(r'posts', PostViewSet)
# 5. Define URL patterns
urlpatterns = [
path('', include(router.urls)),
]
# To run this example (requires Django and DRF installed):
# 1. Create a quickstart_app directory with an __init__.py inside your Django project
# 2. Add 'quickstart_app' to INSTALLED_APPS in settings.py
# 3. Add 'path('api/', include(router.urls))' to your project's urls.py
# 4. python manage.py makemigrations quickstart_app
# 5. python manage.py migrate
# 6. python manage.py createsuperuser (optional)
# 7. python manage.py runserver
# Then visit http://127.0.0.1:8000/posts/ or use a tool like Postman with Accept: application/vnd.api+json