Renaming files in Django FileField

12,078

Solution 1

I don't think you need to use raw SQL for this. I think you need to rename the file using the os facility, then set the model's FileField name to the new name. Maybe something like:

os.rename(model.direct_file.path, new_path)
model.direct_file.name = new_name
model.save()

Solution 2

The current Django documentation states:

"When you access a FileField on a model, you are given an instance of FieldFile as a proxy for accessing the underlying file." See docs for further reading.

Instead of using the Python File object to open the file, you should use FieldFile.open() to open the file, then manipulate the file's path accordingly. Afterward, save the model object, and the changes to the path should persist.

Solution 3

 new_name = 'photos_preview/' + str(uuid.uuid1())
 os.rename(photo.image_preview.path, settings.MEDIA_ROOT + new_name)
 photo.image_preview.name = new_name
 photo.save()

Solution 4

I came across this issue when I had blobs saved into django with no file extension, and I wanted to correct that. Best used when looping over a filtered queryset.

You cannot change instance.picture.path, and trying to access instance.picture.file.* will give an error because accessing it will try to open the old file. Setting instance.picture.name will still not let you access instance.picture.file.*, even after saving.

You can simply set the ImageField object itself to the location and all will work:

(Tested with django 1.10)

import imghdr
import os

from django.db import models

class MyModel(models.Model):
    picture = models.ImageField()

instance = MyModel.objects.first()
if os.path.exists(instance.picture.path):
    extension = imghdr.what(instance.picture.path)
    os.rename(instance.picture.path, instance.picture.path + '.' + extension)
    instance.picture = instance.picture.name + '.' + extension
    instance.save()

Solution 5

You may use the following:

Suppose 'obj' is the django object that you want to rename. Then do this:

obj.file_field_name.name = new_name

obj.save()

Share:
12,078
aemdy
Author by

aemdy

Updated on June 03, 2022

Comments

  • aemdy
    aemdy about 2 years

    I know that there is a very similar thread here, but I cannot find the solution to my problem.

    I need to rename a file which is save in django models.FileField

    I tried this

    os.rename(old_path, new_path)
    mod.direct_file = File(open(new_path))
    mod.save()
    

    And this

    mod.direct_file.save(new_path, File(open(old_path)))
    os.remove(old_path)
    

    And many other ways, but nothing seemed to help. A new file is created in all ways, however, data in filefield does not change at all.

    EDIT: SOLVED

    os.rename(old_path, new_path)
    cursor = connection.cursor()
    cursor.execute("UPDATE mods_mod SET direct_file = %s WHERE id = %s", [new_name, mod.id])
    transaction.commit_unless_managed()
    
  • aemdy
    aemdy almost 12 years
    Open method opens already assigned file. FieldFile has no method to open another file.
  • droxey
    droxey almost 12 years
    The file is assigned via the FileField, correct? Are you trying to change all of the files in your model, or a single instance of the model?
  • aemdy
    aemdy almost 12 years
    I'd like to rename the file direct_file = models.FileField(default=None, blank=True, null=True, upload_to="mod_files") uploaded in this field.
  • droxey
    droxey almost 12 years
    It's still unclear to me whether you're trying to rename the model field 'direct_file', or you're trying to rename the actual file stored on the filesystem. My answer applies when attempting to rename the file stored on the filesystem.
  • aemdy
    aemdy almost 12 years
    I want to rename the file in filesystem.
  • WhyNotHugo
    WhyNotHugo over 3 years
    This will only work when using FileSystemStorage.