diff --git a/src/viralhostrange/viralhostrangedb/forms.py b/src/viralhostrange/viralhostrangedb/forms.py index e71b26bce87333ab6be0e1fc6b38eeb1221a320a..0f15a240f75f43891f408956323a12bace1fea01 100644 --- a/src/viralhostrange/viralhostrangedb/forms.py +++ b/src/viralhostrange/viralhostrangedb/forms.py @@ -7,14 +7,14 @@ import string import pandas as pd from basetheme_bootstrap.user_preferences_utils import get_user_preferences_for_user -from crispy_forms import helper as crispy_forms_helper +from crispy_forms import helper as crispy_forms_helper from crispy_forms import layout as crispy_forms_layout from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Layout, Row, Column from django import forms from django.conf import settings from django.contrib.auth import get_user_model -from django.core.exceptions import FieldDoesNotExist +from django.core.exceptions import FieldDoesNotExist, ValidationError from django.db.models import Q, Min, Max from django.forms import widgets from django.utils import timezone @@ -483,6 +483,10 @@ class AutoMergeSplitUpdateFormSet(forms.BaseModelFormSet): obj.save() # And use this copy as its alter_ego alter_ego = obj + elif alter_ego.data_source.filter(pk=self.__data_source.pk).exists(): + raise ValidationError( + mark_safe(ugettext("Duplicated entry <b>%s</b> have been found but is not allowed.") + % alter_ego.explicit_name_html)) # remove the old instance from the current data_source old_o.data_source.remove(self.__data_source) diff --git a/src/viralhostrange/viralhostrangedb/tests/test_views_data_source.py b/src/viralhostrange/viralhostrangedb/tests/test_views_data_source.py index 66940cb2b66a5b08a7a479d2a0a55ed54161f0fd..432282f5ca64c218f6deb129f29419dca6b87514 100644 --- a/src/viralhostrange/viralhostrangedb/tests/test_views_data_source.py +++ b/src/viralhostrange/viralhostrangedb/tests/test_views_data_source.py @@ -190,7 +190,7 @@ class DataSourceUpdateViewTestCase(ViewTestCase): form_data = dict( name=self.public_data_source_of_user.name, life_domain="bacteria", - description="a "*20, + description="a " * 20, public=True, allowed_users_editor= "\n".join(["%s %s;%i;%s" % (gu.user.last_name, gu.user.first_name, gu.user.pk, gu.can_write) @@ -1405,6 +1405,41 @@ class DataSourceVirusOrHostUpdateTestCase(ViewTestCase): self.assertEqual(initial_overall_count, getattr(data_source, entry_set).first().__class__.objects.count()) + def test_host_duplication_fails(self): + url = 'viralhostrangedb:data-source-host-update' + self.actual_test_duplication_fails(url, "host_set", self.private_data_source_of_toto) + + def test_virus_duplication_fails(self): + url = 'viralhostrangedb:data-source-virus-update' + self.actual_test_duplication_fails(url, "virus_set", self.private_data_source_of_toto) + + def actual_test_duplication_fails(self, url, entry_set, data_source): + is_virus = entry_set.startswith("virus") + url = reverse(url, args=[data_source.pk]) + self.client.force_login(self.toto) + count = getattr(data_source, entry_set).order_by("id").count() + + self.assertFalse(getattr(data_source, entry_set).filter(name="Tralala").exists()) + + form_data = { + "form-TOTAL_FORMS": count, + "form-INITIAL_FORMS": count, + "form-MIN_NUM_FORMS": 0, + "form-MAX_NUM_FORMS": 1000, + } + for i, v in enumerate(getattr(data_source, entry_set).order_by("id")): + form_data["form-%i-name" % i] = "Tralala" + form_data["form-%i-id" % i] = v.id + form_data["form-%i-identifier" % i] = "" + if is_virus: + form_data["form-%i-her_identifier" % i] = "" + + response = self.client.post(url, form_data) + self.assertEqual(len(list(response.context['messages'])), 1) + self.assertEqual(response.status_code, 200) + + self.assertFalse(getattr(data_source, entry_set).filter(name="Tralala").exists()) + def test_delete_not_possible(self): url = reverse('viralhostrangedb:data-source-virus-update', args=[self.private_data_source_of_toto.pk]) entry_set = "virus_set" diff --git a/src/viralhostrange/viralhostrangedb/views.py b/src/viralhostrange/viralhostrangedb/views.py index be3f1e5ccfb68cca65fe59b44141395c81623a89..d13c6699524e4be7074fba2d7314b90b91bb3fef 100644 --- a/src/viralhostrange/viralhostrangedb/views.py +++ b/src/viralhostrange/viralhostrangedb/views.py @@ -19,7 +19,7 @@ from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.contenttypes.models import ContentType from django.core import signing -from django.core.exceptions import PermissionDenied +from django.core.exceptions import PermissionDenied, ValidationError from django.core.files import storage from django.core.files.temp import NamedTemporaryFile from django.core.mail import EmailMultiAlternatives @@ -852,6 +852,8 @@ def data_source_entry_update(request, pk, entry_class, formset_class, title, for ], altered_data=altered_data, ) + except ValidationError as e: + messages.error(request=request, message=e.message) except Exception as e: messages.error(request=request, message=e) else: