Почему я получаю, что объект 'NoneType' не вызывается при попытке удалить элемент с отношениями m2m? - PullRequest
0 голосов
/ 25 июня 2019

Я пишу приложение для представления некоторых систем: некоторые устройства будут содержать статьи об оборудовании, например, сервер будет содержать жесткие диски.

Для операций CRUD я использую DRF ModelViewSet (ничего не переопределяется).

Когда я удаляю оборудование, для которого отношение m2m не установлено, оно работает нормально, но я получаю сообщение об ошибке, когда оно установлено.

Вот упрощенная версия схемы модели.

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

Ниже приведена полная трассировка.

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

Редактировать: добавить информацию

Чтобы выполнить удаление, я вызываю представление hardareEN, используя запрос ajax. Представление является ModelViewSet, как показано ниже:

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

Сериализатор выглядит так:

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

Для информации я попытался удалить переопределение to_representation, но безуспешно.

1 Ответ

3 голосов
/ 28 июня 2019

Проблема заключалась в том, что я переопределил метод __getattr__ модели HardwareEN, но забыл добавить AttributeError для несуществующих атрибутов. Следовательно, при извлечении атрибутов модели среда не получала ошибку атрибута при необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...