I have a small app that has a form that grabs data about a new hire, emails people about it, and stores the data for future use. Everything is working fine, but I can't seem to find info on using djangoforms and check boxes. These are obviously a boolean value, but if I add a db.Boolean value to my db.Model class, and then had it to djangoforms.ModelForm class to generate it, nothing appears. I added it to my db>model, it creates a record default to false, but there is no way to modify from the form. Also,db.Text doesn't produce a fiel either. I am probably not being clear enough here, due to the fact this is my first GAE and Django project. Code is below
import cgi
import wsgiref.handlers
from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.api import mail
from google.appengine.ext.db import djangoforms
class Item(db.Model):
first_name = db.StringProperty()
last_name = db.StringProperty()
goes_by = db.StringProperty()
Studio = db.StringProperty()
Discipline = db.StringProperty()
position = db.StringProperty()
level = db.StringProperty(default='choice', choices=['choice', 'choice',
'choice', 'choice', 'choice', 'choice'])
start_date = db.DateTimeProperty()
buddy_name = db.StringProperty()
past_employee = bool()
email = db.EmailProperty()
cell_phone = db.PhoneNumberProperty()
phone = db.PhoneNumberProperty()
hire_type = db.StringProperty(default='Full Time',choices=[
'Temp', 'Intern', 'Contract', 'Full Time'])
seating_location = db.StringProperty()
additional_comments = db.Text()
entry_time = db.DateTimeProperty(auto_now_add=True)
added_by = db.UserProperty()
class ItemForm(djangoforms.ModelForm):
class Meta:
model = Item
exclude = ['added_by']
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body><head><link type="text/css" rel="stylesheet" href="/stylesheets/form.css"></head>'
'<div id=header><div id="logo><img src="/img/placeimg.gif"></div><div id ="headertxt"><h2>Place New Hire Portal</h2>'
'<p>Please filll out this form as accurately as possible, this information is used to create employee files and to setup IS equipment</div> '
'</div><div id="contain">'
'<form method="POST" '
'action="/">'
'<table>')
# This generates our fields and writes it in the response
self.response.out.write(ItemForm())
self.response.out.write('</table>'
'<input type="submit">'
'</form></div></body></html>')
def post(self):
data = ItemForm(data=self.request.POST)
if data.is_valid():
# Save the data, and redirect to the view page
entity = data.save(commit=False)
entity.added_by = users.get_current_user()
entity.put()
self.redirect('/items.html')
mailing_address = ("person#place.com")
sender_address = ("person#place.com")
subject = "A new hire has been made - Please begin Process"
body = ("""
The Following Person is scheduled to start at place on :
%s %s - %s \ %s - %s - %s
Please find the orientation template attached. In order to be sure all employees are oriented in the same way
please be sure to cover the items listed under your name.
In addition, afer the completion of your session, please escort the new hire to the next session and makle introductions. This will
ensure that the schedule continues in order.
Buddy, thank you very much for being a buddy to %s, Your time and lunch expenses should be charged to your Studio Operations number. Thank you
very much for helping %s with their transiton to Place."""
%(entity.first_name, entity.last_name, entity.Studio, entity.Discipline, entity.seating_location,
entity.buddy_name, entity.first_name, entity.first_name))
mail.send_mail(sender_address, mailing_address, subject, body)
else:
# Reprint the form
self.response.out.write('<html><body>'
'<form method="POST" '
'action="/">'
'<table>')
self.response.out.write(data)
self.response.out.write('</table>'
'<input type="submit">'
'</form></body></html>')
class ItemPage(webapp.RequestHandler):
def get(self):
self.response.out.write('</br></br>Return to Form Entry</br></br>')
query = db.GqlQuery("SELECT * FROM Item ORDER BY first_name")
for item in query:
self.response.out.write('Edit - ' %
item.key().id())
self.response.out.write("%s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s | %s </br>"%
(item.first_name, item.last_name, item.goes_by, item.Studio, item.Discipline, item.position,
item.level, item.start_date, item.past_employee, item.cell_phone, item.seating_location,
item.additional_comments, item.email, item.phone, item.hire_type))
class EditPage(webapp.RequestHandler):
def get(self):
id = int(self.request.get('id'))
item = Item.get(db.Key.from_path('Item', id))
self.response.out.write('<html><body>'
'<form method="POST" '
'action="/edit">'
'<table>')
self.response.out.write(ItemForm(instance=item))
self.response.out.write('</table>'
'<input type="hidden" name="_id" value="%s">'
'<input type="submit">'
'</form></body></html>' % id)
def post(self):
id = int(self.request.get('_id'))
item = Item.get(db.Key.from_path('Item', id))
data = ItemForm(data=self.request.POST, instance=item)
if data.is_valid():
# Save the data, and redirect to the view page
entity = data.save(commit=False)
entity.added_by = users.get_current_user()
entity.put()
self.redirect('/items.html')
else:
# Reprint the form
self.response.out.write('<html><body>'
'<form method="POST" '
'action="/edit">'
'<table>')
self.response.out.write(data)
self.response.out.write('</table>'
'<input type="hidden" name="_id" value="%s">'
'<input type="submit">'
'</form></body></html>' % id)
def main():
application = webapp.WSGIApplication(
[('/', MainPage),
('/edit', EditPage),
('/items.html', ItemPage),
],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__=="__main__":
main()
Wobble answered it for me
should be TextProperty and BooleanProperty. db.Text is just an alias to datastore_types.Text, not a Property subclass, and db.Boolean should raise an exception as far as I can see
Related
I'm currently working through the O'Reilly book, Programming Python. Below is code that reads a shelve and creates a web interface allowing you to access those values from the shelf. You can fetch and update the values
'''
Implement a web-based interface for viewing and updating class instances
stored in a shelve; the shelve lives on server (same machine if localhost)
'''
import cgi, sys, os
import shelve, html
shelvename = 'class-shelve'
fieldnames = ('name', 'age', 'job', 'pay')
form = cgi.FieldStorage()
print('Content-type: text/html')
sys.path.insert(0, os.getcwd())
# main html template
replyhtml = """
<html>
<title>People Input Form</title>
<body>
<form method=POST action=peoplecgi.py>
<table>
<tr><th>key<td><input type=text name=key value="%(key)">
$ROWS$
</table>
<p>
<input type=submit value="Fetch", name=action>
<input type=submit value="Update", name=action>
</form>
</body></html>
"""
# insert html for data rows at $ROWS$
rowhtml = '<tr><th>%s<td><input type=text name=%s value="%%(%s)s">\n'
rowshtml = ""
for fieldname in fieldnames:
rowshtml += (rowhtml % ((fieldname,)*3))
replyhtml = replyhtml.replace('$ROWS$', rowshtml)
def htmlize(adict):
new = adict.copy()
for field in fieldnames:
value = new[field]
new[field] = html.escape(repr(value))
return new
def fetchRecord(db, form):
try:
key = form['key'].value
record = db[key]
fields = record.__dict__
fields['key'] = key
except:
fields = dict.fromkeys(fieldnames, '?')
fields['key'] = 'Missing or invalid key!'
return fields
def updateRecord(db, form):
if not 'key' in form:
fields = dict.fromkeys(fieldnames, '?')
fields['key'] = 'Missing key input!'
else:
key = form['key'].value
if key in db:
record = db[key]
else:
from person_start import Person
record = Person(name='?', age='?')
for field in fieldnames:
setattr(record, field, eval(form[field].value))
db[key] = record
fields = record.__dict__
fields['key'] = key
return fields
db = shelve.open(shelvename)
action = form['action'].value if 'action' in form else None
if action == 'Fetch':
fields = fetchRecord(db, form)
elif action == 'Update':
fields = updateRecord(db, form)
else:
fields = dict.fromkeys(fieldnames, '?')
fields['key'] = 'Missing or invalid action!'
db.close()
print(replyhtml % htmlize(fields))
However, for some reason, printing is continually failing. I've tried many times to remove the "" the error is stating, but to no avail.
Does anyone see why this is failing to print the form?
After checking the complete code , I believe the issue is in the replyhtml , in line -
<tr><th>key<td><input type=text name=key value="%(key)">
The issue is in the format - "%(key)" . You need to specify the type of the element like s or d etc , I believe you may need s (for string). Example -
<tr><th>key<td><input type=text name=key value="%(key)s">
I'm working though the GAE Tutorial and I'm getting the following error.
File "/Users/cparrish/bin/guestbook/guestbook.py", line 62, in get
for greeting in greetings:
NameError: global name 'greetings' is not defined
So I think the problem is here somewhere.
greetings_query = Greeting.query(
ancestor = guestbook_key(guestbook_name)).order(-Greeting.date)
greeetings = greetings_query.fetch(10)
for greeting in greetings:
if greeting.author:
self.response.write(
'<b>%s</b> wrote:' % greeting.author.nickname())
Which are lines 58 - 66
So I'm wondering if anyone else can see what I'm apparently missing here.
Full code base below.
import cgi
import urllib
from google.appengine.api import users
from google.appengine.ext import ndb
import webapp2
MAIN_PAGE_FOOTER_TEMPLATE = """\
<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">
</from>
%s
</body>
</html>
"""
DEFAULT_GUESTBOOK_NAME = 'default_guestbook'
# We set a parent key on the 'Greetings' to ensure that they are all in the same
# entity group. Queries across the signle entity group will be consistent.
# However, the write rate should be limited to -1/second.
def guestbook_key(guestbook_name="DEFAULT_GUESTBOOK_NAME"):
""" Constructs a Datastore key for a Guestbook entity with guestbook_name. """
return ndb.Key('Guestbook', guestbook_name)
class Greeting(ndb.Model):
"""Models an individual Guestbook entry with author, content, and date. """
author = ndb.UserProperty()
content = ndb.StringProperty( indexed = False )
date = ndb.DateTimeProperty( auto_now_add = True )
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.write('<html><body>')
guestbook_name = self.request.get('guestbook_name', DEFAULT_GUESTBOOK_NAME)
# Ancestor Queries, as shown here, are strongly consisten with the High
# Replication Datastore. Queries that span entity groups are eventually
# consisten. If we omitted the ancestor from this query there would be
# a slight chance that Greetings that had just been written would not
# show up in a query.
greetings_query = Greeting.query(
ancestor = guestbook_key(guestbook_name)).order(-Greeting.date)
greeetings = greetings_query.fetch(10)
for greeting in greetings:
if greeting.author:
self.response.write(
'<b>%s</b> wrote:' % greeting.author.nickname())
else:
self.response.write('An anonymous person wrote:')
self.response.write('<blockquote>%s</blockquote' %
cgi.escape(greeting.content))
if users.get_current_user():
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
# Write the submission form and the footer of the page
sign_query_parms = urllib.urlencode({'guestbook_name': guestbook_name})
self.response.write(MAIN_PAGE_FOOTER_TEMPLATE % (sign_query_parms, cgi.escape(guestbook_name), url, url_linktext))
class Guestbook(webapp2.RequestHandler):
def post(self):
# We set the same parent key on the 'Greeting' to ensure each getting
# is in the same entity group. Queries across the single entity group
# will be consistent. However, the write reate to a sing entity groupo
# should be limited to ~1/second.
guestbook_name = self.request.get('guestbook_name',
DEFAULT_GUESTBOOK_NAME)
greeting = Greeting(parent=guestbook_key(guestbook_name))
if users.get_current_user():
greeting.author = users.get_current_user()
greeting.content = self.request.get('content')
greeting.put()
query_params = {'guestbook_name': guestbook_name}
self.redirect('/?' + urllib.urlencode(query_params))
application = webapp2.WSGIApplication([
('/', MainPage),
('/sign', Guestbook),
], debug=True)
There are three e's in your assignment of greeetings.
greeetings = greetings_query.fetch(10)
for greeting in greetings:
One of these es is not like the others, one of these es just doesn't belong...
I am trying to get my ancestor query to work but I keep getting this error:
BadQueryError: Parse Error: Identifier is a reserved keyword at symbol
ANCESTOR
at this line:
TweepleKey(twitter_handle))
I was following Using the Datastore tutorial (which works) but when I tried to apply the concepts of ancestor query to my code (see below) it keeps producing the above mentioned error. Where did I go wrong?
import cgi
import urllib
import webapp2
import cgi
from google.appengine.ext import db
# defines a data model for a geotweet
# GeoTweet model has 1 property: twitter_handle
class GeoTweet(db.Model):
twitter_handle = db.StringProperty()
date = db.DateTimeProperty(auto_now_add=True)
def TweepleKey(twitter_handle=None):
# Constructs a Datastore key for a TweepleStore entity with twitter_handle
return db.Key.from_path('TweepleStore', twitter_handle or 'default_handle')
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.out.write("""<html><body>""")
twitter_handle = self.request.get('twitter_handle')
tweeple = db.GqlQuery("SELECT * "
"FROM GeoTweet "
"WHERE ANCESTOR = :1 "
"ORDER BY date DESC LIMIT 10",
TweepleKey(twitter_handle))
for t in tweeple:
if t.twitter_handle:
self.out.write('<b>Found %s. Saved on %s.</b>' % (t.twitter_handle, t.date))
else:
self.out.write('<b>%s was not found!' % twitter_handle)
self.response.out.write("""<form action="/search" method="post">
<div><textarea name="twitter_handle" rows="1" cols="20">#example</textarea>
<div><input type="submit" value="Find"></div>
</form>
</body>
</html>""")
class TweepleStore(webapp2.RequestHandler):
def post(self):
twitter_name = self.request.get('twitter_handle')
geotweet = GeoTweet(parent=TweepleKey(twitter_name))
geotweet.twitter_handle = twitter_name
geotweet.put()
self.redirect('/?' + urllib.urlencode({'twitter_name': twitter_name}))
app = webapp2.WSGIApplication([('/', MainPage),
('/search', TweepleStore)], debug=True)
The GQL reference says to use WHERE ANCESTOR IS.
I am having difficulties in storing and then retrieving the blobstore key. It looks like I am able to get the database row key # instead of the blob key#....
1) I am not sure how to store the key
2) Also, I am not sure how the data currently gets stored into the UserPhoto datastructure
set up
3) How do I retrieve the Blob's key related to the current user, so I can display a link to i?
any help would be greatly appreciated.
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
from google.appengine.ext import db
import urllib
class UserPhoto(db.Model):
user = db.StringProperty()
user1 = db.EmailProperty()
blob_prop = blobstore.BlobKey
blob_key = blobstore.BlobReferenceProperty()
class MainPage(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
upload_url = blobstore.create_upload_url('/upload')
existing_data = "<br>"
if user:
data = UserPhoto.all()
#filter data by user e-mail
results = data.filter("user1 = ", user.email())
for dt in results:
existing_data +='<a href="/serve/%s' % dt.key() + '">'
existing_data += '%s' % dt.key() + '<br>'
self.response.out.write(
'<div align=center>Hello %s <a align="center" href="%s">Sign out</a><br>Is administrator: %s' %
(user.nickname(), users.create_logout_url("/"), users.is_current_user_admin())
+'<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url+
"""<br>Upload File: <input type="file" name="file"><br> <input type="submit"
name="submit" value="Submit"> </form>
<br>"""+existing_data + "</div>"
)
#the code below is used for testing...purposes only...
for b in blobstore.BlobInfo.all():
self.response.out.write('<li>' + str(b.filename) + '')
else:
self.redirect(users.create_login_url(self.request.uri))
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
upload_files = self.get_uploads('file') # 'file' is file upload field in the form
blob_info = upload_files[0]
user = users.get_current_user()
if user:
data = UserPhoto()
data.user1 = users.get_current_user().email()
data.blob_key = str(blob_info.key())
# data.user2[0] = self.get_uploads()
data.blob_prop = blob_info.key()
data.put()
#self.redirect('/serve/%s' % blob_info.key())
self.redirect('/')
class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self, photo_key):
blob_key = str(urllib.unquote(photo_key))
if not blobstore.get(photo_key):
self.error(404)
else:
#self.send_blob(photo_key)
#self.send_blob('/serve/%s' % photo_key)
self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)
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)
application = webapp.WSGIApplication([('/', MainPage),
('/upload', UploadHandler),
('/serve/([^/]+)?', ServeHandler),
('/view_photo/([^/]+)?', ViewPhotoHandler)
],debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
You're asking for the UserPhoto entity key when you construct the output, not the blobstore reference within that entity. It should be:
existing_data +='<a href="/serve/%s">' % dt.blob_key
I have a question similar to my previous question.
In the same app I have the VoteHandler that adds +1 when users click on the up arrow and then redirects to the same page.
Now that I added the url parameters to the pages and urls look like this
/dir?type=tshirt
I need to be able to redirect to the correct page.
And as mentioned here by Nick Johnson referrer is not a good way of redirecting.
I would appreciate help about how to fix VoteHandler so that it redirects to the correct page.
Thanks!
class VoteHandler(webapp.RequestHandler):
def get(self, id):
id = int(id)
item = Item.get_by_id(id)
user = users.get_current_user()
if user:
greeting = ("%s (<a href='%s'>sign out</a>)" %
(user.nickname(), users.create_logout_url(self.request.uri)))
#--check if user voted on this item before--#
query = SiteUser.all()
query.filter("liked_items =", (str(item.key().id())))
already_voted = query.get()
if already_voted:
self.redirect("/onevote")
else:
query = SiteUser.all()
query.filter("site_user =", users.get_current_user())
data = query.get()
data.total_votes += 1
data.liked_items = str(item.key().id())
data.site_user = users.get_current_user()
db.put(data)
item.points += 1
item.put()
if self.request.referrer == 'http://localhost:8083//newest':
self.redirect('/newest')
elif self.request.referrer == 'http://localhost:8083/hot':
self.redirect('/hot')
#How do I fix this line to get the correct url parameter?
elif self.request.referrer == 'http://localhost:8083/dir?type=tshirt':
self.redirect('/dir/tshirt')
else:
self.redirect("/")
else:
greeting = ("<a href='%s'>Sign in with your Google account or register</a>." %
cgi.escape(users.create_login_url(self.request.uri)))
UPDATE
The answer by systempuntoout works great but I had to change the vote link in Directory from
/vote/%s
to
/vote/%s?type=%s
so that I could get the merchandise_type in VoteHandler:
self.response.out.write("<ol>")
for item in items:
self.response.out.write("""<li>
^ %s <span id='Small'>(%s)</span><br />
<div id='Small'>
%s points %s by %s |
</div>
</li><br /> """ %
(str(item.key().id()), merchandise_type, item.url, item.title, urlparse(item.url).netloc,
item.points, item.date.strftime("%B %d, %Y %I:%M%p"), item.user_who_liked_this_item, str(item.key().id()), str(item.key().id())))
self.response.out.write("</ol>")
I would use the type parameter in this way:
class VoteHandler(webapp.RequestHandler):
def get(self, id):
id = int(id)
item = Item.get_by_id(id)
merchandise_type = self.request.get("type", "")
..
self.redirect('/%s' % merchandise_type)