Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Model Auto Increment Primary Key Based on Foreign Key

I'm trying to figure out how to lay out two of my Django models so that when a new model is saved to the database, its primary key is incremented such that it is the next highest value for all records with the same foreign key.

It's much like this question asked, but I'm wondering how you would do it in Django. Here's an excerpt from the question which demonstrates a similar situation:

id | job_id | title
0     1        hi
1     1        hello
2     1        goodbye
0     2        hi
1     2        hello

I know you can't have multiple primary keys in a Django model and you can use unique_together, but the documentation says it uses the equivalent UNIQUE statement in the CREATE statements. Would

class ModelA(models.Model):
   key = models.PositiveIntegerField(primary_key = True)
   fk = models.ForeignKey(ModelB)

   def Meta(self):
      unique_together = ("key", "fk")

in the models work with this answer to accomplish what I'm looking for? The relationship between the models is one ModelA having many ModelBs, but each ModelB having only one ModelA.

like image 550
Dirk Avatar asked Jan 21 '12 01:01

Dirk


People also ask

Is it possible to set a foreign key as auto increment?

When creating a table, there is an option for us to set the numeric primary key as autoincrement where its value increases whenever a new data in inserted. This primary number can be used for setting the relationship of a table where it is assigned as a foreign key to that table.

Is primary key always auto increment?

The above statement is true. Primary key should always be auto increment.

Can a model have two foreign keys in Django?

Your intermediate model must contain one - and only one - foreign key to the source model (this would be Group in our example), or you must explicitly specify the foreign keys Django should use for the relationship using ManyToManyField.


1 Answers

You have to make some changes to the model (if possible). So, ModelA should look something like this

class ModelA(models.Model):
    key = models.PositiveIntegerField()
    fk = models.ForeignKey(ModelB)

    def Meta(self):
        unique_together = ("key", "fk")

    def save(self, *args, **kwargs):
        key = cal_key(self.fk)
        self.key = key
        super(ModelA, self).save(*args, **kwargs)

As, you can see, I have overridden the default save method to calculate the key value in a cal_key function that takes fk as an argument. So, define the cal_key function in the models file.

def cal_key(fk):
    present_keys = ModelA.objects.filter(fk=fk).order_by('-key').values_list('key', flat=True)
    if present_keys:
        return present_keys[0]+1
    else:
        return 0

The cal_key function clearly indicates what you actually require.

like image 187
Sandip Agarwal Avatar answered Oct 12 '22 15:10

Sandip Agarwal