web-dev-qa-db-ja.com

プログラムで画像をDjango ImageFieldに保存する

わかりました、ほぼすべてのことを試してみましたが、これを機能させることはできません。

  • ImageFieldを含むDjangoモデルがあります
  • HTTP経由で画像をダウンロードするコードがあります(テスト済みで動作します)
  • 画像は「upload_to」フォルダーに直接保存されます(upload_toはImageFieldに設定されているものです)
  • 必要なのは、既存の画像ファイルパスをImageFieldに関連付けることだけです

このコードは、6つの異なる方法で作成しました。

私が実行している問題は、私が書いているすべてのコードが次の動作をもたらすことです:(1)Djangoは2番目のファイルを作成し、(2)新しいファイルの名前を変更して、_ファイル名の最後まで、(3)データを転送せず、基本的に空の名前変更されたファイルのままにします。 'upload_to'パスに残っているのは、2つのファイルです。1つは実際の画像で、もう1つは画像の名前ですが、空です。もちろん、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

...しかし、それはもちろん機能しません。

そして、そうです this oneFile のDjango docのような他の質問もここで行いました。

UPDATEさらにテストした後、Windows Server上のApacheで実行する場合にのみこの動作を行います。 XPの「runserver」の下で実行している間、この動作は実行されません。

私は困惑しています。

XPで正常に実行されるコードは次のとおりです...

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

Webから画像を取得してモデルに保存するコードがいくつかあります。重要なビットは次のとおりです。

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からプルされた画像はnot upload_toフォルダーに保存され、代わりにurllib.urlretrieve()によって一時ファイルとして保存され、後で破棄されます。
  • 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()
160
tvon

モデルがまだ作成されていない場合は、非常に簡単です。

最初、画像ファイルをアップロードパスにコピーします(以下のスニペットでは= 'path /'と仮定)。

、次のようなものを使用します。

class Layout(models.Model):
    image = models.ImageField('img', upload_to='path/')

layout = Layout()
layout.image = "path/image.png"
layout.save()

Django 1.4でテストおよび動作している場合、既存のモデルでも動作する可能性があります。

85
Rabih Kodeih

ほんの少しの発言。 tvon answerは機能しますが、Windowsで作業している場合は、'rb'でファイルをopen()したいでしょう。このような:

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バイトでファイルが切り捨てられます。

41
Tiago Almeida

うまく機能し、ファイルを特定の形式に変換できる方法を次に示します(「モードPをJPEGとして書き込めない」エラーを回避するため)。

import urllib2
from Django.core.files.base import ContentFile
from PIL import Image
from StringIO import StringIO

def download_image(name, image, url):
    input_file = StringIO(urllib2.urlopen(url).read())
    output_file = StringIO()
    img = Image.open(input_file)
    if img.mode != "RGB":
        img = img.convert("RGB")
    img.save(output_file, "JPEG")
    image.save(name+".jpg", ContentFile(output_file.getvalue()), save=False)

imageはDjango ImageFieldまたはyour_model_instance.imageです。使用例は次のとおりです。

p = ProfilePhoto(user=user)
download_image(str(user.id), p.image, image_url)
p.save()

お役に立てれば

16
michalk

私がやったことは、ファイルをディスクに保存しない独自のストレージを作成することでした:

from Django.core.files.storage import FileSystemStorage

class CustomStorage(FileSystemStorage):

    def _open(self, name, mode='rb'):
        return File(open(self.path(name), mode))

    def _save(self, name, content):
        # here, you should implement how the file is to be saved
        # like on other machines or something, and return the name of the file.
        # In our case, we just return the name, and disable any kind of save
        return name

    def get_available_name(self, name):
        return name

次に、私のモデルでは、ImageFieldに新しいカスタムストレージを使用しました。

from custom_storage import CustomStorage

custom_store = CustomStorage()

class Image(models.Model):
    thumb = models.ImageField(storage=custom_store, upload_to='/some/path')
11
Nicu Surdu

わかりました。既存の画像ファイルパスをImageFieldに関連付けるだけでよい場合は、この解決策が役立ちます。

from Django.core.files.base import ContentFile

with open('/path/to/already/existing/file') as f:
  data = f.read()

# obj.image is the ImageField
obj.image.save('imgfilename.jpg', ContentFile(data))

真剣に考えれば、既存の画像ファイルはImageFieldに関連付けられませんが、このファイルのコピーはupload_to dirに「imgfilename.jpg」として作成され、ImageFieldに関連付けられます。

10
rmnff

私の意見では最も簡単なソリューション:

from Django.core.files import File

with open('path_to_file', 'r') as f:   # use 'rb' mode for python3
    data = File(f)
    model.image.save('filename', data, True)
7
Ivan Semochkin

ファイルのロードと再保存のオーバーヘッドを発生させずに(!!)、またはcharfieldを使用する(!!!)ことなく、実際のファイル名を「設定」したい場合は、次のようなことを試してください。 -

model_instance.myfile = model_instance.myfile.field.attr_class(model_instance, model_instance.myfile.field, 'my-filename.jpg')

これにより、実際にファイルをアップロードしたかのように、model_instance.myfile.urlとその他すべてが点灯します。

@ t-stoneが言うように、本当に欲しいのはinstance.myfile.path = 'my-filename.jpg'を設定できるようにすることですが、Djangoは現在サポートしていません。

7
s29

これはあなたが探している答えではないかもしれません。ただし、ImageFileの代わりにcharfieldを使用してファイルのパスを保存できます。そのようにして、ファイルを再作成せずに、アップロードされた画像をプログラムでフィールドに関連付けることができます。

2
Mohamed
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()
1
sawan gupta

あなたが試すことができます:

model.ImageField.path = os.path.join('/Upload', generated_image_path)
1
panda
class Pin(models.Model):
    """Pin Class"""
    image_link = models.CharField(max_length=255, null=True, blank=True)
    image = models.ImageField(upload_to='images/', blank=True)
    title = models.CharField(max_length=255, null=True, blank=True)
    source_name = models.CharField(max_length=255, null=True, blank=True)
    source_link = models.CharField(max_length=255, null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    tags = models.ForeignKey(Tag, blank=True, null=True)

    def __unicode__(self):
        """Unicode class."""
        return unicode(self.image_link)

    def save(self, *args, **kwargs):
        """Store image locally if we have a URL"""
        if self.image_link and not self.image:
            result = urllib.urlretrieve(self.image_link)
            self.image.save(os.path.basename(self.image_link), File(open(result[0], 'r')))
            self.save()
            super(Pin, self).save()
1
Nishant

Django REST_ framework およびpython Requests ライブラリを使用して、プログラムを使用して画像を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) 
0
Rajiv Sharma

ワーキング! FileSystemStorageを使用して画像を保存できます。以下の例を確認してください

def upload_pic(request):
if request.method == 'POST' and request.FILES['photo']:
    photo = request.FILES['photo']
    name = request.FILES['photo'].name
    fs = FileSystemStorage()
##### you can update file saving location too by adding line below #####
    fs.base_location = fs.base_location+'/company_coverphotos'
##################
    filename = fs.save(name, photo)
    uploaded_file_url = fs.url(filename)+'/company_coverphotos'
    Profile.objects.filter(user=request.user).update(photo=photo)
0
Nids Barthwal