Thursday, 4 July 2019

Why do I get 'NoneType' object is not callable when trying to delete item with m2m relations?

I'm writing an app to represent some systems : some equipments will contain hardware articles, for exemple a server will contain hard drives.

For CRUD operations i'm using DRF ModelViewSet (nothing overriden).

When I delete an equipment which m2m relation is not set it works fine, but I get an error when it is.

Here is a simplified version of the model scheme.

class Hardware(models.Model):
    equipment = models.ManyToManyField('Equipment', blank=True, through='HardwareEQ')
    # attributes

class HardwareEQ(models.Model):
    hardware = models.ForeignKey(Hardware, on_delete=models.CASCADE)
    equipment = models.ForeignKey(Equipment, on_delete=models.CASCADE)
    # relation attributes

Below is full traceback.

Traceback:

File "C:\Users\USER\Envs\venv\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "C:\Users\USER\Envs\venv\lib\site-packages\rest_framework\viewsets.py" in view
  103.             return self.dispatch(request, *args, **kwargs)

File "C:\Users\USER\Envs\venv\lib\site-packages\rest_framework\views.py" in dispatch
  483.             response = self.handle_exception(exc)

File "C:\Users\USER\Envs\venv\lib\site-packages\rest_framework\views.py" in handle_exception
  443.             self.raise_uncaught_exception(exc)

File "C:\Users\USER\Envs\venv\lib\site-packages\rest_framework\views.py" in dispatch
  480.             response = handler(request, *args, **kwargs)

File "C:\Users\USER\Envs\venv\lib\site-packages\rest_framework\mixins.py" in destroy
  93.         self.perform_destroy(instance)

File "C:\Users\USER\Envs\venv\lib\site-packages\rest_framework\mixins.py" in perform_destroy
  97.         instance.delete()

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\base.py" in delete
  918.         collector.collect([self], keep_parents=keep_parents)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\deletion.py" in collect
  224.                         field.remote_field.on_delete(self, field, sub_objs, self.using)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\deletion.py" in CASCADE
  16.                       source_attr=field.name, nullable=field.null)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\deletion.py" in collect
  220.                     sub_objs = self.related_objects(related, batch)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\deletion.py" in related_objects
  236.             **{"%s__in" % related.field.name: objs}

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\query.py" in filter
  892.         return self._filter_or_exclude(False, *args, **kwargs)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\query.py" in _filter_or_exclude
  910.             clone.query.add_q(Q(*args, **kwargs))

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\sql\query.py" in add_q
  1290.         clause, _ = self._add_q(q_object, self.used_aliases)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\sql\query.py" in _add_q
  1318.                     split_subq=split_subq, simple_col=simple_col,

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\sql\query.py" in build_filter
  1202.         value = self.resolve_lookup_value(value, can_reuse, allow_joins, simple_col)

File "C:\Users\USER\Envs\venv\lib\site-packages\django\db\models\sql\query.py" in resolve_lookup_value
  1037.                         sub_value.resolve_expression(self, reuse=can_reuse, allow_joins=allow_joins)

Exception Type: TypeError at /Sycoma2/ensemble/2/
Exception Value: 'NoneType' object is not callable

Edit : add information

To perform the deletion, I call the hardareEN view using ajax request. The view is a ModelViewSet, like below :

class HardwareENViewSet(viewsets.ModelViewSet):
    queryset = HardwareEN.objects.all()
    serializer_class = HardwareENSerializer

The serializer looks like this :

class HardwareENSerializer(VerboseSerializer):
    class Meta:
        model = HardwareEN
        fields = '__all__'

    def to_representation(self, instance):
        """
        Add hardware data
        :param instance:
        :return:
        """
        data = super().to_representation(instance)
        for key, value in HardwareSerializer(instance.hardware).data.items():
            try:
                if not data[key]:
                    data[key] = value
            except KeyError:
                data[key] = value
        return data

For information, I tried removing the to_representation override, without more success.



from Why do I get 'NoneType' object is not callable when trying to delete item with m2m relations?

No comments:

Post a Comment