Signalen / backend

Backend for Signalen, an application that helps cities manage and prioritize nuisance reports.
https://signalen.org
Mozilla Public License 2.0
5 stars 5 forks source link

Backend throws exception for additional questions that return multiple categories #110

Open bartjkdp opened 3 years ago

bartjkdp commented 3 years ago
File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py", line 505, in dispatch
response = self.handle_exception(exc)
File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py", line 465, in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
raise exc
File "/usr/local/lib/python3.8/site-packages/rest_framework/views.py", line 502, in dispatch
response = handler(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/datapunt_api/rest.py", line 65, in list
return super().list(request, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/rest_framework/mixins.py", line 38, in list
queryset = self.filter_queryset(self.get_queryset())
File "/usr/local/lib/python3.8/site-packages/rest_framework/generics.py", line 150, in filter_queryset
queryset = backend().filter_queryset(self.request, queryset, self)
File "/usr/local/lib/python3.8/site-packages/django_filters/rest_framework/backends.py", line 94, in filter_queryset
if not filterset.is_valid() and self.raise_exception:
File "/usr/local/lib/python3.8/site-packages/django_filters/filterset.py", line 206, in is_valid
return self.is_bound and self.form.is_valid()
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 185, in is_valid
return self.is_bound and not self.errors
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 180, in errors
self.full_clean()
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 381, in full_clean
self._clean_fields()
File "/usr/local/lib/python3.8/site-packages/django/forms/forms.py", line 399, in _clean_fields
value = field.clean(value)
File "/usr/local/lib/python3.8/site-packages/django/forms/fields.py", line 148, in clean
value = self.to_python(value)
File "/usr/local/lib/python3.8/site-packages/django_filters/fields.py", line 302, in to_python
return super().to_python(value)
File "/usr/local/lib/python3.8/site-packages/django/forms/models.py", line 1248, in to_python
value = self.queryset.get(**{key: value})
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 410, in get
raise self.model.MultipleObjectsReturned(
signals.apps.signals.models.category.Category.MultipleObjectsReturned: get() returned more than one Category -- it returned 4!

We see this error quite often. I think we should fix this permanently by handling this case more gracefully or not allowing multiple categories in the database scheme.

CBuiVNG commented 3 years ago

This issue can only occur when we have more than 1 record with the same slug. The (slug, parent_id) combination is unique.

This can only be triggered when issuing a Category.objects.get(slug=<slug>) without parent filtering. The only time we are doing a get(slug=) is in CategoryHyperlinkedRelatedField. But here we already handle the parent_id != null case.

I would assume that we have some issues with categories due to a bug in load_categories.

we should check the output of: select slug, count(*) from signals_category group by slug having count(*) > 1; and select slug, parent_id, count(*) from signals_category group by slug, parent_id having count(*) > 1;