How to access Model’s pk/id when you create an instance in Django

If you need to modify instance fields depending on the instance’s pk or id, hop on.

When you create an instance, before it is saved, you can’t have pk or id as it is not yet created.

    def save(self, *args, **kwargs):
        # self.pk == None
        # self.id == None
        super().save(*args, **kwargs)
        # self.pk != None
        # self.id != None        

If you have a property that somehow depends on the value of self.pk or self.id and you want to have it saved on creating, you have two options.

Make it a @property

If you don’t really need it for MyModel.objects.filter() or MyModel.objects.get() purposes, then just make it a @property and chill:

 @property
 def something_coded(self):
     return 'something_' + str(self.pk)

Make it a field

Make a models.CharField or whatever you want and modify the save method:

    def save(self, *args, **kwargs):
        # self.pk == None
        # self.id == None
        super().save(*args, **kwargs)
        # self.pk != None
        # self.id != None  
        if not self.something_coded:
            obj = MyModel.objects.get(pk=self.pk)
            obj.something_coded = 'something_' + str(self.pk)
            obj.save()

This way it will only work once – if your field something_coded is empty (just when you create it).

The only problem with this is that when you create an instance like that somewhere in your code (say, in views or in a @classmethod) it works like this:

new_instance = MyModel.objects.create()
print(new_instance.something_coded)
>> null

So if you want to access something_coded field immediately, do this instead:

pk = MyModel.objects.create()
new_instance = MyModel.objects.get(pk=pk)
print(new_instance.something_coded)
>> 'something_5'

I am yet to test if it works with ManyToManyField (without through table).

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.