django-rest-framework Bulk operations

Bulk operations

New in DRF-extensions 0.2.4

Bulk operations allows you to perform operations over set of objects with one request. There is third-party package
django-rest-framework-bulk with support for all CRUD methods, but it iterates over every
instance in bulk operation, serializes it and only after that executes operation.

It plays nice with create or update
operations, but becomes unacceptable with partial update and delete methods over the QuerySet. Such kind of
QuerySet could contain thousands of objects and should be performed as database query over the set at once.

Please note - DRF-extensions bulk operations applies over QuerySet, not over instances. It means that:

  • No serializer’s save or delete methods would be called
  • No viewset’s pre_save, post_save, pre_delete and post_delete would be called
  • No model signals would be called

Safety

Bulk operations are very dangerous in case of making stupid mistakes. For example you wanted to delete user instance
with DELETE request from your client application.

# Request
DELETE /users/1/ HTTP/1.1
Accept: application/json

# Response
HTTP/1.1 204 NO CONTENT
Content-Type: application/json; charset=UTF-8

That was example of successful deletion. But there is the common situation when client could not get instance id and sends
request to endpoint without it:

# Request
DELETE /users/ HTTP/1.1
Accept: application/json

# Response
HTTP/1.1 204 NO CONTENT
Content-Type: application/json; charset=UTF-8

If you used bulk destroy mixin for /users/ endpoint, then all your user objects would be deleted.

To protect from such confusions DRF-extensions asks you to send X-BULK-OPERATION header
for every bulk operation request. With this protection previous example would not delete any user instances:

# Request
DELETE /users/ HTTP/1.1
Accept: application/json

# Response
HTTP/1.1 400 BAD REQUEST
Content-Type: application/json; charset=UTF-8

{
  "detail": "Header 'X-BULK-OPERATION' should be provided for bulk operation."
}

With X-BULK-OPERATION header it works as expected - deletes all user instances:

# Request
DELETE /users/ HTTP/1.1
Accept: application/json
X-BULK-OPERATION: true

# Response
HTTP/1.1 204 NO CONTENT
Content-Type: application/json; charset=UTF-8

You can change bulk operation header name in settings:

REST_FRAMEWORK_EXTENSIONS = {
    'DEFAULT_BULK_OPERATION_HEADER_NAME': 'X-CUSTOM-BULK-OPERATION'
}

To turn off protection you can set DEFAULT_BULK_OPERATION_HEADER_NAME as None.

Bulk destroy

This mixin allows you to delete many instances with one DELETE request.

from rest_framework_extensions.bulk_operations.mixins import ListDestroyModelMixin

class UserViewSet(ListDestroyModelMixin, viewsets.ModelViewSet):
    serializer_class = UserSerializer

Bulk destroy example - delete all users which emails ends with gmail.com:

# Request
DELETE /users/?email__endswith=gmail.com HTTP/1.1
Accept: application/json
X-BULK-OPERATION: true

# Response
HTTP/1.1 204 NO CONTENT
Content-Type: application/json; charset=UTF-8

Bulk update

This mixin allows you to update many instances with one PATCH request. Note, that this mixin works only with partial update.

from rest_framework_extensions.mixins import ListUpdateModelMixin

class UserViewSet(ListUpdateModelMixin, viewsets.ModelViewSet):
    serializer_class = UserSerializer

Bulk partial update example - set email_provider of every user as google, if it’s email ends with gmail.com:

# Request
PATCH /users/?email__endswith=gmail.com HTTP/1.1
Accept: application/json
X-BULK-OPERATION: true

{"email_provider": "google"}

# Response
HTTP/1.1 204 NO CONTENT
Content-Type: application/json; charset=UTF-8

Settings

DRF-extensions follows Django Rest Framework approach in settings implementation.

In Django Rest Framework you specify custom settings by changing REST_FRAMEWORK variable in settings file:

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.YAMLRenderer',
    ),
    'DEFAULT_PARSER_CLASSES': (
        'rest_framework.parsers.YAMLParser',
    )
}

In DRF-extensions there is a magic variable too called REST_FRAMEWORK_EXTENSIONS:

REST_FRAMEWORK_EXTENSIONS = {
    'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 15
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章