def onSuccess(self, fields, REQUEST=None): """Save the data from the form into a relational database. It works in the following way: if a query is defined on the adapter, it will use that query to insert the data into the database. If no query is defined, it will try to automatically save all form fields. "Normal" fields will be saved into the primary table, while FormDataGridField and FormFileField fields will be saved into separate tables. For this to work, your database and tables have to be created and set up according to the following rules: - Name of the primary table for storing the form data is same as the id of the form (with '-' changed to '_' and '.' to '') - All "auxiliary" tables for FormDataGridField and FormFileField fields are named in the convention of form_table_name + _ + field.id. Also, each auxiliary table must have a form_table_name_id column, which is a foreign key. - All table colums must be named after form field id's (with '-' changed to '_' and '.' to '') :param fields: form fields :param REQUEST: request object """ try: db = getUtility(IDatabase, self.db_utility_name) except ComponentLookupError: logger.exception('Can not write to database, wrong configuration') return { FORM_ERROR_MARKER: _( 'Can not write to database, wrong configuration. Please ' 'contact site owner.' ) } form_table_name = cleanString(self.getParentNode().id) query_args = self._constructQueryData( fields, form_table_name, REQUEST) query = self.query try: connection = db.connection.engine.connect() except: logger.exception('Error connecting to database.') return { FORM_ERROR_MARKER: _( 'Can not write to database, wrong configuration. Please ' 'contact site owner.' ) } try: # begin transaction for all executions trans = connection.begin() if(query): # custom query was defined on the adapter, let's use that connection.execute(query, **query_args[0][1]) else: # no query was defined, store all form fields select_string = "SELECT MAX(ID) FROM {0}".format( form_table_name) form_id = (connection.execute( select_string).scalar() or 0) + 1 if db.engine.url.drivername == 'postgresql': paramstyle = 'pyformat' else: paramstyle = 'named' for field in query_args: table_name = field[0] # insert FormDataGridField fields into separate tables if(type(field[1]) == list): for item in field[1][:]: # Setting grid table name, based on the form name item[form_table_name + "_id"] = form_id params = item.keys() query_string = \ "INSERT INTO {0} {1} VALUES {2}".format( table_name, self._join_params(params), self._join_params( params, paramstyle=paramstyle ) ) connection.execute(query_string, **item) # insert "normal" fields into the primary table else: params = field[1].keys() query_string = \ "INSERT INTO {0} {1} VALUES {2}".format( table_name, self._join_params(params), self._join_params( params, paramstyle=paramstyle ) ) connection.execute(query_string, **field[1]) # commit the transaction, saving the changes trans.commit() except: trans.rollback() logger.exception('Error writing to database.') return { FORM_ERROR_MARKER: _( 'Can not write to database, wrong configuration. Please ' 'contact site owner.' ) }
def _getProperty(self): return _("RDB Action Adapter")
# insert "normal" fields into the primary table else: params = field[1].keys() query_string = \ "INSERT INTO {0} {1} VALUES {2}".format( table_name, self._join_params(params), self._join_params( params, paramstyle=paramstyle ) ) connection.execute(query_string, **field[1]) # commit the transaction, saving the changes trans.commit() except: trans.rollback() logger.exception('Error writing to database.') return { FORM_ERROR_MARKER: _( 'Can not write to database, wrong configuration. Please ' 'contact site owner.' ) } RDBPloneFormGenAdapterFactory = Factory( RDBPloneFormGenAdapterContent, title=_('Add RDB Action Configuration') )