Django:上传文件已锁定。无法重命名

时间:2009-03-12 02:14:52

标签: python django file-io

我试图在文件的上传保存方法中重命名文件。我正在将文件重命名为文件主键和文件标题的组合。

首次上传文件,上传新文件以及文件或文件标题没有任何更改时,我都能使用它。

但是,当文件的标题发生更改,并且系统尝试将旧文件重命名为新路径时,我收到以下错误:

WindowsError at /admin/main/file/1/
(32, 'The process cannot access the file because it is being used by another process')

我真的不知道怎么解决这个问题。我试过把文件复制到新路径。这有效,但我不知道我可以删除旧版本。

缩短模型:

class File(models.Model):
    nzb = models.FileField(upload_to='files/')
    name = models.CharField(max_length=256)
    name_slug = models.CharField(max_length=256, blank=True, null=True, editable=False)

    def save(self):
        # Create the name slug.
        self.name_slug = re.sub('[^a-zA-Z0-9]', '-', self.name).strip('-').lower()
        self.name_slug = re.sub('[-]+', '-', self.name_slug)

        # Need the primary key for naming the file.
        super(File, self).save()

        # Create the system paths we need.
        orignal_nzb = u'%(1)s%(2)s' % {'1': settings.MEDIA_ROOT, '2': self.nzb}
        renamed_nzb = u'%(1)sfiles/%(2)s_%(3)s.nzb' % {'1': settings.MEDIA_ROOT, '2': self.pk, '3': self.name_slug}

        # Rename the file.
        if orignal_nzb not in renamed_nzb:
            if os.path.isfile(renamed_nzb):
                os.remove(renamed_nzb)

            # Fails when name is updated.
            os.rename(orignal_nzb, renamed_nzb)

        self.nzb = 'files/%(1)s_%(2)s.nzb' % {'1': self.pk, '2': self.name_slug}

        super(File, self).save()

我想问的是,当上传的文件没有重新上传时,是否有人知道如何重命名上传的文件?这是它似乎被锁定/正在使用的唯一时间。


更新

Tyler的方法正在运行,除非上传新文件时主键不可用,并且下面的技巧会引发错误。

if not instance.pk:
    instance.save()

错误:

maximum recursion depth exceeded while calling a Python object

有没有办法获取主键?

3 个答案:

答案 0 :(得分:5)

我认为你应该更仔细地看看upload_to字段。这可能比在保存期间重命名更简单。

http://docs.djangoproject.com/en/dev/ref/models/fields/#filefield

  

这也可以是可调用的,例如a   函数,将被调用   获取上传路径,包括   文件名。这个可调用必须能够   接受两个参数,并返回一个   Unix风格的路径(带正斜杠)   被传递到存储器   系统。这两个论点将是   传递的是:

答案 1 :(得分:3)

我的其他答案已被弃用,请改用:

class File(models.Model):
    nzb = models.FileField(upload_to=get_filename)
    ...
    def get_filename(instance, filename):
        if not instance.pk:
            instance.save()
        # Create the name slug.
        name_slug = re.sub('[^a-zA-Z0-9]', '-', instance.name).strip('-').lower()
        name_slug = re.sub('[-]+', '-', name_slug)

        filename = u'filess/%(2)s_%(3)s.nzb' % {'2': instance.pk, '3': name_slug}

        return filename

从1.0开始,upload_to can be callable,在这种情况下,它应该返回文件名,包括路径(相对于MEDIA_ROOT)。

答案 2 :(得分:0)

上传后,您拥有的只是内存中的图像对象,对吗?

您可以将此对象自己保存在您选择的文件夹中,然后手动编辑数据库条目。

你将绕过整个Django ORM,除非我找不到更多的Django方式,否则我不会这样做。