mirror of
https://github.com/veekun/pokedex.git
synced 2024-08-20 18:16:34 +00:00
Use a class + mapper instead of dynamic declarative magic
This commit is contained in:
parent
b3c7689d41
commit
d0d4d1aa96
1 changed files with 36 additions and 33 deletions
|
@ -25,7 +25,9 @@ from sqlalchemy.ext.declarative import (
|
||||||
declarative_base, declared_attr, DeclarativeMeta,
|
declarative_base, declared_attr, DeclarativeMeta,
|
||||||
)
|
)
|
||||||
from sqlalchemy.ext.associationproxy import association_proxy
|
from sqlalchemy.ext.associationproxy import association_proxy
|
||||||
from sqlalchemy.orm import backref, eagerload_all, relation, class_mapper
|
from sqlalchemy.orm import (
|
||||||
|
backref, eagerload_all, relation, class_mapper, synonym, mapper,
|
||||||
|
)
|
||||||
from sqlalchemy.orm.session import Session
|
from sqlalchemy.orm.session import Session
|
||||||
from sqlalchemy.orm.collections import attribute_mapped_collection
|
from sqlalchemy.orm.collections import attribute_mapped_collection
|
||||||
from sqlalchemy.sql import and_
|
from sqlalchemy.sql import and_
|
||||||
|
@ -1770,52 +1772,53 @@ def makeTextTable(object_table, name_plural, name_singular, columns, lazy):
|
||||||
if safe_name == 'language':
|
if safe_name == 'language':
|
||||||
safe_name = 'lang'
|
safe_name = 'lang'
|
||||||
|
|
||||||
fields = {
|
tablename = object_table.__singlename__ + '_' + name_plural
|
||||||
safe_name + '_id': Column(Integer,
|
singlename = object_table.__singlename__ + '_' + name_singular
|
||||||
ForeignKey(object_table.id), primary_key=True, nullable=False,
|
|
||||||
info=dict(description="ID of the object this table represents")
|
class Strings(object):
|
||||||
|
__tablename__ = tablename
|
||||||
|
__singlename__ = singlename
|
||||||
|
|
||||||
|
for name, plural, column in columns:
|
||||||
|
column.name = name
|
||||||
|
|
||||||
|
table = Table(tablename, metadata,
|
||||||
|
Column(safe_name + '_id', Integer, ForeignKey(object_table.id),
|
||||||
|
primary_key=True, nullable=False),
|
||||||
|
Column('language_id', Integer, ForeignKey(Language.id),
|
||||||
|
primary_key=True, nullable=False),
|
||||||
|
*(column for name, plural, column in columns)
|
||||||
|
)
|
||||||
|
|
||||||
|
mapper(Strings, table,
|
||||||
|
properties={
|
||||||
|
"object_id": synonym(safe_name + '_id'),
|
||||||
|
"language": relation(
|
||||||
|
Language,
|
||||||
|
primaryjoin=table.c.language_id == Language.id,
|
||||||
),
|
),
|
||||||
'__tablename__': table.__singlename__ + '_' + name_plural,
|
},
|
||||||
'__singlename__': table.__singlename__ + '_' + name_singular,
|
)
|
||||||
'is_%s_table' % name_singular: True,
|
|
||||||
}
|
|
||||||
|
|
||||||
fields.update((name, col) for name, plural, col in columns)
|
|
||||||
|
|
||||||
name = table.__name__ + name_singular.capitalize()
|
|
||||||
|
|
||||||
# There are some dynamic things that can only be set at class
|
|
||||||
# creation time because of declarative metaclass magic.
|
|
||||||
# So create class dynamically.
|
|
||||||
Strings = type(name, (TableBase, LanguageSpecific), fields)
|
|
||||||
|
|
||||||
# Alias the described thing to 'object', to make meta stuff easier
|
|
||||||
Strings.object_id = getattr(Strings, safe_name + '_id')
|
|
||||||
|
|
||||||
# The relation to the object
|
# The relation to the object
|
||||||
setattr(table, name_plural, relation(
|
setattr(object_table, name_plural, relation(
|
||||||
Strings,
|
Strings,
|
||||||
primaryjoin=(table.id == Strings.object_id),
|
primaryjoin=(object_table.id == Strings.object_id),
|
||||||
backref=safe_name,
|
backref=safe_name,
|
||||||
collection_class=attribute_mapped_collection('language'),
|
collection_class=attribute_mapped_collection('language'),
|
||||||
lazy=lazy,
|
lazy=lazy,
|
||||||
))
|
))
|
||||||
|
|
||||||
Strings.object = getattr(Strings, safe_name)
|
Strings.object = getattr(Strings, safe_name)
|
||||||
|
|
||||||
Strings.object_table = table
|
# Link the tables themselves, so we can get to them
|
||||||
setattr(table, name_singular + '_table', Strings)
|
Strings.object_table = object_table
|
||||||
|
setattr(object_table, name_singular + '_table', Strings)
|
||||||
Strings.language = relation(
|
|
||||||
Language,
|
|
||||||
primaryjoin=Strings.language_id == Language.id,
|
|
||||||
)
|
|
||||||
|
|
||||||
for colname, pluralname, column in columns:
|
for colname, pluralname, column in columns:
|
||||||
# Provide a relation with all the names, and an English accessor
|
# Provide a relation with all the names, and an English accessor
|
||||||
# for backwards compatibility
|
# for backwards compatibility
|
||||||
def scope(colname, pluralname, column):
|
def scope(colname, pluralname, column):
|
||||||
def get_string(self):
|
def get_strings(self):
|
||||||
return dict(
|
return dict(
|
||||||
(l, getattr(t, colname))
|
(l, getattr(t, colname))
|
||||||
for l, t in getattr(self, name_plural).items()
|
for l, t in getattr(self, name_plural).items()
|
||||||
|
@ -1823,16 +1826,16 @@ def makeTextTable(object_table, name_plural, name_singular, columns, lazy):
|
||||||
|
|
||||||
def get_english_string(self):
|
def get_english_string(self):
|
||||||
try:
|
try:
|
||||||
return get_string(self)['en']
|
return get_strings(self)['en']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise AttributeError(colname)
|
raise AttributeError(colname)
|
||||||
|
|
||||||
setattr(table, pluralname, property(get_string))
|
setattr(object_table, pluralname, property(get_strings))
|
||||||
setattr(table, colname, property(get_english_string))
|
setattr(object_table, colname, property(get_english_string))
|
||||||
scope(colname, pluralname, column)
|
scope(colname, pluralname, column)
|
||||||
|
|
||||||
if colname == 'name':
|
if colname == 'name':
|
||||||
table.name_table = Strings
|
object_table.name_table = Strings
|
||||||
|
|
||||||
return Strings
|
return Strings
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue