Skip to content

Instantly share code, notes, and snippets.

@nphilipp
Created May 19, 2019 14:55
Show Gist options
  • Save nphilipp/a1b490b762c1616baf48bf1e5930c637 to your computer and use it in GitHub Desktop.
Save nphilipp/a1b490b762c1616baf48bf1e5930c637 to your computer and use it in GitHub Desktop.
SQLAlchemy: Association proxy of a hybrid property test case
from sqlalchemy import create_engine, Column, ForeignKey, Integer, String, Unicode
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import relationship, scoped_session, sessionmaker
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.sql import case
maker = sessionmaker(autoflush=True, autocommit=False)
DBSession = scoped_session(maker)
DeclarativeBase = declarative_base()
class Language(DeclarativeBase):
__tablename__ = 'languages'
id = Column(Integer, primary_key=True)
lang = Column(String(2), nullable=False)
territory = Column(String(2), nullable=True)
@classmethod
def by_iso_code(cls, iso_code):
try:
obj = DBSession.query(cls).filter_by(iso_code=iso_code).one()
except NoResultFound:
obj = cls(iso_code=iso_code)
DBSession.add(obj)
return obj
@hybrid_property
def iso_code(self):
if self.territory:
return f"{self.lang}_{self.territory}"
else:
return self.lang
@iso_code.setter
def iso_code(self, iso_code):
try:
self.lang, self.territory = iso_code.split("_")
except ValueError:
self.lang, self.territory = iso_code, None
@iso_code.expression
def iso_code(cls):
return case(
[(cls.territory != None, cls.lang + "_" + cls.territory)],
else_=cls.lang)
class Keyword(DeclarativeBase):
__tablename__ = 'keywords'
id = Column(Integer, primary_key=True)
keyword = Column(Unicode(255), nullable=False)
lang_id = Column(Integer, ForeignKey(Language.id))
_lang = relationship(Language)
lang = association_proxy('_lang', 'iso_code',
creator=Language.by_iso_code)
engine = create_engine('sqlite://')
DeclarativeBase.metadata.create_all(engine)
DBSession.configure(bind=engine)
iso_codes_keywords = {
'en': ('Dog', 'Cat', 'Mouse'),
'de_DE': ('Hund', 'Katze', 'Maus'),
}
for iso_code, keywords in iso_codes_keywords.items():
for keyword in keywords:
k = Keyword(keyword=keyword, lang=iso_code)
DBSession.add(k)
for iso_code in iso_codes_keywords:
print("{} keywords: {}".format(
iso_code, ", ".join(
r[0] for r in DBSession.query(Keyword.keyword).filter_by(
lang=iso_code
)
)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment