copy file from one model to another

后端 未结 5 1707
孤城傲影
孤城傲影 2020-12-09 03:34

I have 2 simple models:

class UploadImage(models.Model):
   Image = models.ImageField(upload_to=\"temp/\")

class RealImage(models.Model):
   Image = models.         


        
相关标签:
5条回答
  • 2020-12-09 03:59

    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

    0 讨论(0)
  • 2020-12-09 04:00

    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.

    0 讨论(0)
  • 2020-12-09 04:04

    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
    

    Variable's Used:

    1. src_obj = source attachment object.
    2. src_field_name = source attachment object's FileField Name.
    3. dest_obj = destination attachment object.
    4. dest_field_name = destination attachment object's FileField Name.
    0 讨论(0)
  • 2020-12-09 04:06

    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)[1]
    im.save(settings.MEDIA_ROOT + newpath)
    r = RealImage.objects.create(Image=newpath)
    

    Hope that helped...

    0 讨论(0)
  • 2020-12-09 04:09

    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()
    
    0 讨论(0)
提交回复
热议问题