Controller logic is below. Error 1 is occuring under the "dashboard" function. Errors 2/3 under the user function.
# -*- coding: utf-8 -*- # this file is released under public domain and you can use without limitations ############################################################################### ## Launch with all settings via "sudo python run_server.py" ############################################################################### import operator # needed for manager_status variable response.title = 'nolabills' def jspage(): link = URL('static', 'main.js') return dict(link=link) def index(): """ For registered users, redirects to the requests page For unregistered users, displays intro message """ signup = URL(a=request.application, c='default', f='user/register') return dict(is_logged_in=auth.is_logged_in(), signup=signup) @auth.requires_membership('manager') def manage(): """ This page, accessible by only managers, shows the current employees of a company as well as any users who are registering themselves as employees of the company. From this page a manager can approve a pending user's membership, as well as revoke the membership of a user on the current employee list. """ pending_list = [] approved_list = [] if request.post_vars: for each in request.post_vars: key = request.post_vars.keys()[0] underscore = key.find('_') id = key[0:underscore] change = key[underscore+1:len(key)] change = None if change == "approve" else "unapproved" # modify db accordingly record = db(db.auth_user.id==id).select().first() record.registration_key=change record.update_record() for row in db().select(): #for row in db(db.auth_user.company==auth.user.company).select(): if row.registration_key: # if pending approval by manager pending_list.append({row.id:{"first":row.first_name,"last":row.last_name}}) else: manager_status = auth.has_membership('manager', row.id) approved_list.append({row.id:{"first":row.first_name,"last":row.last_name,"manager_status":manager_status}}) return dict(pending_list=pending_list, approved_list=approved_list) @auth.requires_login() def dashboard(): """ This page allows a user to send an email to a potential customer, requesting access to bill data """ i = 0 already_submitted = False # default is false; can only be changed if request.post_vars == True # SQLFORM version data_requests = SQLFORM.grid(db(db.data_requests.company==auth.user.company), fields=[db.data_requests.last_name, \ db.data_requests.first_name, \ db.data_requests.email, \ db.data_requests.status, \ db.data_requests.bill_1, ], headers={'data_requests.bill_1':'Most Recent Bill'}, sortable=False, create=False, editable=False, deletable=True, details=False, maxtextlength=30, csv=False, upload=URL('download'), ) pending_list = db().select(db.data_requests.email) # if a new request has been made, update the database if request.post_vars: while not already_submitted and i <= len(data_requests): already_submitted = [True for row in pending_list if row.email == request.post_vars.email] i += 1 from entergy_scraper import download from mailer import send_request if not already_submitted: # generate token import random, base64, sha token = base64.b64encode(sha.sha(str(random.random())).hexdigest())[:8] db.tokens.insert(token = token, first_name = request.post_vars.first_name, last_name = request.post_vars.last_name, email = request.post_vars.email, company = auth.user.company, ) # send request to user db.scheduler_task.insert(status = 'QUEUED', application_name = request.application+'/default', task_name = 'request', group_name = 'email', function_name = 'send_request', args = '["{0}", "{1}", "{2}", "{3}"]'.format( \ request.post_vars.first, request.post_vars.last, request.post_vars.email, token), vars = '{}', enabled = True, start_time = request.now, timeout = 500, # should take less than 500 secs ) # update data_requests to show that the task is AWAITING_CUSTOMER db.data_requests.insert(first_name = request.post_vars.first_name, last_name = request.post_vars.last_name, email = request.post_vars.email, company = auth.user.company, status = 'AWAITING_CUSTOMER', ) return dict(already_submitted=already_submitted, data_requests=data_requests, pending_list=pending_list) def approve_request(): """ Allows a customer to approve a data request """ submitted = 'submitted' valid_token = 'valid_token' invalid_token = 'invalid_token' # if the user has submitted their data and it's not already in the database, let them know we'll get their data if request.post_vars: status = submitted token_submitted = True if db(db.data_requests.email == request.post_vars.email).select(db.tokens.submitted).first() else False if token_submitted == False: # download data db.data_requests.insert(first_name = request.post_vars.first_name, last_name = request.post_vars.last_name, email = request.post_vars.email, company = auth.user.company, energy_username = request.post_vars.energy_username, energy_password = request.post_vars.energy_password, ) # if no submission of info, try to give them the option to do so else: try: status = valid_token token = request.get_vars.token token_row = db(db.tokens.token == token).select().first() first_name = token_row.first_name last_name = token_row.last_name email = token_row.email except: status = invalid_token if status == submitted or status == invalid_token: return dict(status=status, submitted=submitted, invalid_token=invalid_token, token_submitted=token_submitted) else: return dict(status=status, first_name=first_name, last_name=last_name, email=email, submitted=False, invalid_token=False, token_submitted=False) def user(): """ exposes: http://..../[app]/default/user/login http://..../[app]/default/user/logout http://..../[app]/default/user/register http://..../[app]/default/user/profile http://..../[app]/default/user/retrieve_password http://..../[app]/default/user/change_password http://..../[app]/default/user/bulk_register use @auth.requires_login() @auth.requires_membership('group name') @auth.requires_permission('read','table name',record_id) to decorate functions that need access control also notice there is http://..../[app]/appadmin/manage/auth to allow administrator to manage users """ return dict(form=auth()) @cache.action() def download(): """ allows downloading of uploaded files http://..../[app]/default/download/[filename] """ return response.download(request, db) def call(): """ exposes services. for example: http://..../[app]/default/call/jsonrpc decorate with @services.jsonrpc the functions to expose supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv """ return service() On Thursday, June 16, 2016 at 9:36:18 AM UTC-4, Marty Jones wrote: > > I uploaded a local application to my DigitalOcean droplet and have been > having a nightmare of a time with the databases. I get this variety of > errors on various pages: > > *Error 1:* > > Traceback (most recent call last): > File "/home/murtyjones/app/gluon/restricted.py", line 227, in restricted > exec ccode in environment > File "/home/murtyjones/app/applications/nolabills/controllers/default.py" > <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>, > line 230, in <module> > File "/home/murtyjones/app/gluon/globals.py", line 417, in <lambda> > self._caller = lambda f: f() > File "/home/murtyjones/app/gluon/tools.py", line 4241, in f > return action(*a, **b) > File "/home/murtyjones/app/applications/nolabills/controllers/default.py" > <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>, > line 73, in dashboard > data_requests = > SQLFORM.grid(db(db.data_requests.company==auth.user.company), > File "/home/murtyjones/app/gluon/packages/dal/pydal/objects.py", line 91, > in __getattr__ > raise AttributeError > AttributeError > > > *Error 2 (trying to apply changes as a user to own profile):* > > Traceback (most recent call last): > File "/home/murtyjones/app/gluon/restricted.py", line 227, in restricted > exec ccode in environment > File "/home/murtyjones/app/applications/nolabills/controllers/default.py" > <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>, > line 230, in <module> > File "/home/murtyjones/app/gluon/globals.py", line 417, in <lambda> > self._caller = lambda f: f() > File "/home/murtyjones/app/applications/nolabills/controllers/default.py" > <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>, > line 211, in user > return dict(form=auth()) > File "/home/murtyjones/app/gluon/tools.py", line 1941, in __call__ > return getattr(self, args[0])() > File "/home/murtyjones/app/gluon/tools.py", line 4026, in profile > hideerror=self.settings.hideerror): > File "/home/murtyjones/app/gluon/sqlhtml.py", line 1744, in accepts > self.id_field_name]).update(**fields) > File "/home/murtyjones/app/gluon/packages/dal/pydal/objects.py", line 2041, > in update > ret = db._adapter.update("%s" % table._tablename, self.query, fields) > File "/home/murtyjones/app/gluon/packages/dal/pydal/adapters/base.py", line > 519, in update > raise e > OperationalError: attempt to write a readonly database > > > *Error 3 (trying to logout as a user):* > > Traceback (most recent call last): > File "/home/murtyjones/app/gluon/restricted.py", line 227, in restricted > exec ccode in environment > File "/home/murtyjones/app/applications/nolabills/controllers/default.py" > <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>, > line 230, in <module> > File "/home/murtyjones/app/gluon/globals.py", line 417, in <lambda> > self._caller = lambda f: f() > File "/home/murtyjones/app/applications/nolabills/controllers/default.py" > <https://nolabills.com/admin/default/edit/nolabills/controllers/default.py>, > line 211, in user > return dict(form=auth()) > File "/home/murtyjones/app/gluon/tools.py", line 1941, in __call__ > return getattr(self, args[0])() > File "/home/murtyjones/app/gluon/tools.py", line 3235, in logout > self.log_event(log, self.user) > File "/home/murtyjones/app/gluon/tools.py", line 2530, in log_event > self.table_event().insert(description=str(description % vars), > origin=origin, user_id=user_id) > File "/home/murtyjones/app/gluon/packages/dal/pydal/objects.py", line 740, > in insert > ret = self._db._adapter.insert(self, self._listify(fields)) > File "/home/murtyjones/app/gluon/packages/dal/pydal/adapters/base.py", line > 482, in insert > raise e > IntegrityError: FOREIGN KEY constraint failed > > > *db.py* > ## app configuration made easy. Look inside private/appconfig.ini > from gluon.contrib.appconfig import AppConfig > ## import current for current.db = db line > from gluon import current > > ## once in production, remove reload=True to gain full speed > myconf = AppConfig(reload=True) > > ## if NOT running on Google App Engine use SQLite or other DB > db = DAL(myconf.take('db.uri'), pool_size=myconf.take('db.pool_size', > cast=int), migrate_enabled = myconf.get('db.migrate'), > check_reserved=['all']) > > ## define current.db for module usage > current.db = db > > ## by default give a view/generic.extension to all actions from localhost > ## none otherwise. a pattern can be 'controller/function.extension' > response.generic_patterns = ['*'] if request.is_local else [] > ## choose a style for forms > response.formstyle = myconf.take('forms.formstyle') # or > 'bootstrap3_stacked' or 'bootstrap2' or other > response.form_label_separator = myconf.take('forms.separator') > > from gluon.tools import Auth, Service, PluginManager > > auth = Auth(db) > service = Service() > plugins = PluginManager() > > auth.settings.extra_fields['auth_user']= [ > Field('company'), > ] > > ## create all tables needed by auth if not custom tables > auth.define_tables(username=False, signature=False, migrate=True, > fake_migrate=True) > > ## configure email > mail = auth.settings.mailer > mail.settings.server = 'smtp.gmail.com' > mail.settings.sender = 'em...@gmail.com' > mail.settings.login = 'em...@gmail.com:password' > > ## configure auth policy > auth.settings.registration_requires_verification = True > auth.settings.registration_requires_approval = True > auth.settings.reset_password_requires_verification = True > > ## after defining tables, uncomment below to enable auditing > # auth.enable_record_versioning(db) > > > ## create list of companies for which this is available > db.define_table('company_info', > Field('name'), > Field('street_address'), > ) > > ## create a table for the queue of not yet fulfilled data requests > db.define_table('data_requests', > Field('first_name'), > Field('last_name'), > Field('entergy_username'), > Field('entergy_password'), > Field('email'), > Field('company'), > Field('status', default='QUEUED'), > Field('runs', 'integer', default=0), > Field('bill_1', 'upload', uploadfield='bill_1_file'), > Field('bill_1_file', 'blob'), > ) > > > ## create a table for generating tokens > db.define_table('tokens', > Field('first_name'), > Field('last_name'), > Field('email'), > Field('company'), > Field('token'), > Field('submitted', default=False), > ) > > > > *sql.log* > timestamp: 2016-06-15T14:20:52.811948 > CREATE TABLE auth_user( > id INTEGER PRIMARY KEY AUTOINCREMENT, > first_name CHAR(128), > last_name CHAR(128), > email CHAR(512), > password CHAR(512), > registration_key CHAR(512), > reset_password_key CHAR(512), > registration_id CHAR(512) > ); > success! > timestamp: 2016-06-15T14:20:52.856816 > CREATE TABLE auth_group( > id INTEGER PRIMARY KEY AUTOINCREMENT, > role CHAR(512), > description TEXT > ); > success! > timestamp: 2016-06-15T14:20:52.899975 > CREATE TABLE auth_membership( > id INTEGER PRIMARY KEY AUTOINCREMENT, > user_id INTEGER REFERENCES auth_user (id) ON DELETE CASCADE , > group_id INTEGER REFERENCES auth_group (id) ON DELETE CASCADE > ); > success! > timestamp: 2016-06-15T14:20:53.040386 > CREATE TABLE auth_permission( > id INTEGER PRIMARY KEY AUTOINCREMENT, > group_id INTEGER REFERENCES auth_group (id) ON DELETE CASCADE , > name CHAR(512), > table_name CHAR(512), > record_id INTEGER > ); > success! > timestamp: 2016-06-15T14:20:53.092848 > CREATE TABLE auth_event( > id INTEGER PRIMARY KEY AUTOINCREMENT, > time_stamp TIMESTAMP, > client_ip CHAR(512), > user_id INTEGER REFERENCES auth_user (id) ON DELETE CASCADE , > origin CHAR(512), > description TEXT > ); > success! > timestamp: 2016-06-15T14:20:53.223004 > CREATE TABLE auth_cas( > id INTEGER PRIMARY KEY AUTOINCREMENT, > user_id INTEGER REFERENCES auth_user (id) ON DELETE CASCADE , > created_on TIMESTAMP, > service CHAR(512), > ticket CHAR(512), > renew CHAR(1) > ); > success! > timestamp: 2016-06-15T14:22:53.166163 > ALTER TABLE auth_user ADD company CHAR(512); > success! > timestamp: 2016-06-15T14:22:53.554653 > CREATE TABLE company_info( > id INTEGER PRIMARY KEY AUTOINCREMENT, > name CHAR(512), > street_address CHAR(512) > ); > success! > timestamp: 2016-06-15T14:22:53.604055 > CREATE TABLE data_requests( > id INTEGER PRIMARY KEY AUTOINCREMENT, > first_name CHAR(512), > last_name CHAR(512), > entergy_username CHAR(512), > entergy_password CHAR(512), > email CHAR(512), > company CHAR(512), > status CHAR(512), > runs INTEGER, > bill_1 CHAR(512), > bill_1_file BLOB > ); > success! > timestamp: 2016-06-15T14:22:53.645905 > CREATE TABLE tokens( > id INTEGER PRIMARY KEY AUTOINCREMENT, > first_name CHAR(512), > last_name CHAR(512), > email CHAR(512), > company CHAR(512), > token CHAR(512), > submitted CHAR(512) > ); > success! > timestamp: 2016-06-15T14:22:56.435830 > CREATE TABLE scheduler_task( > id INTEGER PRIMARY KEY AUTOINCREMENT, > application_name CHAR(512), > task_name CHAR(512), > group_name CHAR(512), > status CHAR(512), > function_name CHAR(512), > uuid CHAR(255) UNIQUE, > args TEXT, > vars TEXT, > enabled CHAR(1), > start_time TIMESTAMP, > next_run_time TIMESTAMP, > stop_time TIMESTAMP, > repeats INTEGER, > retry_failed INTEGER, > period INTEGER, > prevent_drift CHAR(1), > timeout INTEGER, > sync_output INTEGER, > times_run INTEGER, > times_failed INTEGER, > last_run_time TIMESTAMP, > assigned_worker_name CHAR(512) > ); > success! > timestamp: 2016-06-15T14:22:56.501649 > CREATE TABLE scheduler_run( > id INTEGER PRIMARY KEY AUTOINCREMENT, > task_id INTEGER REFERENCES scheduler_task (id) ON DELETE CASCADE , > status CHAR(512), > start_time TIMESTAMP, > stop_time TIMESTAMP, > run_output TEXT, > run_result TEXT, > traceback TEXT, > worker_name CHAR(512) > ); > success! > timestamp: 2016-06-15T14:22:56.546304 > CREATE TABLE scheduler_worker( > id INTEGER PRIMARY KEY AUTOINCREMENT, > worker_name CHAR(255) UNIQUE, > first_heartbeat TIMESTAMP, > last_heartbeat TIMESTAMP, > status CHAR(512), > is_ticker CHAR(1), > group_names TEXT, > worker_stats TEXT > ); > success! > timestamp: 2016-06-15T14:22:56.589493 > CREATE TABLE scheduler_task_deps( > id INTEGER PRIMARY KEY AUTOINCREMENT, > job_name CHAR(512), > task_parent INTEGER, > task_child INTEGER REFERENCES scheduler_task (id) ON DELETE CASCADE , > can_visit CHAR(1) > ); > success! > > No idea where to even start with this and would appreciate help. > > -- Resources: - http://web2py.com - http://web2py.com/book (Documentation) - http://github.com/web2py/web2py (Source code) - https://code.google.com/p/web2py/issues/list (Report Issues) --- You received this message because you are subscribed to the Google Groups "web2py-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to web2py+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.