我有一个将 CSV 导出到 S3 的函数:
def export_csv(report_id):
# MyModel has a JsonField called `json_data`
items = MyModel.objects.all()
data = [x.json_data for x in items]
df = pd.DataFrame(data)
file_buffer = io.StringIO()
# QUOTE_ALL to avoid separators from throwing off columns
df.to_csv(
file_buffer,
index=False,
encoding='utf-8',
quotechar='"',
quoting=csv.QUOTE_ALL,
)
report.report_data_file.save(
"data.csv", ContentFile(file_buffer.getvalue())
)
我正在使用以下字段字段:
class PrivateMediaStorage(S3Boto3Storage):
location = settings.AWS_PRIVATE_MEDIA_LOCATION
default_acl = 'private'
file_overwrite = False
custom_domain = False
class Report(BaseModel):
...
report_data_file = models.FileField(
storage=PrivateMediaStorage(),
upload_to=export_location,
null=True,
blank=True,
)
这在我的本地环境中运行良好,其中PrivateMediaStorage
定义为
class PrivateMediaStorage(FileSystemStorage):
pass
在我使用django-storages
的生产环境中,运行此函数时出现以下错误:
TypeError: a bytes-like object is required, not 'str'
这是完整的回溯:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/celery/app/trace.py", line 385, in trace_task
R = retval = fun(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/celery/app/trace.py", line 650, in __protected_call__
return self.run(*args, **kwargs)
File "/code/apps/benchmark/tasks.py", line 45, in export_report_data_task
report.export_json_data()
File "/code/apps/benchmark/models.py", line 470, in export_json_data
export_csv(self.id)
File "/code/apps/benchmark/utils/export_report_data.py", line 46, in export_csv
report.report_data_file.save(
File "/usr/local/lib/python3.8/site-packages/django/db/models/fields/files.py", line 87, in save
self.name = self.storage.save(name, content, max_length=self.field.max_length)
File "/usr/local/lib/python3.8/site-packages/django/core/files/storage.py", line 52, in save
return self._save(name, content)
File "/usr/local/lib/python3.8/site-packages/storages/backends/s3boto3.py", line 495, in _save
self._save_content(obj, content, parameters=parameters)
File "/usr/local/lib/python3.8/site-packages/storages/backends/s3boto3.py", line 510, in _save_content
obj.upload_fileobj(content, ExtraArgs=put_parameters)
File "/usr/local/lib/python3.8/site-packages/boto3/s3/inject.py", line 619, in object_upload_fileobj
return self.meta.client.upload_fileobj(
File "/usr/local/lib/python3.8/site-packages/boto3/s3/inject.py", line 539, in upload_fileobj
return future.result()
File "/usr/local/lib/python3.8/site-packages/s3transfer/futures.py", line 106, in result
return self._coordinator.result()
File "/usr/local/lib/python3.8/site-packages/s3transfer/futures.py", line 265, in result
raise self._exception
File "/usr/local/lib/python3.8/site-packages/s3transfer/tasks.py", line 255, in _main
self._submit(transfer_future=transfer_future, **kwargs)
File "/usr/local/lib/python3.8/site-packages/s3transfer/upload.py", line 558, in _submit
self._submit_multipart_request(
File "/usr/local/lib/python3.8/site-packages/s3transfer/upload.py", line 622, in _submit_multipart_request
for part_number, fileobj in part_iterator:
File "/usr/local/lib/python3.8/site-packages/s3transfer/upload.py", line 270, in yield_upload_part_bodies
fileobj, full_size = self._get_upload_part_fileobj_with_full_size(
File "/usr/local/lib/python3.8/site-packages/s3transfer/upload.py", line 343, in _get_upload_part_fileobj_with_full_size
return six.BytesIO(data), len(data)
TypeError: a bytes-like object is required, not 'str'