Django - How to get self.id when saving a new object?

32,077

Solution 1

If it's a new object, you need to save it first and then access self.id, because

"There's no way to tell what the value of an ID will be before you call save(), 
 because that value is calculated by your database, not by Django."

Check django's document https://docs.djangoproject.com/en/dev/ref/models/instances/

Solution 2

You might need to save this file/instance twice:

You can use a post_save signal on the model that looks for the created flag, and re-saves the instance updating the url (and moving/renaming the file as necessary), since the instance will now have an ID. Make sure you only do this conditioned on created, though, otherwise you will continuously loop in saving: saving kicks off a post-save signal, which does a save, which kicks off a post-save signal...

See https://docs.djangoproject.com/en/dev/ref/signals/#post-save

Solution 3

There is actually a way to trick this out.

class Test(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=150)

    def __str__(self):
        return self.name

    def update_model(self):
        # You now have both access to self.id and self.name
    
        test_id = Test.objects.get(name=self.name).id
        print(test_id)
    
        # Do some stuff, update your model...
        Test.objects.filter(id=test_id).update(name='New Name')
        

    def save(self, *args, **kwargs):
        super(Test, self).save(*args, **kwargs)
        self.update_model() # Call the function

Solution 4

I understand this is old but for anyone that stumbles across this in the future, here's actually how you do it now in Django.

def url(instance, filename):
        pdb.set_trace()

        url = "MultimediaData/HelpAdImages/ItemKind/%s/%s" % (instance.id, filename)
        return url

Solution 5

Note: You need to have the models.AutoField(primary_key=True) attribute set, otherwise the database will be updated with a new id but Django will not recognize it.

models.AutoField(primary_key=True)
Share:
32,077
André
Author by

André

Updated on July 09, 2022

Comments

  • André
    André almost 2 years

    I have a problem in one of my models. I'm uploading an image, and I want to store the id (pk in the database table) but I need to know at which point Django will have access to self.id.

    models.py

    class BicycleAdItemKind(MPTTModel):
        def url(self, filename):
            pdb.set_trace()
    
            url = "MultimediaData/HelpAdImages/ItemKind/%s/%s" % (self.id, filename)
            return url
    
        def item_kind_image(self):
            return '<img align="middle" src="/media/%s" height="60px" />' % self.image
        item_kind_image.allow_tags = True     
    
        # Bicicleta completa, Componentes para bicicleta, Acessorios para ciclista
        n_item_kind      = models.CharField(max_length=50) 
        parent           = TreeForeignKey('self', null=True,
                                          blank=True, related_name='children')
        description      = models.TextField(null=True, blank=True)
        image            = models.ImageField(upload_to=url, null=True, blank=True)
        date_inserted    = models.DateTimeField(auto_now_add=True)
        date_last_update = models.DateTimeField(auto_now=True)
    
        def __unicode__(self):
            return self.n_item_kind
    
        class MPTTMeta:
            order_insertion_by = ['n_item_kind']
    

    The problem is in the url() method; I can only get self.id when updating an object, I don't get the self.id when creating a new object. How can I modify this model so that I get self.id when creating a new object?

    With the current code, when I'm creating a new object I will end up with a url like:

    MultimediaData/HelpAdImages/ItemKind/None/somefile.jpg
    

    And I need to have something like:

    MultimediaData/HelpAdImages/ItemKind/35/somefile.jpg
    

    Any clues?

  • André
    André over 11 years
    Hi! Thanks for your reply. Any idea on how to upload the image inside the save) method? Best Regards,
  • Qiang Jin
    Qiang Jin over 11 years
    @André You need to save it twice, save it, access the id, then update the model and save again.
  • shoconinja
    shoconinja about 9 years
    @QiangJin What do you mean save it twice? save it, access the id. I still can't seem to do it. Could you post some example code PLEASSEE
  • Tony
    Tony over 7 years
    This code is dangerous and should not be used. In a multi-user environment there's no way you can guarantee what an id will be until you insert the row in to the database. If two users were to end up executing this code before performing a save you will end up with duplicate primary keys and one insert will fail.
  • mexekanez
    mexekanez over 7 years
    It's on of the way to get ID, question is "how to get self id". So if solution works and it can be used - it means that is working solution. To use it or not - up to each developer!
  • Tony
    Tony over 7 years
    Just because this method works in a development environment with one user does not mean it's a valid solution. I would absolutely not put this code on a production server with multiple users. It is going to fail at some point.
  • mexekanez
    mexekanez over 7 years
    Fair point. I was thinking in a way - there is nothing impossible. I think any developer must solve any task. So I was just interested how to get ID with conditions above. p.s if autoincrement turned off - this solution is wrong in general.
  • Tony Dean
    Tony Dean over 2 years
    Thank you!!! I have been trying to figure this out for hours and you were the one that could finally make it click in my head!!!