Set unique primary key based on foreignkey

I have a model defined as -

class sales_order(models.Model):
    customer=models.ForeignKey()
    item=models.ForeignKey()
    branch=models.ForeignKey()
    ---
    ---other fields

Now for each branch, I want to start the primary key from 1 ("id" for eg.), but the default functionality of Django will increment the id irrespective of any other data.

I'm ok even if id keeps on incrementing as it does, and then I set my own field making it unique per branch and this field should auto increment without the user passing the data by checking the previous value from the database such as -

class order_serializer(serializers.ModelSerializer):
    class Meta:
        validators = [
            UniqueTogetherValidator(
                queryset=sales_order.objects.all(),
                fields=['myOwnDefinedField', 'branch']
            )
        ]

I'm in a state of no idea how to achieve this. Using Django 3.1.5.

Any help?

1 answer

  • answered 2021-10-12 18:25 Iain Shelvington

    In the model's save method you can perform a query to get the greatest value in the field for the current branch, add 1 to this value and then save that as the new value. Only do this if there is not already a value so that we don't overwrite existing rows

    Use Meta.unique_together to enforce this constraint at the DB level too

    from django.db.models.functions import Coalesce
    
    class SalesOrder(models.Model):
        branch = models.ForeignKey(Branch, on_delete=models.CASCADE)
        branch_unique_id = models.IntegerField(editable=False, blank=True)
    
        class Meta:
            unique_together = (
                ('branch', 'branch_unique_id'),
            )
    
        def save(self, *args, **kwargs):
            if not self.branch_unique_id:
                self.branch_unique_id = SalesOrder.objects.filter(
                    branch=self.branch
                ).aggregate(
                    max=Coalesce(models.Max('branch_unique_id'), 0)
                )['max'] + 1
            super().save(*args, **kwargs)
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum