Proper syntax for __table_args__ ?

416 views
Skip to first unread message

Don O'Hara

unread,
Oct 13, 2015, 7:16:14 AM10/13/15
to sqlalchemy
I'm looking for advice on best SA coding practices to accomplish:

1. Use bind keys
2. Add user-defined tags to tables, to allow iterating through the metadata later to find tables with those tags.
3. Use base table classes for common attributes and methods

Is there a chance that class member names will get mangled in derived classes,
and cause problems somewhere downstream? The code works now, but when I remove one of the
base classes, and code the metadata directly in the table class things break.

I'd like to get  a better understanding of how it all fits, and make sure I'm setting things up correctly.

Thanks,
Don



My code:

in config.py

SQLALCHEMY_BINDS = {
   
'api': 'postgresql+psycopg2://oharad:dino@localhost:5432/dev_api_02',
   
'person_indexes': 'postgresql+psycopg2://oharad:dino@localhost:5432/dev_person_ix_01',
   
'analysis_result': 'postgresql+psycopg2://oharad:dino@localhost:5432/dev_analysis_res_01'
}

in models/__init__.py

ACCOUNT_SCHEMA_NAMESPACE = 'account'

class BaseAppTable(db.Model):
    __abstract__ = True
    def to_json(self):
        json = {c.name: str(getattr(self, c.name)) or '' for c in self.__table__.columns}
        return json


in models/account.py


from models import BaseAppTable, db, ACCOUNT_SCHEMA_NAMESPACE

_BASE_TABLE_ARGS = {'info': {'table_namespace': ACCOUNT_SCHEMA_NAMESPACE}}

class BaseAccountTable(object):
  __bind_key__ = 'api'
  __table_args__ = _BASE_TABLE_ARGS

class Account(BaseAppTable, BaseAccountTable):
    __tablename__ = "account"
    #
    # need to explicitly code __table_args__ here to use 'tuple, dict' syntax
    __table_args__ = (UniqueConstraint('name', 'company_id', name='account_uq_ix1'), 
                      _BASE_TABLE_ARGS)
    account_id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(length=50), nullable=False)
    company_id = db.Column(db.Integer, db.ForeignKey('global.company.company_id'), nullable=False)


class RoleGroup(BaseAppTable, BaseAccountTable):
    __tablename__ = "role_group"
    role_group_id = db.Column(UUID, primary_key=True)
    type_code = db.Column(db.SmallInteger, nullable=False)
    name = db.Column(db.String(length=100), nullable=False, unique=True)


This code works fine, but I'm worried something might break due to name mangling.

When I change the code to avoid base classes, I get an error:

class AccountCodeNamespace(BaseAppTable):
  __tablename__
= "account_code_namespace"
  __table_args__
= _BASE_TABLE_ARGS
  __bind_key__
= 'api'



  #  AssertionError: Bind 'api' is not specified.  Set it in the SQLALCHEMY_BINDS configuration variable



Mike Bayer

unread,
Oct 13, 2015, 11:30:41 AM10/13/15
to sqlal...@googlegroups.com


On 10/13/15 7:16 AM, Don O'Hara wrote:
> I'm looking for advice on best SA coding practices to accomplish:
>
> 1. Use bind keys

I'm not familiar with that, I see you using something called
__bind_key__ and SQLALCHEMY_BINDS. These are not constructs that are
part of SQLAlchemy; if this is a third-party package of some kind, I'd
ask them for help.





> 2. Add user-defined tags to tables, to allow iterating through the
> metadata later to find tables with those tags.
> 3. Use base table classes for common attributes and methods
>
> Is there a chance that class member names will get mangled in derived
> classes,
> and cause problems somewhere downstream? The code works now, but when I
> remove one of the
> base classes, and code the metadata directly in the table class things
> break.
>
> I'd like to get a better understanding of how it all fits, and make
> sure I'm setting things up correctly.
>
> Thanks,
> Don
>
>
>
> My code:
>
> |
> _inconfig.__py
> _
> SQLALCHEMY_BINDS ={
> 'api':'postgresql+psycopg2://oharad:dino@localhost:5432/dev_api_02',
>
> 'person_indexes':'postgresql+psycopg2://oharad:dino@localhost:5432/dev_person_ix_01',
>
> 'analysis_result':'postgresql+psycopg2://oharad:dino@localhost:5432/dev_analysis_res_01'
> }
>
> _in models/__init__.py_
>
> ACCOUNT_SCHEMA_NAMESPACE = 'account'
>
> class BaseAppTable(db.Model):
> __abstract__ = True
> def to_json(self):
> json = {c.name: str(getattr(self, c.name)) or '' for c in
> self.__table__.columns}
> return json
>
>
> _in models/account.py_
> * # AssertionError: Bind 'api' is not specified. Set it in the
> SQLALCHEMY_BINDS configuration variable*
>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to sqlalchemy+...@googlegroups.com
> <mailto:sqlalchemy+...@googlegroups.com>.
> To post to this group, send email to sqlal...@googlegroups.com
> <mailto:sqlal...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

Don O'Hara

unread,
Oct 13, 2015, 12:22:19 PM10/13/15
to sqlal...@googlegroups.com
Oops - should have asked the Flask-SQLAlchemy folks!

Thanks

You received this message because you are subscribed to a topic in the Google Groups "sqlalchemy" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sqlalchemy/7kb-9pSu3Bk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sqlalchemy+...@googlegroups.com.
To post to this group, send email to sqlal...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages