29

我有 2 个简单的模型:

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

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

还有一种形式

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

我需要将文件从 UploadImage 保存到 RealImage。我怎么能这样做。下面的代码不起作用

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

寻求帮助。

4

5 回答 5

39

受 Gerard 解决方案的启发,我想出了以下代码:

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

这实际上会通过在文件名中添加“_1”来重命名文件,以便原始文件和文件的新副本可以同时存在于磁盘上。

于 2012-06-04T17:51:08.280 回答
8

虽然这已经晚了,但我会这样解决这个问题,

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

如果我使用模型表单来处理这个过程,我会这样做

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

请注意,我确保 upload_image 文件已关闭,因为调用 real_image.save() 将打开文件并读取其内容。这由 ImageField 实例使用的任何存储系统处理

于 2014-01-31T14:47:23.893 回答
2

尝试在不使用表格的情况下这样做。在不知道您得到的确切错误的情况下,我只能推测表单的 clean() 方法由于 upload_to 参数不匹配而引发错误。

这让我想到了下一点,如果你试图将图像从“temp/”复制到“real/”,你将不得不自己进行一些文件处理来移动文件(如果你有 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)

希望有帮助...

于 2011-07-27T04:44:35.993 回答
1

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()
于 2012-02-21T22:18:34.470 回答
-2

更新 Gerard 的解决方案以通用方式处理它:

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

变量的使用:

  1. src_obj = 源附件对象。
  2. src_field_name = 源附件对象的 FileField 名称。
  3. dest_obj = 目标附件对象。
  4. dest_field_name = 目标附件对象的 FileField 名称。
于 2012-05-10T10:18:31.173 回答