Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sqlalchemy classical mapping relationship issue

I am on a mission to finally learn sqlAlchemy so that I can reap the benefits in the years to come.

I am neck deep in the sqlalchemy documents and have been for the past two days. I am hell bent on learning the classical mapping way, instead of the declarative, bc the db I want to hook up to exists, and does not have a unique id column in all of it's tables. According to this article classical mapping is the way to go under such circumstances

I have been following the classical examples from the sqlalchemy site, but I just cannot seem to find the correct relationship configuration to get this to work.

Here is all my code:

engine = create_engine(
    "mssql+pyodbc://someaddress/test?driver=FreeTDS?TDS_version=8.0", echo=True)

metadata = MetaData(engine)

class User(object):

    def __repr__(self):
        return "<User(User_id='%s', name='%s', age='%s')>" % (
                            self.user_id, self.name, self.age)
class Email(object):

    def __repr__(self):
        return "<User(email_id='%s', address='%s', user_id='%s')>" % (
                            self.email_id, self.address, self.user_id)

users = Table('users', metadata,
    Column('user_id', Integer, primary_key=True),
    Column('name', String(40)),
    Column('age', Integer),
    schema='test.dbo.users')

mapper(User, users, properties={'Email': relationship(Email, primaryjoin=users.c.user_id==emails.c.user_id)})

emails = Table('emails', metadata,
    Column('email_id', Integer, primary_key=True),
    Column('address', String),
    Column('user_id', Integer, ForeignKey('test.dbo.users.user_id')),
    schema='test.dbo.emails')

mapper(Email, emails)

Session = sessionmaker(bind=engine)
session = Session()

mary = session.query(User, Email).filter(User.user_id == Email.user_id)

The pursuing error message makes it clear that it is the mapper / relationship that is the problem.

InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers.  Original exception was: Could not determine join condition between parent/child tables on relationship User.Email - there are no foreign keys linking these tables.  Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.

I have tried a long list of different things to try to remedy, but I just cannot get to the bottom of it.

Any pointers in the right direction would be much appreciated!

The sqlalchemy version I am on is;

'1.0.12'
like image 277
Rookie Avatar asked Dec 28 '16 15:12

Rookie


People also ask

What is mapping in SQLAlchemy?

SQLAlchemy now refers to these two mapping styles as imperative mapping and declarative mapping. Regardless of what style of mapping used, all ORM mappings as of SQLAlchemy 1.4 originate from a single object known as registry , which is a registry of mapped classes.

What is Back_populates in SQLAlchemy?

The back_populates argument tells SqlAlchemy which column to link with when it joins the two tables. It allows you to access the linked records as a list with something like Parent.

What is Primaryjoin?

primaryjoin – A SQL expression that will be used as the primary join of the child object against the parent object, or in a many-to-many relationship the join of the parent object to the association table.

What does SQLAlchemy relationship do?

The relationship function is a part of Relationship API of SQLAlchemy ORM package. It provides a relationship between two mapped classes. This corresponds to a parent-child or associative table relationship.


1 Answers

I had better luck with:

Column('user_id', Integer, ForeignKey('users.user_id')),

I also reordered the table and mapping code slightly:

users = Table('users', metadata,
    Column('user_id', Integer, primary_key=True),
    Column('name', String(40)),
    Column('age', Integer))

emails = Table('emails', metadata,
    Column('email_id', Integer, primary_key=True),
    Column('address', String),
    # foreign key to table users
    Column('user_id', Integer, ForeignKey('users.user_id')))

mapper(Email, emails)

mapper(User, users, properties={
    'Email': relationship(
        Email, primaryjoin=users.c.user_id==emails.c.user_id)})
like image 79
Stephen Rauch Avatar answered Sep 19 '22 10:09

Stephen Rauch