README.rst 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. Django REST Framework Bulk
  2. ==========================
  3. .. image:: https://badge.fury.io/py/djangorestframework-bulk.png
  4. :target: http://badge.fury.io/py/djangorestframework-bulk
  5. .. image:: https://d2weczhvl823v0.cloudfront.net/miki725/django-rest-framework-bulk/trend.png
  6. :alt: Bitdeli badge
  7. :target: https://bitdeli.com/free
  8. Django REST Framework bulk CRUD view mixins.
  9. Overview
  10. --------
  11. Django REST Framework comes with many generic views however none
  12. of them allow to do bulk operations such as create, update and delete.
  13. To keep the core of Django REST Framework simple, its maintainer
  14. suggested to create a separate project to allow for bulk operations
  15. within the framework. That is the purpose of this project.
  16. Requirements
  17. ------------
  18. * Python (2.6, 2.7 and 3.3)
  19. * Django 1.3+
  20. * Django REST Framework >= 2.2.5 (when bulk features were added to serializers)
  21. Installing
  22. ----------
  23. Using pip::
  24. $ pip install djangorestframework-bulk
  25. or from source code::
  26. $ pip install -r git+http://github.com/miki725/django-rest-framework-bulk#egg=djangorestframework-bulk
  27. Example
  28. -------
  29. The bulk views (and mixins) are very similar to Django REST Framework's own
  30. generic views (and mixins)::
  31. from rest_framework_bulk import ListBulkCreateUpdateDestroyAPIView
  32. class FooView(ListBulkCreateUpdateDestroyAPIView):
  33. model = FooModel
  34. The above will allow to create the following queries
  35. ::
  36. # list queryset
  37. GET
  38. ::
  39. # create single resource
  40. POST
  41. {"field":"value","field2":"value2"} <- json object in request data
  42. ::
  43. # create multiple resources
  44. POST
  45. [{"field":"value","field2":"value2"}]
  46. ::
  47. # update multiple resources (requires all fields)
  48. PUT
  49. [{"field":"value","field2":"value2"}] <- json list of objects in data
  50. ::
  51. # partial update multiple resources
  52. PATCH
  53. [{"field":"value"}] <- json list of objects in data
  54. ::
  55. # delete queryset (see notes)
  56. DELETE
  57. Router
  58. -------
  59. It's also pretty easy to define a router that handle the bulk operation ::
  60. class BulkRouter(DefaultRouter):
  61. routes = SimpleRouter.routes
  62. routes[0] = Route(
  63. url=r'^{prefix}{trailing_slash}$',
  64. mapping={
  65. 'get': 'list',
  66. 'post': 'create',
  67. 'put': 'bulk_update',
  68. 'patch': 'partial_bulk_update',
  69. 'delete': 'bulk_destroy'
  70. },
  71. name='{basename}-list',
  72. initkwargs={'suffix': 'List'}
  73. )
  74. class UserViewSet(BulkCreateModelMixin
  75. BulkUpdateModelMixin,
  76. BulkDestroyModelMixin,
  77. viewsets.ModelViewSet):
  78. model = User
  79. def allow_bulk_destroy(self, qs, filtered):
  80. """Don't forget to fine-grain this method"""
  81. router = BulkRouter()
  82. router.register(r'users', UserViewSet)
  83. Notes
  84. -----
  85. Most API urls have two URL levels for each resource:
  86. 1. ``url(r'foo/', ...)``
  87. 2. ``url(r'foo/(?P<pk>\d+)/', ...)``
  88. The second url however is not applicable for bulk operations because
  89. the url directly maps to a single resource. Therefore all bulk
  90. generic views only apply to the first url.
  91. There are multiple generic view classes in case only a certail
  92. bulk functionality is required. For example ``ListBulkCreateAPIView``
  93. will only do bulk operations for creating resources.
  94. For a complete list of available generic view classes, please
  95. take a look at the source code at ``generics.py`` as it is mostly
  96. self-explanatory.
  97. Most bulk operations are pretty safe in terms of how they operate,
  98. that is you excplicitly describe all requests. For example, if you
  99. need to update 3 specific resources, you have to explicitly identify
  100. those resources in the request's ``PUT`` or ``PATCH`` data.
  101. The only exception to this is bulk delete. Conside a ``DELETE``
  102. request to the first url. That can potentially delete all resources
  103. without any special confirmation. To try to account for this, bulk delete
  104. mixin allows to implement a hook to determine if the bulk delete
  105. request should be allowed::
  106. class FooView(BulkDestroyAPIView):
  107. def allow_bulk_destroy(self, qs, filtered):
  108. # custom logic here
  109. # default checks if the qs was filtered
  110. # qs comes from self.get_queryset()
  111. # filtered comes from self.filter_queryset(qs)
  112. return qs is not filtered
  113. By default it checks if the queryset was filtered and if not will not
  114. allow the bulk delete to complete. The logic here is that if the request
  115. is filtered to only get certain resources, more attention was payed hence
  116. the action is less likely to be accidental. On how to filter requests,
  117. please refer to Django REST
  118. `docs <http://www.django-rest-framework.org/api-guide/filtering>`_.
  119. Either way, please use bulk deletes with extreme causion since they
  120. can be dangerous.
  121. Credits
  122. -------
  123. Maintainers/contributors:
  124. * Miroslav Shubernetskiy - https://github.com/miki725
  125. * Arien Tolner - https://github.com/Bounder
  126. * Kevin Brown - https://github.com/kevin-brown
  127. * Martin Cavoj - https://github.com/macav
  128. * Mjumbe Poe - https://github.com/mjumbewu