I am writing a website with python and jinja2 in google app engine. My html page is showing this on the page:
Status: 200
Content-Type: text/html;
charset=utf-8
Cache-Control: no-cache
Content-Length: 432
Any idea where this problem is coming from? Also, why is {{ initial_city }} not displaying the results?
My main.py script is:
from google.appengine.ext import db
from google.appengine.api import memcache
from models import Deal
import os
import webapp2
import jinja2
#databasestuff
deal = Deal(title='Hello',
description='Deal info here',
city='New York')
deal.put()
print deal
jinja_environment = jinja2.Environment(autoescape=True,
loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))
class MainPage(webapp2.RequestHandler):
def get(self):
template = jinja_environment.get_template('index.html')
self.response.out.write(template.render())
class DealHandler(webapp2.RequestHandler):
def get(self):
def get_deals(choose_city, update=False):
key = str(choose_city)
all_deals = memcache.get(key)
return all_deals
choose_city = self.request.get('c')
try:
initial_city = str(choose_city)
choose_city = initial_city
except ValueError:
initial_city = 0
choose_city = initial_city
template = jinja_environment.get_template('deal.html')
self.response.out.write(template.render())
class ContentHandler(webapp2.RequestHandler):
def get(self):
template = jinja_environment.get_template('content.html')
self.response.out.write(template.render())
app = webapp2.WSGIApplication([('/', MainPage),
('/deal', DealHandler),
('/content', ContentHandler)],
debug=True)
My html page:
<!DOCTYPE html>
<html>
<head>
<title>
Deallzz: Chosen City: {{ initial_city }}
</title>
</head>
...
To display initial_city, pass the variable to the template using the render method:
self.response.out.write(template.render(initial_city = initial_city))
Its the "print deal" that is causing the problem. Its being output before any response.write
This is just the headers of the HTML page. You should provide more informations/code of what you are trying now.
Related
I am trying to populate a Datastore with my older course notes so that in future I can add notes like a comments board or guestbook.
I can't seem to get the previous notes in the Datastore and have been trolling over GAE documentation and searching the web to no avail.
Here is my code:
import time
import cgi
import os
import jinja2
import webapp2
from google.appengine.ext import ndb
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir), autoescape = True)
dataEntery = [[1, 4, 'Networks','''
<p>A network is a group of entities that can communicate, even </p>'''],
[2, 4, 'Measuring Networks','''
<p>The two main ways of measuring a network are;</p>
'''], etc]
class CourseData(ndb.Model):
id_index = ndb.IntegerProperty()
stage_number = ndb.IntegerProperty()
note_title = ndb.StringProperty(indexed=False)
note_content = ndb.StringProperty(indexed=False)
for a in dataEntery:
newEntry = CourseData(id_index=a[0], stage_number=a[1], note_title=a[2], note_content=a[3])
newEntry.put()
time.sleep(.2)
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.out.write('''
<!DOCTYPE HTML>
<html>
<head>
<title>Lee's Notes</title>
<link href="../styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1 class="opener">Lee's Notes on Intro to Programming</h1>
''')
query = CourseData.query(stage_number == 4).fetch()
self.response.out.write('<article id="note%s"><h2>%s</h2>' % cgi.escape(query.note_title), cgi.escape(query.note_title))
self.response.out.write('%s</article>' % cgi.escape(query.note_content))
app = webapp2.WSGIApplication([
('/', MainHandler)], debug=True)
First thing to note is that the appengine datastore is eventually consistent. Read this article: https://cloud.google.com/appengine/docs/python/datastore/structuring_for_strong_consistency?hl=en
For you're case you don't really need a query. Make a good index and then retrieval is a lot easier with a key.get(). Note, this is assuming you don't want to use id_index...
for a in dataEntery:
entityKey = ndb.Key(CourseData._get_kind(), stage_number=a[1])
newEntry = CourseData(key=entityKey, id_index=a[0], stage_number=a[1], note_title=a[2], note_content=a[3])
newEntry.put()
Retrieval then becomes:
entity_key = CourseData.build_key(4)
I am trying to build a basic blog model using Google App Engine in Python. However, something's wrong with my code I suppose, and I am getting a 404 error when I try to display all the posted blog entries on a single page. Here's the python code:
import os
import re
import webapp2
import jinja2
from string import letters
from google.appengine.ext import db
template_dir = os.path.join(os.path.dirname(__file__), 'templates')
jinja_env = jinja2.Environment(loader = jinja2.FileSystemLoader(template_dir), autoescape=True)
class Handler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
def render_str(self, template, **params):
t = jinja_env.get_template(template)
return t.render(params)
def render(self, template, **kw):
self.write(self.render_str(template, **kw))
def post_key(name = "dad"):
return db.Key.from_path('blog', name)
class Blogger(db.Model):
name = db.StringProperty()
content = db.TextProperty()
created = db.DateTimeProperty(auto_now_add = True)
def render(self):
self._render_text = self.content.replace('\n', '<br>')
return render_str("post.html", p = self)
class MainPage(Handler):
def get(self):
self.response.write("Visit our blog")
class BlogHandler(Handler):
def get(self):
posts = db.GqlQuery("SELECT * FROM Blogger order by created desc")
self.render("frontblog.html", posts = posts)
class SubmitHandler(Handler):
def get(self):
self.render("temp.html")
def post(self):
name = self.request.get("name")
content = self.request.get("content")
if name and content:
a = Blogger(name = name, content = content, parent = post_key())
a.put()
self.redirect('/blog/%s' % str(a.key().id()))
else:
error = "Fill in both the columns!"
self.render("temp.html", name = name, content = content, error = error)
class DisplayPost(Handler):
def get(self, post_id):
po = Blogger.get_by_id(int(post_id))
if po:
self.render("perma.html", po = po)
else:
self.response.write("404 Error")
app = webapp2.WSGIApplication([('/', MainPage),
('/blog', BlogHandler),
('/blog/submit', SubmitHandler),
('/blog/([0-9]+)', DisplayPost)], debug=True)
After posting my content, it gets redirected to a permalink. However, this is the error I am getting on submitting my post:
404 Not Found
The resource could not be found
Here's the frontblog.html source code, in case that would help:
<!DOCTYPE html>
<html>
<head>
<title>CS 253 Blog</title>
</head>
<body>
<a href="/blog">
CS 253 Blog
</a>
<div id="content">
{% block content %}
{%for post in posts%}
{{post.render() | safe}}
<br></br>
{%endfor%}
{% endblock %}
</div>
</body>
</html>
So basically, I am not being redirected to the permalink page. What seems to be the problem?
When you create your post, you're giving it a parent (not sure why). But when you get it, you do so by the ID only, and don't take into account the parent ID. In the datastore, a key is actually a path consisting of all the parent kinds and IDs/names and then those of the current entity, and to get an object you need to pass the full path.
Possible solutions here:
Drop the parent key, since it isn't doing anything here as you're always setting it to the same value;
Use it when you get the object: Blogger.get_by_id(post_id, parent=parent_key()) - obviously this only works if the parent is always the same;
Use the full stringified key in the path, rather than just the ID, and do Blogger.get(key) - you'll also need to change the route regex to accept alphanumeric chars, eg '/blog/(\w+)', and change the redirect to '/blog/%s' % a.key().
I'm following this tutorial to learn how to get OAuth2.0 login onto my site, and I'm having some problems. My site is registered on GAE and I have my client ID. I also pip installed google-api-python-client. However, I don't know what to import into my project. I have two pages in my application. One that handles authorization and one that actually has the page.
authorize.py
import cgi, webapp2
from google.appengine.api import users
LOGIN_PAGE_HTML="""\
<html>
<body>
<input type="submit" method="post" action="/AuthorizeUser"/>
</body>
</html>
"""
class LoginPage(webapp2.RequestHandler):
def get(self):
self.response.write(LOGIN_PAGE_HTML)
class AuthorizeUser(webapp2.RequestHandler):
def post(self):
state = ''.join(random.choice(string.ascii_uppercase + string.digits)for x in xrange(32))
session['state'] = state
response = make_response('/LandingPage',
CLIENT_ID='MY ID',
STATE=state
APPLICATION_NAME='Summit Tech Help'))
if request.args.get('state','') != session['state']:
response = make_response(json.dumps('Invalid state parameter.'), 401)
response.headers['Content-Type'] = 'application/json'
return response
application = webapp2.WSGIApplication([
('/',LoginPage),
('/AuthorizeUser',AuthorizeUser),
], debug=True)
landing.py
import cgi, webapp2
from google.appengine.api import mail
LANDING_PAGE_HTML="""\
<html>
<body>
<p>test</p>
</body>
</html>
"""
class LandingPage(webapp2.RequestHandler):
def get(self):
self.response.write(LANDING_PAGE_HTML)
application = webapp2.WSGIApplication([
('LandingPage',LandingPage),
],debug=True)
My app.yaml has '-url: /.*' set to script:authorize.application
Any help would be much appreciated!
~Carpetfizz
to use a 3rd party module you need to import it in your app, if that's what you meant to ask,
also do check this link to use external libraries in gae.
You can check this example app for using Oauth2.0 in GAE
This is what I got from flex 4 file reference upload:
self.request =
Request: POST /UPLOAD
Accept: text/*
Cache-Control: no-cache
Connection: Keep-Alive
Content-Length: 51386
Content-Type: multipart/form-data; boundary=----------ei4cH2gL6ae0ei4ae0gL6GI3KM7ei4
Host: localhost:8080
User-Agent: Shockwave Flash
------------ei4cH2gL6ae0ei4ae0gL6GI3KM7ei4
Content-Disposition: form-data; name="Filename"
36823_117825034935819_100001249682611_118718_676534_n.jpg
------------ei4cH2gL6ae0ei4ae0gL6GI3KM7ei4
Content-Disposition: form-data; name="Filedata"; filename="36823_117825034935819_100001249682611_118718_676534_n.jpg"
Content-Type: application/octet-stream
���� [AND OTHER STRANGE CHARACTERS]
My class:
class Upload(webapp.RequestHandler):
def post(self):
content = self.request.get("Filedata")
return "done!"
Now what I'm missing in the Upload class in order to save that file to disk?
i have in the content var some strange characters (viewing in debug).
An App Engine application cannot:
write to the filesystem. Applications must use the App Engine
datastore for storing persistent data.
What you need to do is presenting a form with a file upload field to the user.
When the form is submitted, the file is uploaded and the Blobstore creates a blob from the file's contents and returns a blob key useful to retrieve and serve the blob later.
The maximum object size permitted is 2 gigabytes.
Here is a working snippet that you can try as is:
#!/usr/bin/env python
#
import os
import urllib
from google.appengine.ext import blobstore
from google.appengine.ext import webapp
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
class MainHandler(webapp.RequestHandler):
def get(self):
upload_url = blobstore.create_upload_url('/upload')
self.response.out.write('<html><body>')
self.response.out.write('<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
self.response.out.write("""Upload File: <input type="file" name="file"><br> <input type="submit"
name="submit" value="Submit"> </form></body></html>""")
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
upload_files = self.get_uploads('file')
blob_info = upload_files[0]
self.redirect('/serve/%s' % blob_info.key())
class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self, resource):
resource = str(urllib.unquote(resource))
blob_info = blobstore.BlobInfo.get(resource)
self.send_blob(blob_info)
def main():
application = webapp.WSGIApplication(
[('/', MainHandler),
('/upload', UploadHandler),
('/serve/([^/]+)?', ServeHandler),
], debug=True)
run_wsgi_app(application)
if __name__ == '__main__':
main()
EDIT1:
in your specific case you could use a BlobProperty (limited to 1MB) to store your request:
class Photo(db.Model):
imageblob = db.BlobProperty()
then adapt your webapp.RequestHandler to save your request:
class Upload(webapp.RequestHandler):
def post(self):
image = self.request.get("Filedata")
photo = Photo()
photo.imageblob = db.Blob(image)
photo.put()
EDIT2:
You don't need to change your app.yaml, just add a new handler and map it in your WSGI.
To retrieve the stored photo you should add another handler to serve your photos:
class DownloadImage(webapp.RequestHandler):
def get(self):
photo= db.get(self.request.get("photo_id"))
if photo:
self.response.headers['Content-Type'] = "image/jpeg"
self.response.out.write(photo.imageblob)
else:
self.response.out.write("Image not available")
then map your new DownloadImage class:
application = webapp.WSGIApplication([
...
('/i', DownloadImage),
...
], debug=True)
You would be able to get images with a url like:
yourapp/i?photo_id = photo_key
As requested, if for any odd reason you really want to serve your images using this kind of url www.mysite.com/i/photo_key.jpg , you may want to try with this:
class Download(webapp.RequestHandler):
def get(self, photo_id):
photo= db.get(db.Key(photo_id))
if photo:
self.response.headers['Content-Type'] = "image/jpeg"
self.response.out.write(photo.imageblob)
else:
self.response.out.write("Image not available")
with a slightly different mapping:
application = webapp.WSGIApplication([
...
('/i/(\d+)\.jpg', DownloadImage),
...
], debug=True)
I don't know why I can't upload my file? When I hit submit instead of redirecting to the default page (which is http://localhost:8082), it redirects to http://localhost:8082/sign. I didn't build no such path, so it return link broken. Here's my html:
<form action="/sign" enctype="multipart/form-data" method="post">
<div><label>Excel file submit:</label></div>
<div><input type="file" name="excel"/></div>
<div><input type="submit" value="Upload file"></div>
</form>
my app.yaml:
application: engineapp01
version: 1
runtime: python
api_version: 1
handlers:
- url: /js
static_dir: js
- url: /css
static_dir: css
- url: .*
script: main.py
main.py:
import os;
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template
from google.appengine.ext import db
from mmap import mmap,ACCESS_READ
from xlrd import open_workbook
class Account(db.Model):
name = db.StringProperty()
type = db.StringProperty()
no = db.IntegerProperty()
co = db.IntegerProperty()
class MyFile(db.Model):
filedata = db.BlobProperty()
class MainHandler(webapp.RequestHandler):
def get(self):
#delete all old temporary entries
query = Account.all()
results = query.fetch(limit=40)
db.delete(results)
#temporary entry
acc = Account(name='temporaryAccountName',
type='temporaryType',
no=0,
co=500)
acc.put()
temp = os.path.join(os.path.dirname(__file__),'templates/index.htm')
tableData = ''
query = Account.all()
query.order('name')
results = query.fetch(limit=20)
for account in results:
tempStr= """
<tr>
<td align='left' valign='top'>%s</td>
<td align='left' valign='top'>%s</td>
<td align='left' valign='top'>%d</td>
<td align='left' valign='top'>%d</td>
</tr>""" % (account.name,account.type,account.no,account.co)
tableData = tableData + tempStr
outstr = template.render(
temp,
{'tabledata':tableData})
self.response.out.write(outstr)
def post(self):
myFile = MyFile()
excel = self.request.get("excel")
myFile.fileData = db.Blob(excel)
myFile.put()
self.redirect('/')
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
Why are you sending the form data to a page that doesn't exist?
Try changing the HTML to:
<form action="/" enctype="multipart/form-data" method="post">
...
...since "/" is where your form-handling code resides.