Skip to content

Commit fb07668

Browse files
authored
Merge pull request #592 from RmStorm/bugfix/allow-declarative-table-names
Fixed bug when using a declarative function for the __tablename__
2 parents 72588ae + 0bae7cd commit fb07668

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

gino/declarative.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,12 @@ def _init_table(cls, sub_cls):
152152
for each_cls in sub_cls.__mro__[::-1]:
153153
for k, v in getattr(each_cls, '__namespace__',
154154
each_cls.__dict__).items():
155-
if callable(v) and getattr(v, '__declared_attr__', False):
156-
if k == '__tablename__':
157-
table_name = v(sub_cls)
158-
continue
155+
declared_callable_attr = callable(v) and \
156+
getattr(v, '__declared_attr__', False)
157+
if k != '__tablename__' and declared_callable_attr:
159158
v = updates[k] = v(sub_cls)
159+
elif k == '__tablename__':
160+
table_name = v(sub_cls) if declared_callable_attr else v
160161
if isinstance(v, sa.Column):
161162
v = v.copy()
162163
if not v.name:
@@ -166,8 +167,6 @@ def _init_table(cls, sub_cls):
166167
updates[k] = sub_cls.__attr_factory__(k, v)
167168
elif isinstance(v, (sa.Index, sa.Constraint)):
168169
inspected_args.append(v)
169-
if table_name is None:
170-
table_name = getattr(sub_cls, '__tablename__', None)
171170
if table_name is None:
172171
return
173172
sub_cls._column_name_map = column_name_map

tests/test_declarative.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,39 @@ class Model(db.Model):
260260
select_col = db.Column(name=db.quoted_name('select', False))
261261
assert select_col.name == 'select'
262262
assert not select_col.name.quote
263+
264+
265+
async def test_overwrite_declared_table_name():
266+
class MyTableNameMixin:
267+
@db.declared_attr
268+
def __tablename__(cls):
269+
return cls.__name__.lower()
270+
271+
class MyTableWithoutName(MyTableNameMixin, db.Model):
272+
id = db.Column(db.Integer, primary_key=True)
273+
274+
class MyTableWithName(MyTableNameMixin, db.Model):
275+
__tablename__ = 'manually_overwritten_name'
276+
id = db.Column(db.Integer, primary_key=True)
277+
278+
assert MyTableWithoutName.__table__.name == 'mytablewithoutname'
279+
assert MyTableWithName.__table__.name == 'manually_overwritten_name'
280+
281+
282+
async def test_multiple_inheritance_overwrite_declared_table_name():
283+
class MyTableNameMixin:
284+
@db.declared_attr
285+
def __tablename__(cls):
286+
return cls.__name__.lower()
287+
288+
class AnotherTableNameMixin:
289+
__tablename__ = "static_table_name"
290+
291+
class MyTableWithoutName(AnotherTableNameMixin, MyTableNameMixin, db.Model):
292+
id = db.Column(db.Integer, primary_key=True)
293+
294+
class MyOtherTableWithoutName(MyTableNameMixin, AnotherTableNameMixin, db.Model):
295+
id = db.Column(db.Integer, primary_key=True)
296+
297+
assert MyTableWithoutName.__table__.name == 'static_table_name'
298+
assert MyOtherTableWithoutName.__table__.name == 'myothertablewithoutname'

0 commit comments

Comments
 (0)