copy file from one model to another
I have 2 simple models:
class UploadImage(models.Model): Image = models.ImageField(upload_to="temp/") class RealImage(models.Model): Image = models.ImageField(upload_to="real/")
And one form
class RealImageForm(ModelForm): class Meta: model = RealImage
I need to save file from UploadImage into RealImage. How could i do this. Below code doesn't work
Tnx for help.
Inspired by Gerard's solution I came up with the following code:
from django.core.files.base import ContentFile #... class Example(models.Model): file = models.FileField() def duplicate(self): """ Duplicating this object including copying the file """ new_example = Example() new_file = ContentFile(self.file.read()) new_file.name = self.file.name new_example.file = new_file new_example.save()
This will actually go as far as renaming the file by adding a "_1" to the filename so that both the original file and this new copy of the file can exist on disk at the same time.
Although this is late, but I would tackle this problem thus,
class UploadImage(models.Model): Image = models.ImageField(upload_to="temp/") # i need to delete the temp uploaded file from the file system when i delete this model # from the database def delete(self, using=None): name = self.Image.name # i ensure that the database record is deleted first before deleting the uploaded # file from the filesystem. super(UploadImage, self).delete(using) self.Image.storage.delete(name) class RealImage(models.Model): Image = models.ImageField(upload_to="real/") # in my view or where ever I want to do the copying i'll do this import os from django.core.files import File uploaded_image = UploadImage.objects.get(id=image_id).Image real_image = RealImage() real_image.Image = File(uploaded_image, uploaded_image.name) real_image.save() uploaded_image.close() uploaded_image.delete()
If I were using a model form to handle the process, i'll just do
# django model forms provides a reference to the associated model via the instance property form.instance.Image = File(uploaded_image, os.path.basename(uploaded_image.path)) form.save() uploaded_image.close() uploaded_image.delete()
note that I ensure the uploaded_image file is closed because calling real_image.save() will open the file and read its content. That is handled by what ever storage system is used by the ImageField instance
Try doing that without using a form. Without knowing the exact error that you are getting, I can only speculate that the form's clean() method is raising an error because of a mismatch in the upload_to parameter.
Which brings me to my next point, if you are trying to copy the image from 'temp/' to 'real/', you will have to do a some file handling to move the file yourself (easier if you have PIL):
import Image from django.conf import settings u = UploadImage.objects.get(id=image_id) im = Image.open(settings.MEDIA_ROOT + str(u.Image)) newpath = 'real/' + str(u.Image).split('/', 1) im.save(settings.MEDIA_ROOT + newpath) r = RealImage.objects.create(Image=newpath)
Hope that helped...
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()
Update Gerard's Solution to handle it in a generic way:
try: from cStringIO import StringIO except ImportError: from StringIO import StringIO from django.core.files.base import ContentFile init_str = "src_obj." + src_field_name + ".read()" file_name_str = "src_obj." + src_field_name + ".name" try: tmp_file = StringIO(eval(str(init_str))) tmp_file = ContentFile(tmp_file.getvalue()) tmp_file.name = os.path.basename(eval(file_name_str)) except AttributeError: tmp_file = None if tmp_file: try: dest_obj.__dict__[dest_field_name] = tmp_file dest_obj.save() except KeyError: pass
- src_obj = source attachment object.
- src_field_name = source attachment object's FileField Name.
- dest_obj = destination attachment object.
- dest_field_name = destination attachment object's FileField Name.