Attribute Error with multiple forms in webpy - python

I'm creating a webpy app that has multiple forms that take input and than that input is executed by python, however I keep getting an Attribute Error on Key Error on the first form : AttributeError : 'Pycode' , no clue why this is happening, here's the code :
import web
from Commands import *
import Commands
operations = [method for method in dir(port) if callable(getattr(port, method))]
test = port(0)
def make_text(string):
return string
urls = ('/', 'tutorial')
render = web.template.render('templates/',globals={'oper':operations})
app = web.application(urls, globals())
pythonCode = web.form.Form(
web.form.Textarea(name='', class_='Pycode', id='Pycode')
)
setProportionalGain = web.form.Form(
web.form.Textbox(name='Set Proportional Gain', class_='SG', id='SG')
)
setIntegralGain = web.form.Form(
web.form.Textbox(name='Set Inegral Gain', class_='SI', id='SI')
)
setDerivativeGain = web.form.Form(
web.form.Textbox(name='Set Derivative Gain', class_='SD', id='SD')
)
class tutorial:
def GET(self):
code = pythonCode()
proportional = setProportionalGain()
integral = setIntegralGain()
derivative = setDerivativeGain()
return render.tutorial(code,proportional,integral,derivative, "Input Command for ohm")
def POST(self):
form = pythonCode()
proportional = setProportionalGain()
integral = setIntegralGain()
derivative = setDerivativeGain()
form.validates()
data = web.input()
print data
print data.Pycode
s = data.Pycode
proportionalGain = "test.setProportionalGain(%s)" % data.SG
integralGain = "test.setItegralGain(%s)" % data.SI
derivativeGain = "test.setDerivativeGain(%s)" % data.SD
try:
exec(proportionalGain)
exec(integralGain)
exec(derivativeGain)
exec(data.Pycode)
s = "This is Python!"
except:
pass
return s
if __name__ == '__main__':
app.run()

Check the docs of how to use form inputs. Every input should have name as it first argument and what you have in your name attributes should be description.

Related

How to use SELECT query based on method parameter in Flask restplus Api?

I want to handle a GET request in my Flask REST API.The request will include List parameter and I use this to be a typical GET request:
https://localhost:5000/organisation?List=1
this request, will return all of Organisation Model information. Organisation is a Model class for a table of my MySQL database(by peewee).
I want to enter PrivenceId parameter in request and will return all of Organisation Model information where Organisation.PrivencedId == PrivenceId parameter, But I encounter the following Error:
TypeError: 'Organisation' object is not iterable
my code (OrganisationController.py file) is:
from flask_restplus import Resource, reqparse
from Models.Organisation import Organisation
from flask import request
# Define parser and request args
parser = reqparse.RequestParser()
parser.add_argument('List', type=int)
parser.add_argument('ProvinceId', type=int)
class List(Resource):
def get(self):
args = parser.parse_args()
List = args['List']
ProvinceId = args['ProvinceId']
if List :
Organisations = Organisation.select()
Ls = [dict (
ID = c.ID,
Title = c.Title,
Code = c. Code,
OrgEnumId = c.OrgEnumId,
ProvinceId = c.ProvinceId,
CityId = c.CityId,
Address = c.Address,
Phone = c.Phone,
) for c in Organisations
]
return dict(Organisations = Ls)
elif (ProvinceId) :
Organisations = Organisation.select().where
(
Organisation.ProvinceId ==args['ProvinceId']
).get()
Ls = [dict (
ID = c.ID,
Title = c.Title,
Code = c. Code,
OrgEnumId = c.OrgEnumId,
ProvinceId = c.ProvinceId,
CityId = c.CityId,
Address = c.Address,
Phone = c.Phone,
) for c in Organisations
]
return dict(Organisations = Ls)
and boot.py file for run api is :
from flask import Flask
from flask_restplus import Api
from Controllers import OrganisationController
app = Flask(__name__)
api = Api(app)
api.add_resource(OrganisationController.List, '/organisation')
if __name__ == "__main__":
app.run ('127.0.0.1', 5000, True)
Could you help me?
I changed this line of my code and solved my problem:
Organisations = Organisation.select().where
(
Organisation.ProvinceId ==args['ProvinceId']
)

gloabl name cx not defined

I wanna call an Oracle function returning an objectby using cx_Oracle`s cursor.callfunc(). But this is not working
Here you can see my code:
import cx_Oracle
import json
import web
urls = (
"/", "index",
"/grid", "grid",
)
app = web.application(urls, globals(),web.profiler )
web.config.debug = True
connection = cx_Oracle.Connection("TEST_3D/limo1013#10.40.33.160:1521/sdetest")
typeObj = connection.gettype("MDSYS.SDO_GEOMETRY")
class index:
def GET(self):
return "hallo moritz "
class grid:
def GET(self):
web.header('Access-Control-Allow-Origin', '*')
web.header('Access-Control-Allow-Credentials', 'true')
web.header('Content-Type', 'application/json')
cursor = connection.cursor()
cursor.arraysize = 10000 # default = 50
cursor.execute("""SELECT a.id AS building_nr, c.Geometry AS geometry, d.Classname FROM building a, THEMATIC_SURFACE b, SURFACE_GEOMETRY c, OBJECTCLASS d WHERE a.grid_id_400 = 4158 AND a.id = b.BUILDING_ID AND b.LOD2_MULTI_SURFACE_ID = c.ROOT_ID AND c.GEOMETRY IS NOT NULL AND b.OBJECTCLASS_ID = d.ID""")
obj = cursor.fetchone()
obj = obj[1]
print obj
cursor.callfunc("SDO2GEOJSON", cx.Oracle.OBJECT, [obj])
# Aufruf der App
if __name__ == "__main__":
app.run(web.profiler)
Error message:
at /grid
global name 'cx' is not defined
But I am sure that cx_Oracle is correct installed. Furthermore I use import cx_Oracle at the beginning and this is working.
What is wrong?
Simple typo. In the line
cursor.callfunc("SDO2GEOJSON", cx.Oracle.OBJECT, [obj])
You should use cx_Oracle.OBJECT

Configure auto reload template and enable bytecode cache for jinja2 in appengine

How to configure jinja2 in Appengine to:
Auto reload when template is updated.
Enable bytecode cache, so it can be share among each instances. I prefer jinja2 to produce bytecode when compiling template, and store it to datastore. So next instance will load bytecode instead of repeatedly compile the template.
I have added the bcc like this, using the app engine memcache Client()::
loader = dynloaders.DynLoader() # init Function loader
bcc = MemcachedBytecodeCache(memcache.Client(), prefix='jinja2/bytecode/', timeout=None)
return Environment(auto_reload=True, cache_size=100, loader=FunctionLoader(loader.load_dyn_all),
bytecode_cache=bcc)
My function loader:
def html(self, cid):
def _html_txt_up_to_date(): # closure to check if template is up to date
return CMSUpdates.check_no_update(cid, template.modified)
template = ndb.Key('Templates', cid, parent=self.parent_key).get()
if not template:
logging.error('DynLoader (HTML/TXT): %s' % cid)
return None # raises TemplateNotFound exception
return template.content, None, _html_txt_up_to_date
The template model uses template.modified : ndb.DateTimeProperty(auto_now=True)
The closure function:
class CMSUpdates(ndb.Model):
updates = ndb.JsonProperty()
#classmethod
def check_no_update(cls, cid, cid_modified):
cms_updates = cls.get_or_insert('cms_updates', updates=dict()).updates
if cid in cms_updates: # cid modified has dt microseconds
if cid_modified >= datetime.strptime(cms_updates[cid], '%Y-%m-%d %H:%M:%S'):
if (datetime.now() - timedelta(days=1)) > cid_modified:
del cms_updates[cid]
cls(id='cms_updates', updates=cms_updates).put_async()
return True
return False # reload the template
return True
Been few weeks i looking for the solution. And finally i figured it out, i would like to share my code for everyone. There are 4 python source files in my code.
TemplateEngine.py, ContentRenderer.py, TestContent.py & Update_Template.py
File: TemplateEngine.py
Note:
i use now = datetime.utcnow() + timedelta(hours=8) because my timezone is GMT+8
You must use ndb.BlobProperty to store the bytecode, ndb.TextProperty will not work!
from google.appengine.ext import ndb
from datetime import datetime,timedelta
class SiteTemplates(ndb.Model):
name = ndb.StringProperty(indexed=True, required=True)
data = ndb.TextProperty()
uptodate = ndb.BooleanProperty(required=True)
class SiteTemplateBytecodes(ndb.Model):
key = ndb.StringProperty(indexed=True, required=True)
data = ndb.BlobProperty(required=True)
mod_datetime = ndb.DateTimeProperty(required=True)
class LocalCache(jinja2.BytecodeCache):
def load_bytecode(self, bucket):
q = SiteTemplateBytecodes.query(SiteTemplateBytecodes.key == bucket.key)
if q.count() > 0:
r = q.get()
bucket.bytecode_from_string(r.data)
def dump_bytecode(self, bucket):
now = datetime.utcnow() + timedelta(hours=8)
q = SiteTemplateBytecodes.query(SiteTemplateBytecodes.key == bucket.key)
if q.count() > 0:
r = q.get()
r.data = bucket.bytecode_to_string()
r.mod_datetime = now
else:
r = SiteTemplateBytecodes(key=bucket.key, data=bucket.bytecode_to_string(), mod_datetime=now)
r.put()
def Update_Template_Source(tn, source):
try:
q = SiteTemplates.query(SiteTemplates.name == tn)
if q.count() == 0:
u = mkiniTemplates(name=tn, data=source, uptodate=False)
else:
u = q.get()
u.name=tn
u.data=source
u.uptodate=False
u.put()
return True
except Exception,e:
logging.exception(e)
return False
def Get_Template_Source(tn):
uptodate = False
def Template_Uptodate():
return uptodate
try:
q = SiteTemplates.query(SiteTemplates.name == tn)
if q.count() > 0:
r = q.get()
uptodate = r.uptodate
if r.uptodate == False:
r.uptodate=True
r.put()
return r.data, tn, Template_Uptodate
else:
return None
except Exception,e:
logging.exception(e)
return None
File: ContentRenderer.py
Note: It is very important to set cache_size=0, otherwise bytecode cache function will be disable. I have no idea why.
from TemplateEngine import Get_Template_Source
import jinja2
def Render(tn,tags):
global te
return te.Render(tn, tags)
bcc = LocalCache()
te = jinja2.Environment(loader=jinja2.FunctionLoader(Get_Template_Source), cache_size=0, extensions=['jinja2.ext.autoescape'], bytecode_cache=bcc)
File: Update_Template.py
Note: Use Update_Template_Source() to update template source to datastore.
from TemplateEngine import Update_Template_Source
template_source = '<html><body>hello word to {{title}}!</body></html>'
if Update_Template_Source('my-template.html', template_source):
print 'template is updated'
else:
print 'error when updating template source'
File: TestContent.py
Note: Do some test
from ContentRenderer import Render
print Render('my-template.htmnl', {'title':'human'})
'hello world to human!'
You will realize, even you have more than 20 instances in your application, the latency time will not increase, even you update your template. And the template source will update in 5 to 10 seconds.

Login and logout with web.py

I have a little problem with web.py. Exacly I have problem with sessions.
Link to my app:
http://len.iem.pw.edu.pl/~witkowr1/apps/demo/
Login/password: wtq/wtq
Code:
# -*- coding: utf-8 -*-
import web
import json
from web.contrib.template import render_jinja
import datetime
prefix = '/~witkowr1/apps/demo'
urls = (
prefix + '/login','Login',
prefix + '/logout','Logout',
prefix + '/', 'Index',
)
app = web.application(urls, globals())
wsgi = app.wsgifunc()
session = web.session.Session(app, web.session.DiskStore('sessions'),initializer={'time':datetime.datetime.now()})
render = render_jinja('static', encoding = 'utf-8')
render._lookup.globals.update(assets=prefix+'/static')
class Login:
def GET(self):
web.seeother(prefix+'/')
def POST(self):
login = web.input().login
password = web.input().passwd
if login == 'wtq' and password == 'wtq':
session.logged_in = True
session.time = datetime.datetime.now()
last_login = web.cookies().get('time')
if last_login == None:
last_login_data = u'Zalogowałeś się pierwszy raz.'
else:
last_login_data = last_login
return render.logged(name=login, date_last_login=last_login_data)
else:
session.logged_in = False
error=u'Niepoprawne dane. SprĂłbuj jeszcze raz.'
return render.login(error_msg=error)
class Logout:
def GET(self):
web.seeother(prefix+'/')
def POST(self):
session.logged_in = False
web.setcookie('time',session.time)
message = u'Zostałeś poprawnie wylogowany.'
session.kill()
return render.login(error_msg=message)
class Index:
def GET(self):
return render.login()
if __name__ == "__main__":
app.run()
I would like to verify session and if I login early, I see site with latest login date.
Now, when I refresh the site, I must login again.
I think, that I check session, when I rendering HTML site, but I don't know, what I do it.
Please help!
The problem here is that you are not checking whether they are logged in if they access the page with GET method.
You would need to make a change like:
def GET(self):
if session.logged_in:
last_login = web.cookies().get('time')
if last_login == None:
last_login_data = u'Zalogowałeś się pierwszy raz.'
else:
last_login_data = last_login
return render.logged(name=login, date_last_login=last_login_data)
else:
web.seeother(prefix+'/')
But you should rewrite this, a lot, so that you are taken to another page once you are logged in, and that page is responsible for rendering this information. There is a lot of room for improvement in the structure of your application.
That said, the simple answer is - even though you store the session, the "GET" method of login is entirely unaware of sessions, and will always return the login prompt.
Not sure if you solved your problem already but since it looks like there are often some problems with sessions in web.py I pushed a small and crude demo of it to bitbucket. Works fine for me so hope this works for you.
You can get it via:
git clone https://victorkohler#bitbucket.org/victorkohler/webpy-login.git
I solved my problem.
Very stupid mistakes :)
Code:
# -*- coding: utf-8 -*-
import web
from web.contrib.template import render_jinja
import datetime
prefix = ''
urls = (
prefix + '/', 'Index',
prefix + '/login','Login',
prefix + '/logout','Logout',
)
app = web.application(urls, globals())
wsgi = app.wsgifunc()
web.config.debug = False
session = web.session.Session(app, web.session.DiskStore('sessions'),initializer={'time':datetime.datetime.now()})
render = render_jinja('static', encoding = 'utf-8')
render._lookup.globals.update(assets=prefix+'/static')
allowed = (
('user','user'),
)
class Login:
def GET(self):
web.seeother(prefix+'/')
def POST(self):
login = web.input().login
passwd = web.input().passwd
if(login,passwd) in allowed:
session.logged_in = True
session.login = login
session.time = datetime.datetime.now()
last_login = web.cookies().get('time')
if last_login == None:
last_login_data = u'Zalogowałeś się pierwszy raz.'
else:
last_login_data = last_login
return render.logged(name=login, date_last_login = last_login_data)
else:
session.logged_in = False
error=u'Niepoprawne dane. Spróbuj jeszcze raz.'
return render.login(error_msg=error)
class Logout:
def GET(self):
web.seeother(prefix+'/')
def POST(self):
session.logged_in = False
web.setcookie('time',session.time)
message = u'Zostałeś poprawnie wylogowany.'
session.kill()
return render.login(error_msg=message)
class Index:
def GET(self):
if session.get ('logged_in') == True:
last_login = web.cookies().get('time')
if last_login == None:
last_login_data = u'Zalogowałeś się pierwszy raz.'
else:
last_login_data = last_login
return render.logged(name=session.get ('login'), date_last_login = last_login_data)
else:
return render.login()
if __name__ == "__main__":
app.run()
This is not an answer to your question but an extension of the question. I have a similar solution to the login from the webpy cookbook (http://webpy.org/cookbook/userauthbasic) but would like to load the variable allowed from a database.
allowed = (
('user','user'),
)
When I tried a read to assign the value to the variable it comes out as "None" when executed in the login class.
def readUsersDb():
def POST(self):
# load user data into allowed variable
usersDbFilePath = 'userdata/irf/default/'
usersDbFile = 'usersDb.db'
usersDbFilePath = usersDbFilePath + usersDbFile
conn = sqlite3.connect(usersDbFilePath)
c = conn.cursor()
c.execute('SELECT * FROM users')
output = c.fetchall()
conn.close()
global allowed
allowed = output
readUsersDb()
The login functions when the variable allowed is hard coded. I used the format from the database read and it still functions as expected so it is not a format issue.
#response: [(u'user1', 'user1'), (u'user2', 'user2'), (u'user3', 'user3')]
Hopefully someone has tried to do this previously. If it is a faux pas to add a question as an answer I apologize ahead of time.

Google App Engine: TypeError: 'tuple' object is not callable

Currently trying to create a basic blog using Google App Engine in Python. Here's the python code that I am using:
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(parent = post_key(), name = name, content = content)
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(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)
However, when I try to run this code on my local server, this is what I get as an error:
File "F:\Python 2.7\engineapp1\HelloApp\appapp\main.py", line 66, in <module>
('/blog/([0-9]+)', DisplayPost)], debug=True)
TypeError: 'tuple' object is not callable
What seems to be the problem here?
You forgot to add a comma.
('/blog/submit', SubmitHandler) <---- missed comma over here
('/blog/([0-9]+)', DisplayPost)], debug=True)
It's acting like a function in this case, you're passing a parameter to a tuple which result in an error that the tuple is not callable.
('/blog/submit', SubmitHandler)(parameter)
There's a missing comma at the line:
('/blog/submit', SubmitHandler)
It should be:
('/blog/submit', SubmitHandler),
Without the comma, you have ('/blog/submit', SubmitHandler)('/blog/([0-9]+)', DisplayPost), which is trying to call ('/blog/submit', SubmitHandler) as a function, with '/blog/([0-9]+)' and DisplayPost as parameters. Since that's not a function, but a tuple, you get that error.

Categories