gpt4 book ai didi

python - Django模型ImageField每次上传文件时都会创建一个嵌套文件夹

转载 作者:行者123 更新时间:2023-12-02 02:30:51 24 4
gpt4 key购买 nike

我确信我错过了一些愚蠢的东西,但我很困惑。

我的个人资料有以下模型:

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(
default="default.jpg",
upload_to="profile_pics/",
validators=[FileExtensionValidator(["jpeg", "jpg", "png"])],
)

def __str__(self):
return f"{self.user.username} Profile"

def save(self, *args, **kwargs):
if self.image:
self.image = make_thumbnail(self.image, size=(200, 200))
super().save(*args, **kwargs)
else:
super().save(*args, **kwargs)

但是 profile_pics 文件夹继续嵌套,所以我的文件夹结构开始如下所示:

enter image description here

我相信,settings.py 中的变量看起来很正常:

BASE_DIR = Path(__file__).resolve().parent.parent
MEDIA_ROOT = os.path.join(BASE_DIR, "media")
MEDIA_URL = "/media/"

我相信嵌套文件夹的问题源于我的 Profile 类中的保存方法,特别是:

def save(self, *args, **kwargs):
if self.image:
self.image = make_thumbnail(self.image, size=(200, 200))
super().save(*args, **kwargs)
else:
super().save(*args, **kwargs)

由我的信号触发:

@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()

为什么要嵌套文件夹?

我在博客文章图像上使用相同的保存方法,并且文件夹不嵌套。

我错过了什么?

P.S.:如果有帮助的话,这是 make_thumbnail:

from io import BytesIO
from django.core.files import File
from PIL import Image

def make_thumbnail(image, size=(600, 600)):
im = Image.open(image)
if im.format == "JPEG":
im.convert("RGB")
im.thumbnail(size)
thumb_io = BytesIO()
im.save(thumb_io, "JPEG", quality=85)
image = File(thumb_io, name=image.name)
else:
im.convert("RGBA")
im.thumbnail(size)
thumb_io = BytesIO()
im.save(thumb_io, "PNG", quality=85)
image = File(thumb_io, name=image.name)
return image

编辑:

我偶然发现了这个解决方案,它避免了主要问题,尽管我不确定它的效率如何:

def save(self, *args, **kwargs):
if self.image:
self.image = make_thumbnail(self.image, size=(200, 200))
image_name = self.image.name
ext = image_name.split(".")[-1]
filename = "%s.%s" % (uuid.uuid4(), ext)
clean_name = os.path.join("", filename)
self.image.name = clean_name
super().save(*args, **kwargs)
else:
super().save(*args, **kwargs)

最佳答案

我打赌你想调整this post满足您的需求。作者没有问题,因为他“没有重复使用他保存的内容”。

self.image 具有属性name。当您检查它是否存在时(if self.image),它已经有了一个名称。然后,每次更新时,您都会不断调整已调整大小的图像的大小,这也会不断将现有的图像名称添加到 upload_to 路径中,因此每次迭代都会执行 upload_to + self.图像.名称。但 self.image.name 已经是 /profile_pics/...

要解决此问题,只需添加 is_resized 列即可。

class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(
default="default.jpg",
upload_to="profile_pics/",
validators=[FileExtensionValidator(["jpeg", "jpg", "png"])],
)
is_resized = models.BooleanField(default=False)

def __str__(self):
return f"{self.user.username} Profile"

def save(self, *args, **kwargs):
if self.image and not self.is_resized:
self.is_resized = True
self.image = make_thumbnail(self.image, size=(200, 200))
super().save(*args, **kwargs)

每当图像发生变化时,请记住将 is_resized 设置为 False

旁注,信号通常是一种不好的做法。我也不认为让两个信号作用于同一个对象是一个好主意。

如果您确实需要它们,请考虑用单个信号替换它们。

@receiver(post_save, sender=User)
def handle_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
else:
instance.profile.save()

不过,如果您在 View 中调整缩略图的大小,效果会更好。

关于python - Django模型ImageField每次上传文件时都会创建一个嵌套文件夹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65060763/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com