Irfan Harun
Irfan Harun

Reputation: 1059

Django ORM : restrict foreignkey relationship between models to limited number of times

i have two models: vehicle and Driver. At any given point of time, a vehicle can have zero, one or maximum of two drivers. my current models setup allows by to have more than 2 drivers on one vehicle. How can i restrict the number of driver to just two per vehicle ?

my current models

class DriverStatus(models.Model):
status = models.CharField(max_length=200)
def __str__(self):
    return f'{self.status}'



class Driver(models.Model):
    name = models.CharField(max_length=200)
    driver_num = models.IntegerField()
    profile_image = models.ImageField(default="default.jpg",upload_to="images")
    status = models.ForeignKey(DriverStatus, on_delete=models.CASCADE)
    current_vehicle = models.ForeignKey(Vehicle, on_delete=models.SET_NULL,null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    def __str__(self):
        return f'{self.name}'


class Vehicle(models.Model):
    vehicle_number = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    def __str__(self):
        return f'{self.vehicle_number

Upvotes: 0

Views: 104

Answers (1)

Elektordi
Elektordi

Reputation: 350

You cannot do that on the database level. But you can add model validation: https://docs.djangoproject.com/en/3.0/ref/validators/

Or you can do your validation in the clean method of your model: Validate count() constraint in many to many relation before saving an instance in django


Add this in Driver class:

  def clean(self):
    cleaned_data = super(Driver, self).clean()
    vehicle = self.cleaned_data.get('current_vehicle')
    if not vehicle:
        return cleaned_data
    drivers_count = Driver.objects.filter(current_vehicle=vehicle).exclude(pk=self.instance.pk).count()
    if drivers_count >= 2:
      raise ValidationError('Maximum drivers reached')
    return cleaned_data

I haven't tested it, but that's the idea!

Upvotes: 1

Related Questions