我正在尝试检查现有文件并覆盖它,到目前为止我可以使用自定义存储来完成此操作,如下所示
from django.core.files.storage import FileSystemStorage
class DuplicateFileStorage(FileSystemStorage):
def get_available_name(self, name, max_length=None):
return name
def _save(self, name, content):
if self.exists(name):
self.delete(name)
return super(DuplicateFileStorage, self)._save(name, content)
上面的类检查现有文件并将其删除。
它所关注的模型是:
class DataStorageModel(models.Model):
user = models.ForeignKey(User, related_name='data_storage', on_delete=models.CASCADE)
file_name = models.CharField(blank=True, max_length=200, help_text="File Name")
file = models.FileField(blank=True, null=True, upload_to=user_directory_path, storage=DuplicateFileStorage())
relative_path = models.CharField(blank=True, max_length=200, help_text="Relative Path if folder else null")
def delete(self, using=None, keep_parents=False):
self.file.delete()
return super(DataStorageModel, self).delete()
问题是,虽然它删除并写入相同的文件,但它也会创建一个具有相同现有路径的新模型条目,也就是说,如果我上传相同的文件两次,我会在操作系统路径中得到一个文件,但会得到两个模型条目。像这样的东西(这里有一张图片):
所以我尝试使用clean()
方法与self.file.storage.exists(self.file.name)
(根据this https://stackoverflow.com/questions/50606068/how-to-ensure-file-exists-in-django-project)但我得到的存在是False
,即使那里有一个文件。
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
self.full_clean()
return super(DataStorageModel, self).save()
def clean(self):
print(self.file.storage.exists(self.file.name)) # <--- False
所以我的问题是,我应该如何检查是否存在重复文件,覆盖该文件但不创建新记录?
Edit
我忘记输入user_director_path()
:
def user_directory_path(instance, filename):
"""
If relative path is not ``null`` the files will be stored as is else it will be
stored to the root directory.
"""
if instance.relative_path != 'null':
return 'user_{0}{1}'.format(instance.user.id, instance.relative_path)
return 'user_{0}/{1}'.format(instance.user.id, filename)
我想如果我这样做我就明白了:
def clean_fields(self, exclude=None):
if self.file.storage.exists('user_{0}{1}'.format(self.user.id, self.relative_path)):
raise ValidationError('File already exists.')
它可以工作,但整个上传失败,甚至无法重写文件