Django: ajouter une image dans un ImageField à partir de l'url de l'image
veuillez m'excuser pour mon laid anglais 😉
Imagine ce modèle très simple :
class Photo(models.Model):
image = models.ImageField('Label', upload_to='path/')
Je voudrais créer une Photo à partir d'une URL de l'image (c'est à dire, pas à la main dans le site d'administration de django).
Je pense que j'ai besoin de faire quelque chose comme ceci :
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)
J'espère que j'ai bien expliqué le problème, si pas de me le dire.
Merci 🙂
Edit :
Cela peut fonctionner, mais je ne sais pas comment convertir content
à un django Fichier :
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)
Vous devez vous connecter pour publier un commentaire.
Je viens de créer http://www.djangosnippets.org/snippets/1890/ pour ce même problème. Le code est similaire à pithyless' réponse ci-dessus, sauf qu'il utilise urllib2.urlopen parce que urllib.urlretrieve n'effectue pas de gestion d'erreur par défaut de sorte qu'il est facile d'obtenir le contenu d'un 404/500 page au lieu de ce que vous avez besoin. Vous pouvez créer fonction de rappel & la coutume URLOpener sous-classe mais je l'ai trouvé plus facile de créer mon propre fichier temp comme ceci:
im
objet en venir?im
était le modèle de l'instance etfile
a été l'imagination nom d'un FileField/ImageField sur cette instance. Le réel de l'API docs voici ce qu'est la matière – cette technique devrait fonctionner partout où vous disposez d'un Django Fichier objet lié à un objet: docs.djangoproject.com/en/1.5/ref/files/file/...requests
au lieu deurllib2
que vous pouvez faire:image_content = ContentFile(requests.get(url_image).content)
et puisobj.my_image.save("foo.jpg", image_content)
.Combinant ce que Chris Adams et Stan a dit et la mise à jour des choses à travailler sur Python 3, si vous installez Les demandes vous pouvez faire quelque chose comme ceci:
Plus pertinents de la documentation dans Django ContentFile documentation et Les demandes de téléchargement de fichier exemple.
ImageField
est juste une chaîne, un chemin d'accès relatif à votreMEDIA_ROOT
réglage. Il suffit d'enregistrer le fichier (vous pouvez utiliser PIL pour vérifier qu'il est une image) et de remplir le champ avec le nom du fichier.Si elle diffère de votre code que vous avez besoin pour enregistrer la sortie de votre
urllib.urlopen
de fichier (à l'intérieur de votre emplacement), déterminer le chemin d'accès, la sauvegarde de votre modèle.Je le fais de cette façon sur Python 3, qui devrait fonctionner avec de simples adaptations sur Python 2. Ceci est basé sur ma connaissance, que les fichiers que je suis la récupération sont de petite taille. Si le vôtre ne le sont pas, je recommenderais de l'écriture de la réponse dans un fichier au lieu de mise en mémoire tampon dans la mémoire.
BytesIO est nécessaire parce que Django appels seek() sur le fichier de l'objet, et urlopen réponses n'ont pas de soutien à la recherche. Vous pouvez transmettre les octets de l'objet renvoyé par read() pour Django ContentFile à la place.
__repr__
méthode pourFile
écrit le nom. Si vous préférez, vous pouvez définir laname
attribut sur laFile
objet après la création de ce avecFile(io)
, mais dans mon expérience, il n'est pas question (à l'exception de la rendre plus agréable si vous l'imprimer). ymmv.c'est le droit et la façon de travailler