[Zope] PSQLINPUT Wizard Error
Zope
zope@philosoft.at
Wed, 6 Oct 1999 13:29:31 +0200
This is a multi-part message in MIME format.
------=_NextPart_000_000E_01BF0FFE.D2931E70
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
I had the same error, but I could fix it:
1. open the file Zope\lib\python\Products\PSQLInput\Wizard.py
2. goto line 357, containing the following:
self.aq_parent.manage_addZSQLMethod(sqlId, sqlTitle,
self.connection_id,
args, command)
3. replace the previous statement by the following:
self.aq_parent._setObject(sqlId, Products.ZSQLMethods.SQL.SQL(sqlId,
sqlTitle,
self.connection_id, args, command))
4. restart Zope
I attached the complete Wizard.py
hope it helped
phil
----- Original Message -----
From: Ping Lau
To: zope@zope.org
Sent: Sunday, October 03, 1999 8:40 AM
Subject: [Zope] PSQLINPUT Wizard Error
Has anyone successfully used PSQLInput Product? It gave me the error:
Error Type: AttributeError
Error Value: manage_addZSQLMethod
I am running Zope 2.0.1 & MySQL on Win98.
Regards,
Ping
------=_NextPart_000_000E_01BF0FFE.D2931E70
Content-Type: application/octet-stream;
name="Wizard.py"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="Wizard.py"
"""P SQL Input Wizard
Help to create method, form and result page to insert data in a =
database.
This is a wizard to help create database input forms and SQL methods.=20
The idea is to help the user to select the database tables and columns =
to=20
which input data and the wizard automagically creates the insert SQL=20
method and the HTML input form.
You'll probably have to edit the generated documents and method. The =
method=20
specially if you are inputing data in multiple tables, since you'll want =
to=20
have the same data in multiple dates (e.g. person_id).
Remember that it is easier to take out paramenters than to search your=20
documentation/database for them, so don't be shy selecting items.
This software is released under GNU public license. See details in the =
URL:
http://www.gnu.org/copyleft/gpl.html
Author: Paulo Eduardo Neves <neves@inf.puc-rio.br>
Please send me bugs and feedback about how to improve it.
"""
import string
import Acquisition
from Globals import HTMLFile, Persistent, MessageDialog
import Products.ZSQLMethods.SQL
def implementedSQLConnectionIDs(self):
"""Find SQL database connections in the current folder and above
This function return a list of ids.
Shameless stolen (with little modifications) from SQL.py
"""
ids=3D{}
have_id=3Dids.has_key
StringType=3Dtype('')
while self is not None:
if hasattr(self, 'objectValues'):
for o in self.objectValues():
try:
if (hasattr(o,'_isAnSQLConnection')=20
and o._isAnSQLConnection
and hasattr(o,'id')):
#let's see if this DB is suported
if not hasattr(o, 'database_type'):
raise ImportError
exec('import DBInfo.' + getattr(o, 'database_type'))
=09
id=3Do.id
if type(id) is not StringType: id=3Did()
if not have_id(id):
if hasattr(o,'title_and_id'): o=3Do.title_and_id()
else: o=3Did
ids[id]=3Did
except ImportError:
#Database is not supported
pass=20
if hasattr(self, 'aq_parent'): self=3Dself.aq_parent
else: self=3DNone
ids=3Dmap(lambda item: (item[1], item[0]), ids.items())
ids.sort()
return ids
manage_startWizard =3D HTMLFile('selectDB', globals())
def _generateId(self, baseName):
"Returns a not used attribute in the self object"
id =3D baseName
count =3D 1
while hasattr(self, id):
id =3D baseName + `count`
count =3D count + 1
return id
def debug(self):
"debug"
return ""
def manage_createWizard(self, connection_id, REQUEST):
"""Create the wizard for the desired connection_id
and call it's default method """
id =3D _generateId(self, "psqlwiz") #default name
wiz =3D PSQLInputWizard(id, connection_id)
setattr(self, id, wiz)
REQUEST.RESPONSE.redirect("%s/%s" % (REQUEST['URL1'], id))
class Table:
"""Class to group table and columns atributtes
Just to have a cleaner (dtml) code"""
def __init__(self, name, columns, optionalColumns =3D []):
self.tableName =3D name
self.columns =3D columns
self.optional =3D optionalColumns
=09
def __str__(self):
return "Table Name:%s<BR>\nColumns:%s" % (self.tableName, =
`self.columns`)
class PSQLInputWizard(
Acquisition.Implicit,
Persistent,
):
"""A Wizard to create forms and methods to insert data in databases
The wizard uses a sequence of forms to ask the user for data,
these data are stored as attributes in the wizard. When all the =
necessary=20
data are gathered it creates the input form, result page and method.
"""
__ac_permissions__ =3D (
('Use SQL Wizard', ('index_html', 'collectIds',=20
'selectColumns', 'getObjectsInfo',
'createSQLInput', 'quit')),
)
meta_type =3D 'P SQL Input Wizard'
dtmlDir =3D 'Products/PSQLInput/'
def __init__(self, id, connection_id):
self.id =3D id
self.connection_id =3D connection_id
self.tables =3D []
self.selectedTables =3D []
self.tableColumns =3D []
self.selectedColumns =3D []
self.sqlArguments =3D []
def _infoFactory(self):
connection =3D getattr(self, self.connection_id)
exec('import DBInfo.' + connection.database_type)
return eval('DBInfo.' + connection.database_type + '.Info(connection)')
def index_html(self):
"Start input wizard data gathering, show database tables to the user"
self.info =3D self._infoFactory()
self.tables =3D self.info.getTablesNames()=20
selectTables =3D HTMLFile( self.dtmlDir + 'selectTables')
return selectTables(self, self)
def queryColumns(self, selectedTables =3D []):
"Ask user to select data columns in selected tables"
if selectedTables !=3D []:
self.selectedTables =3D []
for i in selectedTables:
self.selectedTables.append(self.tables[i])
self.tableColumns =3D []
for i, j in self.info.getColumnsNames(self.selectedTables).items():
self.tableColumns.append(Table(i,j))
selectColumns =3D HTMLFile(self.dtmlDir + 'selectColumns')
return selectColumns(self,self)
=09
=20
def _cleanColName(self, name):
return string.join(map(string.capitalize, string.split(name, '_')))
=20
def _uniqueCol(self, table, column):
#return table + string.capitalize(column)
return table + '.' + column
=20
def _buildInputForm(self, resultPageId):
#base %s parameters: result page id, form contents
base =3D """<!--#var standard_html_header-->
<H2><!--#var title_or_id--> <!--#var document_title--></H2>
<P><FORM ACTION=3D"%s" METHOD=3D"POST">
<TABLE>
%s
</TABLE>
<input type=3D"SUBMIT" name=3D"submit" value=3D"Insert">
</FORM>
<!--#var standard_html_footer-->"""
inputBase =3D '\t<TR><TD ALIGN=3D"RIGHT">%s</TD><TD><INPUT =
TYPE=3D"TEXT" NAME=3D"%s"></TD></TR>'
form =3D []
for i in self.selectedColumns:
form.append('<TR BGCOLOR=3D"#CCCCCC"><TD COLSPAN=3D2>%s</TD></TR>'=20
% i.tableName)
for j in i.columns:
if j in i.optional:
form.append(inputBase=20
% (self._cleanColName(j),=20
self._uniqueCol(i.tableName, j)))
else:
form.append(inputBase=20
% ("<B>" + self._cleanColName(j) + "</B>",=20
self._uniqueCol(i.tableName, j)))
return base % (resultPageId, string.join(form, '\n'))
def _buildResultPage(self, sqlMethodId):
base =3D """<!--#var standard_html_header-->
<H2><!--#var title_or_id--> <!--#var document_title--></H2>
<P><!--#call "%s(REQUEST)"-->
Your data was inserted in the Database!
<!--#var standard_html_footer-->""" # How do I catch SQL errors?
return base % sqlMethodId
def debug(self):
"sss"
x =3D ''
for i in table.columns: x=3D x+ ' ' + i
x =3D x+ '\n************\n'
for i in table.optional: x=3D x+ ' ' + i
return x
def _buildSQLValues(self, table, nonOptCol):
template =3D '<!--#sqlvar %s type=3D%s %s-->'
args =3D []
for i in table.columns:
tp =3D self.info.type(table.tableName, i)
opt =3D self.info.nullable(table.tableName, i)
uniqueCol =3D self._uniqueCol(table.tableName, i)
=20
oneArg =3D template % (uniqueCol, tp, opt) + ','
if i in table.optional:
args.append('<!--#if %s-->\n\t\t\t%s\n\t\t<!--#/if-->'
% (uniqueCol, oneArg))
else:
args.append(oneArg)
#there's just missing the non optional (without the comma)
tp =3D self.info.type(table.tableName, nonOptCol)
opt =3D self.info.nullable(table.tableName, nonOptCol)
uniqueCol =3D self._uniqueCol(table.tableName, nonOptCol)
args.append(template % (uniqueCol, tp, opt))
return string.join(args, '\n\t\t')
def _buildSQLInto(self, table, nonOptCol):
tempCols =3D []
for i in table.columns:
tempCols.append(i + ',')
newCol =3D []
for i in range(len(table.columns)):
if table.columns[i] in table.optional:
newCol.append('<!--#if %s -->\n\t\t%s\n\t<!--#/if-->' %=20
(self._uniqueCol(table.tableName,
table.columns[i]),=20
tempCols[i]))
else:
newCol.append(tempCols[i])
newCol.append(nonOptCol)
return string.join(newCol,'\n\t')
=09
def _buildSQLInputCommand(self):
baseCommand =3D "INSERT INTO %s \n\t(%s)\n\tVALUES (%s)"
command =3D []
inputArgs =3D []
for i in self.selectedColumns:
#building sql method arguments
for j in i.columns:
tempArg =3D self._uniqueCol(i.tableName, j)
if j in i.optional:
tempArg =3D tempArg + '=3D""'
inputArgs.append(tempArg)
#Let's find a column that isn't optional,=20
#I've already verified in getObjectsInfo that it exists
for col in i.columns:
if col not in i.optional:
nonOptCol =3D col
i.columns.remove(col)
break
#building sql method
command.append(baseCommand % (i.tableName,=20
self._buildSQLInto(i, nonOptCol),
self._buildSQLValues(i, nonOptCol)))
return string.join(inputArgs), string.join(command,'\n<!--#var =
sql_delimiter -->\n')
def getObjectsInfo(self, REQUEST):
"Store data and Collect id's and title of objects to be created"
self.selectedColumns =3D []
for i in self.selectedTables:
if REQUEST.has_key(i):
optional =3D []
if REQUEST.has_key('opt.' + i):
optional =3D REQUEST['opt.' + i]
oneColNonOptional =3D None
for j in REQUEST[i]:
if j not in optional:
oneColNonOptional =3D 1
break
if oneColNonOptional is None:
return MessageDialog(title=3D"Error",
message =3D "<h1>Error</h1>There must be at least one selected =
non-optional column",
action =3D REQUEST['HTTP_REFERER']
)
=09
self.selectedColumns.append(Table(i, REQUEST[i],=20
optional))
if self.selectedColumns =3D=3D []:
return MessageDialog(title=3D"Error",
message =3D "<h1>Error</h1>You Must select at least one column of =
one table",
action =3D REQUEST['HTTP_REFERER']
)
allTables =3D string.join(map(string.capitalize, =
self.selectedTables),'')
defaultTitles =3D string.join(map(string.capitalize,=20
self.selectedTables))
formDefaultId =3D _generateId(self.aq_parent, allTables + "InsertForm")
resultDefaultId =3D _generateId(self.aq_parent,=20
allTables + "InsertResult")
sqlMethodDefaultId =3D _generateId(self.aq_parent,=20
allTables + "InsertMethod")
collectIds =3D HTMLFile(self.dtmlDir + 'collectIds')
return collectIds(self,=20
formId=3DformDefaultId,=20
resultId=3DresultDefaultId,
sqlId=3DsqlMethodDefaultId,
titles=3DdefaultTitles)
=20
def createSQLInput(self, RESPONSE, URL2, formId, resultId, sqlId,=20
formTitle=3D'', resultTitle =3D '', sqlTitle =3D ''):
"""Method to add the Z SQL Method and a Form to access it,=20
also delete Wizard from parent folder """
try:
self.aq_parent.manage_addDTMLDocument(formId, formTitle,=20
self._buildInputForm(resultId) )=20
except AttributeError:
self.aq_parent.manage_addDocument(formId, formTitle,=20
self._buildInputForm(resultId) )=20
try:
self.aq_parent.manage_addDTMLDocument(resultId, resultTitle,=20
self._buildResultPage(sqlId) )=20
except AttributeError:
self.aq_parent.manage_addDocument(resultId, resultTitle,=20
self._buildResultPage(sqlId) )=20
=20
args, command =3D self._buildSQLInputCommand()
#self.aq_parent.manage_addZSQLMethod(sqlId, sqlTitle,=20
# self.connection_id,
# args, command)
#corrected by Philosoft Okt 1,1999:
self.aq_parent._setObject(sqlId, Products.ZSQLMethods.SQL.SQL(sqlId, =
sqlTitle,
self.connection_id, args, command))
self.quit(RESPONSE, URL2)
def quit(self, RESPONSE, URL2):
"Cleans temporary objects used by P SQL Wizard"
=09
delattr(self.aq_parent, self.id) #deleting wizard, if you leave in the =
middle there will be trash in your folder
=09
=09
RESPONSE.redirect(URL2 + '/manage_main') #should I show some message?
=20
------=_NextPart_000_000E_01BF0FFE.D2931E70--