[python] Django : 이미지 URL에서 ImageField에 이미지 추가

내 추악한 영어로 실례합니다 😉

이 매우 간단한 모델을 상상해보십시오.

class Photo(models.Model):
    image = models.ImageField('Label', upload_to='path/')

이미지 URL에서 사진을 만들고 싶습니다 (즉, django 관리 사이트에서 손으로하지 않음).

다음과 같이해야한다고 생각합니다.

from myapp.models import Photo
import urllib

img_url = 'http://www.site.com/image.jpg'
img = urllib.urlopen(img_url)
# Here I need to retrieve the image (as the same way that if I put it in an input from admin site)
photo = Photo.objects.create(image=image)

말하지 않더라도 문제를 잘 설명했으면합니다.

감사합니다 🙂

편집하다 :

이것은 작동 할 수 있지만 contentdjango 파일 로 변환하는 방법을 모르겠습니다 .

from urlparse import urlparse
import urllib2
from django.core.files import File

photo = Photo()
img_url = 'http://i.ytimg.com/vi/GPpN5YUNDeI/default.jpg'
name = urlparse(img_url).path.split('/')[-1]
content = urllib2.urlopen(img_url).read()

# problem: content must be an instance of File
photo.image.save(name, content, save=True)



답변

이 같은 문제에 대해 방금 http://www.djangosnippets.org/snippets/1890/ 을 만들었습니다 . 이 코드는 urllib2.urlopen을 사용한다는 점을 제외하면 위의 pithyless ‘답변과 유사합니다. urllib.urlretrieve는 기본적으로 오류 처리를 수행하지 않으므로 필요한 내용 대신 404/500 페이지의 내용을 쉽게 얻을 수 있기 때문입니다. 콜백 함수 및 사용자 지정 URLOpener 하위 클래스를 만들 수 있지만 다음과 같이 내 임시 파일을 만드는 것이 더 쉽다는 것을 알았습니다.

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

img_temp = NamedTemporaryFile(delete=True)
img_temp.write(urllib2.urlopen(url).read())
img_temp.flush()

im.file.save(img_filename, File(img_temp))


답변


from myapp.models import Photo
import urllib
from urlparse import urlparse
from django.core.files import File

img_url = 'http://www.site.com/image.jpg'

photo = Photo()    # set any other fields, but don't commit to DB (ie. don't save())
name = urlparse(img_url).path.split('/')[-1]
content = urllib.urlretrieve(img_url)

# See also: http://docs.djangoproject.com/en/dev/ref/files/file/
photo.image.save(name, File(open(content[0])), save=True)


답변

Chris Adams와 Stan이 말한 것을 결합하고 Python 3에서 작동하도록 업데이트하면 Requests 를 설치 하면 다음과 같이 할 수 있습니다.

from urllib.parse import urlparse
import requests
from django.core.files.base import ContentFile
from myapp.models import Photo

img_url = 'http://www.example.com/image.jpg'
name = urlparse(img_url).path.split('/')[-1]

photo = Photo() # set any other fields, but don't commit to DB (ie. don't save())

response = requests.get(img_url)
if response.status_code == 200:
    photo.image.save(name, ContentFile(response.content), save=True)

Django의 ContentFile 문서Requests의 파일 다운로드 예제 에서 더 관련있는 문서 .


답변

ImageFieldMEDIA_ROOT설정에 상대적인 경로 인 문자열 입니다. 파일을 저장하고 (PIL을 사용하여 이미지인지 확인하고 싶을 수 있음) 필드를 파일 이름으로 채 웁니다.

따라서 출력 urllib.urlopen을 파일 (미디어 위치 내부)에 저장하고 경로를 확인하고 모델 에 저장해야한다는 점에서 코드와 다릅니다 .


답변

저는 Python 3에서 이렇게합니다.이 방법은 Python 2에서 간단한 개조로 작동합니다. 이것은 제가 검색하는 파일이 작다는 제 지식을 기반으로합니다. 그렇지 않은 경우 메모리 버퍼링 대신 파일에 응답을 작성하는 것이 좋습니다.

Django는 파일 객체에서 seek ()를 호출하고 urlopen 응답은 검색을 지원하지 않기 때문에 BytesIO가 필요합니다. read ()가 반환 한 bytes 객체를 Django의 ContentFile에 대신 전달할 수 있습니다.

from io import BytesIO
from urllib.request import urlopen

from django.core.files import File


# url, filename, model_instance assumed to be provided
response = urlopen(url)
io = BytesIO(response.read())
model_instance.image_field.save(filename, File(io))


답변

최근에 저는 파이썬 3과 장고 3에서 다음과 같은 접근 방식을 사용합니다. 아마도 이것은 다른 사람들에게도 흥미로울 것입니다. Chris Adams 솔루션과 유사하지만 더 이상 작동하지 않았습니다.

# -*- coding: utf-8 -*-
import urllib.request
from django.core.files.uploadedfile import SimpleUploadedFile
from urllib.parse import urlparse

from demoapp import models


img_url = 'https://upload.wikimedia.org/wikipedia/commons/f/f7/Stack_Overflow_logo.png'
basename = urlparse(img_url).path.split('/')[-1]
tmpfile, _ = urllib.request.urlretrieve(img_url)

new_image = models.ModelWithImageOrFileField()
new_image.attribute_a = True
new_image.attribute_b = 'False'
new_image.file = SimpleUploadedFile(basename, open(tmpfile, "rb").read())
new_image.save()


답변

임시 파일을 생성 할 필요가 없다는 것을 방금 발견했습니다.

django에서 minio로 직접 URL 콘텐츠 스트리밍

내 파일을 minio에 저장하고 디스크 공간없이 django docker 컨테이너를 가져야하고 큰 비디오 파일을 다운로드해야했기 때문에 이것은 나에게 정말 도움이되었습니다.