简体   繁体   中英

Foreign Key to Same Table in sqlalchemy

I have a MySQL table, defined in sqlalchemy with following structure:

class User(Base):
    __tablename__ = 'user'
    __table_args__ = {'mysql_charset': 'utf8', 'mysql_engine': 'InnoDB'}
    id = Column(Integer, primary_key=True)
    handle = Column(String(250), nullable=False)
    owned = Column(Boolean(), default=False)
    owner_id = Column(Integer, ForeignKey("user.id"), nullable=True, default=null )
    current_price = Column(Integer, nullable=False, default=1)
    balance = Column(Integer, nullable=False, default=0)

I want a relationship so that the owner_id can either be null, OR if it is set it must refer to a valid user.id, in the same table.

I don't quite understand the sqlalchemy relationship stuff well enough to be able to do it. The special stuff at the top of this page http://docs.sqlalchemy.org/en/latest/orm/relationship_persistence.html seems to suggest that it's possible, but I can't figure it out.

I want to then be able to either add Users like:

u1 = User(handle="bob")
u2 = User(handle="jim", owner=u1)

Thanks for any help!

I should add that sqlalchemy has no problem doing the CREATE TABLE with the correct FOREIGN KEY constraint, and I can manually INSERT data into the table that obeys the rules as I want them in MySQL, it's only using the sqlalchemy model that fails.

EDIT: SOLVED

The 'default=null' on owner_id was causing the problem for some reason. Helpful docs were here: http://docs.sqlalchemy.org/en/rel_1_0/orm/self_referential.html and code example from that page here: http://docs.sqlalchemy.org/en/rel_1_0/orm/examples.html#examples-adjacencylist

For the google spider bots, errors that I got during this process were:

sqlalchemy.exc.IntegrityError: (_mysql_exceptions.IntegrityError) (1452, 'Cannot add or update a child row: a foreign key constraint fails (`twitfriends`.`tree`, CONSTRAINT `tree_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `tree` (`id`))') [SQL: u'INSERT INTO tree (parent_id, name) VALUES (%s, %s)'] [parameters: (<sqlalchemy.sql.elements.Null object at 0x7fe7e8c468d0>, 'rootnode')]

And

ArgumentError: Node.next and back-reference Node.prev are both of the same direction <symbol 'ONETOMANY>.  Did you mean to set remote_side on the many-to-one side ?

Since there is only one foreign key for User , I would expect sqlalchemy to automatically figure out the join conditions. You can also add a backref so you can get the other side of the relationship.

class User(Base):
    ...
    owner = relationship('User', remote_side=['id'], backref='owned_users')

Docs

Ex.

u1 = User(handle="bob")
u2 = User(handle="jim", owner=u1)
print u2.owned_users[0] == u1
# True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM