1. ホーム
  2. パイソン

[解決済み】DjangoのImageFieldにプログラム的に画像を保存する

2022-04-04 04:52:55

質問

OK、あらゆることを試しましたが、これがうまくいきません。

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

このコードは6通りほど書きました。

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

解決方法は?

ウェブから画像を取得し、それをモデルに保存するコードがあります。 重要なビットは次のとおりです。

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() によって 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()