Django.fun

Django Constraining Foreign Keys for multiple nested objects

Let's start with the models:

class Brand(models.Model):
    id = models.UUIDField(primary_key=True
    name = models.CharField(max_length=255)

class ProductLine(models.Model):
    id = models.UUIDField(primary_key=True
    name = models.CharField(max_length=255)
    brand = models.ForeignKey(Brand, on_delete=models.CASCADE)

class Product(models.Model):
    id = models.UUIDField(primary_key=True
    name = models.CharField(max_length=255)
    brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
    product_line = models.ForeignKey(ProductLine, on_delete=models.CASCADE, blank=True, null=True)

So we have brands. Brands can have 0 or more product_lines. A product always has a brand, and may also be within a product_line.

My goal is to constrain the product_line of a product to also have the same brand as the product itself.

For example:

  • Brand A has 2 product_lines: Premium, Standard
  • Brand B has 1 product_line: Platinum

Suppose we have a product that belongs to brand B. I want to allow the product_line to be either null or Platinum, but not one of the product_lines that belong to Brand A (Premium or Standard)

I'm not sure how to achieve this, or even if this should happen in serializers, at the model level, or somewhere else. Any help from seasoned django-ers would be much appreciated!

Answers: 1

Answered by daneil James, Jan. 13, 2022, 12:51 p.m.

I have not tested alot in detail But I feel this might work

class Product(models.Model):
    name = models.CharField(max_length=255)
    brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
    product_line = models.ForeignKey(ProductLine, on_delete=models.CASCADE, blank=True, null=True)

    def __str__(self):
        return self.name

    def clean(self):
        if Product.objects.filter(product_line=self.product_line).exists():
            raise ValidationError({'product_line': 'this product line is already selected'})