django-rest-framework-bulk icon indicating copy to clipboard operation
django-rest-framework-bulk copied to clipboard

URL syntax for Bulk modifications

Open justjess678 opened this issue 6 years ago • 1 comments

Although the Bulk Actions are present in my project I haven't used them to their full potential yet. I'm beginning my tests with bulk deletes. Mymodel inherits from BulkModelViewSet.

In my urls.py file I define the URL used to interact with my model:

router.register(r"v1/mymodels", mymodels_views_v1.MyModelViewSet)

this allows me to GET, POST, PUT and DELETE on the URL: www.my-api.com/v1/mymodels/{{mymodel_id}}

Can I use this same URL for bulk operations? If so, what is the correct syntax? eg: www.my-api.com/v1/mymodels/[{{mymodel_id1}},{{mymodel_id2}}] If not, what changes should I make?

Thanks

justjess678 avatar Jul 23 '19 08:07 justjess678

This question is more suitable to stack overflow but answering here too because it can be helpful in future if someone tries to open an issue.

There are two things they are saying at the documentation.

  1. Most 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.

That means it won't take url kwarg parameter.

  1. The only exception to this is bulk delete. Consider a DELETE request 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 filtered

Solution:- You could do like this

class SimpleViewSet(generics.BulkModelViewSet):
    def filter_queryset(self, queryset):
        ids = self.request.query_params.get('ids')
        if ids:
            return queryset.filter(id__in=ids.split(',')
        # returns normal query set if no param
        return queryset

kernelshard avatar Jul 23 '19 15:07 kernelshard