1

I have a model like this:

THRESHOLD_CLASSES = {
    MinimumThreshold.name: MinimumThreshold,
    MaximumThreshold.name: MaximumThreshold
}

class Threshold(models.Model):
    thingie = models.ForeignKey(Thingie, models.CASCADE)
    threshold_types = THRESHOLD_CLASSES.keys()
    type = models.TextField(choices=zip(threshold_types, threshold_types))
    threshold = models.DecimalField()

With these related classes:

import abc
import operator


class Threshold(abc.ABC):
    @abc.abstractmethod
    def __init__(self):
        pass


class MinimumThreshold(Threshold):
    name = 'minimum'
    operator = operator.lt
    operator_name = 'lower than'

    def __init__(self):
        self.other_class = MaximumThreshold


class MaximumThreshold(Threshold):
    name = 'maximum'
    operator = operator.gt
    operator_name = 'greater than'

    def __init__(self):
        self.other_class = MinimumThreshold

In my serializer I have to verify that the minimum threshold for a thingie is less than its maximum:

def validate(self, instance):
    instance_type = instance['type']
    instance_threshold_class = models.THRESHOLD_CLASSES[instance_type]
    other_threshold_class = instance_threshold_class().other_class
    other = models \
        .AlarmParameterThreshold \
        .objects \
        .filter(thingie=instance['thingie'], type=other_threshold_class.name) \
        .first()
    if other:
        if other_threshold_class.operator(instance['threshold'], other.threshold):
            message = "The {} threshold cannot be {} the {} threshold of {}".format(
                instance_type,
                other_threshold_class.operator_name,
                other_threshold_class.name,
                other.threshold
            )
            raise serializers.ValidationError({'threshold': message})

This is already complicated, and I want to ensure that the complexity doesn't explode. One currently unhandled case if when the user changes the type of an existing Threshold - I would end up comparing it against an instance which is about to be replaced, and so I would have to make sure to exclude the instance which is currently being updated from the query to find the other threshold.

In this case, a simpler approach would be to simply disallow changes to type once it's been set, but I don't know of a way of doing that which is easier than excluding the current item from the comparison.

Please note that I'm not looking for a Django Forms solution - this is an API and the validation must be performed on the server side.

l0b0
  • 55,365
  • 30
  • 138
  • 223
  • See [this answer](https://stackoverflow.com/a/23363123/2011147). You can then revert to the old value of `type` before saving the instance even if the user has changed it. – Selcuk Oct 05 '18 at 04:04

0 Answers0