Django Rest Framework 2/3

JunePyo Suh·2020년 7월 6일
0

Generic API View & Mixins

The GenericAPIView class is often used with Mixins, classes that provide further functionalities to our views, increasing their capabilities.

The Mixin Classes provide action methods such as .list() or .create() rather than defining the handler methods, such as .get() or .post() directly, as is usually done with the APIView class.

class EbookListCreateAPIView(mixins.ListModelMixin,
                             mixins.CreateModelMixin,
                             generics.GenericAPIView):
    queryset = Ebook.objects.all()
    serializer_class = EbookSerializer

    # define handler methods
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

Attributes

Basic settings:

The folllowing attributes control the basic view behavior.

  • queryset : the queryset that should be used for returninb objects from this view
  • serializer_class
  • lookup_field
  • lookup_url_kwarg

Pagination:

  • pagination_class

Filtering:

  • filter_backends : a list of filter backend classes that should be used for filtering the queryset

Concrete View Classes

Each one of the concrete view classes extends the GenericAPIView class and Mixins that offer the functionalities that the class is meant to provide.

RetrieveUpdateAPIView for example will extend the GenericAPIView class as well as RetrieveModelMixin and UpdateModelMixin.

CreateAPIView

Used for create-only endpoints.

ListAPIView

Used for read-only endpoints to represent a collection of model instances.

RetrieveAPIView

Used for read-only endpoints to represent a single model instance.

DestroyAPIView

Used for delete-only endpoints for a single model instance.

UpdateAPIView

Used for update-only endpoints for a single model instance.

ListCreateAPIView

Used for read-write endpoints to represent a collection of model instances.

RetrieveUpdateAPIView

Used for read or update endpoints to represent a single model instance.

RetrieveDestroyAPIView

Used for read or delete endpoints to represent a single model instance.

RetrieveUpdateDestroyAPIView

Used for read-write-delete endpoints to represent a single model instance.

Passing additional attributes to .save()

Sometimes you wnat your view code to inject additional data at the point of saving an instance. This additional data could be a foreign key object, current time, or anything else that is not part of the request data.
You can do so by including additional keyword arguments when calling .save().

serializer.save(owner=request.user)
serializer.save(author=author)

Overriding .save() directly

In some cases .create() and .update() methods may not be meaningful. This can be the case when sending a verification email to a user, instead of creating new instances.
By overriding .save() directly, you can make the method more meaningful.

class ContactForm(serializers.Serializer):
    email = serializers.EmailField()
    message = serializers.CharField()

    def save(self):
        email = self.validated_data['email']
        message = self.validated_data['message']
        send_email(from=email, message=message)

Permissions

Permission system can be managed globally in settings.py, or locally (per view) in each view class.

Grant access only to authenticated users

Using built-in permissions,

class EbookListCreateAPIView(generics.ListCreateAPIView):
    queryset = Ebook.objects.all()
    serializer_class = EbookSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

Or create a custom permission class for more precise access permissions,

// In permissions.py
class IsAdminUserOrReadOnly(permissions.IsAdminUser):
    def has_permission(self, request, view):
        // IsAdminUser's has_permission method
        is_admin = super().has_permission(request, view)
        return request.method in permissions.SAFE_METHODS or is_admin
        // SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
        
// In views.py
class EbookListCreateAPIView(generics.ListCreateAPIView):
    queryset = Ebook.objects.all()
    serializer_class = EbookSerializer
    permission_classes = [IsAdminUserOrReadOnly]

Grant write permissions only to authorized users

class IsReviewAuthorOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.review_author == request.user

Pagination

The pagination style may be set globally, using the DEFAULT_PAGINATION_CLASS and PAGE_SIZE settings keys.

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 100
}

Or, you can also set a pagination class for an individual view by using the pagination_class attribute.

// In pagination.py
from rest_framework.pagination import PageNumberPagination


class SmallSetPagination(PageNumberPagination):
    page_size = 3

UnorderedObjectListWarning

If no ordering is provided, pagination may yield inconsistent results with an unordered object list. To prevent potential errors, provide ordering.

class EbookListCreateAPIView(generics.ListCreateAPIView):
    queryset = Ebook.objects.all().order_by("-id")
    serializer_class = EbookSerializer
    permission_classes = [IsAdminUserOrReadOnly]
    pagination_class = SmallSetPagination

0개의 댓글