I am trying to convert old sqlite3 code to sql alchemy. I am trying to make sense of how best to handle my use case. I am new to the ORM method of database access.
I am trying to dynamically generate unique table names based on a common definition. I have read the mixins guide as well as the post on how to use type to dynamically declare classes, but I am still unsure how of I would go about this. Here is what I have so far:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.ext.declarative import declared_attr
Base = declarative_base()
class DynamicName(object):
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
class Genome(DynamicName, Base):
__tablename__ = 'AbstractGenome'
AlignmentId = Column(Integer, primary_key=True)
StartOutOfFrame = Column(Integer)
BadFrame = Column(Integer)
def build_genome_table(genome):
d = {'__tablename__': genome}
table = type(genome, (Genome,), d)
return table
If I try to use this, it doesn't work:
>>> from sqlalchemy import create_engine
>>> engine = create_engine('sqlite:///:memory:', echo=True)
>>> genomes = ["A", "B"]
>>> tables = {x: build_genome_table(x) for x in genomes}
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <dictcomp>
File "<stdin>", line 3, in build_genome_table
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py", line 55, in __init__
_as_declarative(cls, classname, cls.__dict__)
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 88, in _as_declarative
_MapperConfig.setup_mapping(cls, classname, dict_)
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 103, in setup_mapping
cfg_cls(cls_, classname, dict_)
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 135, in __init__
self._early_mapping()
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 138, in _early_mapping
self.map()
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 529, in map
**self.mapper_args
File "<string>", line 2, in mapper
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 623, in __init__
self._configure_inheritance()
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 930, in _configure_inheritance
self.local_table)
File "<string>", line 2, in join_condition
File "/cluster/home/ifiddes/python2.7/lib/python2.7/site-packages/sqlalchemy/sql/selectable.py", line 839, in _join_condition
(a.description, b.description, hint))
sqlalchemy.exc.NoForeignKeysError: Can't find any foreign key relationships between 'AbstractGenome' and 'A'.
How do I go about dynamically generating a Genome table based on a passed name? I also would ideally like a setup where I can have hierarchical inheritance, so that I can declare different subclasses like ReferenceGenome or TargetGenome which have additional columns but also can have dynamic names.
Atable and theAbstractGenometable. Are you actually intending to create both anAtable as well as anAbstractGenometable? If not, you should put__abstract__ = Truein yourclass Genomedefinition.