Download a remote image and save it to a Django model

后端 未结 6 903
醉话见心
醉话见心 2020-12-01 01:52

I am writing a Django app which will fetch all images of particular URL and save them in the database.

But I am not getting on how to use ImageField in Django.

相关标签:
6条回答
  • 2020-12-01 02:30

    Try doing it this way instead of assigning path to the image...

        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
    

    use the above function like this..

        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.
    
    0 讨论(0)
  • 2020-12-01 02:32

    As an example of what I think you're asking:

    In forms.py:

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

    In models.py:

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

    So there will be a POST request from the user (when the user completes the form). That request will contain basically a dictionary of data. The dictionary holds the submitted files. To focus the request on the file from the field (in our case, an ImageField), you would use:

    request.FILES['imgfield']
    

    You would use that when you construct the model object (instantiating your model class):

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

    To save that the simple way, you'd just use the save() method bestowed upon your object (because Django is that awesome):

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

    Your image will be stored, by default, to the directory you indicate for MEDIA_ROOT in settings.py.

    Accessing the image in the template:

    <img src="{{ MEDIA_URL }}{{ image.imgfile.name }}"></img>
    

    The urls can be tricky, but here's a basic example of a simple url pattern to call the stored images:

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

    I hope it helps.

    0 讨论(0)
  • 2020-12-01 02:40

    Similar to @boltsfrombluesky's answer above you can do this in Python 3 without any external dependencies like so:

    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
    
    0 讨论(0)
  • 2020-12-01 02:43

    If you want to save downloaded images without saving them to disk first (without using NamedTemporaryFile etc) then there's an easy way to do that.

    This will be slightly quicker than downloading the file and writing it to disk as it is all done in memory. Note that this example is written for Python 3 - the process is similar in Python 2 but slightly different.

    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))
    

    Where your_model is an instance of the model you'd like to save to and .image_field is the name of the ImageField.

    See the documentation for io for more info.

    0 讨论(0)
  • 2020-12-01 02:43
    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 
    
    0 讨论(0)
  • 2020-12-01 02:50

    Django Documentation is always good place to start

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

    UPDATED

    So this script works.

    • Loop over images to download
    • Download image
    • Save to temp file
    • Apply to model
    • Save model

    .

    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:
        # Stream the image from the url
        response = requests.get(image_url, stream=True)
    
        # Was the request OK?
        if response.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 response.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 it is valid
        image.image.save(file_name, files.File(lf))
    

    Some reference links:

    1. requests - "HTTP for Humans", I prefer this to urllib2
    2. tempfile - Save temporay file and not to disk
    3. Django filefield save
    0 讨论(0)
提交回复
热议问题