不要在重复文件上保存模型-Django 2

时间:2019-04-29 07:08:37

标签: python django

我正在尝试检查现有文件并将其覆盖,到目前为止,我已经能够使用自定义存储(看起来像这样)来进行

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()

问题是,尽管它删除并写入了相同的文件,但它还会创建一个具有相同现有路径的新模型条目,也就是说,如果我上载相同的文件两次,则在OS路径中会得到一个文件,但会有两个模型条目。这样的东西(这里有图片):

screenshot

所以我尝试将clean()self.file.storage.exists(self.file.name)一起使用False方法(根据this),但是即使那里有文件,我也以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 的形式存在。 / p>

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.')

如果我这样做的话,我想我明白了

"@@MAX_CONNECTIONS"

工作正常,但整个上传失败,甚至没有重写文件

1 个答案:

答案 0 :(得分:0)

条件 if instance.relative_path != 'null': 错误。它应该只是 if instance.relative_path:

当我尝试您的代码片段时,我感觉 user_directory_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.

    The "relative_path" path should not be start or ends with a slash ("/") but, can use slash inside

    /foo/ -> Not allowed
    /foo/bar -> Not allowed
    foo/bar/ -> Not allowed

    foo -> Allowed
    foo/bar -> Allowed
    foo/bar/foobar -> Allowed

    """

    if instance.relative_path:
        relative_path = instance.relative_path
        if relative_path[0] == '/':
            relative_path = relative_path[1:]
        if relative_path[:-1] == '/':
            relative_path = relative_path[:-1]

        return 'user_{0}/{1}/{2}'.format(instance.user.id, relative_path, filename)
    return 'user_{0}/{1}'.format(instance.user.id, filename)

现在进入我们的解决方案,我创建了一个示例视图来解决该问题。

from django.http.response import HttpResponse


def foo(request):
    if request.method == 'POST':
        create_data = {
            "user_id": request.user.pk,
            "file": request.FILES['file_name']
        }

        ds_temp = DataStorageModel(**create_data)
        path = user_directory_path(ds_temp, ds_temp.file.name)
        try:
            ds_existing = DataStorageModel.objects.get(file=path)
            ds_existing.file = create_data['file']
            ds_existing.save()
            return HttpResponse("instance modified")
        except DataStorageModel.DoesNotExist:
            ds_temp.save()
            return HttpResponse("new instance created")
    return HttpResponse("HTTP GET method")