views:

61

answers:

3

I'm trying to get multiple image paths from my database in order to display them, but it currently doesn't work.

Here's what i'm using:

def get_image(self, userid, id):
    image = meta.Session.query(Image).filter_by(userid=userid)
    permanent_file = open(image[id].image_path, 'rb')
    if not os.path.exists(image.image_path):
        return 'No such file'
    data = permanent_file.read()
    permanent_file.close()
    response.content_type = guess_type(image.image_path)[0] or 'text/plain'
    return data

I'm getting an error regarding this part:

image[id].image_path

What i want is for Pylons to display several jpg files on 1 page. Any idea how i could achieve this?

+1  A: 

Twice you use image.image_path, but in one spot (where, you tell us, you get a mistake) you use image[id].image_path instead. What's id that you believe could be a proper index into image, and why the discrepancy in usage among different spots of your code?

If you want a certain number of images, why not use slicing syntax? E.g. you can get the first 10 images (be sure to include an order_by to get predictable, repeatable results) you can slice the results of the filter_by by [0:10]; the second 10 images, [10:20]; and so forth.

Alex Martelli
+1  A: 

My guess is that what you were assuming/hoping is that the result of the filter_by query contains a dictionary mapping the images retrieved to their ids. Instead it holds a query object which represents a promise to return an iterable result set when it is forced to by an access to either a slice expression like Alex mentioned or an iteration operation.

This probably isn't the best way to solve this problem, but my guess is that modifying your code to look like this will probably accomplish what you want:

def get_image(self, userid, id):
    image = meta.Session.query(Image).filter_by(userid=userid)
    image = dict((img.id, img) for img in image)
    permanent_file = open(image[id].image_path, 'rb')
    if not os.path.exists(image.image_path):
        return 'No such file'
    data = permanent_file.read()
    permanent_file.close()
    response.content_type = guess_type(image.image_path)[0] or 'text/plain'
    return data

The more sensible way would be something like this:

def get_image(self, userid, id):
    image = meta.Session.query(Image).filter_by(userid=userid).filter_by(id=id).first()
    # TODO: Handle the case when image is None
    permanent_file = open(image[id].image_path, 'rb')
    if not os.path.exists(image.image_path):
        return 'No such file'
    data = permanent_file.read()
    permanent_file.close()
    response.content_type = guess_type(image.image_path)[0] or 'text/plain'
    return data

Of course you're assuming that an image exists that matches the query and it may not, so you should probably have some error handling for that where I left the TODO comment.

Of course any of these changes will only return the data for a single image. If you want multiple images, you're going to have to call this function once for each image, probably in the request handler for some sort of image view.

If you really do want to return the raw image data for multiple images at once, then Alex's suggestion to use slicing to get back e.g. 10 records at a time from the database is probably the best way to go, but then you'll have to modify the rest of the code to iterate over the list of N images and retrieve the data for each from the file system and return something like a list of the raw image data blobs.

John
A: 

Assuming that "id" contains a number from 0 to however many images there are, you need to convert it from a string into an int before you can index an array. I'd do something like

def get_image(self, userid, id):
    images = meta.Session.query(Image).filter_by(userid=userid)
    try:
        image = images[int(id)]
        with open(image.image_path, 'rb') as f:
            data = f.read()
    except (IndexError, ValueError, IOError):
        abort(404)
    response.content_type = guess_type(image.image_path)[0] or 'application/octet-stream'
    return data
Marius Gedminas