2012-05-04 5 views
4

У меня есть модель с FileField:Не удается удалить файл FileField в post_delete

class FileModel(models.Model): 
    name = models.CharField(max_length=100) 
    description = models.CharField(max_length=200) 
    file = models.FileField(upload_to='myfiles') 

При удалении экземпляра модели с FileField, Джанго не автоматически удалять основной файл из файловой системы, так Я настроил сигнал, чтобы удалить базовый файл на post_delete:

def on_delete(sender, instance, **kwargs): 
    instance.file.delete() 

models.signals.post_delete.connect(on_delete, sender=FileModel) 

проблема заключается в том, когда я удалить FileModel объект (скажем, со страницы Джанго администратора) удаляет файл из файловой системы, но Безразлично» t удалить t он модель. Если я удалю его снова, он удалит модель, но затем вызывает исключение, когда пытается удалить файл из файловой системы, потому что файл не существует.

Когда я меняю удаление файла на pre_delete вместо post_delete, он ведет себя так, как должен. Единственное, что я могу подумать об этом, может привести к тому, что удаление файла из FileField автоматически сохранит модель, что приведет к ее воссозданию в post_delete.

Так что мой вопрос: почему вызов метода удаления FileField в post_delete предотвращает удаление модели?

ответ

5

Когда вы получаете доступ к атрибуту FileField, вы получаете экземпляр оболочки FieldFile. Теперь думает, что код его методы .delete ... (вырванный из django.db.models.fields.files)

def delete(self, save=True): 
     # Only close the file if it's already open, which we know by the 
     # presence of self._file 
     if hasattr(self, '_file'): 
      self.close() 
      del self.file 

     self.storage.delete(self.name) 

     self.name = None 
     setattr(self.instance, self.field.name, self.name) 

     # Delete the filesize cache 
     if hasattr(self, '_size'): 
      del self._size 
     self._committed = False 

     if save: 
      self.instance.save() 

Таким образом, вы были правы :)

Если я читаю его правильно, теперь вы можете снова подключить его к сигналу post_delete и передать save=False по методу удаления, и он должен работать.

И да, я просто искал его из-за вашего вопроса.

+0

Я ценю, что вы нашли время, чтобы исследовать это так тщательно. – dgel

1

Попробуйте django-cleanup, он удаляет старые файлы при удалении экземпляра модели и удаляет старые файлы при загрузке нового файла в FileField или ImageField.

+0

Это очень приятно, но в настоящее время на CDN фактически загружено много файлов, которые не хранятся локально. – NeoWang

Смежные вопросы