I am just testing out displaying images on GAE, I have this little .py
import cgi
import wsgiref.handlers
from google.appengine.api import users
from google.appengine.api import images
from google.appengine.ext import db
from google.appengine.ext import webapp
class ImgUpload(db.Model):
project_name = db.StringProperty()
project_description = db.StringProperty(multiline=True)
img_name = db.StringProperty()
img_img = db.BlobProperty()
date = db.DateTimeProperty(auto_now_add=True)
class UploadPage(webapp.RequestHandler):
def get(self):
self.response.out.write("""<html><body>
<form action="/upload" enctype="multipart/form-data" method="post">
<div><label>Project Name</label></div>
<div><textarea name="title" rows="2" columns "60"></textarea></div>
<div><label>Despcription:</label></div>
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><label>Image Name</label></div>
<div><textarea name="imgname" row="1" cols="60"></textarea></div>
<div><label>Image</label></div>
<div><input type="file" name="img"/></div>
<div><input type="submit" value="Upload" /></div>
</form>
</body>
</html>""")
def post(self):
images = ImgUpload()
project_name = self.request.get('title')
project_description = self.request.get('content')
img_img = self.request.get('img')
img_name = self.request.get('imgname')
images.img_img = db.Blob(img_img)
images.project_name = project_name
images.project_description = project_description
images.img_name = img_name
images.put()
self.redirect('/upload')
class DisplayPage(webapp.RequestHandler):
def get(self):
display = db.GqlQuery("SELECT * "
"FROM display "
"WHERE ANCESTOR IS :1 "
"ORDER BY date DESC LIMIT 5"
)
for record in display:
self.response.out.write('<b>%s</> is the Name' % record.project_name)
def main():
application = webapp.WSGIApplication(
[('/', UploadPage),
('/display', DisplayPage)
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__=="__main__":
main()
When I run this, I get a KindError: No implementation for kind 'display'. Is this an issue pertaining to lack of a DB key, I know they data is in the store, I can see it in the admin, and I can't see any naming issue (at least off the top of my head, there could be thousands for all that I know). What exactly is causing this error to pop? Thank you in advance for your advice.
In your GQL you are selecting from the "display" kind. You don't have a display kind defined, you have a "ImgUpload" kind defined. Using the object interface to query will help you avoid this type of problem.
I also don't see a parameter being passed to the query for it to filter on, so you're going to get another error there.
Related
I'm learning python with book "Learn python the hard way"
I'm doing the web exercise, but I can't find a concrete information.
import web
urls =( '/hello', 'Index')
app = web.application(urls,globals())
render = web.template.render(<mypath>)
class Index(object):
def GET(self):
return render.hello_form()
def POST(self):
form = web.input(name="Nobody", greet="Hello")
greeting = "%s, %s" %(form.greet, form.name)
return render.index(greeting = greeting)
then... in my "hello_form"
<form action="/hello" method="POST">
A greeting <input type=text" name="greet">
<br/>
Your Name: <input type="text" name="name">
<br/>
<input type="submit>
</form>
well, I can't access to the action="/hello".
but I can access with action="/" well I don't know which is the reason
Someone could explain me?
when you run you app.py bu default you are directed here:
http://0.0.0.0:8080/
But it says to you "File Not Found" because you have to go here:
http://0.0.0.0:8080/hello
So either you change your app.py keeping only / in your urls
either you add manually /hello in your URL.
Cheers,
Filiberto
I have use ImageField in my django model to have the image upload facility. ImageField uses the ClearableFileInput widget but it does not provide well formatted html markup that i can customize using CSS. Shown bellow is the html markup that rendered by ClearableFileInput.
<div class="form-group" id="div_id">
<label class="control-label " for="id_image">
Guide
</label>
<div class="controls ">
Currently:
de.png
<input type="checkbox" name="image_" id="image_">
<label for="image_te">
Clear
</label><br>
Change:
<input type="file" name="image_te" id="id_i" class="clearablefileinput">
</div>
</div>
Simply what i want to do is to add custom css classes to these elements and change the order as i want. It would be really great if someone can suggest me a solution to this.
Just make your own Input class and alter the render callable to whatever you want. As an example, here's one I made to add in a little avatar. It's quick and dirty, in that it's not DRY, but it serves a purpose:
class AvatarInput(ClearableFileInput):
'''renders the input file as an avatar image, and removes the 'currently' html'''
template_with_initial = u'%(initial)s %(clear_template)s<br />%(input_text)s: %(input)s'
def render(self, name, value, attrs=None):
substitutions = {
'input_text': self.input_text,
'clear_template': '',
'clear_checkbox_label': self.clear_checkbox_label,
}
template = u'%(input)s'
substitutions['input'] = super(AvatarInput, self).render(name, value, attrs)
if value and hasattr(value, "url"):
template = self.template_with_initial
substitutions['initial'] = (u'<img src="%s" width="60" height="60"></img>'
% (escape(value.url)))
if not self.is_required:
checkbox_name = self.clear_checkbox_name(name)
checkbox_id = self.clear_checkbox_id(checkbox_name)
substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name)
substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id)
substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id})
substitutions['clear_template'] = self.template_with_clear % substitutions
return mark_safe(template % substitutions)
Then just drop it into your form class Meta:
class Meta:
model = <your model>
widgets = {'your-field-name': AvatarInput()
I'm using this link as an example to uploading images:
https://gist.github.com/jdstanhope/5079277
My HTML code:
<form action="/upload_image" method="post" id="form1" runat="server">
<div class="fileButtons">
<input type='file' id="imgInp" name="imgInput" accept="image/*"/><br><br>
<input type='button' id='remove' value='Remove' />
</div></form>
main.py:
class SetImage(webapp2.RequestHandler):
def post(self):
logging.debug("test")
id = str(self.request.get('id'))
image = self.request.get('imgInput')
app = webapp2.WSGIApplication([('/upload_image', SetImage),
('/', MainPage)], debug=True)
But when I add an image, nothing is being done, and the log console doesn't print:
logging.debug("test")
The recommended way of uploading images to GAE is by using blobstore.
Here is a quick breakdown of the doc to help you achieve this fast:
Imports:
import os
import urllib
import webapp2
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
Serve the form HTML. this form performs the POST to GAE with the selected files data:
class MainHandler(webapp2.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>""")
Add a handler for receiving the POST data (binary content of the file). the last line in this function is to redirect the response to the location from where the file could be downloaded:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
# 'file' is file upload field in the form
upload_files = self.get_uploads('file')
blob_info = upload_files[0]
self.redirect('/serve/%s' % blob_info.key())
Add handler to serve the image that you uploaded using the UploadHandler described above:
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)
And finally, define the routes for the app:
app = webapp2.WSGIApplication([('/', MainHandler),
('/upload', UploadHandler),
('/serve/([^/]+)?', ServeHandler)],
debug=True)
Regarding the issue of your log statement not firing: The default log level for dev_appserver.py is info, which you can override with the --dev_appserver_log_level flag.
Reference the new dev_appserver documentation.
To access uploaded files from a multipart/form-data POST request, the webapp2 documentation states that they're available in request.POST.
I want to do something very similar to the Guestbook example GAE provides in Python.
But instead allowing one user to sign multiple times, I want each submission to overwrite any preexisting one by the current user.
I'm having trouble figuring out how to edit this example to make that work.
import cgi
import datetime
import urllib
import wsgiref.handlers
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class Greeting(db.Model):
"""Models an individual Guestbook entry with an author, content, and date."""
author = db.StringProperty()
content = db.StringProperty(multiline=True)
date = db.DateTimeProperty(auto_now_add=True)
def guestbook_key(guestbook_name=None):
"""Constructs a Datastore key for a Guestbook entity with guestbook_name."""
return db.Key.from_path('Guestbook', guestbook_name or 'default_guestbook')
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
guestbook_name=self.request.get('guestbook_name')
# Ancestor Queries, as shown here, are strongly consistent with the High
# Replication Datastore. Queries that span entity groups are eventually
# consistent. If we omitted the ancestor from this query there would be a
# slight chance that Greeting that had just been written would not show up
# in a query.
greetings = db.GqlQuery("SELECT * "
"FROM Greeting "
"WHERE ANCESTOR IS :1 "
"ORDER BY date DESC LIMIT 10",
guestbook_key(guestbook_name))
for greeting in greetings:
if greeting.author:
self.response.out.write(
'<b>%s</b> wrote:' % greeting.author)
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(greeting.content))
self.response.out.write("""
<form action="/sign?%s" method="post">
<div><textarea name="content" rows="3" cols="60"></textarea></div>
<div><input type="submit" value="Sign Guestbook"></div>
</form>
<hr>
<form>Guestbook name: <input value="%s" name="guestbook_name">
<input type="submit" value="switch"></form>
</body>
</html>""" % (urllib.urlencode({'guestbook_name': guestbook_name}),
cgi.escape(guestbook_name)))
class Guestbook(webapp.RequestHandler):
def post(self):
# We set the same parent key on the 'Greeting' to ensure each greeting is in
# the same entity group. Queries across the single entity group will be
# consistent. However, the write rate to a single entity group should
# be limited to ~1/second.
guestbook_name = self.request.get('guestbook_name')
greeting = Greeting(parent=guestbook_key(guestbook_name))
if users.get_current_user():
greeting.author = users.get_current_user().nickname()
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/?' + urllib.urlencode({'guestbook_name': guestbook_name}))
application = webapp.WSGIApplication([
('/', MainPage),
('/sign', Guestbook)
], debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
The easiest way to do this is to modify the post method of the Guestbook class, so that it checks for an existing post from the current user and updates it, if it exists.
class Guestbook(webapp.RequestHandler):
def post(self):
guestbook_name = self.request.get('guestbook_name')
user = users.get_current_user()
nickname = None
if user:
nickname = user.nickname()
greeting = Greeting.gql('WHERE author = :1 AND ANCESTOR IS :2',
nickname, guestbook_key(guestbook_name)).get()
if not greeting:
greeting = Greeting(parent=guestbook_key(guestbook_name))
greeting.author = nickname
greeting.content = self.request.get('content')
greeting.put()
self.redirect('/?' + urllib.urlencode({'guestbook_name': guestbook_name}))
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.