On 8/30/15 1:58 PM, r...@rosenfeld.to wrote:
Hi All,

I'm trying to replace string definitions prgrammatically where possible. I have the following working:

|
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

import pprint


Base = declarative_base()


class Parent(Base):
__tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
children = relationship("Child", backref=__tablename__)


class Child(Base):
__tablename__ = 'child'
    id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))


p = Parent()
pprint.pprint('p table name: {}'.format(p.__tablename__))
c = Child()
pprint.pprint('c table name: {}'.format(c.__tablename__))
c.parent = p
pprint.pprint('Children: {}'.format(p.children))
pprint.pprint('Parent: {}'.format(c.parent))

|

But I'd like to follow the mixin example from the docs to inherit common columns and a function for __tablename__ via the Common class.

|
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.declarative import declared_attr

import pprint
from inflection import underscore


class Common(object):
@declared_attr
def __tablename__(cls):
  return underscore(cls.__name__)
    id = Column(Integer, primary_key=True)


Base = declarative_base(cls=Common)


class Parent(Base):
children = relationship("Child", backref=__tablename__)


class Child(Base):
parent_id = Column(Integer, ForeignKey('parent.id'))


p = Parent()
pprint.pprint('p table name: {}'.format(p.__tablename__))
c = Child()
pprint.pprint('c table name: {}'.format(c.__tablename__))
c.parent = p
pprint.pprint('Children: {}'.format(p.children))
pprint.pprint('Parent: {}'.format(c.parent))

|


I cannot figure out how to refer to the __tablename__ property in backref using this model.
well it needs to be a callable function that is called when the "cls", in this case Parent, is available. It would be awkward but you'd need to do it like this:

@declared_attr
def children(cls):
    return relationship("Child", backref=cls.__tablename__)

this is because the way it is now, "children = relationship" needs to know the name "Parent" which is explicitly not available yet, because you're in a class block named "Parent" - that name isn't known to the script until you exit that block. relationship() allows a lot of its members to be passed as functions but backref / back_populates aren't one of them because these have to do with the class mapping, rather than tables/columns which is why the deferred approach is provided.

You can make your own function that generates that @declared_attr in one step to save on verbosity.





If I refer to Base.__tablename__ or Common.__tablename__, it gets the wrong value. Can you help me fix this?

Thanks,
Rob
--
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+unsubscr...@googlegroups.com <mailto:sqlalchemy+unsubscr...@googlegroups.com>. To post to this group, send email to sqlalchemy@googlegroups.com <mailto:sqlalchemy@googlegroups.com>.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

--
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+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to