Python App Engine - Blobstore for non-images - python

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

Related

Error in my code from transferring data from flask variable in python to html file

I am creating a flask web application which asks users to complete a quiz through a form and collect data from each session. I use a main.py file, 1 html file with the quiz, and then another one which is supposed to display dynamic results. When the submit button is clicked, it automatically directs users to the second html page with their results. It is my intention to display results based upon what options the user clicks. I attempted to accomplish this by:
Collecting data:
session["symptom1"] = form.symptom1.data
Writing this into a file
user_data.write(form.symptom1.data)
Reading file contents into a variable (3 characters into each variable)
data1 = user_data.read(3)
Assigning a Boolean value to a python variable based upon the data using a conditional:
if data1 == "op3" or data1 == "op4":
global adhd1
adhd1 = True
Rendering this to an html file:
return render_template("takethequiz.html", form = form,adhd1=adhd1,adhd2=adhd2,adhd3=adhd3,adhd4=adhd4)
Creating a conditional in a second html file (treatmentplan.html)=
{% if adhd1 == True %}
Use productivity apps to increase your focus
{% else %}
Great job! You are skilled at staying on task!
{% endif %}
However this does not do anything. Meaning, no matter what I click, the treatment plan is always set to adhd1 = False. How do I combat this?
Code Screenshots on Google Doc: https://docs.google.com/document/d/1uF1Q-zfKNx-d5jzbaIK_BKGbLRm0tCGgaz92-V2hDjE/edit?usp=sharing
Thank you!

Access to file uploaded with FileField Django

I'm trying to create a Django form with a filefield to upload a pdf based on a model.
#models.py
class ProductionRequest(models.Model):
...
contract_file = models.FileField('Contract file (PDF)', upload_to='contracts/')
...
I can upload the file and save it in my object, but when I try to show the file in my template with this code
{{ prod_req.contract_file }}
it only show me the path to the file
"contracts/file_uploaded.pdf". How can I make a link to download (or open in a new tab ) the file ?
Plus : when I try to open the file from Django admin, with this link
Contract file (PDF) : Currently: contracts/file_uploaded.pdf
I don't show me the file, i got this :
Page not found (404) Request URL: http://127.0.0.1:8000/admin/appname/productionrequest/1/change/contracts/file_uploaded.pdf/change/
How can I access to my file ?
It works just like a Python file. So, the way you have just refers to a file object.
To get the text, you need to use f.read(). So, in your template, instead of
{{ prod_req.contract_file }}
use
{{ prod_req.contract_file.read }}
BUT, note that calling read moves the cursor to the end of the file. The first time you call read on a file, it returns all the text. The second time, it returns nothing. This is only a problem if you need the text twice, but in that case, store the text directly on the context object.
Let me know if anything was unclear.

Issues in displaying a flash message in my HTML page

I just started to learn python some months ago...
I would like to display an message when there is no result for a query in my Query page (html). I am using python and flask. The code that I tried did not display any message.
My id.html code is (I included the code outside the search form):
<div class="flashes">
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
</div>
And my python code is:
#app.route('/id')
def id():
params={}
params['entryname']='Search ID'
idn=request.args.get('idn')
sql=text('select * from DATA where info LIKE :id')
words=engine.execute(sql,id=idn).fetchall()
params['objs']=words
if params['objs']==0:
flash('No Results')
return render_template('id.html', **params)
I also tried this just for testing and did not work
if params['objs']>0:
flash('Results')
I am not sure what is wrong in my code, the query search is working, but no message...
"I also tried this just for testing and did not work"
if params['objs']>0:
flash('Results')
I don't use Python but it sounds like you're trying to check the size to make sure it contains something? If yes, then possibly this logic might help you :
Either use is_empty or the len properties :
if is_empty(params)==True:
flash('No Results')
if len(params)==0:
flash('No Results')
Also if you wanted bigger-than then write as : if len(params) > 0: flash('Results')

Why am I getting this syntax error in my python-jinja2 app

I am new to python and the google app engine. I am trying to create this app that fetches feed from yahoo pipes and displays it using jinja2 templates. However I am getting a syntax error and I am not understanding the reason behind it.
import webapp2
from webapp2_extras import jinja2
import logging
import feedparser
import urllib
class BaseHandler(webapp2.RequestHandler):
#webapp2.cached_property
def jinja2(self):
return jinja2.get_jinja2(app=self.app)
def render_response(self, _template, **context):
rv = self.jinja2.render_template(_template, **context)
self.response.write(rv)
class MainHandler(BaseHandler):
def get(self):
feed = feedparser.parse("http://pipes.yahoo.com/pipes/pipe.run?_id=1nWYbWm82xGjQylL00qv4w&_render=rss&textinput1=dogs" )
feed = [{"link": item.link, "title":item.title, "description" : item.description} for item in feed["items"]
context = {"feed" : feed, "search" : "dogs"}
self.render_response('index.html', **context)
def post(self):
terms = self.request.get('search_term')
terms = urllib.quote(terms)
feed = feedparser.parse("http://pipes.yahoo.com/pipes/pipe.run?_id=1nWYbWm82xGjQylL00qv4w&_render=rss&textinput1=" + terms )
feed = [{"link": item.link, "title":item.title, "description" : item.description} for item in feed["items"]]
context = {"feed": feed, "search": terms}
self.render_response('index.html', **context)
app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)
Here is the index.html file
<!DOCTYPE html>
<html>
<head>
<title>Byte 1 Tutoral</title>
</head>
<body>
<h1>Data Pipeline Project Byte 1 Example</h1>
<form action="search" method="POST">
Search Term: <input name="search_term" value={{search}}><br>
<input type="submit" value="Enter Search Term">
</form>
{% if search: %}
<p>Searching for {{search}}</p>
{% endif %}
<h2>Feed Contents</h2>
{% for item in feed %}
{{ item.title }}<br>
{{item.description|safe}}
<br>
{% endfor %}
</body>
</html>
and this is the error that I am getting.
Traceback (most recent call last):
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 239, in Handle
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 298, in _LoadHandler
handler, path, err = LoadObject(self._handler)
File "C:\Program Files (x86)\Google\google_appengine\google\appengine\runtime\wsgi.py", line 84, in LoadObject
obj = __import__(path[0])
File "C:\googleapps\ykelkar-byte1\main.py", line 38
context = {"feed" : feed, "search" : "dogs"}
^
SyntaxError: invalid syntax
INFO 2014-01-16 23:15:25,845 module.py:612] default: "GET / HTTP/1.1" 500 -
Thanks.
There should be one more ] at then end of line37:
feed = [{"link": item.link, "title":item.title, "description" : item.description} for item in feed["items"]]
There's two syntax errors:
missing ] from the end of line 37
Incorrect indenting of the post function in MainHandler. Python syntax is indent sensitive, so it's very important to keep it consistent.
When looking for syntax errors, read the error message as carefully as possible. When you're starting out, a lot of it may not make much sense, but try and work out as much as possible. In this case, the reference to Line 38 is a good tip. Read that line carefully, and if it looks okay, start looking above it.
It's also really handy to use an editor that support syntax highlighting, which will make these sorts of syntax errors immediately obvious.

Troubleshooting dynamically generated KML

I use dynamically generated KML that fails intermittently seemingly because of "timing issues" with Google's server's. Last time I checked it worked but that seems like a coincident. Should I make a cron job that accesses the page every 5 minutes to make data stay fresh in memory? The serverside KML generator is:
class KMLHandler(webapp2.RequestHandler):
def get(self):
self.response.headers['Cache-Control'] = 'public,max-age=%s' \
% 86400
start = datetime.datetime.now() - timedelta(days=60)
from google.appengine.api import memcache
memcache_key = 'ads'
data = memcache.get(memcache_key)
if data is None:
a = Ad.all().filter('modified >',
start).filter('published =',
True).order('-modified').fetch(1000)
memcache.set('ads', a)
else:
a = data
dispatch = 'templates/kml.html'
template_values = {'a': a, 'request': self.request,
'host': os.environ.get('HTTP_HOST',
os.environ['SERVER_NAME'])}
path = os.path.join(os.path.dirname(__file__), dispatch)
output = template.render(path, template_values)
self.response.headers['Content-Type'] = \
'application/vnd.google-earth.kml+xml'
self.response.headers['Content-Length'] = len(output)
self.response.out.write(output)
--
The template file is:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
{% for ad in a %}
{% if ad.geopt %}
<Placemark><name></name><description>
<![CDATA[{% if ad.uri2view %}<img src="{{ ad.uri2view }}">{% endif %} {{ ad.title }} <br/>{{ad.text|truncatewords:20}}]]></description><Point><coordinates>{{ad.geopt.lon|floatformat:2}},{{ad.geopt.lat|floatformat:2}}</coordinates></Point></Placemark>{% endif %}{% endfor %}</Document></kml>
--
I've also run the output through a KML validator to ensure that it is correct. It is dynamically generated and I try to cache it. It just fails intermittently for no apperant reason. I have Python that generates the KML and the code is checked and should be working. I don't see where the program is wrong? I can take the output of my script, save it as a static kml file, and that works and the KML is valid so it seems there are "timing issues" in serving it to google when it is being dynamically generated. But how can I troubleshoot this further? I could change the whole strategy to using JSON instead but that will be a lot of recoding and I think I'm close to making it work.
The 3 strategies I can think of is
Change to Jinja2 templates
Change to JSON instead of KML
Write a cron job that accesses the file every 5 minutes to keep the data in memcache
Thanks for any help
I suspect it's taking too long to build your KML so Google is giving up. I tested the link a few times and each time it took several seconds to load, sometimes >5 seconds. The servers that download and render these KML files will time out / give up if the file can't be loaded quickly. This sort of behavior is consistent with intermittent failures when the file can't be loaded sometimes or the cache (when a good load has occured) expires.
If the process that generates the KML can't be improved, you should cache the actual file data you generate so you can return it quicker in the future. Using the Task Queue API / Cron you could keep that cache up to date by running a rebuild task every N minutes.

Categories

Resources