django - 无法使用 upload_to 动态创建路径
问题描述
在我的用户模型中,我有一个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
功能。当我删除它时,它会保存。如何修复此功能以使其在存在时覆盖?
解决方案
我认为您的问题 IDinstance.user.id
建议您尝试按如下方式导入用户,这可能会有所帮助
从 django.contrib.auth.models 导入用户 用户 = User.objects.get(id=user_id) def create_user_image_path(实例,image_name): image_name = str(user) + image_name[-4:] return 'users/{0}/avatars/{1}'.format(user.id, image_name)
但是 django 建议用户AUTH_USER_MODEL
实现
从 django.contrib.auth 导入 get_user_model 用户 = get_user_model()
更新
当您查看覆盖存储时,该变量name
会获取您要上传的图像的名称。您的file_path = os.path.dirname(name)
,您正在返回一个带有图像名称的文件夹。当 shutil.rmtree 绑定找到文件夹时,它返回错误它找不到路径。使用条件语句即if
或try except block
如下所示。
从 django.core.files.storage 导入 FileSystemStorage 从 django.conf 导入设置 从 django.core.files.storage 导入 default_storage 导入操作系统 类覆盖存储(文件系统存储): def get_available_name(self, name, max_length=None): """返回目标存储系统上可用的文件名,并且 可用于写入新内容。 见 http://djangosnippets.org/snippets/976/ 此文件存储解决了上传问题的覆盖。其他 建议的解决方案是覆盖模型上的保存方法 像这样(来自https://code.djangoproject.com/ticket/11663): def 保存(自我,*args,**kwargs): 尝试: 这 = MyModelName.objects.get(id=self.id) 如果 this.MyImageFieldName != self.MyImageFieldName: this.MyImageFieldName.delete() 除了:通过 super(MyModelName, self).save(*args, **kwargs) """ # 如果文件名已经存在,则删除它,就好像它是一个真正的文件系统一样 如果 self.exists(name): os.remove(os.path.join(settings.MEDIA_ROOT, name)) # default_storage.delete(os.path.join(settings.MEDIA_ROOT, name)) 返回名称
就像你的情况一样
类覆盖存储(文件系统存储): def get_available_name(self, name, *args, **kwargs): # 在添加新头像之前删除目录中的所有头像。 # (有时我们有不同的扩展名,所以不能按名字删除 如果 self.exists(name): file_path = os.path.dirname(name) shutil.rmtree(os.path.join(settings.MEDIA_ROOT, file_path)) 返回名称
推荐阅读
- typescript - Typescript:对类型化地图的动态分配
- node.js - npm init -y install 的 package.json 错误
- javascript - 如果属性为真,则从对象数组返回指定值的函数
- azure-ad-b2c - 登录重定向后 msal.js 2.0 tokenResponse null
- python - 如何操作列表中文本文件中的元素?
- javascript - 无法使用 ... 运算符或 Array.from() 或 slice(0),,Javascript/React 分隔处于状态的对象数组
- cmake - 如何设置 CMake 变量以包含目录
- algorithm - 合并排序 O(n log n) 每个级别的操作数
- r - 根据 2 列值合并行
- javascript - contenteditable 将焦点移动到行中的位置