Vacasa / drf-jsonapi

JSON API with Django Rest Framework
MIT License
3 stars 5 forks source link
library missing-circleci missing-classification missing-codeclimate missing-pull-request-template public team-fearless-trapeze

JSON API with Django Rest Framework

Maintainability Test Coverage

What is this?

This package adds support for the JSON API spec with Django Rest Framework. It is a collection of base classes that abstract away much of the logic needed to handle requests and responses according to the JSON API spec.

Features

What's included?

drf_jsonapi.serializers

drf_jsonapi.filters

drf_jsonapi.viewsets

drf_jsonapi.mixins

What's missing?

Quickstart Guide

This guide assumes you have a resource (we'll assume the resource is a Django Model but it could be any object) and you want to expose API endpoints for users to interact (CRUD + relationship management) with the resources.

NOTE: This guide does NOT include any authentication or access control. That is outside of the scope of this document but since this package is built on Django Rest Framework all of the same methods apply.

Serializers

The first step is to create a Serializer class for your resource. If your resource is a Django model you can sub-class drf_jsonapi.serializers.ResourceModelSerializer. Otherwise, you'll want to sub-class drf_jsonapi.serializers.ResourceSerializer. The big difference between the two is that ResourceModelSerializer can automatically create the serializer fields based on the model definition. If you use ResourceSerializer you'll have to define the fields manually.

Serializer Meta options

Most of the behavior for the Serializer is defined in the Meta class. This follows Django Rest Framework conventions. The following Meta attributes are supported:

Relationships

If you define any relationships in the Meta class of your serializer you need to define methods for fetching those relaitonships and define a method for getting the serializer for the related resource. These methods exist in the base RelationshipHandler class in relationships.py as abstract (not implemented) classes get_related and get_serializer_class. For example: If you define a relationship called roles you'll need to override the method get_related(self, instance) to fetch that relationship on the base instance. The resource instance is passed in to this method and the return type should be the related resource or a collection of related resources.

Additionally defined abstract methods in the RelationshipHandler include add_related, set_related, and remove_related for the corresponding POST, PATCH, and DELETE requests.

Further, RelationshipHandler comes equiped with validation via the validate method, and links to the related resources via the build_relationship_links(self, base_serializer, relation, resource) method. Once the build_relationship_links method has been called the get_links method will return the built list of links.

Views

The jsonapi class uses the Django Rest Framework ViewSet classes. For convenience there are two base classes you can extend: ReadOnlyViewSet and ReadWriteViewSet. These classes include the necessary mixins to define basic default behavior.

ViewSet class attributes

For your custom ViewSet to work properly you'll need to define some class-level attributes:

Filters

To support filtering of data via query params like filter[field]=value you can define custom FilterSet classes and attach them to your view via the filter_class attribute. These FilterSet classes are based on the django_filters.FilterSet classes but have custom validation and translation of the query params to support the syntax.

There are two base classes for FilterSet, drf_jsonapi.filters.FilterSet and drf_jsonapi.filters.GenericFilterSet. The one you extend depends on whether or not the underlying resource is a Django model. For Django models use FilterSet. This is simply a sub-class of django_filters.FilterSet with additional validation and translation. It assumes that the filter is working with a QuerySet. For non-model filtering use GenericFilterSet. This class is optimized for working with lists of resources.