[python] Django ImageField에 이미지를 프로그래밍 방식으로 저장

좋아, 나는 거의 모든 것을 시도했지만 이것을 작동시킬 수 없다.

  • ImageField가있는 장고 모델이 있습니다.
  • HTTP를 통해 이미지를 다운로드하는 코드가 있습니다 (테스트 및 작동)
  • 이미지는 ‘upload_to’폴더 (ImageField에 설정되어있는 upload_to)에 직접 저장됩니다.
  • 이미 존재하는 이미지 파일 경로를 ImageField와 연결하기 만하면됩니다.

이 코드를 6 가지 방법으로 작성했습니다.

내가 겪고있는 문제는 내가 쓰고있는 모든 코드가 다음과 같은 결과를 초래한다는 것입니다. (1) Django는 두 번째 파일을 만들고 (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

… 물론 작동하지 않습니다.

그리고 그래 내가 좋아하는 여기에 다른 질문 겪었어요 이것 뿐만 아니라에서 장고 문서 파일

업데이트
추가 테스트 후 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 ()에 의해 임시 파일로 저장되고 나중에 폐기됩니다.
  • 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()


답변

모델이 아직 생성되지 않은 경우 매우 쉽습니다.

먼저 이미지 파일을 업로드 경로에 복사하십시오 ( 다음 스 니펫의 = ‘path /’ 라고 가정 ).

둘째 , 다음과 같은 것을 사용하십시오 :

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

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

django 1.4에서 테스트되고 작동하면 기존 모델에서도 작동 할 수 있습니다.


답변

약간의 발언. tvon answer가 작동하지만 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바이트 에서 파일이 잘립니다 .


답변

다음은 잘 작동하고 파일을 특정 형식으로 변환 할 수있는 방법입니다 ( “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()

도움이 되었기를 바랍니다


답변

좋아, 이미 존재하는 이미지 파일 경로를 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와 연결됩니다.


답변

내가 한 것은 파일을 디스크에 저장하지 않는 자체 저장소를 만드는 것이 었습니다.

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


답변

실제 파일 이름을 “설정”하고 파일을로드하고 다시 저장하는 오버 헤드 (!!) 나 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’를 설정할 수 있지만 장고는 현재이를 지원하지 않습니다.