ここで SQLalchemy ユーザーを開始します。テーブルの主キーとして UUID を使用する予定です。
チュートリアルでは、ORM クラスでネイティブの Python UUID タイプを使用するためのコードを見ました。ユーレカ!システム データベースに Postgresql のネイティブ UUID タイプを使用できます。この TypeDecorator は、モバイル クライアントの SQLite の UUID を文字列化します。
http://docs.sqlalchemy.org/en/latest/core/types.html#backend-agnostic-guid-type
悲しみ。UUID を主キーとして文字列化した既存のSQLite データベースでこれを使用すると、変更をコミットしようとすると古いデータ エラーが発生します。
このクラスは、コミット時に古いデータでクラッシュします。
class CommodityTypes(Base):
__tablename__ = 'CommodityTypes'
uuidKey = Column(GUID, primary_key=True)
myName = Column(String, unique = True)
sortKey = Column(Integer, unique = True)
、しかし、このクラスは動作します:
class NewTypes(Base):
__tablename__ = 'CommodityTypes'
uuidKey = Column(String, primary_key=True)
myName = Column(String, unique = True)
sortKey = Column(Integer, unique = True)
CommodityTypes クラスから照会されたオブジェクトは、uuidKey の Python UUID タイプを示します。スクリプトはオブジェクトを正しくクエリします。設定を変更できますが、コミットできません。装飾された uuidKey が機能していないようです。
uuidKey 列に文字列を使用するだけで先に進むことができますが、http://docs.sqlalchemy.org/en/latest/core/types.html#backend-agnostic-guid-typeのコードが ほとんど機能することに不満を感じています。
問題のあるサンプルコードを次に示します。GUID タイプのデコレータを使用しない文字列の回避策はコメント アウトされています。
#system modules
import uuid
#other modules
import sqlalchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref, sessionmaker
from sqlalchemy.types import TypeDecorator, CHAR
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
engine = create_engine('sqlite:////home/XXXX/XobfuscatedXXXX/XXXXXXXX.sqlite')
Base = declarative_base()
Session = sessionmaker(bind=engine)
class GUID(TypeDecorator):
"""Platform-independent GUID type.
Uses Postgresql's UUID type, otherwise uses
CHAR(32), storing as stringified hex values.
"""
impl = CHAR
def load_dialect_impl(self, dialect):
if dialect.name == 'postgresql':
return dialect.type_descriptor(UUID())
else:
return dialect.type_descriptor(CHAR(32))
def process_bind_param(self, value, dialect):
if value is None:
return value
elif dialect.name == 'postgresql':
return str(value)
else:
if not isinstance(value, uuid.UUID):
return "%.32x" % uuid.UUID(value)
else:
# hexstring
return "%.32x" % value
def process_result_value(self, value, dialect):
if value is None:
return value
else:
return uuid.UUID(value)
from sqlalchemy import Column, Boolean, DateTime, Date, Float, ForeignKey, Integer, Numeric, String
class CommodityTypes(Base):
__tablename__ = 'CommodityTypes'
uuidKey = Column(GUID, primary_key=True)
myName = Column(String, unique = True)
sortKey = Column(Integer, unique = True)
#class NewTypes(Base):
# __tablename__ = 'CommodityTypes'
# uuidKey = Column(String, primary_key=True)
# myName = Column(String, unique = True)
# sortKey = Column(Integer, unique = True)
if __name__=="__main__":
session = Session()
# newList = session.query(NewTypes).order_by(NewTypes.sortKey)
# for instance in newList:
# print(instance.myName)
#
# nt = newList[1]
# print(nt.myName)
# print(nt.sortKey)
# nt.sortKey = 11
# print(nt.sortKey)
# session.commit()
# print(nt.sortKey)
ctList = session.query(CommodityTypes).order_by(CommodityTypes.sortKey)
for instance in ctList:
print(instance.myName)
ct = ctList[1]
print(ct.myName)
print(ct.sortKey)
ct.sortKey = 22
print(ct.sortKey)
session.commit()
print(ct.sortKey)
ああ、ソフトウェアのバージョンについて言及するのを忘れていました:
Python 3.1.3 (r313:86834、2010 年 12 月 1 日、06:15:12)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-48)] linux2 上