好吧,我几乎什么都试过了,但我不能让它工作。

我有一个带有ImageField的Django模型 我有通过HTTP下载图像的代码(测试和工作) 图像直接保存到'upload_to'文件夹中(upload_to是在ImageField中设置的) 我所需要做的就是将已经存在的图像文件路径与ImageField关联起来

我用六种不同的方式写了这段代码。

The problem I'm running into is all of the code that I'm writing results in the following behavior: (1) Django will make a 2nd file, (2) rename the new file, adding an _ to the end of the file name, then (3) not transfer any of the data over leaving it basically an empty re-named file. What's left in the 'upload_to' path is 2 files, one that is the actual image, and one that is the name of the image,but is empty, and of course the ImageField path is set to the empty file that Django try to create.

如果你不清楚,我将尝试说明:

## 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 doc on File

更新 经过进一步的测试,它只有在Windows Server上的Apache下运行时才会执行此行为。当在XP的“runserver”下运行时,它不会执行此行为。

我被难住了。

下面是在XP上成功运行的代码…

f = open(thumb_path, 'r')
model.thumbnail = File(f)
model.save()

当前回答

class DemoImage(models.Model):
    title = models.TextField(max_length=255, blank=False)
    image = models.ImageField(blank=False, upload_to="images/DemoImages/")

import requests
import urllib.request
from django.core.files import File
url = "https://path/to/logo.jpg"

# Below 3 lines is to fake as browser agent 
# as many sites block urllib class suspecting to be bots
opener = urllib.request.build_opener()
opener.addheaders = [("User-agent", "Mozilla/5.0")]
urllib.request.install_opener(opener)

# Issue command to actually download and create temp img file in memory        
result = urllib.request.urlretrieve(url)

# DemoImage.objects.create(title="title", image=File(open(result[0], "rb"))) 
# ^^ This erroneously results in creating the file like 
# images/DemoImages/path/to/temp/dir/logo_image_file 
# as opposed to 
# images/DemoImages/logo_image_file

# Solution to get the file in images/DemoImages/
reopen = open(result[0], "rb") # Returns a BufferedReader object of the temp image
django_file = File(reopen)     # Create the file from the BufferedReader object 
demoimg = DemoImage()
demoimg.title = "title"
demoimg.image.save("logo.png", django_file, save=True)

如果这样配置,这种方法还会触发文件上传到cloudinary/S3

其他回答

你可以使用Django REST框架和python请求库以编程方式将图像保存到Django ImageField中

下面是一个例子:

import requests


def upload_image():
    # PATH TO DJANGO REST API
    url = "http://127.0.0.1:8080/api/gallery/"

    # MODEL FIELDS DATA
    data = {'first_name': "Rajiv", 'last_name': "Sharma"}

    #  UPLOAD FILES THROUGH REST API
    photo = open('/path/to/photo', 'rb')
    resume = open('/path/to/resume', 'rb')
    files = {'photo': photo, 'resume': resume}

    request = requests.post(url, data=data, files=files)
    print(request.status_code, request.reason) 

在Django 3中, 用这样一个模型:

class Item(models.Model):
   name = models.CharField(max_length=255, unique=True)
   photo= models.ImageField(upload_to='image_folder/', blank=True)

如果图片已经上传,我们可以直接做:

Item.objects.filter(...).update(photo='image_folder/sample_photo.png')

or

my_item = Item.objects.get(id=5)
my_item.photo='image_folder/sample_photo.png'
my_item.save()

我有一些代码,从网络上获取图像,并将其存储在模型中。重要的部分是:

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

这有点令人困惑,因为它是从我的模型中提取出来的,有点脱离上下文,但重要的部分是:

从web中提取的图像不存储在upload_to文件夹中,而是由urllib.urlretrieve()存储为tempfile,然后丢弃。 ImageField.save()方法接受一个文件名(os.path.basename位)和一个django.core.files.File对象。

如果您有问题或需要澄清,请告诉我。

编辑:为了清晰起见,下面是模型(减去任何必需的import语句):

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

很多答案都过时了,我花了很多时间在沮丧中(我对Django和web开发还是个新手)。然而,我从@iambibhas: https://gist.github.com/iambibhas/5051911上找到了这个很棒的要点

import requests

from django.core.files import File
from django.core.files.temp import NamedTemporaryFile


def save_image_from_url(model, url):
    r = requests.get(url)

    img_temp = NamedTemporaryFile(delete=True)
    img_temp.write(r.content)
    img_temp.flush()

    model.image.save("image.jpg", File(img_temp), save=True)

class tweet_photos(models.Model):
upload_path='absolute path'
image=models.ImageField(upload_to=upload_path)
image_url = models.URLField(null=True, blank=True)
def save(self, *args, **kwargs):
    if self.image_url:
        import urllib, os
        from urlparse import urlparse
        file_save_dir = self.upload_path
        filename = urlparse(self.image_url).path.split('/')[-1]
        urllib.urlretrieve(self.image_url, os.path.join(file_save_dir, filename))
        self.image = os.path.join(file_save_dir, filename)
        self.image_url = ''
    super(tweet_photos, self).save()