Форумы сайта python.su
Вы не зашли.
Здравствуйте!
Я пока только разбираюсь с ТГ и у меня, наверное, совсем дурацкая проблема: я попыталась сгенерировать классы на основе существующей базы postgres, в файл model.py вписала:
class BBPoP(SQLObject):
class sqlmeta:
fromDatabase = Trueзагрузила admin toolbox, и при попытке зайти в model designer мне выдало длинный лог ошибок. Последние неск. строк:
File "H:\db4\db4\model.py", line 9, in <module>
class BBPoP(SQLObject):
File "c:\python25\lib\site-packages\SQLObject-0.10.2-py2.5.egg\sqlobject\declarative.py", line 92, in __new__
cls.__classinit__(cls, new_attrs)
File "c:\python25\lib\site-packages\SQLObject-0.10.2-py2.5.egg\sqlobject\main.py", line 791, in __classinit__
cls.sqlmeta.addColumnsFromDatabase()
File "c:\python25\lib\site-packages\SQLObject-0.10.2-py2.5.egg\sqlobject\main.py", line 447, in addColumnsFromDatabase
for columnDef in conn.columnsFromSchema(sqlmeta.table, soClass):
File "c:\python25\lib\site-packages\SQLObject-0.10.2-py2.5.egg\sqlobject\postgres\pgconnection.py", line 212, in columnsFromSchema
keyData = self.queryAll(keyQuery % self.sqlrepr(tableName))
File "c:\python25\lib\site-packages\SQLObject-0.10.2-py2.5.egg\sqlobject\dbconnection.py", line 686, in queryAll
return self._dbConnection._queryAll(self._connection, s)
File "c:\python25\lib\site-packages\SQLObject-0.10.2-py2.5.egg\sqlobject\dbconnection.py", line 343, in _queryAll
self._executeRetry(conn, c, s)
File "c:\python25\lib\site-packages\SQLObject-0.10.2-py2.5.egg\sqlobject\dbconnection.py", line 329, in _executeRetry
return cursor.execute(query)
ProgrammingError: FEHLER: Relation »bb_po_p« existiert nichtВ смысле, рилейшн »bb_po_p« не найден.
В этом рилейшне явно опечатка - правильно должно быть »bb_pop«.
А теперь, собсно, вопрос: можно как-то определить, где эту опечатку искать? В файле model.py ее нет, а на большее у меня фантазии не хватает...
Заранее большое спасибо!
Неактивен
Спасибо!
Действительно, логично :-)
Но дальше все равно непонятно:
class BBPoP(SQLObject):
class sqlmeta:
fromDatabase = True
table = 'parameter.bb_pop'
idName = 'parameter.bb_pop.id_bbpop' # или ' id_bbpop'Почему-то ругается на отсутствие в таблице primary key, хотя в базе колонка ' id_bbpop' указана как primary key.
От отчаяния даже переименовала ее в просто 'id', но это тоже не сработало.
Вообще есть где-нить women-friendly мануалы, чтобы почитать про turbogears+sqlobject+postgres? Можно на английском. Оф. дока sqlobject не помогла, про TG тоже почти нигде ничего нет...
Неактивен
Какого типа поле id_bbpop? Перечитайте внимательно еще раз вот этот раздел Legacy Database Schemas
Отредактированно PooH (2008-10-08 12:44:50)
Неактивен
у поля id_bbpop тип INT, в базе оно объявлено как SERIAL PRIMARY KEY.
UPD:
Короче говоря, я сдалась. Оказалось, это довольно старый малоизвестный баг, который не дает склобжекту корректно работать с user-defined schemas. Буду изыскивать другие инструменты.
Спасибо большое за помощь!
Отредактированно hildi (2008-10-08 13:38:19)
Неактивен
hildi написал:
Оказалось, это довольно старый малоизвестный баг, который не дает склобжекту корректно работать с user-defined schemas. Буду изыскивать другие инструменты.
Не приходилось работать через sqlobject с унаследованными базами. Ради интереса дайте ссылочку на баг.
ЗЫ: Перешел на SQLAlchemy и не жалею ![]()
Неактивен
Я вообще в фреймворках и базах полный ноль. Меня брали на работу только простенький парсер написать, но у шефа вечно семь пятниц на неделе и постоянно какие-то наполеоновские планы, и вот результат :-) Мне, в общем, все равно, пусть будут фреймворки, раз они готовы платить за то, что я большую часть времени читаю на работе мануалы и интернет.
Про баг тут есть, и больше нигде:
http://article.gmane.org/gmane.comp.pyt … bject/3903
Щаз я тоже перейду на SQLAlchemy и как всем покажу! :-)
Неактивен
hildi, можно версии ТГ, sqlobject и pgsql?
у меня ТГ 1.0.4.4, SQLObject-0.8.2-py2.4.egg и postgresql 8.1 и всё работает без ошибок
class Client(SQLObject):
class sqlmeta:
fromDatabase = True
table = 'client'PS это в своё время также было проверено на MS SQL
Неактивен
У меня все равно не работает (см. выше). Может, это из-за схем, которые не public?
У меня turbogears 1.0.7, а Postgres 8.3.
А то же самое в SQL Alchemy можно просто сделать? Подозреваю, что это делается двумя строчками, знать бы только как :-(
Неактивен
hildi написал:
У меня все равно не работает (см. выше). Может, это из-за схем, которые не public?
можешь выложить структуру БД?
хотя бы одной таблицы?
PS TG 1.0.7 не сильно отличается от 1.0.4.4
Неактивен
Ох... Надеюсь, я правильно поняла:
-- Table: parameter.bbpop
-- DROP TABLE parameter.bbpop;
CREATE TABLE parameter.bbpop
(
id_bbpop serial NOT NULL,
bezeichnung character varying NOT NULL,
region smallint,
plz character varying(5),
ort character varying,
strasse character varying,
hnr character varying,
etage character varying,
raum character varying,
inbetrieb boolean NOT NULL DEFAULT false,
separiert boolean NOT NULL DEFAULT false,
date_created timestamp with time zone,
date_live timestamp with time zone,
CONSTRAINT bbpop_pkey PRIMARY KEY (id_bbpop)
)
WITH (OIDS=FALSE);
ALTER TABLE parameter.bbpop OWNER TO stat_admin;
Это одна таблица, там их штук 8, они объединены в категорию parameter, а база содержит несколько таких категорий.
Неактивен
pythonwin написал:
PS TG 1.0.7 не сильно отличается от 1.0.4.4
Посмотри ссылку на баг, которую она дала, он проявляется на постгрессе, на таблицах в схеме отличной от public.
Неактивен
С SQLAlchemy тоже непонятно :-(
вот это прекрасно генерирует классы из таблиц в интерпретаторе, но при добавлении этого кода в model.py, классы не видны из TG model designer... В model.py надо что-то специально для этого прописывать, чтобы можно было пользоваться TG model designer и Catwalk?
from sqlalchemy import *
engine = create_engine("postgres://...")
meta = MetaData()
meta.reflect(bind = engine, schema = "parameter")
bbpop = Table('parameter.bbpop', meta, autoload = True, autoload_with = engine)
...
class BBPoP(object): pass
...
mapper(BBPoP, bbpop)
...Я, наверное, ужасно глупые вопросы задаю, но что-то я никак не разберусь, как алхимия взаимодействует с ТГ :-(
Неактивен
sqlobject при создании класса генерирует код sql
SELECT pg_index.indisprimary,
pg_catalog.pg_get_indexdef(pg_index.indexrelid)
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
pg_catalog.pg_index AS pg_index
WHERE c.relname = 'boo.author'
AND c.oid = pg_index.indrelid
AND pg_index.indexrelid = c2.oid
AND pg_index.indisprimaryкоторый ищет в таблице boo.autor id, но который не работает в самом postgres.
нужен аналог этого кода, но для не для public схемы.
Неактивен
пока проблему решил так:
в pgconnection.py заменил
def columnsFromSchema(self, tableName, soClass):
keyQuery = """
SELECT pg_catalog.pg_get_constraintdef(oid) as condef
FROM pg_catalog.pg_constraint r
WHERE r.conrelid = %s::regclass AND r.contype = 'f'"""
colQuery = """
SELECT a.attname,
pg_catalog.format_type(a.atttypid, a.atttypmod), a.attnotnull,
(SELECT substring(d.adsrc for 128) FROM pg_catalog.pg_attrdef d
WHERE d.adrelid=a.attrelid AND d.adnum = a.attnum)
FROM pg_catalog.pg_attribute a
WHERE a.attrelid =%s::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum"""
primaryKeyQuery = """
SELECT pg_index.indisprimary,
pg_catalog.pg_get_indexdef(pg_index.indexrelid)
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
pg_catalog.pg_index AS pg_index
WHERE c.relname = %s
AND c.oid = pg_index.indrelid
AND pg_index.indexrelid = c2.oid
AND pg_index.indisprimary
"""
primaryKeyQueryMySchema = """
SELECT
pg_index.indisprimary,
pg_indexes.indexdef
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index AS pg_index, pg_indexes
WHERE c.relname = '%(tableNameOnly)s'
AND c.oid = pg_index.indrelid
AND pg_index.indexrelid = c2.oid
AND pg_index.indisprimary
AND pg_indexes.tablename = '%(tableNameOnly)s'
AND pg_indexes.schemaname = '%(schemaname)s'
AND pg_catalog.pg_get_indexdef(pg_index.indexrelid) = pg_indexes.indexdef;
"""
keyData = self.queryAll(keyQuery % self.sqlrepr(tableName))
keyRE = re.compile(r"\((.+)\) REFERENCES (.+)\(")
keymap = {}
for (condef,) in keyData:
match = keyRE.search(condef)
if match:
field, reftable = match.groups()
keymap[field] = reftable.capitalize()
if '.' in tableName:
schemaname, tableNameOnly = tableName.split('.')
else:
schemaname, tableNameOnly = 'public', tableName
sql = primaryKeyQueryMySchema%{'schemaname':schemaname, 'tableNameOnly':tableNameOnly}
#primaryData = self.queryAll(primaryKeyQuery % self.sqlrepr(tableName))
primaryData = self.queryAll(sql)
primaryRE = re.compile(r'CREATE .*? USING .* \((.+?)\)')
primaryKey = None
for isPrimary, indexDef in primaryData:
match = primaryRE.search(indexDef)
assert match, "Unparseable contraint definition: %r" % indexDef
assert primaryKey is None, "Already found primary key (%r), then found: %r" % (primaryKey, indexDef)
primaryKey = match.group(1)
assert primaryKey, "No primary key found in table %r" % tableName
if primaryKey.startswith('"'):
assert primaryKey.endswith('"')
primaryKey = primaryKey[1:-1]
colData = self.queryAll(colQuery % self.sqlrepr(tableName))
results = []
if self.unicodeCols:
client_encoding = self.queryOne("SHOW client_encoding")[0]
for field, t, notnull, defaultstr in colData:
if field == primaryKey:
continue
colClass, kw = self.guessClass(t)
if self.unicodeCols and colClass is col.StringCol:
colClass = col.UnicodeCol
kw['dbEncoding'] = client_encoding
kw['name'] = soClass.sqlmeta.style.dbColumnToPythonAttr(field)
kw['dbName'] = field
kw['notNone'] = notnull
if defaultstr is not None:
kw['default'] = self.defaultFromSchema(colClass, defaultstr)
elif not notnull:
kw['default'] = None
if keymap.has_key(field):
kw['foreignKey'] = keymap[field]
results.append(colClass(**kw))
return resultsпосле этого заработало
>>> import sqlobject
>>> from sqlobject import *
>>> connection_string = "postgres://postgres@localhost/t1"
>>> connection = sqlobject.connectionForURI(connection_string)
>>> sqlobject.sqlhub.processConnection = connection
>>> hub = connection.transaction()
>>> class Author(SQLObject):
... class sqlmeta:
... table = 'boo.author'
... fromDatabase = True
...
>>> class Author1(SQLObject):
... class sqlmeta:
... table = 'author'
... fromDatabase = True
...
>>> Author.sqlmeta.columns
{'login': <SOStringCol login not null>, 'password': <SOStringCol password not null>, 'name': <SOStringCol name not null>}
>>> Author(login='login', password='password', name='name')
<Author 1L login='login' password='password' name='name'>
>>> Author.select()
<SelectResults at -4883e954>
>>> Author.select()[:]
<SelectResults at -4883ea14>
>>> Author.select()[0:]
<SelectResults at -4883e954>
>>> Author.select()[0:5]
<SelectResults at -4883e874>
>>> print Author.select()[0:5]
SELECT boo.author.id, boo.author.login, boo.author.password, boo.author.name FROM boo.author WHERE 1 = 1 LIMIT 5
>>> l = list(Author.select())
>>> l
[<Author 1L login='login' password='password' name='name'>]
>>> Author1(login='login', password='password', name='name')
<Author1 1L login='login' password='password' name='name'>
>>> list(Author1.select())
[<Author1 1L login='login' password='password' name='name'>]
PS SQLObject-0.8.2-py2.4.egg, debian lenny
через catwalk тоже работатет
Неактивен
hildi, для твоей таблицы это будет выглядеть так
class BBPoP(SQLObject):
class sqlmeta:
fromDatabase = True
table = 'boo.bbpop'
idName = 'id_bbpop'Неактивен
Спасибо, pythonwin!
Правда, тулбокс хоть на скрипт и не ругается, но ничего и не отображает :-)
Фиг с ним, я уже SQLAlchemy добилась нужного результата и застряла на следующем действии :-)
апд: сорри, все работает, миллион спасибо!
Отредактированно hildi (2008-10-10 14:41:49)
Неактивен
Скажите, а вот эту книжку http://python.su/forum/viewtopic.php?pid=5162#p5162 вы не смотрели? Жаль мне она попала поздно, к этому времени почти во всем уже разобрался сам
Неактивен
К сож., я с работы не могу качать нелегитимные копии чего-либо, у нас довольно сильно пасут это дело, но дома посмотрю непременно, спасибо!
У меня другая книжка "Rapid Web Development with Python" by Michael Weigend. Отличная книжка, только там все примеры мне как-то... мимо кассы :-)
Вот бы еще что-нить про темплейты подробное почитать, а то я их логику вообще понять не могу. Как маленькие подстановки делать, я разобралась, но мне надо большие таблицы из этой дурацкой базы генерировать, и непонятно, где это надо формулировать? В модели или прямо в темплейте? Или в контроллере?
Блин, с чистым питоном и tk все так просто было! :-(
Отредактированно hildi (2008-10-10 15:12:15)
Неактивен
hildi написал:
Как маленькие подстановки делать, я разобралась, но мне надо большие таблицы из этой дурацкой базы генерировать, и непонятно, где это надо формулировать? В модели или прямо в темплейте? Или в контроллере?
Блин, с чистым питоном и tk все так просто было! :-(
Что именно формулировать? Логику выборки? Тогда лучшее место в методе контроллера, хотя если похожие выборки делаются во многих местах, я выношу запрос в модель, как метод класса или делаю промежуточный слой между моделью и контроллером, ну это в основном от величины задачи зависит.
Если речь именно о формировании html, то можно и прямо в шаблоне, отдаете туда результат запроса, например
#в контролере
def find(self, **kw):
q = database.session.query(model.BlaBla).all()
return dict(result=q)
#в шаблоне
<tr py:for="item in result">
<td>${item[0]}</td>
<td>${item[1]}</td>
</tr>Но лучше воспользоваться готовым виджетом DataGrid или PaginateDataGrid. и посмотрите декоратор paginate.
Вообщем книжку то почитайте. там все хорошо расписано ![]()
Отредактированно PooH (2008-10-13 07:02:52)
Неактивен
PooH, Вы просто сокровище!
Похоже, моя контора все-таки получит свой дурацкий портал до Рождества.
Кстати, о Рождестве...
Хотите рождественских пряников? Я Вам пришлю! Только ПМ-ните мне адрес :-)
Неактивен
hildi написал:
Похоже, моя контора все-таки получит свой дурацкий портал до Рождества.
можно поподробней? что за портал?
Неактивен