Django REST Framework API Guide (1) : Requesting Django REST Framework API Guide (2) : Responding to Django REST Framework API Guide (3) : Views Django REST Framework API Guide (4) : Generic Views Django REST Framework API Guide (5) : View Sets Django REST Framework API Guide (6) : Routing Django REST Framework API Guide (7) : Parsing

Link to official text

General view

One of the main advantages of class-based views is that they allow you to write reusable behavior. The REST framework takes advantage of this by providing a large number of pre-built views to provide common patterns.

The generic views provided by the REST Framework allow you to quickly build API views that map tightly to your database model.

If a generic view doesn’t meet your needs, you can use a regular APIView class or combine a reusable view with mixin features and base classes.

Take a chestnut

Typically, when using a generic view, you need to inherit the view and set several class properties.

from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from rest_framework.permissions import IsAdminUser

class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAdminUser,)
Copy the code

For more complex cases, you might also want to override various methods in the view class. For example.

class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsAdminUser,)

    def list(self, request):
        # Note that 'get_querySet ()' is used instead of 'self.querySet'
        queryset = self.get_queryset()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)
Copy the code

For very simple cases, you might want to use the.as_view() method to pass class attributes. For example, your URLconf might contain something like the following entry:

url(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')
Copy the code

Set the related property parameters directly in the URLconf, so that the view class does not need to be written.

API reference

GenericAPIView

The GenericAPIView class inherits from the REST Framework’s APIView class and adds common behavior to standard lists and detailed views.

Each of the built-in concrete generic views is built by combining the GenericAPIView class with one or more Minxin classes.

attribute

Basic setup

The following properties control the basic view behavior.

  • queryset– The query set used to return objects from this view. Normally, you must set this property, or overrideget_queryset()Methods. If you override a view method, in a view method, you should callget_queryset()Rather than accessing the property directly, this is important! Because REST will be internally alignedquerysetIs cached for all subsequent requests.
  • serializer_class– Serialized classes used to validate and deserialize input and serialize output. Normally, you must set this property, or overrideget_serializer_class()Methods.
  • lookup_field– The model field used to perform object lookups for each model instance. The default is'pk'. Note that when using the HyperLinked API, if you need to use custom values, you need to make sure that the API view and the serialized class have lookup Field set.
  • lookup_url_kwarg– URL keyword argument for object lookups. The URL conf should contain keyword arguments corresponding to this value. If this parameter is not set, and is used by defaultlookup_fieldSame value.

For the last two parameters, I have attached the source code of the object query so that you can understand it.

Omit some code, easy to understand

def get_object(self):
	Get the data set first
    queryset = self.filter_queryset(self.get_queryset())
	Get the key of the query parameter
    lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
	{key:value}
    filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
    # query
    obj = get_object_or_404(queryset, **filter_kwargs)
	# return
    return obj
Copy the code
paging

When used with list views, the following properties are used to control paging.

  • pagination_class– The paging class to use when paging a list. The default value andDEFAULT_PAGINATION_CLASSThe Settings are the same, i.erest_framework.pagination.PageNumberPagination. Set up thepagination_class = NonePaging for this view is disabled.
filter
  • filter_backends– List of filter classes used to filter the query set. The default value andDEFAULT_FILTER_BACKENDSThe values are the same.

methods

Basic method

get_queryset(self)

The query set for the list view should be returned and should be used as the basis for viewing the detailed view. The queryset specified by the queryset attribute is returned by default.

You should always use this method instead of accessing self.querySet directly, because REST will internally cache the results of self.querySet for all subsequent requests.

You can override to provide dynamic behavior, such as returning different data for different user requests.

Here’s an example:

def get_queryset(self):
    user = self.request.user
    return user.accounts.all()
Copy the code

get_object(self)

The object instance of the detail view should be returned. The lookup_field parameter is used by default to filter the base query set.

Can be overridden to provide more complex behavior, such as object lookups based on multiple URL KwarGs.

Here’s an example:

def get_object(self):
    queryset = self.get_queryset()
    filter = {}
    for field in self.multiple_lookup_fields:
        filter[field] = self.kwargs[field]

    obj = get_object_or_404(queryset, **filter)
    self.check_object_permissions(self.request, obj)
    return obj
Copy the code

Note that if your API does not contain any object-level permissions, you can choose to exclude self.check_object_permissions and simply look up the returned object from get_object_or_404.

filter_queryset(self, queryset)

Given a query set, use a filter to filter and return a new query set.

Here’s an example:

def filter_queryset(self, queryset):
    filter_backends = (CategoryFilter,)

    if 'geo_route' in self.request.query_params:
        filter_backends = (GeoRouteFilter, CategoryFilter)
    elif 'geo_point' in self.request.query_params:
        filter_backends = (GeoPointFilter, CategoryFilter)

    for backend in list(filter_backends):
        queryset = backend().filter_queryset(self.request, queryset, view=self)

    return queryset
Copy the code

get_serializer_class(self)

Returns the class used for serialization. The serializER_class attribute is returned by default.

Can be overridden to provide dynamic behavior, such as using different serializers for read and write operations, or providing different serializers for different types of users.

Here’s an example:

def get_serializer_class(self):
    if self.request.user.is_staff:
        return FullAccountSerializer
    return BasicAccountSerializer
Copy the code
Save and delete hooks

The following methods are provided by the Mixin class to easily override the save and delete behavior of an object.

  • perform_create(self, serializer)– When saving a new object instanceCreateModelMixinThe call.
  • perform_update(self, serializer)– When saving an existing object instanceUpdateModelMixinThe call.
  • perform_destroy(self, instance)– Deletes an object instanceDestroyModelMixinThe call.

These hooks are particularly useful for setting properties that are implied in the request but not part of the request data. For example, you can set properties on an object based on the requesting user or based on the URL keyword parameter.

def perform_create(self, serializer):
    serializer.save(user=self.request.user)
Copy the code

These overlay points are also particularly useful for actions that occur before or after adding save objects, such as sending confirmation e-mails or logging updates.

def perform_create(self, serializer):
    queryset = SignupRequest.objects.filter(user=self.request.user)
    if queryset.exists():
        raise ValidationError('You have already signed up')
    serializer.save(user=self.request.user)
Copy the code

Note: These methods replace the older 2.x pre_save, post_save, pre_DELETE, and post_delete methods, which are no longer available.

Other methods

The following methods usually do not need to be overridden, but they may need to be called if you write a custom view using GenericAPIView.

  • get_serializer_context(self)– Returns a dictionary containing any additional context that should be provided for serialization. The default include'request'.'view''format'The key.
  • get_serializer(self, instance=None, data=None, many=False, partial=False)– Returns an instance of the serializer.
  • get_paginated_response(self, data)– Returns paging styleResponseObject.
  • paginate_queryset(self, queryset)– Paging query sets, or returning a page object as needed; If no paging is configured for this viewNone.
  • filter_queryset(self, queryset)– Given a query set, use a filter to filter and return a new query set.

Mixins

Mixin classes are used to provide operations for basic view behavior. Note that mixin classes provide action methods rather than directly defining processing methods, such as.get() and.post(). This allows for a more flexible combination of actions.

Mixin classes can be imported from rest_framework.mixins.

ListModelMixin

Provide a.list(request, *args, **kwargs) method that implements listing a query set.

If the queryset is populated, a 200 OK response is returned with the serialized representation of the queryset as the body of the response. Response data can be paginated.

CreateModelMixin

Provide.create(request, *args, **kwargs) methods to create and save new model instances.

If an object is Created, a 201 Created response is returned with the serialized representation of the object as the body of the response. If the representation contains a key named URL, the Location header of the response populates that value.

If the Request data provided to create the object is invalid, the 400 Bad Request response is returned with the error details as the body of the response.

RetrieveModelMixin

Provides the.Retrieve (Request, *args, **kwargs) method, which implements the return of an existing model instance in a response.

If the object can be retrieved, a 200 OK response is returned with the serialized representation of the object as the body of the response. Otherwise, a 404 Not Found is returned.

UpdateModelMixin

Provide.update(request, *args, **kwargs) methods to update and save existing model instances. A.partial_update(request, *args, **kwargs) method is also provided, which is similar to the update method, except that all fields updated are optional. This allows HTTP PATCH requests to be supported.

If the object is successfully updated, a 200 OK response is returned with the serialized representation of the object as the body of the response.

If the Request data provided to update the object is invalid, the 400 Bad Request response is returned with the error details as the body of the response.

DestroyModelMixin

Provide a.destroy(Request, *args, **kwargs) method to destroy existing model instances.

If an object is deleted, it returns a 204 No Content, otherwise it returns a 404 Not Found.

List of built-in view classes

The following classes are concrete generic views. In general, you should use them all, unless you need a high degree of customization.

These view classes can be imported from rest_framework.generics.

CreateAPIView

Only for instance creation.

Provides a method for handling post requests.

Inherited from: GenericAPIView, CreateModelMixin

ListAPIView

Only used to read the list of model instances.

Provides a method for handling get requests.

Inherited from: GenericAPIView, ListModelMixin

RetrieveAPIView

Only used to query a single model instance.

Provides a method for handling get requests.

Inherited from: GenericAPIView, RetrieveModelMixin

DestroyAPIView

Only used to delete a single model instance.

Provides a method for handling delete requests.

Inherited from: GenericAPIView, DestroyModelMixin

UpdateAPIView

Only used to update a single model instance.

Provides methods for processing PUT and patch requests.

Inherited from: GenericAPIView, UpdateModelMixin

ListCreateAPIView

You can either get a collection of instances, or create a list of instances

Provides the handling of GET and POST requests.

Inherited from: GenericAPIView, ListModelMixin, CreateModelMixin

RetrieveUpdateAPIView

Individual instances can be queried and updated

Provides methods for handling GET, PUT, and patch requests.

Inherited from: GenericAPIView, RetrieveModelMixin, UpdateModelMixin

RetrieveDestroyAPIView

Individual instances can be queried or deleted

Provides the handling of GET and DELETE requests.

Inherited from: GenericAPIView, RetrieveModelMixin, DestroyModelMixin

RetrieveUpdateDestroyAPIView

Support query, update, delete

Provides methods for handling GET, PUT, Patch, and DELETE requests.

Inherited from: GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin

Custom generic view classes

Often you want to use the existing generic view and customize the behavior a little bit. If you find yourself reusing some custom behavior in multiple places, you may need to refactor the behavior into a normal class and then apply it to any view or set of views as needed.

Custom mixins

For example, if you need to find objects based on multiple fields in the URL conf, you can create a mixin class.

Here’s an example:

class MultipleFieldLookupMixin(object):
    """ Apply this mixin to any view or set of views to get multiple field filtering based on the 'lookup_fields' attribute, instead of the default single field filtering. "" "
    def get_object(self):
        queryset = self.get_queryset()             Get the basic query set
        queryset = self.filter_queryset(queryset)  # Use filters
        filter = {}
        for field in self.lookup_fields:
            if self.kwargs[field]: # ignore empty fields
                filter[field] = self.kwargs[field]
        obj = get_object_or_404(queryset, **filter)  # find object
        self.check_object_permissions(self.request, obj)
        return obj
Copy the code

This mixin can then be applied to a view or set of views at any time custom behavior needs to be applied.

class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    lookup_fields = ('account'.'username')
Copy the code

If you need custom behavior, using custom mixins is a good choice.

Custom base classes

If you use mixins in multiple views, you can go a step further and create your own set of base views and then use them throughout your project. Such as:

class BaseRetrieveView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
    pass

class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin, generics.RetrieveUpdateDestroyAPIView):
    pass
Copy the code

Using a custom base class is a good choice if the custom behavior always needs to be repeated in a large number of views throughout the project.