jschneier / django-storages

https://django-storages.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
2.77k stars 868 forks source link

s3boto3 from django-storages>1.6.6 doesn't compatible with sorl-thumbnail #619

Closed lampslave closed 7 months ago

lampslave commented 6 years ago

Sorl-thumbnail has fallback {% empty %} template tag which used if original file doesn't exist. With django-storages>1.6.6 sorl uses this fallback for all new files (i.e. if file exists but thumbnail doesn't exist) when storage class based on s3boto3. Tested with Django 1.11 on aws lambda.

sww314 commented 6 years ago

@lampslave did this setup work on an earlier version of django-storages? The storages API is fairly low level. It only copies the file to an external server and will check to see if the file exists.

My guess is this is an issue with sorl-thumbnail not using the storage api, but assuming local file storage. Personally, I use django-imagekit for thumbnail creation and it works with django-storages.

lampslave commented 6 years ago

@sww314 yes, all works with 1.6.6 (even with 16a02b5aa4898bed3b2be14cf905aa83957f0e98, so it was broken somewhere between 16a02b5aa4898bed3b2be14cf905aa83957f0e98 and 1.7).

lampslave commented 5 years ago
Traceback: 

File "/var/task/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/var/task/django/core/handlers/base.py" in _get_response
  217.                 response = self.process_exception_by_middleware(e, request)

File "/var/task/django/core/handlers/base.py" in _get_response
  215.                 response = response.render()

File "/var/task/django/template/response.py" in render
  107.             self.content = self.rendered_content

File "/var/task/django/template/response.py" in rendered_content
  84.         content = template.render(context, self._request)

File "/var/task/django/template/backends/django.py" in render
  66.             return self.template.render(context)

File "/var/task/django/template/base.py" in render
  207.                     return self._render(context)

File "/var/task/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/var/task/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/var/task/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/var/task/django/template/loader_tags.py" in render
  177.             return compiled_parent._render(context)

File "/var/task/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/var/task/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/var/task/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/var/task/django/template/loader_tags.py" in render
  72.                 result = block.nodelist.render(context)

File "/var/task/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/var/task/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/var/task/django/template/defaulttags.py" in render
  322.                 return nodelist.render(context)

File "/var/task/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)

File "/var/task/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/var/task/django/template/defaulttags.py" in render
  216.                     nodelist.append(node.render_annotated(context))

File "/var/task/django/template/base.py" in render_annotated
  957.             return self.render(context)

File "/var/task/sorl/thumbnail/templatetags/thumbnail.py" in render
  60.             return self._render(context)

File "/var/task/sorl/thumbnail/templatetags/thumbnail.py" in _render
  138.         thumbnail = get_thumbnail(file_, geometry, **options)

File "/var/task/sorl/thumbnail/shortcuts.py" in get_thumbnail
  8.     return default.backend.get_thumbnail(file_, geometry_string, **options)

File "/var/task/sorl/thumbnail/base.py" in get_thumbnail
  112.                 source_image = default.engine.get_image(source)

File "/var/task/sorl/thumbnail/engines/pil_engine.py" in get_image
  50.         buffer = BufferIO(source.read())

File "/var/task/sorl/thumbnail/images.py" in read
  162.         f = self.storage.open(self.name)

File "/var/task/django/core/files/storage.py" in open
  38.         return self._open(name, mode)

File "/var/task/storages/backends/s3boto3.py" in _open
  464.             f = S3Boto3StorageFile(name, mode, self)

File "/var/task/storages/backends/s3boto3.py" in __init__
  72.             self.obj.load()

File "/var/task/boto3/resources/factory.py" in do_action
  505.                 response = action(self, *args, **kwargs)

File "/var/task/boto3/resources/action.py" in __call__
  83.         response = getattr(parent.meta.client, operation_name)(**params)

File "/var/task/botocore/client.py" in _api_call
  320.             return self._make_api_call(operation_name, kwargs)

File "/var/task/botocore/client.py" in _make_api_call
  624.             raise error_class(parsed_response, operation_name)

Exception Type: ClientError at /
Exception Value: An error occurred (400) when calling the HeadObject operation: Bad Request