这个问题已经过去了将近 11 年,最知名的答案已经发布。感谢@chris-adams 的回复。我只是重新发布相同的答案以及更新的软件包和支持。
#! /usr/bin/python3
# lib/utils.py
import urllib3 # http Request Package.
from typing import Optional
from django.core.files import File # Handle Files in Django
from django.core.files.temp import NamedTemporaryFile # handling temporary files.
def fetch_image(url: str, instance: models.Model, field: str, name: Optional[str]=None):
"""
fetch_image Fetches an image URL and adds it to the model field.
the parameter instance does not need to be a saved instance.
:url: str = A valid image URL.
:instance: django.db.models.Model = Expecting a model with image field or file field.
:field: str = image / file field name as string;
[name:str] = Preferred file name, such as product slug or something.
:return: updated instance as django.db.models.Model, status of updation as bool.
"""
conn = urllib3.PoolManager()
response = conn.request('GET', url)
if response.status <> 200:
print("[X] 404! IMAGE NOT FOUND")
print(f"TraceBack: {url}")
return instance, False
file_obj = NamedTemporaryFile(delete=True)
file_obj.write( response.data )
file_obj.flush()
img_format = url.split('.')[-1]
if name is None:
name = url.split('/')[-1]
if not name.endswith(img_format):
name += f'.{img_format}'
django_file_obj = File(file_obj)
(getattr(instance, field)).save(name, django_file_obj)
return instance, True
在 Python 3.7.5 中使用 Django==2.2.12 测试
if __name__ == '__main__':
instance = ProductImage()
url = "https://www.publicdomainpictures.net/pictures/320000/velka/background-image.png"
instance, saved = fetch_image(url, instance, field='banner_image', name='intented-image-slug')
status = ["FAILED! ", "SUCCESS! "][saved]
print(status, instance.banner_image and instance.banner_image.path)
instance.delete()