Django应用对接IBM COS默认存储配置错误,无法写入数据库问题
问题根因
- django-storages的S3Boto3Storage默认读取AWS前缀的配置项,你使用了IBM前缀的键名,导致存储类无法获取到bucket名称,触发类型错误
- 视图中手动实现了上传逻辑,但没有绑定已上传文件的路径,Django仍会尝试对表单中的文件对象做二次上传处理
修复步骤
1. 修正settings.py配置
修改适配django-storages的配置规则,确保存储类能正确读取IBM COS的连接参数:
# IBM STORAGE CONFIG IBM_API_KEY_ID = '你的实际IBM_API_KEY_ID' IAM_SERVICE_ID = '你的实际IAM_SERVICE_ID' ENDPOINT = 'https://s3.us-east.cloud-object-storage.appdomain.cloud' IBM_AUTH_ENDPOINT = 'https://iam.bluemix.net/oidc/token' IBM_STORAGE_BUCKET_NAME = 'cloud-object-storage-3u-cos-standard-77w' # django-storages 适配配置 AWS_ACCESS_KEY_ID = IBM_API_KEY_ID AWS_SECRET_ACCESS_KEY = '' # IBM COS使用IAM认证,无需填写传统S3密钥 AWS_STORAGE_BUCKET_NAME = IBM_STORAGE_BUCKET_NAME AWS_S3_ENDPOINT_URL = ENDPOINT AWS_S3_REGION_NAME = 'us-east' AWS_S3_SIGNATURE_VERSION = 'oauth' AWS_S3_CONFIG = { 'ibm_api_key_id': IBM_API_KEY_ID, 'ibm_service_instance_id': IAM_SERVICE_ID, 'ibm_auth_endpoint': IBM_AUTH_ENDPOINT, } AWS_S3_FILE_OVERWRITE = False AWS_DEFAULT_ACL = None DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
2. 简化视图逻辑(推荐方案)
配置正确后,Django的FileField会自动调用默认存储将文件上传到IBM COS,同时自动把路径写入数据库,无需手动实现上传逻辑:
class upload_to_ibm_auto(LoginRequiredMixin, CreateView): model = Video context_object_name = 'Videos' form_class = VideoForm template_name = 'app_video/upload_to_ibm_auto.html' success_url = reverse_lazy('video_upload_local') def form_valid(self, form): form.instance.user = self.request.user # 如需自定义存储路径,可在此处修改form.instance.videofile的name属性 return super().form_valid(form)
3. 保留自定义上传逻辑的修复方案
如果需要自己控制上传流程,需手动绑定上传后的路径,避免Django二次处理文件:
def form_valid(self, form): cos_client = ibm_boto3.client(service_name='s3', ibm_api_key_id=settings.IBM_API_KEY_ID, ibm_service_instance_id=settings.IAM_SERVICE_ID, ibm_auth_endpoint=settings.IBM_AUTH_ENDPOINT, config=Config(signature_version='oauth'), endpoint_url=settings.ENDPOINT) upload_name = str(form.cleaned_data['videofilename']) # 直接读取表单文件流,无需存储到本地 file_content = form.cleaned_data['videofile'] userid = str(self.request.user.id) uploadtime = datetime.datetime.now().strftime('%Y%m%d%H%M%S') key = f"video/{userid}-{uploadtime}-{upload_name}" bucket = settings.IBM_STORAGE_BUCKET_NAME try: cos_client.upload_fileobj(Fileobj=file_content, Bucket=bucket, Key=key) except Exception as e: print(e) return super().form_invalid(form) # 手动绑定文件路径,清空表单文件对象 form.instance.videofile = key form.cleaned_data.pop('videofile') form.instance.user = self.request.user return super().form_valid(form)
内容的提问来源于stack exchange,提问作者jablok1
相关产品推荐
相关产品推荐

