python - serve - mostrar imagenes django
Django: agregar imagen en un campo de imagen desde la url de la imagen (7)
por favor discúlpeme por mi feo inglés ;-)
Imagina este modelo muy simple:
class Photo(models.Model):
image = models.ImageField(''Label'', upload_to=''path/'')
Me gustaría crear una foto a partir de una URL de imagen (es decir, no a mano en el sitio de administración de django).
Creo que necesito hacer algo como esto:
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)
Espero haber explicado bien el problema, si no me lo dices.
Gracias :)
Editar:
Esto puede funcionar, pero no sé cómo convertir content
a un archivo django:
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)
Acabo de crear http://www.djangosnippets.org/snippets/1890/ para este mismo problema. El código es similar a la respuesta sin contenido anterior, excepto que usa urllib2.urlopen porque urllib.urlretrieve no realiza ningún manejo de errores de manera predeterminada, por lo que es fácil obtener el contenido de una página 404/500 en lugar de lo que necesita. Puede crear la función de devolución de llamada y la subclase URLOpener personalizada, pero me resultó más fácil simplemente crear mi propio archivo temporal de esta manera:
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))
Combinando lo que Chris Adams y Stan dijeron y actualizando las cosas para trabajar en Python 3, si instalas las Requests puedes hacer algo como esto:
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)
Documentos más relevantes en la documentación de Contenthange de Django y en el ejemplo de descarga de archivos de Solicitudes .
Lo hago de esta manera en Python 3, que debería funcionar con adaptaciones simples en Python 2. Esto se basa en mi conocimiento de que los archivos que estoy recuperando son pequeños. Si el tuyo no lo es, probablemente recomendaría escribir la respuesta en un archivo en lugar de almacenarla en la memoria.
Se necesita BytesIO porque Django llama a seek () en el objeto de archivo y las respuestas de urlopen no son compatibles con la búsqueda. Podría pasar el objeto bytes devuelto por read () al ContentFile de Django en su lugar.
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))
Si está utilizando la función de carga de archivos en su proyecto Django, primero debe instalar Pillow:
pip install pillow==2.6.1
Recuerde configurar la url para archivos multimedia en settings.py:
MEDIA_ROOT = ''media/''
Luego, en su models.py, agregue el siguiente campo de imagen:
userlogo = models.ImageField(upload_to="userlogo/", blank=True, null=True)
Después de escribir este código, migre el modelo usando:
python manage.py makemigrations
python manage.py migrate
Ahora puede cargar archivos de imagen usando el campo de imagen. Los archivos de imagen se subirían al directorio YOUR_PROJECT_ROOT / media / userlogo. No es necesario crear la carpeta ''userlogo'' manualmente.
esta es la forma correcta y funcional
class Product(models.Model):
upload_path = ''media/product''
image = models.ImageField(upload_to=upload_path, null=True, blank=True)
image_url = models.URLField(null=True, blank=True)
def save(self, *args, **kwargs):
if self.image_url:
import urllib, os
from urlparse import urlparse
filename = urlparse(self.image_url).path.split(''/'')[-1]
urllib.urlretrieve(self.image_url, os.path.join(file_save_dir, filename))
self.image = os.path.join(upload_path, filename)
self.image_url = ''''
super(Product, self).save()
ImageField
es solo una cadena, una ruta relativa a su configuración MEDIA_ROOT
. Simplemente guarde el archivo (es posible que desee usar PIL para verificar que sea una imagen) y rellene el campo con su nombre de archivo.
Por lo tanto, difiere de su código en que necesita guardar la salida de su urllib.urlopen
en el archivo (dentro de su ubicación de medios), calcular la ruta y guardarla en su modelo.
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)