通过编程方式将图像保存到Django ImageField
好的,我试了几乎所有的方法,但就是无法让它工作。
- 我有一个Django模型,其中有一个ImageField字段。
- 我有代码可以通过HTTP下载图片(测试过,能正常工作)。
- 图片直接保存在'upload_to'文件夹里(这个文件夹就是ImageField设置的那个)。
- 我只需要把已经存在的图片文件路径和ImageField关联起来。
我写了大约六种不同的代码。
我遇到的问题是,我写的所有代码都会导致以下情况: (1) Django会创建一个第二个文件,(2) 将新文件重命名,在文件名后面加一个下划线,然后 (3) 不会把任何数据转移过去,结果就是一个基本上是空的重命名文件。'upload_to'路径下剩下两个文件,一个是真正的图片,另一个是图片的名字,但它是空的,当然ImageField的路径指向的是Django试图创建的那个空文件。
如果这不太清楚,我试着举个例子:
## Image generation code runs....
/Upload
generated_image.jpg 4kb
## Attempt to set the ImageField path...
/Upload
generated_image.jpg 4kb
generated_image_.jpg 0kb
ImageField.Path = /Upload/generated_image_.jpg
我该如何做到这一点,而不让Django尝试重新存储文件?我真正想要的是类似这样的效果……
model.ImageField.path = generated_image_path
……但当然这样是不行的。
是的,我也看过这里的其他问题,比如这个,还有Django文档中的文件部分。
更新 经过进一步测试,只有在Windows Server的Apache下运行时才会出现这种情况。在XP的'runserver'下运行时不会出现这种行为。
我现在很困惑。
这是在XP上成功运行的代码……
f = open(thumb_path, 'r')
model.thumbnail = File(f)
model.save()
21 个回答
我想说一句小提示。tvon的回答是有效的,但如果你在使用Windows系统,可能需要用 open()
函数以 'rb'
模式打开文件。像这样:
class CachedImage(models.Model):
url = models.CharField(max_length=255, unique=True)
photo = models.ImageField(upload_to=photo_path, blank=True)
def cache(self):
"""Store image locally if we have a URL"""
if self.url and not self.photo:
result = urllib.urlretrieve(self.url)
self.photo.save(
os.path.basename(self.url),
File(open(result[0], 'rb'))
)
self.save()
否则,你的文件在遇到第一个 0x1A
字节时会被截断。
如果模型还没有创建,那就简单得很:
第一步,把你的图片文件复制到上传的路径(假设这个路径是'path/',在下面的代码片段中会用到)。
第二步,使用类似下面的代码:
class Layout(models.Model):
image = models.ImageField('img', upload_to='path/')
layout = Layout()
layout.image = "path/image.png"
layout.save()
这个方法在django 1.4中测试过,可能也适用于已经存在的模型。
我有一些代码可以从网上获取一张图片,并把它存储在一个模型里。重要的部分是:
from django.core.files import File # you need this somewhere
import urllib
# The following actually resides in a method of my model
result = urllib.urlretrieve(image_url) # image_url is a URL to an image
# self.photo is the ImageField
self.photo.save(
os.path.basename(self.url),
File(open(result[0], 'rb'))
)
self.save()
这有点让人困惑,因为这段代码是从我的模型中提取出来的,缺少了一些上下文,但重要的内容是:
- 从网上获取的图片并没有存储在upload_to文件夹里,而是通过urllib.urlretrieve()存储为一个临时文件,之后会被丢弃。
- ImageField.save()方法需要一个文件名(就是os.path.basename那部分)和一个django.core.files.File对象。
如果你有任何问题或者需要进一步解释,随时告诉我。
补充说明:为了更清楚,这里是模型的代码(省略了任何必要的导入语句):
class CachedImage(models.Model):
url = models.CharField(max_length=255, unique=True)
photo = models.ImageField(upload_to=photo_path, blank=True)
def cache(self):
"""Store image locally if we have a URL"""
if self.url and not self.photo:
result = urllib.urlretrieve(self.url)
self.photo.save(
os.path.basename(self.url),
File(open(result[0], 'rb'))
)
self.save()