prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  404 returned when deleting entity with `delete_content` set to `true`
  Probably because sample gets deleted when the last data object is deleted.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `resolwe/flow/views/entity.py`
  Content:
  ```
  1 """Entity viewset."""
  2 from __future__ import absolute_import, division, print_function, unicode_literals
  3 
  4 from distutils.util import strtobool  # pylint: disable=import-error,no-name-in-module
  5 
  6 from django.db.models import Max
  7 from django.db.models.query import Prefetch
  8 
  9 from rest_framework import exceptions, status
  10 from rest_framework.decorators import detail_route
  11 from rest_framework.response import Response
  12 
  13 from resolwe.flow.filters import EntityFilter
  14 from resolwe.flow.models import Collection, Data, Entity
  15 from resolwe.flow.serializers import EntitySerializer
  16 from resolwe.permissions.utils import remove_permission, update_permission
  17 
  18 from .collection import CollectionViewSet
  19 
  20 
  21 class EntityViewSet(CollectionViewSet):
  22     """API view for entities."""
  23 
  24     filter_class = EntityFilter
  25     serializer_class = EntitySerializer
  26 
  27     queryset = Entity.objects.prefetch_related(
  28         Prefetch('data', queryset=Data.objects.all().order_by('id')),
  29         'descriptor_schema',
  30         'contributor'
  31     ).annotate(
  32         latest_date=Max('data__modified')
  33     ).order_by('-latest_date')
  34 
  35     def _check_collection_permissions(self, collection_id, user):
  36         """Check that collection exists and user has `add` permission."""
  37         collection_query = Collection.objects.filter(pk=collection_id)
  38         if not collection_query.exists():
  39             raise exceptions.ValidationError('Collection id does not exist')
  40 
  41         collection = collection_query.first()
  42         if not user.has_perm('add_collection', obj=collection):
  43             if user.is_authenticated():
  44                 raise exceptions.PermissionDenied()
  45             else:
  46                 raise exceptions.NotFound()
  47 
  48     def set_content_permissions(self, user, obj, payload):
  49         """Apply permissions to data objects in ``Entity``."""
  50         # Data doesn't have "ADD" permission, so it has to be removed
  51         payload = remove_permission(payload, 'add')
  52 
  53         for data in obj.data.all():
  54             if user.has_perm('share_data', data):
  55                 update_permission(data, payload)
  56 
  57     def destroy(self, request, *args, **kwargs):
  58         """Destroy a model instance.
  59 
  60         If ``delete_content`` flag is set in query parameters, also all
  61         Data objects contained in entity will be deleted.
  62         """
  63         obj = self.get_object()
  64         user = request.user
  65 
  66         if strtobool(request.query_params.get('delete_content', 'false')):
  67             for data in obj.data.all():
  68                 if user.has_perm('edit_data', data):
  69                     data.delete()
  70 
  71         # NOTE: Collection's ``destroy`` method should be skiped, so we
  72         # intentionaly call it's parent.
  73         return super(CollectionViewSet, self).destroy(  # pylint: disable=no-member,bad-super-call
  74             request, *args, **kwargs
  75         )
  76 
  77     @detail_route(methods=[u'post'])
  78     def add_to_collection(self, request, pk=None):
  79         """Add Entity to a collection."""
  80         entity = self.get_object()
  81 
  82         if 'ids' not in request.data:
  83             return Response({"error": "`ids` parameter is required"}, status=status.HTTP_400_BAD_REQUEST)
  84 
  85         for collection_id in request.data['ids']:
  86             self._check_collection_permissions(collection_id, request.user)
  87 
  88         for collection_id in request.data['ids']:
  89             entity.collections.add(collection_id)
  90 
  91             collection = Collection.objects.get(pk=collection_id)
  92             for data in entity.data.all():
  93                 collection.data.add(data)
  94 
  95         return Response()
  96 
  97     @detail_route(methods=[u'post'])
  98     def remove_from_collection(self, request, pk=None):
  99         """Remove Entity from a collection."""
  100         entity = self.get_object()
  101 
  102         if 'ids' not in request.data:
  103             return Response({"error": "`ids` parameter is required"}, status=status.HTTP_400_BAD_REQUEST)
  104 
  105         for collection_id in request.data['ids']:
  106             self._check_collection_permissions(collection_id, request.user)
  107 
  108         for collection_id in request.data['ids']:
  109             entity.collections.remove(collection_id)
  110 
  111             collection = Collection.objects.get(pk=collection_id)
  112             for data in entity.data.all():
  113                 collection.data.remove(data)
  114 
  115         return Response()
  116 
  117     @detail_route(methods=[u'post'])
  118     def add_data(self, request, pk=None):
  119         """Add data to Entity and it's collection."""
  120         # add data to entity
  121         resp = super(EntityViewSet, self).add_data(request, pk)
  122 
  123         # add data to collections in which entity is
  124         entity = self.get_object()
  125         for collection in entity.collections.all():
  126             collection.data.add(*request.data['ids'])
  127 
  128         return resp
  129
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/resolwe/flow/views/entity.py b/resolwe/flow/views/entity.py
  --- a/resolwe/flow/views/entity.py
  +++ b/resolwe/flow/views/entity.py
  @@ -68,6 +68,11 @@
                   if user.has_perm('edit_data', data):
                       data.delete()
   
  +            # If all data objects in an entity are removed, the entity may
  +            # have already been removed, so there is no need to call destroy.
  +            if not Entity.objects.filter(pk=obj.pk).exists():
  +                return Response(status=status.HTTP_204_NO_CONTENT)
  +
           # NOTE: Collection's ``destroy`` method should be skiped, so we
           # intentionaly call it's parent.
           return super(CollectionViewSet, self).destroy(  # pylint: disable=no-member,bad-super-call
  
verification_info: {"golden_diff": "diff --git a/resolwe/flow/views/entity.py b/resolwe/flow/views/entity.py\n--- a/resolwe/flow/views/entity.py\n+++ b/resolwe/flow/views/entity.py\n@@ -68,6 +68,11 @@\n                 if user.has_perm('edit_data', data):\n                     data.delete()\n \n+            # If all data objects in an entity are removed, the entity may\n+            # have already been removed, so there is no need to call destroy.\n+            if not Entity.objects.filter(pk=obj.pk).exists():\n+                return Response(status=status.HTTP_204_NO_CONTENT)\n+\n         # NOTE: Collection's ``destroy`` method should be skiped, so we\n         # intentionaly call it's parent.\n         return super(CollectionViewSet, self).destroy(  # pylint: disable=no-member,bad-super-call\n", "issue": "404 returned when deleting entity with `delete_content` set to `true`\nProbably because sample gets deleted when the last data object is deleted.\n", "before_files": [{"content": "\"\"\"Entity viewset.\"\"\"\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nfrom distutils.util import strtobool  # pylint: disable=import-error,no-name-in-module\n\nfrom django.db.models import Max\nfrom django.db.models.query import Prefetch\n\nfrom rest_framework import exceptions, status\nfrom rest_framework.decorators import detail_route\nfrom rest_framework.response import Response\n\nfrom resolwe.flow.filters import EntityFilter\nfrom resolwe.flow.models import Collection, Data, Entity\nfrom resolwe.flow.serializers import EntitySerializer\nfrom resolwe.permissions.utils import remove_permission, update_permission\n\nfrom .collection import CollectionViewSet\n\n\nclass EntityViewSet(CollectionViewSet):\n    \"\"\"API view for entities.\"\"\"\n\n    filter_class = EntityFilter\n    serializer_class = EntitySerializer\n\n    queryset = Entity.objects.prefetch_related(\n        Prefetch('data', queryset=Data.objects.all().order_by('id')),\n        'descriptor_schema',\n        'contributor'\n    ).annotate(\n        latest_date=Max('data__modified')\n    ).order_by('-latest_date')\n\n    def _check_collection_permissions(self, collection_id, user):\n        \"\"\"Check that collection exists and user has `add` permission.\"\"\"\n        collection_query = Collection.objects.filter(pk=collection_id)\n        if not collection_query.exists():\n            raise exceptions.ValidationError('Collection id does not exist')\n\n        collection = collection_query.first()\n        if not user.has_perm('add_collection', obj=collection):\n            if user.is_authenticated():\n                raise exceptions.PermissionDenied()\n            else:\n                raise exceptions.NotFound()\n\n    def set_content_permissions(self, user, obj, payload):\n        \"\"\"Apply permissions to data objects in ``Entity``.\"\"\"\n        # Data doesn't have \"ADD\" permission, so it has to be removed\n        payload = remove_permission(payload, 'add')\n\n        for data in obj.data.all():\n            if user.has_perm('share_data', data):\n                update_permission(data, payload)\n\n    def destroy(self, request, *args, **kwargs):\n        \"\"\"Destroy a model instance.\n\n        If ``delete_content`` flag is set in query parameters, also all\n        Data objects contained in entity will be deleted.\n        \"\"\"\n        obj = self.get_object()\n        user = request.user\n\n        if strtobool(request.query_params.get('delete_content', 'false')):\n            for data in obj.data.all():\n                if user.has_perm('edit_data', data):\n                    data.delete()\n\n        # NOTE: Collection's ``destroy`` method should be skiped, so we\n        # intentionaly call it's parent.\n        return super(CollectionViewSet, self).destroy(  # pylint: disable=no-member,bad-super-call\n            request, *args, **kwargs\n        )\n\n    @detail_route(methods=[u'post'])\n    def add_to_collection(self, request, pk=None):\n        \"\"\"Add Entity to a collection.\"\"\"\n        entity = self.get_object()\n\n        if 'ids' not in request.data:\n            return Response({\"error\": \"`ids` parameter is required\"}, status=status.HTTP_400_BAD_REQUEST)\n\n        for collection_id in request.data['ids']:\n            self._check_collection_permissions(collection_id, request.user)\n\n        for collection_id in request.data['ids']:\n            entity.collections.add(collection_id)\n\n            collection = Collection.objects.get(pk=collection_id)\n            for data in entity.data.all():\n                collection.data.add(data)\n\n        return Response()\n\n    @detail_route(methods=[u'post'])\n    def remove_from_collection(self, request, pk=None):\n        \"\"\"Remove Entity from a collection.\"\"\"\n        entity = self.get_object()\n\n        if 'ids' not in request.data:\n            return Response({\"error\": \"`ids` parameter is required\"}, status=status.HTTP_400_BAD_REQUEST)\n\n        for collection_id in request.data['ids']:\n            self._check_collection_permissions(collection_id, request.user)\n\n        for collection_id in request.data['ids']:\n            entity.collections.remove(collection_id)\n\n            collection = Collection.objects.get(pk=collection_id)\n            for data in entity.data.all():\n                collection.data.remove(data)\n\n        return Response()\n\n    @detail_route(methods=[u'post'])\n    def add_data(self, request, pk=None):\n        \"\"\"Add data to Entity and it's collection.\"\"\"\n        # add data to entity\n        resp = super(EntityViewSet, self).add_data(request, pk)\n\n        # add data to collections in which entity is\n        entity = self.get_object()\n        for collection in entity.collections.all():\n            collection.data.add(*request.data['ids'])\n\n        return resp\n", "path": "resolwe/flow/views/entity.py"}], "after_files": [{"content": "\"\"\"Entity viewset.\"\"\"\nfrom __future__ import absolute_import, division, print_function, unicode_literals\n\nfrom distutils.util import strtobool  # pylint: disable=import-error,no-name-in-module\n\nfrom django.db.models import Max\nfrom django.db.models.query import Prefetch\n\nfrom rest_framework import exceptions, status\nfrom rest_framework.decorators import detail_route\nfrom rest_framework.response import Response\n\nfrom resolwe.flow.filters import EntityFilter\nfrom resolwe.flow.models import Collection, Data, Entity\nfrom resolwe.flow.serializers import EntitySerializer\nfrom resolwe.permissions.utils import remove_permission, update_permission\n\nfrom .collection import CollectionViewSet\n\n\nclass EntityViewSet(CollectionViewSet):\n    \"\"\"API view for entities.\"\"\"\n\n    filter_class = EntityFilter\n    serializer_class = EntitySerializer\n\n    queryset = Entity.objects.prefetch_related(\n        Prefetch('data', queryset=Data.objects.all().order_by('id')),\n        'descriptor_schema',\n        'contributor'\n    ).annotate(\n        latest_date=Max('data__modified')\n    ).order_by('-latest_date')\n\n    def _check_collection_permissions(self, collection_id, user):\n        \"\"\"Check that collection exists and user has `add` permission.\"\"\"\n        collection_query = Collection.objects.filter(pk=collection_id)\n        if not collection_query.exists():\n            raise exceptions.ValidationError('Collection id does not exist')\n\n        collection = collection_query.first()\n        if not user.has_perm('add_collection', obj=collection):\n            if user.is_authenticated():\n                raise exceptions.PermissionDenied()\n            else:\n                raise exceptions.NotFound()\n\n    def set_content_permissions(self, user, obj, payload):\n        \"\"\"Apply permissions to data objects in ``Entity``.\"\"\"\n        # Data doesn't have \"ADD\" permission, so it has to be removed\n        payload = remove_permission(payload, 'add')\n\n        for data in obj.data.all():\n            if user.has_perm('share_data', data):\n                update_permission(data, payload)\n\n    def destroy(self, request, *args, **kwargs):\n        \"\"\"Destroy a model instance.\n\n        If ``delete_content`` flag is set in query parameters, also all\n        Data objects contained in entity will be deleted.\n        \"\"\"\n        obj = self.get_object()\n        user = request.user\n\n        if strtobool(request.query_params.get('delete_content', 'false')):\n            for data in obj.data.all():\n                if user.has_perm('edit_data', data):\n                    data.delete()\n\n            # If all data objects in an entity are removed, the entity may\n            # have already been removed, so there is no need to call destroy.\n            if not Entity.objects.filter(pk=obj.pk).exists():\n                return Response(status=status.HTTP_204_NO_CONTENT)\n\n        # NOTE: Collection's ``destroy`` method should be skiped, so we\n        # intentionaly call it's parent.\n        return super(CollectionViewSet, self).destroy(  # pylint: disable=no-member,bad-super-call\n            request, *args, **kwargs\n        )\n\n    @detail_route(methods=[u'post'])\n    def add_to_collection(self, request, pk=None):\n        \"\"\"Add Entity to a collection.\"\"\"\n        entity = self.get_object()\n\n        if 'ids' not in request.data:\n            return Response({\"error\": \"`ids` parameter is required\"}, status=status.HTTP_400_BAD_REQUEST)\n\n        for collection_id in request.data['ids']:\n            self._check_collection_permissions(collection_id, request.user)\n\n        for collection_id in request.data['ids']:\n            entity.collections.add(collection_id)\n\n            collection = Collection.objects.get(pk=collection_id)\n            for data in entity.data.all():\n                collection.data.add(data)\n\n        return Response()\n\n    @detail_route(methods=[u'post'])\n    def remove_from_collection(self, request, pk=None):\n        \"\"\"Remove Entity from a collection.\"\"\"\n        entity = self.get_object()\n\n        if 'ids' not in request.data:\n            return Response({\"error\": \"`ids` parameter is required\"}, status=status.HTTP_400_BAD_REQUEST)\n\n        for collection_id in request.data['ids']:\n            self._check_collection_permissions(collection_id, request.user)\n\n        for collection_id in request.data['ids']:\n            entity.collections.remove(collection_id)\n\n            collection = Collection.objects.get(pk=collection_id)\n            for data in entity.data.all():\n                collection.data.remove(data)\n\n        return Response()\n\n    @detail_route(methods=[u'post'])\n    def add_data(self, request, pk=None):\n        \"\"\"Add data to Entity and it's collection.\"\"\"\n        # add data to entity\n        resp = super(EntityViewSet, self).add_data(request, pk)\n\n        # add data to collections in which entity is\n        entity = self.get_object()\n        for collection in entity.collections.all():\n            collection.data.add(*request.data['ids'])\n\n        return resp\n", "path": "resolwe/flow/views/entity.py"}]}