【问题标题】:Overwriting Image with same name - Django覆盖具有相同名称的图像 - Django
【发布时间】:2019-08-31 09:36:26
【问题描述】:

通过我的项目,我让用户上传了个人资料图片。我将个人资料图片保存为 userID.jpg。如果他们上传新的头像,我想覆盖旧的头像,这样我就不会浪费存储空间。通过浏览之前关于 stackoverflow 的问题,我重新定义了 OverwriteStorage:

class OverwriteStorage(FileSystemStorage):
    def get_available_name(self, name, max_length=None):
        if self.exists(name):
             os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name

上传头像时,在我电脑的目录中可以看到图片已经被覆盖成功。图片保存路径为“media/profile/userID.jpg”。但是,当我在我的网站上显示图像时,它仍然是旧图片。 通过django站点,打开路径的时候看到的是老图,通过admin尝试更改时出现如下错误:

[WinError 32] The process cannot access the file because it is being used by another process: '\media\\profile\\userID.jpg'

我想我错误地覆盖了文件并且另一个实例仍然打开,为了解决它,我需要在覆盖之前正确关闭图像。我试过这样做,但没有成功。

【问题讨论】:

  • 可能是您浏览器的缓存。您是否尝试过使用 ctrl + shift + r 重新加载页面?

标签: python django overwrite


【解决方案1】:

receive and process via signals 很有趣。在某些情况下,它可能比OverwriteStorage(FileSystemStorage) 更方便。

但是,os.remove(filename) 在没有本地文件系统的情况下不安全/工作。我推荐使用Django File Storage API

from django.core.files.storage import default_storage

os.path.isfile(path)  # worse
default_storage.exists(path)  # better

os.remove(path)  # worse
default_storage.delete(path)  # better

【讨论】:

    【解决方案2】:

    我做了类似的事情,但我使用信号来更新和删除图像。

    首先,我在helpers.py中定义了图片的名称

    from django.conf import settings
    from datetime import datetime
    
    def upload_to_image_post(self, filename):
        """
        Stores the image in a specific path regards to date 
        and changes the name of the image with for the name of the post
        """    
        ext = filename.split('.')[-1]
        current_date = datetime.now()
    
        return '%s/posts/main/{year}/{month}/{day}/%s'.format(
            year=current_date.strftime('%Y'), month=current_date.strftime('%m'), 
            day=current_date.strftime('%d')) % (settings.MEDIA_ROOT, filename)
    

    所以,我在我的模型中调用了 def,特别是在图像的字段中

    from django.db import models
    from django.utils.text import slugify
    from .helpers import upload_to_image_post
    
    class Post(models.Model):
        """
        Store a simple Post entry. 
        """
        title = models.CharField('Title', max_length=200, help_text='Title of the post')
        body = models.TextField('Body', help_text='Enter the description of the post')   
        slug = models.SlugField('Slug', max_length=200, db_index=True, unique=True, help_text='Title in format of URL')        
        image_post = models.ImageField('Image', max_length=80, blank=True, upload_to=upload_to_image_post, help_text='Main image of the post')
    
        class Meta:
            verbose_name = 'Post'
            verbose_name_plural = 'Posts'
    

    最后,我定义了在模型中发生操作(更新或删除)之前更新或删除图像的信号。

    import os
    from django.db import models
    from django.dispatch import receiver
    from django.db.models.signals import pre_delete, pre_save
    from .models import Post
    
    @receiver(pre_delete, sender=Post)
    def post_delete(sender, instance, **kwargs):
        """
        Deleting the specific image of a Post after delete it
        """
        if instance.image_post:
            if os.path.isfile(instance.image_post.path):
                os.remove(instance.image_post.path)
    
    @receiver(pre_save, sender=Post)
    def post_update(sender, instance, **kwargs):
        """
        Replacing the specific image of a Post after update
        """
        if not instance.pk:
            return False
    
        if sender.objects.get(pk=instance.pk).image_post:
            old_image = sender.objects.get(pk=instance.pk).image_post
            new_image = instance.image_post
            if not old_image == new_image:
                if os.path.isfile(old_image.path):
                    os.remove(old_image.path)
        else:
            return False
    

    希望对你有所帮助。

    【讨论】:

    • 感谢它现在很好用;但是,我以前从未使用过信号,现在我的网站有点慢。这正常吗?将信号放在 models.py 中还是放在它自己的文件中更好?
    • 您是说您的网站因为信号而变慢吗?或者您的网站在那之前很慢?我用信号,性能不错。
    【解决方案3】:

    将旧的重命名为 userID-old.jpg,然后保存 userID.jpg。很快就不会有人注意到它的发生。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      • 2019-04-23
      • 2020-06-07
      • 1970-01-01
      相关资源
      最近更新 更多