Я пишу приложение для представления некоторых систем: некоторые устройства будут содержать статьи об оборудовании, например, сервер будет содержать жесткие диски.
Для операций 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
, но безуспешно.