Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Copy FileFields

I'm trying to copy a file using a hardlink, where the file is stored as a Django FileField. I'd like to use a hardlink to save space and copy time (no changes are expected to be made to the original file or copy). However, I'm getting some odd errors when I try to call new_file.save() from the snippet below.

AttributeError: 'file' object has no attribute '_committed'

My thinking is that after making the hardlink, I can just open the linked file and store it to the Django new File instance's FileFile. Am I missing a step here or something?

models.py

class File(models.Model):
    stored_file = models.FileField()

elsewhere.py

import os 

original_file = File.objects.get(id=1)
original_file_path = original_file.file.path

new_file = File()
new_file_path = '/path/to/new/file'

os.makedirs(os.path.realpath(os.path.dirname(new_file_path)))
os.link(original_file_path, new_file_path)
new_file.stored_file = file(new_file_path)
new_file.save()
like image 374
Joe J Avatar asked Apr 10 '12 16:04

Joe J


2 Answers

There is no need to create hardlink, just duplicate the file holder:

new_file = File(stored_file=original_file.stored_file)
new_file.save()

update

If you want to specify file to FileField or ImageField, you could simply

new_file = File(stored_file=new_file_path)
# or
new_file = File()
new_file.stored_file = new_file_path
# or
from django.core.files.base import File
# from django.core.files.images import ImageFile # for ImageField
new_file.stored_file = File(new_file_path)

the field accepts path in basestring or File() instance, the code in your question uses file() and hence is not accepted.

like image 131
okm Avatar answered Oct 08 '22 23:10

okm


I think I solved this issue, but not sure why it works. I wrapped the file object in a "DjangoFile" class (I imported as DjangoFile to avoid clashing with my previously defined File model).

from django.core.files.base import File as DjangoFile

...
new_file.stored_file = DjangoFile(file(new_file_path))
new_file.save()

This approached seemed to save the file OK.

like image 25
Joe J Avatar answered Oct 09 '22 00:10

Joe J