django copy filefield

django - copiar archivo de un modelo a otro



copy filefield (5)

Tengo 2 modelos simples:

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

Y una forma

class RealImageForm(ModelForm): class Meta: model = RealImage

Necesito guardar el archivo de UploadImage en RealImage. Cómo podría hacer esto. El siguiente código no funciona

realform.Image=UploadImage.objects.get(id=image_id).Image realform.save()

Tnx por ayuda.


Intenta hacer eso sin usar un formulario. Sin saber el error exacto que está obteniendo, solo puedo especular que el método clean () del formulario genera un error debido a una falta de coincidencia en el parámetro upload_to.

Lo que me lleva al próximo punto, si está tratando de copiar la imagen de ''temp /'' a ''real /'', tendrá que hacer un manejo de archivos para mover el archivo usted mismo (más fácil si tiene 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)

Espero que haya ayudado ...


Tuve el mismo problema y lo resolví así, espero que ayude a cualquiera:

# 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()


Inspirado por la solución de Gerard, se me ocurrió el siguiente código:

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()

Esto realmente irá tan lejos como renombrar el archivo agregando un "_1" al nombre del archivo para que tanto el archivo original como esta nueva copia del archivo puedan existir en el disco al mismo tiempo.


Actualice la solución de Gerard para manejarlo de una manera genérica:

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 utilizada:

  1. src_obj = objeto de enlace de origen.
  2. src_field_name = Nombre del campo de archivos del objeto de archivo adjunto fuente.
  3. dest_obj = objeto de destino de destino.
  4. dest_field_name = Nombre de FileField del objeto de destino de destino.

Aunque esto es tarde, pero abordaría este problema así,

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()

Si estuviera usando un formulario modelo para manejar el proceso, lo haré

# 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()

Tenga en cuenta que me aseguro de que el archivo uploaded_image esté cerrado porque llamar a real_image.save () abrirá el archivo y leerá su contenido. Eso es manejado por el sistema de almacenamiento utilizado por la instancia de ImageField