How to compare two integer fields in a model method in django?

43 views Asked by At

I want to compare two integer fields inside a method in a django model. The two fields are not correctly getting compared and it is throwing an error for example:

    total_slots = models.IntegerField(default=0, help_text="Total number of vehicle slots available for allocation.")
    allocated_slots = models.IntegerField(default=0,
                                          validators=[
                                              MaxValueValidator(total_slots),
                                              MinValueValidator(0)
                                          ], )

    def available_slots_left(self):
    if self.allocated_slots < self.total_slots:
        return True
    return False

I tried to just simply do this:

    def available_slots_left(self):
    if self.allocated_slots < self.total_slots:
        return True
    return False

but it didn't work and it returned this error:


TypeError: '<=' not supported between instances of 'IntegerField' and 'int'
2

There are 2 answers

0
Abdul Aziz Barkat On

The problem is not in your method but rather your validator, specifically MaxValueValidator(total_slots) won't work because MaxValueValidator needs to be passed an integer and not a model field. If you do want to set up some validation for that you can create a CheckConstraint for it:

from django.db import models


class YourModel(models.Model):
    total_slots = models.IntegerField(default=0, help_text="Total number of vehicle slots available for allocation.")
    allocated_slots = models.IntegerField(default=0, validators=[MinValueValidator(0)], )
    
    class Meta:
        constraints = [
            models.CheckConstraint(
                check=models.Q(allocated_slots__lte=models.F("total_slots")),
                name="allocated_slots_lte_total_slots",
            )
        ]
0
MD Jahid Hasan On

Your error is conducted in the MaxValueValidator, this validator only receives integers but in that case you pass a model field. You can use several methods to implement this validation.

Add this method in your model:

def save(self, *args, **kwargs):
    if self.allocated_slots > self.total_slots:
        raise ValidationError("Your error message")
    return super().save(*args, **kwargs)

You can use this clean method in that case you have to call the full_clean() method before save.

def clean(self, *args, **kwargs):
    if self.allocated_slots > self.total_slots:
        raise ValidationError("Your error message")