Package: drf-bulk-compat-writable-nested
Django REST Framework bulk CRUD view mixins.OverviewThis is a package with a slight change to the Django REST Framework Bulk package to allow for compatability with the drf-writable-nested package.
The change has only been tested with DRF >= 3.0.0ORIGINAL OVERVIEW:Django REST Framework comes with many generic views however none
of them allow to do bulk operations such as create, update and delete.
To keep the core of Django REST Framework simple, its maintainer
suggested to create a separate project to allow for bulk operations
within the framework. That is the purpose of this project.RequirementsPython>=2.7Django>=1.3Django REST Framework >= 3.0.0REST Framework >= 2.2.5
(only withDjango<1.8 since DRF<3 does not support Django1.8)InstallingUsing pip:$ pip install djangorestframework-bulkor from source code:$ pip install -e git+https://github.com/axmpda/django-rest-framework-bulk/tree/patch-2ExampleThe bulk views (and mixins) are very similar to Django REST Framework’s own
generic views (and mixins):from rest_framework_bulk import (
    BulkListSerializer,
    BulkSerializerMixin,
    ListBulkCreateUpdateDestroyAPIView,
)

class FooSerializer(BulkSerializerMixin, ModelSerializer):
    class Meta(object):
        model = FooModel
        # only necessary in DRF3
        list_serializer_class = BulkListSerializer

class FooView(ListBulkCreateUpdateDestroyAPIView):
    queryset = FooModel.objects.all()
    serializer_class = FooSerializerThe above will allow to create the following queries# list queryset
GET# create single resource
POST
{"field":"value","field2":"value2"}     <- json object in request data# create multiple resources
POST
[{"field":"value","field2":"value2"}]# update multiple resources (requires all fields)
PUT
[{"field":"value","field2":"value2"}]   <- json list of objects in data# partial update multiple resources
PATCH
[{"field":"value"}]                     <- json list of objects in data# delete queryset (see notes)
DELETERouterThe bulk router can automatically map the bulk actions:from rest_framework_bulk.routes import BulkRouter

class UserViewSet(BulkModelViewSet):
    model = User

    def allow_bulk_destroy(self, qs, filtered):
        """Don't forget to fine-grain this method"""

router = BulkRouter()
router.register(r'users', UserViewSet)DRF3Django REST Framework made many API changes which included major changes
in serializers. As a result, please note the following in order to use
DRF-bulk with DRF3:You must specify customlist_serializer_classif your view(set)
will require update functionality (when usingBulkUpdateModelMixin)DRF3 removes read-only fields fromserializer.validated_data.
As a result, it is impossible to correlate eachvalidated_datainListSerializerwith a model instance to update sincevalidated_datawill be missing the model primary key since that is a read-only field.
To deal with that, you must useBulkSerializerMixinmixin in your serializer
class which will add the model primary key field back to thevalidated_data.
By defaultidfield is used however you can customize that field
by usingupdate_lookup_fieldin the serializersMeta:class FooSerializer(BulkSerializerMixin, ModelSerializer):
    class Meta(object):
        model = FooModel
        list_serializer_class = BulkListSerializer
        update_lookup_field = 'slug'NotesMost API urls have two URL levels for each resource:url(r'foo/',...)url(r'foo/(?P<pk>\d+)/',...)The second url however is not applicable for bulk operations because
the url directly maps to a single resource. Therefore all bulk
generic views only apply to the first url.There are multiple generic view classes in case only a certail
bulk functionality is required. For exampleListBulkCreateAPIViewwill only do bulk operations for creating resources.
For a complete list of available generic view classes, please
take a look at the source code atgenerics.pyas it is mostly
self-explanatory.Most bulk operations are pretty safe in terms of how they operate,
that is you explicitly describe all requests. For example, if you
need to update 3 specific resources, you have to explicitly identify
those resources in the request’sPUTorPATCHdata.
The only exception to this is bulk delete. Consider aDELETErequest to the first url. That can potentially delete all resources
without any special confirmation. To try to account for this, bulk delete
mixin allows to implement a hook to determine if the bulk delete
request should be allowed:class FooView(BulkDestroyAPIView):
    def allow_bulk_destroy(self, qs, filtered):
        # custom logic here

        # default checks if the qs was filtered
        # qs comes from self.get_queryset()
        # filtered comes from self.filter_queryset(qs)
        return qs is not filteredBy default it checks if the queryset was filtered and if not will not
allow the bulk delete to complete. The logic here is that if the request
is filtered to only get certain resources, more attention was payed hence
the action is less likely to be accidental. On how to filter requests,
please refer to Django RESTdocs.
Either way, please use bulk deletes with extreme caution since they
can be dangerous.History0.2.2 (2020-04-26)Allowed for mixed PUT / POST requests0.2.1 (2015-04-26)Fixed a bug which allowed to submit data for update to serializer
without update field.
See#34.Removed support for Django1.8 with DRF2.x0.2 (2015-02-09)Added DRF3 support. Please note that DRF2 is still supported.
Now we support both DRF2 and DRF3!Fixed an issue when using viewsets, single resource update was not working due
toget_object()overwrite in viewset.0.1.4 (2015-02-01)Added base model viewset.Fixed installation issues.
See#18,#22.0.1.3 (2014-06-11)Fixed bug howpost_save()was called in bulk create.0.1.2 (2014-04-15)Fixed bug howpre_save()was called in bulk update.Fixed bug of unable to mixins by importing directlyfrom rest_framework_bulk import <mixin>.
See#5for more info.0.1.1 (2014-01-20)Fixed installation bug with setuptools.0.1 (2014-01-18)First release on PyPI.CreditsDevelopment LeadMiroslav Shubernetskiy -https://github.com/miki725ContributorsArien Tolner -https://github.com/BounderDavide Mendolia -https://github.com/davidemeKevin Brown -https://github.com/kevin-brownMartin Cavoj -https://github.com/macavMatthias Erll -https://github.com/merllMjumbe Poe -https://github.com/mjumbewuThomas Wajs -https://github.com/thomasWajsXavier Ordoquy -https://github.com/xordoquyAlex Davies -https://mooloo.ioLicenseSource code can be found atGithub.The MIT License (MIT):Copyright (c) 2014-2015, Miroslav Shubernetskiy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.