Package easyform :: Module DBGui
[hide private]
[frames] | no frames]

Source Code for Module easyform.DBGui

  1  #coding: utf8; 
  2   
  3  __doc__ = 'DB Easyform creator' 
  4  import os 
  5  import db3k 
  6  import easyform 
  7  from easyform import Entity, Group 
  8  import warn 
  9   
10 -class BaseUI:
11 - def __init__(self, objname):
12 self.objname = objname
13
14 - def populate(self, destdb):
15 for tab in self.show_tables(): 16 tab = tab[0] 17 foreigns = self.foreigns_fields(tab) 18 for desc in self.describe_table(tab): 19 d = {'objname': self.objname, 20 'form': tab, 21 'name': desc[0], 22 'type_code': desc[1], 23 'play_size': desc[2], 24 'internal_size': desc[3], 25 'precision': desc[4], 26 'scale': desc[5], 27 'null_ok': desc[6], 28 'ui_ok': 1 29 } 30 try: 31 foreigntable, foreignfield = foreigns[desc[0]] 32 d['foreigntable'] = foreigntable 33 d['foreignfield'] = foreignfield 34 except KeyError: 35 pass 36 # warn.debug("DDDDDDDDDDDD: ", d) 37 destdb.insert('admin_guigo',d)
38
39 -class Api2UI:
40 - def __init__(self, objname, conn, dbname, schema, structure = {}):
41 BaseUI.__init__(self, objname) 42 self.conn = conn 43 self.dbname = dbname 44 self.schema = schema 45 self.structure = structure # table => foreigns
46 # self.conn.execute("connect information_schema") 47
48 - def show_tables(self):
49 # return self.conn.execute("select table_name,table_catalog,table_rows,table_schema from tables") 50 return self.structure.values()
51
52 - def describe_table(self,tabname):
53 return self.conn.execute("select * from %s"%tabname)[1]
54
55 - def foreigns_fields(self,tabname):
56 return self.structure[tabname]
57 58
59 -class MysqlUI:
60 - def __init__(self, objname, conn, dbname, schema):
61 BaseUI.__init__(self, objname) 62 self.conn = conn 63 self.dbname = dbname 64 self.schema = schema
65 # self.conn.execute("connect information_schema") 66
67 - def show_tables(self):
68 # return self.conn.execute("select table_name,table_catalog,table_rows,table_schema from tables") 69 return self.conn.query("select table_name from tables where table_schema = '%s'"%self.dbname)
70
71 - def describe_table(self,tabname):
72 x = self.conn.query(""" 73 select column_name, data_type, NULL, NULL, NULL, NULL, is_nullable = 'YES' 74 FROM columns where table_schema = %s and table_name = %s""", (self.dbname, tabname)) 75 return x
76
77 - def foreigns_fields(self,tabname):
78 # return [] 79 tabs = self.describe_table(tabname) 80 res = [] 81 for d in tabs: 82 field = d[0] 83 if '_' in field: 84 foreign = field.split("_",1) 85 res.append([tabname, field, foreign[0],foreign[1]]) 86 return res
87
88 -class PgUI(BaseUI):
89 - def __init__(self, objname, conn, database, schema):
90 BaseUI.__init__(self, objname) 91 self.conn = conn 92 self.database = database 93 self.schema = schema
94
95 - def show_tables(self):
96 return self.conn.query("SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = '%s'"%self.schema)
97
98 - def describe_table(self, tabname):
99 return self.conn.execute("SELECT * FROM %s.%s LIMIT 1"%(self.schema, tabname))[1]
100
101 - def foreigns_fields(self,tabname):
102 foreigns = self.conn.query(""" 103 SELECT 104 (SELECT relname FROM pg_class WHERE pg_class.oid = conrelid) as "localtable", 105 (SELECT attname FROM pg_attribute WHERE attrelid = conrelid AND attnum = conkey[1]) as "localfield", 106 (SELECT relname FROM pg_class WHERE pg_class.oid = confrelid) as "foreigntable", 107 (SELECT attname FROM pg_attribute WHERE attrelid = confrelid AND attnum = confkey[1]) as "foreignfield" 108 FROM pg_constraint 109 WHERE contype = 'f' AND conrelid = (SELECT oid FROM pg_class WHERE relname = '%s' and relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = '%s'))"""%(tabname,self.schema)) 110 res = {} 111 for localtable, localfield, foreigntable, foreignfield in foreigns: 112 res[localfield] = (foreigntable, foreignfield) 113 return res
114
115 -class NoDatabaseUI:
116 """ Useful to create empty sites structures, without databases"""
117 - def __init__(self, *args, **kwargs):
118 pass
119
120 - def show_tables(self):
121 return [(),()]
122
123 - def describe_table(self, tabname):
124 return ()
125
126 - def foreign_fields(self, tabname):
127 return [(),()]
128
129 -class ProjectUI:
130 - def __init__(self, objname, guigodb):
131 self.objname = objname 132 self.guigodb = guigodb
133
134 - def get_config(self):
135 return self.guigodb.hquery("SELECT * FROM admin_guigo_project WHERE objname = ? ORDER BY id",(self.objname,))[0]
136
137 - def get_internal_fields(self, tabname):
138 qres = self.guigodb.query("SELECT form FROM admin_guigo WHERE objname = ? AND form = ? AND ui_ok > 0 ORDER BY id",(self.objname,tabname)) 139 return [ q[0] for q in qres ]
140
141 - def show_tables(self):
142 # return self.conn.execute("select table_name,table_catalog,table_rows,table_schema from tables") 143 qres = self.guigodb.query("SELECT DISTINCT form FROM admin_guigo WHERE objname = ? ORDER BY id",(self.objname,)) 144 return [ str(q[0]) for q in qres ]
145
146 - def describe_table(self,tabname):
147 qres = self.guigodb.query("SELECT name, type_code, play_size, internal_size, precision, scale, null_ok " 148 "FROM admin_guigo WHERE objname = ? and form = ? ORDER BY id",(self.objname,tabname)) 149 res = [] 150 for q in qres: 151 xq = list(q) 152 xq[0] = str(q[0]) 153 xq[1] = str(q[1]) 154 res.append(xq) 155 return res
156
157 - def foreigns_fields(self,tabname):
158 return self.guigodb.query("""SELECT form, name, foreigntable, foreignfield """ 159 """FROM admin_guigo WHERE objname = ? AND form = ? AND """ 160 """foreigntable IS NOT NULL""",(self.objname,tabname))
161
162 -def import_user_interface(guigodb, 163 database=None, 164 objname=None, 165 user=None, 166 password=None, 167 host=None, 168 manager='postgresql', 169 language='en', 170 schema=None):
171 if manager == 'postgresql': 172 conn = db3k.Connection(database=database,user=user,password=password,host=host,manager=manager) 173 # warn.debug(locals()) 174 dbm = PgUI(objname, conn, database, schema) 175 elif manager == 'mysql': 176 conn = db3k.Connection(database='information_schema',user=user,password=password,host=host,manager=manager) 177 dbm = MysqlUI(objname, conn, database, schema) 178 elif manager == 'nodb': 179 dbm = NoDatabaseUI() 180 else: 181 raise Exception("This manager (%s) is not supported for UI generation"%manager) 182 dbm.populate(guigodb)
183
184 -class UserInterfaceGenerator:
185 - def __init__(self, guigodb, objname):
186 self.guigodb = guigodb 187 self.objname = objname 188 self.connui = ProjectUI(objname, guigodb)
189
190 - def normalizetype(self, type, length=0):
191 """Returns a tuple easyform-type""" 192 if type.find('char') >= 0: 193 return 'string' 194 elif type.find('int') >= 0: 195 return 'int' 196 elif type.find('text') >= 0: 197 return 'text' 198 elif (type.find('float') >= 0) or (type == 'numeric'): 199 return 'float' 200 elif type.find('list') >= 0: 201 return 'list' 202 elif type.find('datetime') >= 0 or type.find('timestamp') >= 0: 203 return 'datetime' 204 elif type.find('time') >= 0: 205 return 'time' 206 elif type.find('date') >= 0: 207 return 'date' 208 elif type.find('bool') >= 0: 209 return 'boolean' 210 else: 211 raise TypeError, "Unknown database type " + type
212
213 - def groupfromtable(self, tabname):
214 """ Creates a group from a table """ 215 des = self.connui.describe_table(tabname) 216 foreigns = self.connui.foreigns_fields(tabname) 217 warn.debug("DDDDDDDD ", foreigns) 218 config = self.connui.get_config() 219 dfor = {} 220 for f in foreigns: 221 dfor[str(f[1])] = f 222 onsubmit=r"commitform(this, '%s','%s',['%%%%(__mode__)s',Easyform_formToDict(this),%%%%(__cond__)s]);"%(self.objname,tabname) 223 g = Group(tabname,onsubmit=onsubmit,language=config['language'],internal_fields=self.connui.get_internal_fields(tabname)) 224 for d in des: 225 name, type_code, play_size, internal_size, precision, scale, null_ok = d 226 try: 227 name = str(name) 228 warn.debug("OOOO %s>"%tabname, repr(name), dfor) 229 localtable, localfield, foreigntable, foreignfield = dfor[name] 230 warn.debug("================================================> ",dfor[name]) 231 markuptemplate = (r"""<select onfocus="callto({'rawhandler': createhandlerselect('%%(value)s'), 'handlerargs': this},""" 232 r"""'%s','preview_%s',['%s'])" name="%%(name)s:%%(type)s">""" 233 r"""</select>""" 234 r"""<a style="text-decoration: none; font-family: sans-serif;" """ 235 r"""href="javascript: showformmodify('%s', '%s'); void(0);">+</a>""" 236 r"""\n"""%(self.objname, foreigntable, foreignfield, self.objname, foreigntable)) 237 except KeyError: 238 markuptemplate = None 239 constraints = [] 240 if not null_ok: 241 constraints.append("mandatory") 242 entity = Entity(name=name, type=self.normalizetype(type_code), constraints=constraints, markuptemplate=markuptemplate) 243 g.append( entity ) 244 # print name, type_code, play_size, internal_size, precision, scale, null_ok 245 e = Entity("",type="submit",language=config['language']) 246 e.value = e.locale('name_submit') 247 g.append(e) 248 return g
249
250 - def createsite(self, dbconn, objpath):
251 """ Creates the complete site 252 |name| The name of the site. 253 |outdir| The output directory. 254 """ 255 tabres = self.connui.show_tables() 256 config = self.connui.get_config() 257 pycont = easyform.PythonContainer() 258 pycont.begin() 259 for tabname in tabres: 260 g = self.groupfromtable(tabname) 261 pycont.append(g.name, g) 262 import packadmin 263 try: 264 config['fullobjpath'] = os.path.join(objpath,self.objname) 265 if os.path.isfile(config['fullobjpath'] + ".py"): 266 raise Exception("The full path to this object %(fullobjpath)s already exists, please remove it first to recreate"%config) 267 config['fullobjname'] = packadmin.get_objname_from_path(config['fullobjpath']) 268 except packadmin.PathNotAllowed, e: 269 warn.warn("create site: ",e) 270 raise 271 pycont.end(config)
272