Я использую последнюю версию django и django-storage. Я пытаюсь сохранить загруженное изображение и локально сгенерированное изображение с измененным размером. Когда я попытался сохранить изображение, я получил следующие ошибки:
Traceback:
File "/home/..proj/.env/lib/python3.6/site-packages/storages/backends/s3boto3.py" in _normalize_name
431. return safe_join(self.location, name)
File "/home/prism/Desktop/code/viper/.env/lib/python3.6/site-packages/storages/utils.py" in safe_join
75. raise ValueError('the joined path is located outside of the base path'
During handling of the above exception (the joined path is located outside of the base path component), another exception occurred:
File "/home/..proj/.env/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/home/..proj/.env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "/home/..proj/.env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/..proj/.env/lib/python3.6/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
21. return view_func(request, *args, **kwargs)
File "/home/..proj/admin/views.py" in product_update
578. image_model.image_thumbnail_index.save(a.name, File(a))
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/fields/files.py" in save
87. self.name = self.storage.save(name, content, max_length=self.field.max_length)
File "/home/..proj/.env/lib/python3.6/site-packages/django/core/files/storage.py" in save
51. name = self.get_available_name(name, max_length=max_length)
File "/home/..proj/.env/lib/python3.6/site-packages/storages/backends/s3boto3.py" in get_available_name
633. return super(S3Boto3Storage, self).get_available_name(name, max_length)
File "/home/..proj/.env/lib/python3.6/site-packages/django/core/files/storage.py" in get_available_name
75. while self.exists(name) or (max_length and len(name) > max_length):
File "/home/..proj/.env/lib/python3.6/site-packages/storages/backends/s3boto3.py" in exists
528. name = self._normalize_name(self._clean_name(name))
File "/home/..proj/.env/lib/python3.6/site-packages/storages/backends/s3boto3.py" in _normalize_name
434. name)
Exception Type: SuspiciousOperation at /admin/product/update/7/
Exception Value: Attempted access to '/home/..proj/convert/mqedpqL4tepvF4bT7wySMm/jo_308x412.webp' denied.
Модель изображения:
class ProductImage(models.Model):
image = models.ImageField(storage=ProductMediaStorage())
image_thumbnail_index = models.ImageField(storage=ProductMediaStorage())
image_quickview = models.ImageField(storage=MediaStorage())
Пользовательское хранилище S3:
class ProductMediaStorage(S3Boto3Storage):
location = settings.AWS_PRODUCT_LOCATION
default_acl = 'public-read'
file_overwrite = False
class MediaStorage(S3Boto3Storage):
location = settings.AWS_MEDIA_LOCATION
default_acl = 'public-read'
file_overwrite = False
Настройки:
AWS_ACCESS_KEY_ID = JSON_DATA['aws_access_key']
AWS_SECRET_ACCESS_KEY = JSON_DATA['aws_secret_key']
AWS_STORAGE_BUCKET_NAME = JSON_DATA['aws_bucket']
AWS_DEFAULT_ACL = None
AWS_IS_GZIPPED = True
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com'
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
AWS_PRODUCT_LOCATION = 'product'
AWS_MEDIA_LOCATION = 'media'
if not DEBUG:
STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{AWS_STATIC_LOCATION}/'
MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/media/'
STATICFILES_STORAGE = 'hiren.storage.StaticStorage'
DEFAULT_FILE_STORAGE = 'hiren.storage.DefaultStorage'
else:
MEDIA_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/media/'
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'collect_static')
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
DEFAULT_FILE_STORAGE = 'hiren.storage.DefaultStorage'
# uploaded file settings
FILE_UPLOAD_MAX_MEMORY_SIZE = 0
Views.py:
def product_update(request):
product_file = request.FILES.getlist('image', None)
if product_file:
for pro in product_file:
uuid = shortuuid.uuid()
directory = BASE_DIR + '/convert/' + uuid
os.mkdir(directory)
fs = FileSystemStorage(location=directory)
filename = fs.save(pro.name, pro)
image_sizes = ["308x412", "400x400" ]
files = resize_convert(filename, image_sizes, uuid)
# print(files) --> {"308x412": "/home/.../proj/img location"}
image_model = ProductImage(image=pro)
with open(files["308x412"], 'rb') as a, open(files["400x400"], 'rb') as b:
image_model.image_thumbnail_index.save(a.name, File(a))
image_model.image_quickview.save(b.name, File(b))
Из другого ответа stackoverflow Я добавил это решение во все хранилища клиентов:
class MediaStorage(S3Boto3Storage):
location = settings.AWS_MEDIA_LOCATION
default_acl = 'public-read'
file_overwrite = False
def _clean_name(self, name):
return name
def _normalize_name(self, name):
if not name.endswith('/'):
name += "/"
name += self.location
return name
Тогда я получил эту ошибку:
File "/home/..proj/.env/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
34. response = get_response(request)
File "/home/..proj/.env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "/home..proj/.env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/..proj/.env/lib/python3.6/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
21. return view_func(request, *args, **kwargs)
File "/home/..proj/admin/views.py" in product_update
578. image_model.image_thumbnail_index.save(a.name, File(a))
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/fields/files.py" in save
93. self.instance.save()
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/base.py" in save
741. force_update=force_update, update_fields=update_fields)
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/base.py" in save_base
779. force_update, using, update_fields,
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/base.py" in _save_table
870. result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/base.py" in _do_insert
908. using=using, raw=raw)
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
82. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/query.py" in _insert
1186. return query.get_compiler(using=using).execute_sql(return_id)
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in execute_sql
1334. for sql, params in self.as_sql():
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in as_sql
1278. for obj in self.query.objs
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in <listcomp>
1278. for obj in self.query.objs
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in <listcomp>
1277. [self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in pre_save_val
1228. return field.pre_save(obj, add=True)
File "/home/..proj/.env/lib/python3.6/site-packages/django/db/models/fields/files.py" in pre_save
288. file.save(file.name, file.file, save=False)
File "/home..proj/.env/lib/python3.6/site-packages/django/db/models/fields/files.py" in save
87. self.name = self.storage.save(name, content, max_length=self.field.max_length)
File "/home/..proj/.env/lib/python3.6/site-packages/django/core/files/storage.py" in save
52. return self._save(name, content)
File "/home/..proj/.env/lib/python3.6/site-packages/storages/backends/s3boto3.py" in _save
506. self._save_content(obj, content, parameters=parameters)
File "/home/..proj/.env/lib/python3.6/site-packages/storages/backends/s3boto3.py" in _save_content
521. obj.upload_fileobj(content, ExtraArgs=put_parameters)
File "/home/..proj/.env/lib/python3.6/site-packages/boto3/s3/inject.py" in object_upload_fileobj
621. ExtraArgs=ExtraArgs, Callback=Callback, Config=Config)
File "/home/..proj/.env/lib/python3.6/site-packages/boto3/s3/inject.py" in upload_fileobj
539. return future.result()
File "/home/..proj/.env/lib/python3.6/site-packages/s3transfer/futures.py" in result
106. return self._coordinator.result()
File "/home/..proj/.env/lib/python3.6/site-packages/s3transfer/futures.py" in result
265. raise self._exception
File "/home/..proj/.env/lib/python3.6/site-packages/s3transfer/tasks.py" in __call__
126. return self._execute_main(kwargs)
File "/home/..proj/.env/lib/python3.6/site-packages/s3transfer/tasks.py" in _execute_main
150. return_value = self._main(**kwargs)
File "/home/..proj/.env/lib/python3.6/site-packages/s3transfer/upload.py" in _main
692. client.put_object(Bucket=bucket, Key=key, Body=body, **extra_args)
File "/home/..proj/.env/lib/python3.6/site-packages/s3transfer/utils.py" in __exit__
525. self.close()
File "/home/..proj/.env/lib/python3.6/site-packages/s3transfer/utils.py" in close
508. self._fileobj.close()
File "/home/..proj/.env/lib/python3.6/site-packages/s3transfer/upload.py" in close
95. self._fileobj.close()
File "/home/..proj/.env/lib/python3.6/tempfile.py" in close
650. self._closer.close()
File "/home/..proj/.env/lib/python3.6/tempfile.py" in close
587. unlink(self.name)
Exception Type: FileNotFoundError at /admin/product/update/7/
Exception Value: [Errno 2] No such file or directory: '/tmp/tmpfnqmmwq8.upload.jpeg'