无法使用upload_to

时间:2019-06-23 00:08:05

标签: django django-models

在我的用户模型中,我有一个ImageField,其中包含一个upload_to属性,该属性将根据用户的ID动态创建图像路径。

avatar  = models.ImageField(storage=OverwriteStorage(), upload_to=create_user_image_path)

def create_user_image_path(instance, image_name):
    image_name = str(instance.user.id) + image_name[-4:]
    return 'users/{0}/avatars/{1}'.format(instance.user.id, image_name)

注册后,出现如下错误:

  

系统找不到指定的路径:   'C:\ Users \ xx \ PycharmProjects \ project_name \ media \ users \ 150 \ avatars'

如果我删除了ID和头像,只添加了图像名称(没有新目录),它将成功工作并写入图像。我曾尝试在此目录上执行chmod -R 777,但它仍然不能动态创建这些新目录。我不确定自己在做什么错。

编辑

class OverwriteStorage(FileSystemStorage):

    def get_available_name(self, name, *args, **kwargs):

        # Delete all avatars in directory before adding new avatar.
        # (Sometimes we have different extension names, so we can't delete by name
        file_path = os.path.dirname(name)
        shutil.rmtree(os.path.join(settings.MEDIA_ROOT, file_path))

        return name

我看到的问题是由于我的OverwriteStorage函数。当我删除它时,它保存。我该如何修复此功能,以使其覆盖(如果存在)?

1 个答案:

答案 0 :(得分:0)

我认为您的问题instance.user.id 我建议您尝试如下导入用户,这可能会有帮助

from django.contrib.auth.models import User
user = User.objects.get(id=user_id)

def create_user_image_path(instance, image_name):
    image_name = str(user) + image_name[-4:]
    return 'users/{0}/avatars/{1}'.format(user.id, image_name)

但是django向用户AUTH_USER_MODEL推荐 实施

from django.contrib.auth import get_user_model
User = get_user_model()

更新

当您查看替代存储时,变量name将获取您要上传的图像的名称。您的file_path = os.path.dirname(name)返回的是带有图片名称的文件夹。当shutil.rmtree绑定以查找文件夹时,它返回错误,找不到路径。使用条件语句,即iftry except block,如下所示。

from django.core.files.storage import FileSystemStorage
from django.conf import settings
from django.core.files.storage import default_storage
import os


class OverwriteStorage(FileSystemStorage):

    def get_available_name(self, name, max_length=None):
        """Returns a filename that's free on the target storage system, and
        available for new content to be written to.

        Found at http://djangosnippets.org/snippets/976/

        This file storage solves overwrite on upload problem. Another
        proposed solution was to override the save method on the model
        like so (from https://code.djangoproject.com/ticket/11663):

        def save(self, *args, **kwargs):
            try:
                this = MyModelName.objects.get(id=self.id)
                if this.MyImageFieldName != self.MyImageFieldName:
                    this.MyImageFieldName.delete()
            except: pass
            super(MyModelName, self).save(*args, **kwargs)
        """
        # If the filename already exists, remove it as if it was a true file system
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
            # default_storage.delete(os.path.join(settings.MEDIA_ROOT, name))
        return name

像您这样

class OverwriteStorage(FileSystemStorage):

    def get_available_name(self, name, *args, **kwargs):

        # Delete all avatars in directory before adding new avatar.
        # (Sometimes we have different extension names, so we can't delete by name
        if self.exists(name):
            file_path = os.path.dirname(name)
            shutil.rmtree(os.path.join(settings.MEDIA_ROOT, file_path))

        return name