django storages aws s3 从模型记录中删除文件
django storages aws s3 delete file from model record
我的 django aws S3 解决方案基于 https://simpleisbetterthancomplex.com/tutorial/2017/08/01/how-to-setup-amazon-s3-in-a-django-project.html。
现在我正试图找到一种方法来删除模型中包含 S3 文件的行。我可以使用 .delete() 删除该行,但它不会在 S3 中删除。
如何使删除行在 S3 中也被删除?
下面是我的代码:
https://gitlab.com/firdausmah/railercom/blob/master/railercomapp/api.py
@api_view(['POST'])
def delete_employee(request):
# ----- YAML below for Swagger -----
"""
description: This API deletes employee
parameters:
- name: employee_id
type: integer
required: true
location: form
"""
employee_id = request.POST['employee_id']
employee = Employee.objects.get(id = employee_id)
logging.debug(f"API employee username {employee.username}")
employee.delete() <---------- here is where the delete row happens
return Response("Employee Deleted!", status=status.HTTP_200_OK)
https://gitlab.com/firdausmah/railercom/blob/master/railercomapp/models.py
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='employee')
company = models.ForeignKey(Company)
username = models.CharField(max_length=30, blank=False)
upload = models.FileField(blank=True) <--- S3 field
https://gitlab.com/firdausmah/railercom/blob/master/railercom/settings.py(AWS 设置)
AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = config('AWS_STORAGE_BUCKET_NAME')
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
DEFAULT_FILE_STORAGE = 'railercomapp.storage_backends.MediaStorage'
https://gitlab.com/firdausmah/railercom/blob/master/railercomapp/storage_backends.py
从 storages.backends.s3boto3 导入 S3Boto3Storage
class MediaStorage(S3Boto3Storage):
location = 'media/yy'
file_overwrite = False
您必须明确删除该文件。您可以编写 或在 delete_employee
函数中执行此操作。
employee.upload.delete(save=False) # delete file
employee.delete() # delete model instance
FileField.delete()
的文档对此进行了解释。
Note that when a model is deleted, related files are not deleted. If you need to cleanup orphaned files, you’ll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).
您还应确保在删除之前没有其他 FileField 引用完全相同的文件。
我用过这个:
import boto3
client = boto3.client('s3')
client.delete_object(Bucket='mybucketname', Key='myfile.whatever')
但我正在尝试找到一种方法来使用我的模型的 ImageFile 对象,或者可能使用我的存储的一些配置 class:
from storages.backends.s3boto3 import S3Boto3Storage
class MediaStorage(S3Boto3Storage):
location = 'media'
file_overwrite = True
致所有努力删除文件夹 django-storages 的兄弟们。
让我们考虑一个真实的案例。我有一个动态路径,每个文件都存储在文件夹中,我必须执行清理。
def get_upload_path(instance, filename):
return os.path.join(
'organizations',
'files',
str(instance.organization.pk),
str(instance.hash),
str(filename)
)
file = models.FileField(
upload_to=get_upload_path
)
我的问题是在清理过程中我无法删除带有 django-storages 的文件夹。 instance.file.name
会引发错误,因为您不能拥有带有 django-storages 的文件的绝对路径。
为了删除一个文件夹,你应该使用storage.delete()
,因为你不能有一个绝对路径,你不能直接删除一个文件夹(例如shutil.rmtree(...)
)。
我的 clean-up 实现有点复杂,但很可靠。就我而言,我使用了 pre_delete 信号并建议您也这样做。
from django.core.files.storage import get_storage_class
default_storage = get_storage_class()()
@receiver(pre_delete, sender=OrganizationFile)
def delete_has_folder(sender, instance, *args, **kwargs):
# get filename that will be equals to the relative path but not actually the filename
path = Path(instance.file.name)
# get a parent folder str
folder_path = str(path.parent)
# delete a file
instance.file.delete()
# delete a folder.
# shutil.rmtree(absolute_path) wouldn't work
# because instance.file.path will raise an error.
# hence the only way is to delete with a storage default_storage.delete
default_storage.delete(folder_path)
logger.info(f'Pre delete {instance}. Deleted the hash folder {folder_path}')
我的 django aws S3 解决方案基于 https://simpleisbetterthancomplex.com/tutorial/2017/08/01/how-to-setup-amazon-s3-in-a-django-project.html。
现在我正试图找到一种方法来删除模型中包含 S3 文件的行。我可以使用 .delete() 删除该行,但它不会在 S3 中删除。
如何使删除行在 S3 中也被删除?
下面是我的代码:
https://gitlab.com/firdausmah/railercom/blob/master/railercomapp/api.py
@api_view(['POST'])
def delete_employee(request):
# ----- YAML below for Swagger -----
"""
description: This API deletes employee
parameters:
- name: employee_id
type: integer
required: true
location: form
"""
employee_id = request.POST['employee_id']
employee = Employee.objects.get(id = employee_id)
logging.debug(f"API employee username {employee.username}")
employee.delete() <---------- here is where the delete row happens
return Response("Employee Deleted!", status=status.HTTP_200_OK)
https://gitlab.com/firdausmah/railercom/blob/master/railercomapp/models.py
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='employee')
company = models.ForeignKey(Company)
username = models.CharField(max_length=30, blank=False)
upload = models.FileField(blank=True) <--- S3 field
https://gitlab.com/firdausmah/railercom/blob/master/railercom/settings.py(AWS 设置)
AWS_ACCESS_KEY_ID = config('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = config('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = config('AWS_STORAGE_BUCKET_NAME')
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
DEFAULT_FILE_STORAGE = 'railercomapp.storage_backends.MediaStorage'
https://gitlab.com/firdausmah/railercom/blob/master/railercomapp/storage_backends.py 从 storages.backends.s3boto3 导入 S3Boto3Storage
class MediaStorage(S3Boto3Storage):
location = 'media/yy'
file_overwrite = False
您必须明确删除该文件。您可以编写 delete_employee
函数中执行此操作。
employee.upload.delete(save=False) # delete file
employee.delete() # delete model instance
FileField.delete()
的文档对此进行了解释。
Note that when a model is deleted, related files are not deleted. If you need to cleanup orphaned files, you’ll need to handle it yourself (for instance, with a custom management command that can be run manually or scheduled to run periodically via e.g. cron).
您还应确保在删除之前没有其他 FileField 引用完全相同的文件。
我用过这个:
import boto3
client = boto3.client('s3')
client.delete_object(Bucket='mybucketname', Key='myfile.whatever')
但我正在尝试找到一种方法来使用我的模型的 ImageFile 对象,或者可能使用我的存储的一些配置 class:
from storages.backends.s3boto3 import S3Boto3Storage
class MediaStorage(S3Boto3Storage):
location = 'media'
file_overwrite = True
致所有努力删除文件夹 django-storages 的兄弟们。
让我们考虑一个真实的案例。我有一个动态路径,每个文件都存储在文件夹中,我必须执行清理。
def get_upload_path(instance, filename):
return os.path.join(
'organizations',
'files',
str(instance.organization.pk),
str(instance.hash),
str(filename)
)
file = models.FileField(
upload_to=get_upload_path
)
我的问题是在清理过程中我无法删除带有 django-storages 的文件夹。 instance.file.name
会引发错误,因为您不能拥有带有 django-storages 的文件的绝对路径。
为了删除一个文件夹,你应该使用storage.delete()
,因为你不能有一个绝对路径,你不能直接删除一个文件夹(例如shutil.rmtree(...)
)。
我的 clean-up 实现有点复杂,但很可靠。就我而言,我使用了 pre_delete 信号并建议您也这样做。
from django.core.files.storage import get_storage_class
default_storage = get_storage_class()()
@receiver(pre_delete, sender=OrganizationFile)
def delete_has_folder(sender, instance, *args, **kwargs):
# get filename that will be equals to the relative path but not actually the filename
path = Path(instance.file.name)
# get a parent folder str
folder_path = str(path.parent)
# delete a file
instance.file.delete()
# delete a folder.
# shutil.rmtree(absolute_path) wouldn't work
# because instance.file.path will raise an error.
# hence the only way is to delete with a storage default_storage.delete
default_storage.delete(folder_path)
logger.info(f'Pre delete {instance}. Deleted the hash folder {folder_path}')