Latest posts on Транслятор имён в SQLAlchemy. topichttps://python.su/forum/topic/2100/2008-05-19T23:12:15+03:00Общий :: Базы данных :: Транслятор имён в SQLAlchemy.
2008-05-19T23:12:15+03:00ZZZ13177Я, по-началу, тоже об этом подумал, но… На самом деле всё ещё круче!<br/><br/>UsersTable = Table(“users”, metadata,<br/> Column(“user_id”, Integer, primary_key = True, nullable = False, key = “UserId”),<br/> Column(“login”, String(32), nullable = False, key = “Login”)<br/>)<br/><br/>Таким образом преобразование имён происходит ещё во время создания таблицы. Об этом можно только мечтать! Так что реальная проблема решена лучше, чем я расчитывал.<br/><br/>Осталось лишь желание разобраться с метаклассами… Так, для спортивного инетереса…<br/><br/><blockquote><em>j2a</em><br/>p.s. в SQLAlchemy принято, что классы таблиц в нижнем_регистре, а классы-маппинги - в CamelCase</blockquote>Учтём.
Общий :: Базы данных :: Транслятор имён в SQLAlchemy.
2008-05-19T08:09:15+03:00j2a13159Ну создай просто преобразование TransDict->properties_dict:<br/><br/>TransDict = {'UserID': ‘user_id’, ‘Login’: ‘login’}<br/>users_table = sa.Table(…)<br/>class User((object): pass<br/><br/>properties_dict = dict((key, getattr(users_table.c, field)) for key, field in TransDict.items())<br/>sa.mapper(User, users_table, properties=properties_dict)<br/><br/><br/>p.s. в SQLAlchemy принято, что классы таблиц в нижнем_регистре, а классы-маппинги - в CamelCase
Общий :: Базы данных :: Транслятор имён в SQLAlchemy.
2008-05-19T04:26:13+03:00ZZZ13158Не пошёл я спать.<br/>Стоило мне задуматься о том, что я изобретаю очередной велосипед…<br/><br/>mapper(User, UsersTable, properties={<br/> ‘UserId’: UsersTable.c.user_id,<br/> ‘Login’: UsersTable.c.login,<br/>})<br/><br/><br/>Идиотизм, однако, но мне всё-таки интересно разобраться с первым направлением поиска. Для того, чтобы разобраться.
Общий :: Базы данных :: Транслятор имён в SQLAlchemy.
2008-05-19T02:57:17+03:00ZZZ13157Пытаюсь решить самостоятельно.<br/><br/>class Meta(type):<br/> def __new__(cls, name, bases, dct):<br/> return type.__new__(cls, name, bases, dct)<br/><br/> def __init__(cls, name, bases, dct):<br/> type.__init__(cls, name, bases, dct)<br/><br/> def __getattr__(cls, attr):<br/> if attr in cls.TransDict:<br/> try: return cls.__dict__[cls.TransDict]<br/> except KeyError: raise AttributeError(cls.TransDict)<br/> else:<br/> try: return cls.__dict__<br/> except KeyError: raise AttributeError(attr)<br/><br/> def __setattr__(cls, attr, value):<br/> if attr in cls.TransDict:<br/> cls.__dict__[cls.TransDict] = value<br/> else:<br/> cls.__dict__ = value<br/><br/><br/>class DbObject(object):<br/> __metaclass__ = Meta<br/> TransDict = {}<br/> def __getattr__(self, attr):<br/> if attr in self.TransDict:<br/> try: return self.__dict__[self.TransDict]<br/> except KeyError: raise AttributeError(self.TransDict)<br/> else:<br/> try: return self.__dict__<br/> except KeyError: raise AttributeError(attr)<br/><br/> def __setattr__(self, attr, value):<br/> if attr in self.TransDict:<br/> self.__dict__[self.TransDict] = value<br/> else:<br/> self.__dict__ = value<br/><br/><br/>class User(DbObject):<br/> TransDict = { ## Собственно отображение<br/> “UserId”: “user_id”,<br/> “Login”: “login”<br/> }<br/><br/> def __init__(self, user_id, login):<br/> self.user_id = user_id<br/> self.login= login<br/><br/> def __repr__(self):<br/> return “<User('%s','%s')>” % (self.UserId, self.Login)<br/>Теперь, если делаем `print User.Login`, то матерится на отсутствие “login”, т.е. работает правильно.<br/>А вот если print `User.Login` = u“чё-нить”, то мат смещается в сторону невозможности изменить объект типа dictproxy в последней строке __setattr__ метакласса. Т.е __dict__ у классов не изменяем…<br/><br/>Как сломать?<br/><br/>P.S. Практически, это первая серьёзная проба создания метаклассов… Так что уж сильно не смейтесь…<br/>P.P.S. А теперь спать. Продолжу ломать мозг завтра.
Общий :: Базы данных :: Транслятор имён в SQLAlchemy.
2008-05-19T01:50:27+03:00ZZZ13156Привет всем!<br/>Изучаю SQLAlchemy. Всё замечательно.<br/>Xочу на её уровне организовать трансляцию имён из имён базы данных, в имена сервера/клиента. Т.е. существует отображение имён DB к именам программы, назовём его TransDict, и мне нужно, чтобы работал следующий код:<br/><br/><br/># -*- coding: utf-8 -*-<br/><br/>from sqlalchemy import *<br/>from sqlalchemy.orm import *<br/><br/>metadata = MetaData(“sqlite:///:memory:”)<br/>metadata.bind.echo = True<br/><br/>UsersTable = Table(“users”, metadata,<br/> Column(“user_id”, Integer, primary_key = True, nullable = False),<br/> Column(“login”, String(32), nullable = False)<br/>)<br/><br/>metadata.create_all()<br/><br/><br/>class DbObject(object):<br/> TransDict = {}<br/> def __getattr__(self, attr):<br/> if attr in self.TransDict: return getattr(self, self.TransDict)<br/> else:<br/> try: return self.__dict__<br/> except KeyError: raise AttributeError(attr)<br/><br/> def __setattr__(self, attr, value):<br/> if attr in self.TransDict: return setattr(self, self.TransDict, value)<br/> else:<br/> self.__dict__ = value<br/><br/><br/>class User(DbObject):<br/> TransDict = { ## Собственно отображение<br/> “UserId”: “user_id”,<br/> “Login”: “login”<br/> }<br/><br/> def __init__(self, user_id, login):<br/> self.user_id = user_id<br/> self.login= login<br/><br/> def __repr__(self):<br/> return “<User('%s','%s')>” % (self.UserId, self.Login)<br/><br/><br/>mapper(User, UsersTable)<br/><br/>Session = create_session(autoflush=True, transactional=True)<br/><br/>root = User(1, “root”)<br/>Session.save(root)<br/><br/>User2 = User(2, “User2”)<br/>Session.save(User2)<br/><br/>Session.commit()<br/>print Session.query(User).all()<br/><br/>User2.Login = “User22”<br/>Session.commit()<br/>print Session.query(User).all()<br/><br/>## До этого момента всё Ok.<br/>print Session.query(User).filter(User.UserId > 1).all()<br/><br/><br/><br/>Я прекрасно понимаю почему оно не работает (это описывать не надо).<br/>Нутром чую, что решение заключается в создании своего матакласса, но работал с ними настолько мало, что даже на такую проблему меня не хватило.<br/>Фактически зачача не связана с алхимией. Нужно обработать __getattr__ и __setattr__ в подклассе от DbObject, да так, чтобы иметь доступ к TransDict… Очень бы хотелось помощи.<br/><br/>P.S. Для чего это нужно? Для удобства. Дело в том, что клиент у меня на PyQt4 и я пытаюсь сохранить qt'шную стилистику и одно пространство имён как для клиента, так и для сервера. Я намеренно отказался от PEP8. В тоже время, в DB хотелось бы выдержать стиль, принятый в базах данных. Вот и приходится извращатся с, так сказать, шлюзом.