I'm trying to rename a file after it's uploaded in the model's save method. I'm renaming the file to a combination the files primary key and a slug of the file title.
I have it working when a file is first uploaded, when a new file is uploaded, and when there are no changes to the file or file title.
However, when the title of the file is changed, and the system tries to rename the old file to the new path I get the following error:
WindowsError at /admin/main/file/1/
(32, 'The process cannot access the file because it is being used by another process')
I don't really know how to get around this. I've tried just coping the file to the new path. This works, but I don't know I can delete the old version.
Shortened Model:
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()
I suppose the question is, does anyone know how I can rename an uploaded file when the uploaded file isn't be re-uploaded? That's the only time it appears to be locked/in-use.
Update:
Tyler's approach is working, except when a new file is uploaded the primary key is not available and his technique below is throwing an error.
if not instance.pk:
instance.save()
Error:
maximum recursion depth exceeded while calling a Python object
Is there any way to grab the primary key?