我有2种方式上传图片。 1是从用户的文件中选择图像,而另一个是通过URL上传图像。
模型
class Post(models.Model):
...
image = models.FileField(null=True, blank=True)
imageURL = models.URLField(null=True, blank=True)
def download_file_from_url(self):
print('DOWNLOAD') #prints "DOWNLOAD"
# Stream the image from the url
try:
request = requests.get(self, stream=True)
except requests.exceptions.RequestException as e:
# TODO: log error here
return None
if request.status_code != requests.codes.ok:
# TODO: log error here
return None
# Create a temporary file
lf = tempfile.NamedTemporaryFile()
# Read the streamed image in sections
for block in request.iter_content(1024 * 8):
# If no more file then stop
if not block:
break
# Write image block to temporary file
lf.write(block)
return files.File(lf)
HTML
<input id="id_image" type="file" name="image" /> <!--upload from file-->
{{ form_post.imageURL|placeholder:"URL" }} <!--url upload-->
从文件上传图片工作正常,用户只需点击输入并选择他们的文件。但是,当用户决定使用URL选项时,我是否会获取该URL字符串并将其设为image
字段的值?
视图
...
if form_post.is_valid():
instance = form_post.save(commit=False)
if instance.imageURL:
instance.image = Post.download_file_from_url(instance.imageURL)
instance.save()
urls.py
...
if settings.DEBUG:
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
settings.py
...
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
答案 0 :(得分:1)
您不能在FileField上放置字符串。它需要是一个文件。但有一个解决方法。您需要从服务器上的URL下载文件,然后将其保存到数据库中。
这是一个可以帮助您的代码:
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.request.urlretrieve(self.url)
self.photo.save(
os.path.basename(self.url),
File(open(result[0]))
)
self.save()
答案 1 :(得分:1)
Python 3兼容方法:
import requests
import tempfile
from django.core import files
def download_file_from_url(url):
# Stream the image from the url
try:
request = requests.get(url, stream=True)
except requests.exceptions.RequestException as e:
# TODO: log error here
return None
if request.status_code != requests.codes.ok:
# TODO: log error here
return None
# Create a temporary file
lf = tempfile.NamedTemporaryFile()
# Read the streamed image in sections
for block in request.iter_content(1024 * 8):
# If no more file then stop
if not block:
break
# Write image block to temporary file
lf.write(block)
return files.File(lf)
#Do this in your view
if self.url and not self.photo:
self.photo = download_file_from_url(url)