【问题标题】:Delay saving a Django ImageField until after the object has a pk延迟保存 Django ImageField 直到对象有 pk
【发布时间】:2021-08-26 14:55:26
【问题描述】:

我有一个 Book 的 Django 模型,它有一个 slug 字段,该字段是基于其 pk 的哈希值。它还有一个thumbnail,它被保存到包含slug的路径中。

在管理员中,如果我在没有缩略图的情况下创建并保存图书,然后然后添加缩略图并再次保存图书,这样可以:缩略图保存到 /media/books/<slug>/foo.jpg

但是,如果我使用缩略图创建书,并保存它,缩略图会在slug 生成之前保存,因此它会保存到/media/books/foo.jpg。这是因为文件是在模型之前保存的。

我想总是在缩略图的路径中包含slug,但我不知道如何延迟保存缩略图,直到生成slug。有什么想法吗?

from django.db import models
from hashes import Hashids


def upload_path(instance, filename):
    return "/".join([books, instance.slug, filename])


class Book(models.Model):
    title = models.CharField(null=False, blank=False, max_length=255)
    slug = models.SlugField(max_length=10, null=False, blank=True)

    thumbnail = models.ImageField(
        upload_to=upload_path, null=False, blank=True, default=""
    )

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

        if not self.slug:
            # Now we have a pk, generate a slug if it doesn't have one.
            hashids = Hashids(salt="my salt", min_length=5)
            self.slug = hashids.encode(self.pk)
            kwargs["force_insert"] = False
            self.save(*args, **kwargs)

(我知道哈希不安全;有人可以从slug 中找出pk。对于这个用例我很好。)

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    我认为答案是在生成 pk 后将文件移动到正确的位置。型号:

    import os
    from django.conf import settings
    from django.db import models
    from hashes import Hashids
    
    def upload_path(instance, filename):
        return "/".join([books, instance.slug, filename])
    
    class Book(models.Model):
        # field definitions here
    
        def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
    
            if not self.slug:
                # Now we have a pk, generate a slug if it doesn't have one.
                hashids = Hashids(salt="my salt", min_length=5)
                self.slug = hashids.encode(self.pk)
    
            if self.thumbnail and f"/{self.slug}/" not in self.thumbnail.path:
                # Move the thumbnail to correct location.
                initial_path = self.thumbnail.path
                filename = os.path.basename(initial_path)
                new_name = upload_path(self, filename)
                new_path = os.path.join(settings.MEDIA_ROOT, new_name)
    
                if not os.path.exists(os.path.dirname(new_path)):
                    # Make the slug directory if it doesn't exist.
                    os.makedirs(os.path.dirname(new_path))
    
                os.rename(initial_path, new_path)
    
                self.thumbnail.name = new_name
                kwargs["force_insert"] = False
                super().save(*args, **kwargs)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多