Here, I want to inster an image from the directory to html page. I know how to do it using the exact file name but now I'm trying to do it using a variable which refers to the image name.
This is my python file where I save the image name to the database. The picture is already saved in the directory before.
//code.py
#app.route('/add_picture', methods=['POST'])
def add_picture():
if 'user_id' in session:
session['logged_in'] = True
photo = request.form.get('photo')
with sqlite3.connect('memory.db') as conn:
cursor = conn.cursor()
name = session['name']
cursor.execute('''UPDATE users SET photo=? WHERE name=?''', (photo, name))
conn.commit()
return redirect("/settings")
else:
return redirect('/')
//code.html
<img src="{{ url_for('.static', filename='images/IMG_2165.JPG') }}" width="200" height="200">
//we inster the picture by using the image name and it works
<img src="{{ url_for('.static', filename='images/{{ photo }}') }}" width="200" height="200">
//displaying the picture using the variable which refers to the image name but it returns nothing...
1- The image is already saved before in the directory.
2- I saved the image name to the database with the variable "photo".
3- The variable "photo" is being returned from another function.
4- In html I want to display the image using the variable but not the image name "IMG_2165.JPG".
Shouldn't your function return the image's path as a variable (as in return , photo, redirect('/')) ?
Related
I have a flask view function as below:
#app.route('/myfunc', methods = ['POST', 'GET'])
def myfunc():
var = request.form["samplename"]
selected_ecg=ecg.loc[ecg['Patient ID'].isin([var])]
selected_ecg = selected_ecg.drop('Patient ID', 1)
arr = np.array(selected_ecg)
y = arr.T
x=np.array(range(1,189))
plot.plot(x,y)
#Remove the old file
os.remove("static\graph.png")
#Now save the new image file
plot.savefig("static\graph.png")
return render_template("outputs.html")
Outputs.html:
<html>
<head>
</head>
<body>
<h1>Output page</h1>
<img src="static/graph.png" />
</body>
</html>
I use the flask view function to display an image through the outputs.html file. The catch here is that the static image file that is served keeps changing every time based on user inputs. In other words, I keep overwriting the image file based on the inputs the user has selected.
But the problem is that the changing image file is not served. The old image file that was used for first time render is only displayed for every new input of the user.
I have already referred to old posts regarding serving dynamic content in flask. But none of them served useful.
thebjorn's solution is valid. I have found multiple posts on Stack Overflow which suggest identical solutions. To view them, search for how to not cache images on Google. link link2 link3
Below is my solution to your problem. This will delete graph file and create new one with plot.savefig on every GET request to /myfunc. I was not sure on which request you wanted this behavior.
#app.route('/myfunc', methods = ['POST', 'GET'])
def myfunc():
var = request.form["samplename"]
selected_ecg=ecg.loc[ecg['Patient ID'].isin([var])]
selected_ecg = selected_ecg.drop('Patient ID', 1)
arr = np.array(selected_ecg)
y = arr.T
x=np.array(range(1,189))
plot.plot(x,y)
new_graph_name = "graph" + str(time.time()) + ".png"
for filename in os.listdir('static/'):
if filename.startswith('graph_'): # not to remove other images
os.remove('static/' + filename)
plot.savefig('static/' + new_graph_name)
return render_template("outputs.html", graph=new_graph_name)
Outputs.html
<html>
<head>
</head>
<body>
<h1>Output page</h1>
<img src="{{ url_for('static', filename=graph) }}" />
</body>
</html>
You're running into a caching issue. Static resources, like images, are cached at every point in the chain between your server and the browser. This is a good thing. Most reasonable systems are set up to cache images for at least 1 year at the server (and that's if they're not cached in the browser).
To bust through this cache issue, you'll need to either (i) give the files new names, (ii) reconfigure Vary headers to indicate they shouldn't be cached, or (iii) add a uniqueness fragment -- e.g. instead of using static/graph.png, add a timestamp 'static/graph.png?v=' + (new Date()).valueOf() or a md5 hash.
update: Dinko has given you a fine answer (do read the links he provides). To add cache-busting on the server side, without creating new files, you can calculate an md5 checksum (disadvantage: you'll need to read the entire file):
from hashlib import md5
fname = 'static/graph.png'
with open(fname, 'rb') as fp:
checksum = md5.new(fp.read()).hexdigest()
fname += "?v" + checksum
or use the last-modified attribute (not always reliable):
from hashlib import md5
fname = 'static/graph.png'
modified_tstamp = str(int(os.stat(fname).st_mtime * 10**6))
fname += "?v" + checksum
both of these methods will serve a cached version as long as the file doesn't change.
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!
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.
In my Python Appengine 'app' I have been asked to 'attach any file' so I have the following code snippet to 'display' those files...
blobattach = ''
blobmime = 'None'
if pattachment.blobkey <> None:
blobattach = get_serving_url(pattachment.blobkey) # <-- line 104
blob_info = blobstore.BlobInfo.get(pattachment.blobkey)
blobmime = blob_info.content_type[:5]
blobname = blob_info.filename
Using the following HTML
{% if blobmime == 'None' %}
{% else %}
{% if blobmime == 'image' %}
<img src="{{ blobattach }}" alt='Attachment'/>
{% else %}
<br/>
<small><a class="fswideb" href="{{blobattach}}" Title="Download to view"><span>Download to view {{ blobname }}</span></a></small>
{% endif %}
{% endif %}
If the attachment is an image, it is displayed (blobmime=='image'). If not, a link is displayed so the user can download the file and view it however they can.
However, while this works in development, on my laptop (Google App Engine Launcher), I get the following error when trying to 'serve' a .xls file. (No error with .jpg attachments)
File "/base/data/home/apps/s~fs-rentals/20140101.382312463312950329/fmntjobattachmaint.py", line 104, in display
blobattach = get_serving_url(pattachment.blobkey)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/images/__init__.py", line 1794, in get_serving_url
return rpc.get_result()
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
return self.__get_result_hook(self)
File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/images/__init__.py", line 1892, in get_serving_url_hook
raise _ToImagesError(e, readable_blob_key)
TransformationError
All of the examples use images and I have no problems with them, indeed no problems in development. Any thoughts on what I could have missed?
Many thanks
David
As suggested I changed the above to use Google Cloud Storage. I still get exactly the same error. The get_serving_url function errors if the blob is not an image. Is there an equivalent for a file that is not an image?
The sample at https://cloud.google.com/appengine/docs/python/tools/webapp/blobstorehandlers#BlobstoreUploadHandler provides a really good example of what I am trying to do except that I may want to add the person's CV instead of their photo.
Thanks
David
Fixed my problem. I was trying to do too much on one 'screen'
If the blob is an image - get_serving_url as above.
If the blob is not an image - display a link to a different page (target='_blank') that does the following (pretty much copied from another SO post):
if rmntjobattach.mntjobattachid <> 0 \
and rmntjobattach.blobkey:
blob_info = blobstore.BlobInfo.get(rmntjobattach.blobkey)
self.send_blob(blob_info)
else:
self.error(404)
The trick was to display an image blob on the same page and everything else on the new page when the user requested it (clicked the link)
David
Here are three Pyramid view_callables which setup a page with data and two image files. Trouble is, only one of the images (file responses) is returned. It seems I can only return one of the images at a time. If I take one of the file response vc's away, the other images is returned. However, if I have both file respone vc's there, only the second image is returned. Is there some object in the first vc I'm overwriting with the second vc?
Is there a better way to return both images (files), even within the first # title vc? As it is now, even if it worked, I have to retrieve the same document from the database 3 times for the one template. Any advice or clues would be greatly appreciated.
# title
#view_config(
route_name='title',
renderer='templates/titles/title.jinja2')
def title(request):
title = Title().find_one({'_id':ObjectId(request.matchdict['_id'])})
result = dict(
user = request.user,
title = title)
return result
# view title image
#view_config(route_name="view_title_image")
def jpg(request):
fd = Title().find_one({'_id':ObjectId(request.matchdict['title_id'])}).TitleImage
response = Response(content_type='application/jpg')
response.app_iter = fd.File
print fd
return response
# view trailer thumbnail
#view_config(route_name="view_trailer_thumbnail")
def jpg(request):
fd = Title().find_one({'_id':ObjectId(request.matchdict['title_id'])}).TrailerThumbnail
response = Response(content_type='application/jpg')
response.app_iter = fd.File
print fd
return response
Here are the route configs from __init__:
# title
config.add_route('title', '/title/{_id}')
# view title image
config.add_route('view_title_image', '/view/title_image/{title_id}')
# view title image
config.add_route('view_trailer_thumbnail', '/view/trailer_thumbnail/{title_id}')
This is how its used in the Jinja2 template:
<img src="/view/title_image/{{ title._id }}">
<img src="/view/trailer_thumbnail/{{ title._id }}">
I think your problem is that both views have the function named jpg.
Although it's not a great idea to overwrite functions like that, I would have thought that this would be no problem at all for the view_config decorator. The only thing I can think of is that rather recording a reference to the function, view_config works out what the dotted path would be and records that.
Anyway, give the view functions different names and you should be fine.
I'm working on a project and I used the the Images Python API .
For instance in the example given in http://code.google.com/appengine/docs/python/images/usingimages.html
I get an error when ever I do not upload a photo, How can I modify the code so I don't get an error when I don't post anything.
thanks
Try changing the line
avatar = images.resize(self.request.get("img"), 32, 32)
to check if self.request.get("img") is empty:
posted_avatar = self.request.get("img")
if posted_avatar:
avatar = images.resize(posted_avatar, 32, 32)
greeting.avatar = db.Blob(avatar)
greeting.put()
You can simply check if that input element of the form was populated.
From the example code:
<div><input type="file" name="img" /></div>
You'd then add a conditional (if statement) to your handler:
if self.request.get("img"):
# do image processing stuff here
Here's a simple bit of code that does what you want: http://bitbucket.org/abernier/pocasi/src/tip/handlers/admin.py#cl-102
Template code here: http://bitbucket.org/abernier/pocasi/src/tip/templates/create.html