覆盖同名图像 - Django [英] Overwriting Image with same name - Django

查看:70
本文介绍了覆盖同名图像 - Django的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Through my project, I have users upload a profile picture. I save the profile picture as userID.jpg. If they upload a new profile picture, I want to overwrite the old profile picture, so I don't waste storage space. By browsing previously asked questions on stackoverflow, I redefined the 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更改时,出现如下错误:

When I upload the profile picture, I can see in the directory on my computer that the picture has been overwritten successfully.The image is saved with the path "media/profile/userID.jpg". However, when I display the image on my site, it is still the old picture. Through the Django site, when I open the path, I see the old picture, and when I try to change it through the admin, I get the following error:

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

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

I guess I am incorrectly overwriting the file and another instance is still open, and to solve it, I need to properly close the image before overwriting. I tried doing that, but to to no success.

推荐答案

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

I did something similar but I used signals to update and delete images.

首先,我在 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,特别是在图像的字段中

SO, I called the def in my model, specifically in the image's field

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'

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

Finally, I defined signals to update or delete the image before the actions (update or delete) happen in the model.

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

我希望,这对您有所帮助.

I hope, this helped you.

这篇关于覆盖同名图像 - Django的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆