python - django-storages dropbox.stone_validators.ValidationError
问题描述
我正在尝试将保管箱用作媒体存储。我正在尝试通过 django-storages 来实现。
设置.py
DEFAULT_FILE_STORAGE = 'storages.backends.dropbox.DropBoxStorage'
DROPBOX_OAUTH2_TOKEN = 'token'
DROPBOX_ROOT_PATH = '/media/'
模型.py
logo = models.ImageField(upload_to=r'logo/%Y/%m/')
image = models.ImageField(upload_to=r'photos/%Y/%m/',
help_text='Image size: Width=1080 pixel. Height=1920 pixel',)
错误
请求方法:| 邮政
请求网址:| http://127.0.0.1:8000/add
Django 版本:| 2.1.8
异常类型:| 验证错误
异常值:| 'D:/media/10506738_10150004552801856_220367501106153455_o.jpg' 不匹配模式 '(/(.|[\r\n])|id:.)|(rev:[0-9a-f]{9,})|( ns:[0-9]+(/.*)?)'
安慰
dropbox.stone_validators.ValidationError: 'D:/media/10506738_10150004552801856_220367501106153455_o.jpg' 不匹配模式 '(/(.|[\r\n])|id:.)|(rev:[0-9a-f]{ 9,})|(ns:[0-9]+(/.*)?)'
我无法弄清楚为什么会发生此错误?
解决方案
关于为什么会发生此错误,其他答案并不完全正确。保管箱存储对象后端使用 django 实用程序(django.utils._os.safe_join)
来验证目标操作系统的文件名。请参阅此处的代码
即使您传递了upload_to
提供 unix 样式路径(类似于 /save/path)的参数,django 实用程序也会确保该保存路径的根与操作系统的基本路径匹配:(。Dropbox SDK 不喜欢驱动器前缀为所需的保存路径(AKA C:/path/file.name 不是 dropbox 的有效保存目录)。
要在 Windows 上进行这项工作,请确保您做几件事
首先,像这样修改存储后端_full_path方法(或创建自己的子类)。
def _full_path(self, name):
if name == '/':
name = ''
print('Root path in dropbox.storage : ', self.root_path)
# If the machine is windows do not append the drive letter to file path
if os.name == 'nt':
final_path = os.path.join(self.root_path, name).replace('\\', '/')
# Separator on linux system
sep = '//'
base_path = self.root_path
if (not os.path.normcase(final_path).startswith(os.path.normcase(base_path + sep)) and
os.path.normcase(final_path) != os.path.normcase(base_path) and
os.path.dirname(os.path.normcase(base_path)) != os.path.normcase(base_path)):
raise SuspiciousFileOperation(
'The joined path ({}) is located outside of the base path '
'component ({})'.format(final_path, base_path))
# TODO Testing
print('Full file path in storage.dropbox._full_path : ', final_path)
return final_path
else:
return safe_join(self.root_path, name).replace('\\', '/')
其次,确保将内容和名称传递给模型 FileField。当我没有明确传递文件内容和名称时遇到麻烦(关于保留文件名的上传文件上下文?)。我像这样重新实现了我的模型保存方法
def save(self, *args, **kwargs):
# Save file
## Save raw entry from user ##
# Extract files contents
try:
uploaded_raw_entry = kwargs['upload_raw_entry']
except KeyError:
raise UploadError(('No file was passed from the admin interface. ' +
'Make sure a ContentFile was passed when calling this models save method'))
# Test raw_directory_path TODO Remove after testing
print('Raw entry name from model.save : ', raw_directory_path(self, uploaded_raw_entry.name))
with uploaded_raw_entry.open(mode='rb') as f:
raw_entry_content = f.read()
raw_entry_file = ContentFile(content=raw_entry_content.encode('utf-8'),
name=raw_directory_path(self, uploaded_raw_entry.name))
# Save the content file into a model field
raw_entry_file.open(mode='rb')
self.raw_entry.save(raw_entry_file.name, raw_entry_file, save=False)
raw_entry_file.close()
这绝对可以在 Windows 上使用,但需要额外的步骤 :)
推荐阅读
- c++ - 如何修复 curl 链接器错误
- javascript - 格式化和解析输入值
- reactjs - TypeScript 错误类型“{}”缺少类型中的以下属性
- laravel - 在 laravel 中将当前类别设置为活动
- python - 为什么我的函数在 python 中没有打印
- reactjs - useFormState 必须在 a 内部使用
- matlab - Bootstrp在MATLAB中使用矩阵而不是向量?
- file - 将 Windows 文件移动到 Ubuntu 20 的最佳方法是什么?
- bash - 嗨,我必须在 bash 中创建一个名为 "\?$*'ChouMi'*$?\" 的文件
- c# - 网络核心身份锁定不锁定用户帐户