Search code examples
djangodatabasedjango-modelsormmodel

Create Raise error in model (clean method isn't working)


I want to raise some error like: if user create both bus_stop_1 and bus_stop_2 with same foreign key or if the count of an object exceed in a table more than 4

So my doubt is how can i raise the error when i use clean method it is not working properly


class ConnectedRoute(models.Model):
    bus_stop_1 = models.ForeignKey(
        BusStop, on_delete=models.CASCADE, related_name='stop1')
    bus_stop_2 = models.ForeignKey(
        BusStop, on_delete=models.CASCADE, related_name='stop2')
    distance = models.FloatField(blank=True, null=True)
    time = models.TimeField(blank=True, null=True)

    def clean(self):
        if self.bus_stop_1 == self.bus_stop_2:
            raise ValidationError('Both stop cannot to the same')
        count_stop1 = ConnectedRoute.objects.filter(
            bus_stop_1=self.bus_stop_1).count()
        count_stop2 = ConnectedRoute.objects.filter(
            bus_stop_2=self.bus_stop_2).count()

        if count_stop1 + count_stop2 > 4:
            raise ValidationError('Only 4 connections allowed.')

I tried to use this clean method, but i never found it useful is there anything that am missing


Solution

  • You have to call model_instance.save() to invoke clean() method for validation or can manually call model_instance.clean() and then model_instance.save()

    Try to override the save method and call full_clean() in the save.

    class ConnectedRoute(models.Model):
       bus_stop_1 = models.ForeignKey(
           BusStop, on_delete=models.CASCADE, related_name='stop1')
       bus_stop_2 = models.ForeignKey(
           BusStop, on_delete=models.CASCADE, related_name='stop2')
       distance = models.FloatField(blank=True, null=True)
       time = models.TimeField(blank=True, null=True)
    
    
       def clean(self):
          if self.bus_stop_1 == self.bus_stop_2:
             raise ValidationError('Both stop cannot be the same')
          
          count_stop1 = ConnectedRoute.objects.filter(
               bus_stop_1=self.bus_stop_1).count()
          count_stop2 = ConnectedRoute.objects.filter(
               bus_stop_2=self.bus_stop_2).count()
    
          if count_stop1 + count_stop2 > 4:
            raise ValidationError('Only 4 connections allowed.')
    
       def save(self, *args, **kwargs):
          self.full_clean()
          super().save(*args, **kwargs)}