42

我的一个模型有问题。我正在上传一张图片,我想存储 id(数据库表中的 pk),但我需要知道 Django 何时可以访问 self.id.

模型.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']

问题出在url()方法上;我只能在更新对象时得到,在创建新对象时self.id我没有得到。self.id如何修改此模型以便self.id在创建新对象时获得?

使用当前代码,当我创建一个新对象时,我最终会得到一个 url,如:

MultimediaData/HelpAdImages/ItemKind/None/somefile.jpg

我需要有类似的东西:

MultimediaData/HelpAdImages/ItemKind/35/somefile.jpg

有什么线索吗?

4

6 回答 6

42

如果是新对象,需要先保存,再访问self.id,因为

"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."

查看 django 的文档https://docs.djangoproject.com/en/dev/ref/models/instances/

于 2013-01-09T13:36:58.313 回答
5

您可能需要将此文件/实例保存两次:

您可以在模型上使用 post_save 信号来查找 created 标志,并重新保存更新 url 的实例(并根据需要移动/重命名文件),因为实例现在将具有一个 ID。但是,请确保您仅以创建为条件执行此操作,否则您将不断循环保存:保存会启动一个保存后信号,它会执行保存,它会启动一个保存后信号......

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

于 2013-01-09T14:01:46.517 回答
2

实际上有一种方法可以解决这个问题。

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
于 2021-02-19T03:38:09.910 回答
1

注意:您需要models.AutoField(primary_key=True)设置属性,否则数据库将使用新的 id 更新,但 Django 将无法识别它。

models.AutoField(primary_key=True)
于 2016-10-27T18:26:19.713 回答
1

我知道这已经过时了,但是对于将来偶然发现此问题的任何人,这实际上是您现在在 Django 中的操作方式。

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

        url = "MultimediaData/HelpAdImages/ItemKind/%s/%s" % (instance.id, filename)
        return url
于 2019-08-25T18:34:43.347 回答
-5
  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
于 2015-05-08T09:53:39.027 回答