Search code examples
pythonimagethumbnailsweb2pyweb2py-modules

Image Thumbnail in Web2py: Unable to display the thumbnail


I have used the suggestion here http://www.web2pyslices.com/slice/show/1387/upload-image-and-make-a-thumbnail to make a thumbnail of an image. I have got the thumbnail but I am unable to display it.

The following are my functions: db.py :

db.define_table('uploads', Field('dataset', 'reference dataset'),

Field('filename', represent = lambda x, row: "None" if x == None else [:45]),

Field('image', 'upload', uploadseparate=True, requires=IS_NOT_EMPTY() and IS_IMAGE(extensions=('jpeg', 'png','jpg','tif')) ),
Field('thumb', 'upload', uploadseparate=True, requires=IS_NOT_EMPTY() and IS_IMAGE(extensions=('jpeg', 'png', 'jpg', 'tif'))))

default.py :

def makeThumbnail(dbtable,ImageID,size=(150,150)):
    try:
       thisImage=db(dbtable.id==ImageID).select()[0]
       import os, uuid
       from PIL import Image
    except: return
    im=Image.open(request.folder + 'uploads/' + thisImage.image)
    im.thumbnail(size,Image.ANTIALIAS)
    thumbName='uploads.thumb.%s.jpg' % (uuid.uuid4())
    im.save(request.folder + 'uploads/' + thumbName,'jpeg')
    thisImage.update_record(thumb=thumbName)
    return


def insertImage():
    response.menu = [
    (T('Home'),False,URL('default','experimenter')),
    (T('Manage Data Set'),False,URL('default','MDS')),
    (T('Manage Experiment'),False,URL('default','ME')),
    (T('Manage Workflow Element'),False,URL('default','MWE'))]        
    dbtable = db.uploads 
    record = None
    record = db(db.dataset.id ==  request.args[0],ignore_common_filters=True).select().first()
    form = FORM(dbtable, INPUT(_name='up_files', _type='file',
    _multiple=True, requires=IS_NOT_EMPTY()),INPUT(_type='submit')) 
    # The multiple param lets us choose multiple files.
    if form.process().accepted:
    #onvalidation checks the uploaded files to make sure they are only txt,         config, or log.
    makeThumbnail(dbtable,form.vars.id,(300,300))
    response.flash = 'files uploaded' 
    files = request.vars['up_files'] 
       if not isinstance(files, list): 
    #convert files to a list if they are not one already.
        files = [files]
       for file in files:         
         db.uploads.insert(dataset=record.id, filename=file.filename, image=db.uploads.image.store(file, file.filename))

        #store is a FIELD method that let's you save a file to disk.  you can choose the directory if you want using the 'path' param.
    else:
        response.flash = 'Choose the Files you would like to upload'
   return dict(form=form, record=record)

And then the view:

{{extend 'layout.html'}}
<h4>Manage Image of dataset: {{=record.name}}</h4>

{{if images:}}
<div style="overflow: auto;" width="80%">
<table>
<tr> <th> Image </th> </tr>
{{
    for image in images:
    =TR(TD(image.filename),  IMG(_src=URL('default', 'download',    args=image.thumb)), A(str(T('View')),_href=URL("show", args=[image.id,rowId])), A(str(T('Delete')),_href=URL('deleteImage',args=image.id)))}}
    {{pass}}
</table>

</div>
{{pass}}

Note: I am trying to display the the thumbnails for a each image in a list of images.(see the View). I am not getting the thumbnail but rather small question marks in its place. PS: i am unable to upload the image. I want images in place of question mark. I am doing something wrong in insertImage() function and also in the view. Thanks in Advance for the help!


Solution

  • First, you appear to be conflating FORM and SQLFORM. The former is for creating custom forms (not connected with any database tables), and the latter is for building a form based on a database table (and therefore automatically handling inserts). You cannot pass a DAL Table object to FORM as in your code -- that will simply serialize the Table object to its string name, which will be included in the HTML form DOM to no effect. Further, in this case, form.vars.id will simply be None (FORM does not generate record IDs, as it does not do any database inserts).

    Also, rather than directly saving the file in makeThumbnail, a better option would be to save the image to a StringIO object and then pass that object to db.uploads.thumbnail.store() (as you do for storing the original image). In that case, the .store() method of the thumbnail field will handle the file naming and saving automatically.

    from cStringIO import StringIO
    tmp = StringIO()
    im.save(tmp, 'jpeg')
    tmp.seek(0)
    thisImage.update_record(thumb=db.uploads.thumb.store(tmp, filename='thumbnail.jpg'))
    

    For more details, see http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer.