Descarga una imagen remota y guárdala en un modelo Django

Estoy escribiendo una aplicación Django que buscará todas las imágenes de una URL particular y las guardará en la base de datos.

Pero no entiendo cómo usar ImageField en Django.

Settings.py

MEDIA_ROOT = os.path.join(PWD, "../downloads/") # URL that handles the media served from MEDIA_ROOT. Make sure to use a # trailing slash. # Examples: "http://example.com/media/", "htp://media.example.com/" MEDIA_URL = '/downloads/' 

modelos.py

 class images_data(models.Model): image_id =models.IntegerField() source_id = models.IntegerField() image=models.ImageField(upload_to='images',null=True, blank=True) text_ind=models.NullBooleanField() prob=models.FloatField() 

descargar_img.py

 def spider(site): PWD = os.path.dirname(os.path.realpath(__file__ )) #site="http://en.wikipedia.org/wiki/Pune" hdr= {'User-Agent': 'Mozilla/5.0'} outfolder=os.path.join(PWD, "../downloads") #outfolder="/home/mayank/Desktop/dreamport/downloads" print "MAYANK:"+outfolder req = urllib2.Request(site,headers=hdr) page = urllib2.urlopen(req) soup =bs(page) tag_image=soup.findAll("img") count=1; for image in tag_image: print "Image: %(src)s" % image filename = image["src"].split("/")[-1] outpath = os.path.join(outfolder, filename) urlretrieve('http:'+image["src"], outpath) im = img(image_id=count,source_id=1,image=outpath,text_ind=None,prob=0) im.save() count=count+1 

Estoy llamando a download_imgs.py dentro de una vista como

  if form.is_valid(): url = form.cleaned_data['url'] spider(url) 

La Documentación Django es siempre un buen lugar para comenzar.

 class ModelWithImage(models.Model): image = models.ImageField( upload_to='images', ) 

ACTUALIZADO

Así que este script funciona.

  • Bucle sobre imágenes para descargar
  • Descargar imagen
  • Guardar en archivo temporal
  • Aplicar al modelo
  • Guardar modelo

.

 import requests import tempfile from django.core import files # List of images to download image_urls = [ 'http://i.thegrindstone.com/wp-content/uploads/2013/01/how-to-get-awesome-back.jpg', ] for image_url in image_urls: # Steam the image from the url request = requests.get(image_url, stream=True) # Was the request OK? if request.status_code != requests.codes.ok: # Nope, error handling, skip file etc etc etc continue # Get the filename from the url, used for saving later file_name = image_url.split('/')[-1] # 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) # Create the model you want to save the image to image = Image() # Save the temporary image to the model# # This saves the model so be sure that is it valid image.image.save(file_name, files.File(lf)) 

Algunos enlaces de referencia:

  1. peticiones – “HTTP para humanos”, prefiero esto a urllib2
  2. tempfile – Guarda el archivo temporay y no en el disco
  3. Campo de archivo Django guardar

Si desea guardar las imágenes descargadas sin guardarlas primero en el disco (sin usar NamedTemporaryFile etc.), hay una manera fácil de hacerlo.

Esto será un poco más rápido que descargar el archivo y escribirlo en el disco, ya que todo se hace en la memoria. Tenga en cuenta que este ejemplo está escrito para Python 3; el proceso es similar en Python 2 pero ligeramente diferente.

 from django.core import files from io import BytesIO import requests url = "https://example.com/image.jpg" resp = requests.get(url) if resp.status_code != requests.codes.ok: # Error handling here fp = BytesIO() fp.write(resp.content) file_name = url.split("/")[-1] # There's probably a better way of doing this but this is just a quick example your_model.image_field.save(file_name, files.File(fp)) 

Donde your_model es una instancia del modelo que desea guardar y .image_field es el nombre de ImageField .

Consulte la documentación de io para obtener más información.

Como ejemplo de lo que creo que estás preguntando:

En forms.py:

 imgfile = forms.ImageField(label = 'Choose your image', help_text = 'The image should be cool.') 

En models.py:

 imgfile = models.ImageField(upload_to='images/%m/%d') 

Entonces habrá una solicitud POST del usuario (cuando el usuario complete el formulario). Esa solicitud contendrá básicamente un diccionario de datos. El diccionario contiene los archivos enviados. Para enfocar la solicitud en el archivo desde el campo (en nuestro caso, un ImageField), usaría:

 request.FILES['imgfield'] 

Usaría eso cuando construya el objeto modelo (creando una instancia de su clase de modelo):

 newPic = ImageModel(imgfile = request.FILES['imgfile']) 

Para guardar eso de una manera simple, solo usarías el método save () otorgado a tu objeto (porque Django es increíble):

 if form.is_valid(): newPic = Pic(imgfile = request.FILES['imgfile']) newPic.save() 

Su imagen se almacenará, de forma predeterminada, en el directorio que indique para MEDIA_ROOT en settings.py.

Accediendo a la imagen en la plantilla:

  

Las direcciones URL pueden ser difíciles, pero aquí hay un ejemplo básico de un patrón de URL simple para llamar a las imágenes almacenadas:

 urlpatterns += patterns('', url(r'^media/(?P.*)$', 'django.views.static.serve', { 'document_root': settings.MEDIA_ROOT, }), ) 

Espero que ayude.

Intenta hacerlo de esta manera en lugar de asignar una ruta a la imagen …

  import urllib2 from django.core.files.temp import NamedTemporaryFile def handle_upload_url_file(url): img_temp = NamedTemporaryFile() opener = urllib2.build_opener() opener.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1')] img_temp.write(opener.open(url).read()) img_temp.flush() return img_temp 

usa la función anterior como esta …

  new_image = images_data() #rest of the data in new_image and then do this. new_image.image.save(slug_filename,File(handle_upload_url_file(url))) #here slug_filename is just filename that you want to save the file with. 

Al igual que en la respuesta anterior de @ boltsfrombluesky, puedes hacer esto en Python 3 sin ninguna dependencia externa como esta:

 from os.path import basename import urllib.request from urllib.parse import urlparse import tempfile from django.core.files.base import File def handle_upload_url_file(url, obj): img_temp = tempfile.NamedTemporaryFile(delete=True) req = urllib.request.Request( url, data=None, headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36' } ) with urllib.request.urlopen(req) as response: img_temp.write(response.read()) img_temp.flush() filename = basename(urlparse(url).path) result = obj.image.save(filename, File(img_temp)) img_temp.close() return result 
 def qrcodesave(request): import urllib2; url ="http://chart.apis.google.com/chart?cht=qr&chs=300x300&chl=s&chld=H|0"; opener = urllib2.urlopen(url); mimetype = "application/octet-stream" response = HttpResponse(opener.read(), mimetype=mimetype) response["Content-Disposition"]= "attachment; filename=aktel.png" return response