Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/349.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 不要在重复文件上保存模型-Django 2_Python_Django - Fatal编程技术网

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

Python 不要在重复文件上保存模型-Django 2,python,django,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(se

我正在尝试检查一个现有文件并覆盖它,到目前为止,我可以使用一个自定义存储来做这件事,它看起来像这样

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)
(根据)结合使用,但得到的存在形式为
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
如果我这样做,我想我得到了:

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

它可以工作,但整个上传都失败了,甚至没有重写文件的条件,
if instance.relative_path!='空“:
错误。如果instance.relative路径为:

当我尝试你的代码片段时,我觉得
user\u directory\u 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")

如果instance.relative\u path!='空“:错误。如果instance.relative路径为:

当我尝试你的代码片段时,我觉得
user\u directory\u 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")

你试过了吗??]我应该在哪里使用它?在
clean
save()
中,如果我在另存为
DataStorageModel.objects.update_或_create(user=self.user,file=self.file)
中使用它,我会得到
RecursionError:调用Python对象时超过最大递归深度
如果我使用
self.objects.update_或_create(user=self.user,file=self.file)
I get manager无法联系到。您应该提供
默认值
tooodid您可以尝试吗???]我应该在哪里使用它?在
clean
save()
中,如果我在另存为
DataStorageModel.objects.update_或_create(user=self.user,file=self.file)
中使用它,我会得到
RecursionError:调用Python对象时超过最大递归深度
如果我使用
self.objects.update_或_create(user=self.user,file=self.file)
无法联系到我的get manager。您应该提供
默认值
Tootrue,我忘记了这应该在视图中而不是模型中完成
user\u directory\u path
您编写的内容为每个文件创建一个文件夹,即-
temp.txt
它创建
temp.txt/temp.txt
我的逻辑是,如果存在相对路径,它将在用户目录下创建子目录。如果相对路径不存在,则文件将保存到用户目录中。如果我正在上载文件夹,我将分别获得相对路径
something/something text.txt
和文件名,(我正在使用uppy.js)上载文件夹?(文件夹还是文件?)
user\u directory\u path
您编写的内容为每个文件创建一个文件夹,即-
temp.txt
它创建
temp.txt/temp.txt
我的逻辑是,如果存在相对路径,它将在用户目录下创建子目录。如果相对路径不存在,则文件将保存到用户目录中。如果我正在上载文件夹,我将分别获得相对路径
something/something text.txt
和文件名,(我正在使用uppy.js)上载文件夹?(文件夹还是文件?)。