Джанго: загруженный файл заблокирован. Не могу переименовать - PullRequest
3 голосов
/ 12 марта 2009

Я пытаюсь переименовать файл после его загрузки в метод сохранения модели. Я переименовываю файл в комбинацию первичного ключа и фрагмента заголовка файла.

У меня это работает при первой загрузке файла, при загрузке нового файла и при отсутствии изменений в файле или заголовке файла.

Однако, когда заголовок файла изменяется, и система пытается переименовать старый файл в новый путь, я получаю следующую ошибку:

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

Полагаю, вопрос в том, знает ли кто-нибудь, как я могу переименовать загруженный файл, если загруженный файл не загружается повторно? Это единственный раз, когда кажется, что он заблокирован / используется.


Обновление:

Подход Тайлера работает, за исключением того, что при загрузке нового файла первичный ключ недоступен и его методика ниже выдает ошибку.

if not instance.pk:
    instance.save()

Ошибка:

maximum recursion depth exceeded while calling a Python object

Есть ли способ получить первичный ключ?

Ответы [ 3 ]

5 голосов
/ 12 марта 2009

Думаю, вам стоит присмотреться к полю upload_to. Возможно, это будет проще, чем возиться с переименованием во время сохранения.

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

Это также может быть вызываемым, например функция, которая будет вызываться получить путь загрузки, включая имя файла. Этот вызываемый должен уметь принять два аргумента и вернуть Путь в стиле Unix (с косой чертой) быть переданным на хранение система. Два аргумента, которые будут пройдено:

3 голосов
/ 13 марта 2009

Мой другой ответ устарел, используйте вместо этого:

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 может быть вызвано , и в этом случае ожидается возвращение имени файла, включая путь (относительно MEDIA_ROOT).

0 голосов
/ 13 марта 2009

После загрузки все, что у вас есть, это объект изображения в памяти, верно?

Вы можете сохранить этот объект самостоятельно в выбранной вами папке, а затем вручную отредактировать запись в базе данных.

Вы бы обошли весь Django ORM, и я бы не стал этим заниматься, если бы я не смог найти более подходящий способ Django.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...