un1t
un1t

Reputation: 4449

Copying files from one model to another

I have two models like this:

class A(models.Model):
    attachment = FileField(upload_to='a')

class B(models.Model):
    attachment = FileField(upload_to='b')

I have instance of A model:

a = A.objects.get(pk=1)

I need to create instance of B model, with file copied from a instance.

How can I do that?

I was trying something like this, but it is not working:

from django.core.files import File
B.objects.create(attachment=File(open(a.attachment.path, 'rb')))

Upvotes: 3

Views: 1738

Answers (3)

Gerard
Gerard

Reputation: 9418

I had the same problem and solved it like this, hope it helps anybody:

# models.py

class A(models.Model):
    # other fields...
    attachment = FileField(upload_to='a')

class B(models.Model):
    # other fields...
    attachment = FileField(upload_to='b')

# views.py or any file you need the code in

try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO
from django.core.files.base import ContentFile
from main.models import A, B

obj1 = A.objects.get(pk=1)

# You and either copy the file to an existent object
obj2 = B.objects.get(pk=2)

# or create a new instance
obj2 = B(**some_params)

tmp_file = StringIO(obj1.attachment.read())
tmp_file = ContentFile(tmp_file.getvalue())
url = obj1.attachment.url.split('.')
ext = url.pop(-1)
name = url.pop(-1).split('/')[-1]  # I have my files in a remote Storage, you can omit the split if it doesn't help you
tmp_file.name = '.'.join([name, ext])
obj2.attachment = tmp_file

# Remember to save you instance
obj2.save()

Upvotes: 2

un1t
un1t

Reputation: 4449

It strange thing. Now the way I tryed before works perfectly, without any errors. Maybe I missed something at the first time. So it works:

from django.core.files import File
B.objects.create(attachment=File(open(a.attachment.path, 'rb')))

Upvotes: 3

Guillaume Cisco
Guillaume Cisco

Reputation: 2945

Your code is working, but doesn't create a new file.

For creating a new file, you should consider shutil.copy() : http://docs.python.org/library/shutil.html

Moreover, if you copy a file, its name has to be different from the previous one, or you can keep the same name if you create the file in another directory. It Depends what you want...

So your code becomes :

from shutil import copy
B.objects.create(attachment=copy(a.attachment.path, 'my_new_path_or_my_new_filename'))

Also don't forget to .save() your new object.

Upvotes: 0

Related Questions