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

拈花ヽ惹草 提交于 2019-11-27 03:03:19

问题


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?


回答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/




回答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




回答3:


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)



回答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



回答5:


I know this is an old one but I thought this might be of use to someone, seems to work OK so far.

Views.py

    #Queries model and appends id's to list
    try:
        qs = YourModel.objects.all()
        qslist = []

        for item in qs:
            qslist.append(item.id)

        newid = int(max(qslist) + 1)
    #If no entries are found, assume this is the first entry.
    except:
        newid = 1

However, Im not sure how well this will perform on large DBs.




回答6:


  q = Order.objects.values_list('id', flat=True).order_by('-id')[:1]
            if len(q):
                self.number = str(self.id) if self.id else str(int(q.get()) + 1)
            else:
                self.number = 1


来源:https://stackoverflow.com/questions/14234917/django-how-to-get-self-id-when-saving-a-new-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!