From c1a96d6acc3317928d125284f07082cfd1ba34ef Mon Sep 17 00:00:00 2001 From: Cyrus Hiatt Date: Wed, 27 Mar 2019 13:47:54 -0700 Subject: [PATCH] Enforces unique constraint in the tile model re #4375 --- arches/app/datatypes/base.py | 5 ++++- arches/app/models/tile.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/arches/app/datatypes/base.py b/arches/app/datatypes/base.py index 5d045b0a74a..5f076df2e14 100644 --- a/arches/app/datatypes/base.py +++ b/arches/app/datatypes/base.py @@ -24,6 +24,9 @@ def after_update_all(self): """ pass + def values_match(self, value1, value2): + return value1 == value2 + def transform_import_values(self, value, nodeid): """ Transforms values from probably string/wkt representation to specified @@ -315,4 +318,4 @@ def to_rdf(self, edge_info, edge): def from_rdf(self, json_ld_node): print json_ld_node - raise NotImplementedError \ No newline at end of file + raise NotImplementedError diff --git a/arches/app/models/tile.py b/arches/app/models/tile.py index 1859c85f733..14b1e34c92e 100644 --- a/arches/app/models/tile.py +++ b/arches/app/models/tile.py @@ -22,6 +22,7 @@ import pytz from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ValidationError +from django.db.models import Q from django.utils import timezone from django.utils.translation import ugettext as _ from arches.app.models import models @@ -190,6 +191,34 @@ def get_provisional_edit(self, tile, user): edit = edits[str(user.id)] return edit + def check_for_constraint_violation(self, request): + card = models.CardModel.objects.get(nodegroup=self.nodegroup) + constraints = models.ConstraintModel.objects.filter(card=card) + if constraints.count() > 0: + for constraint in constraints: + if constraint.uniquetoallinstances is True: + tiles = models.TileModel.objects.filter(nodegroup=self.nodegroup) + else: + tiles = models.TileModel.objects.filter( + Q(resourceinstance_id=self.resourceinstance.resourceinstanceid) & + Q(nodegroup=self.nodegroup)) + nodes = [node for node in constraint.nodes.all()] + for tile in tiles: + match = False + duplicate_values = [] + for node in nodes: + datatype_factory = DataTypeFactory() + datatype = datatype_factory.get_instance(node.datatype) + nodeid = str(node.nodeid) + if datatype.values_match(tile.data[nodeid], self.data[nodeid]): + match = True + duplicate_values.append(datatype.get_display_value(tile, node)) + else: + return False + if match is True: + message = _('This card violates a unique constraint. The following value is already saved: ') + raise TileValidationError(message + (', ').join(duplicate_values)) + def check_for_missing_nodes(self, request): missing_nodes = [] for nodeid, value in self.data.iteritems(): @@ -235,6 +264,7 @@ def save(self, *args, **kwargs): newprovisionalvalue = None oldprovisionalvalue = None self.check_for_missing_nodes(request) + self.check_for_constraint_violation(request) try: if user is None and request is not None: