1

I have a problem with my relationship(...) and I don't understand why.

The error:

"InvalidRequestError: When initializing mapper Mapper|User|users, expression 'BannedUser' failed to locate a name ("name 'BannedUser' is not defined"). If this is a class name, consider adding this relationship() to the class after both dependent classes have been defined."

This is the code:

User model

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import relationship

from .base import Base as BaseModel


class User(BaseModel, declarative_base()):
     __tablename__ = 'users'

     id = Column(Integer, primary_key=True)
     username = Column(String(16))
     password = Column(String(16))
     nickname = Column(String(16))
     secret_question = Column(String(50))
     secret_answer = Column(String(50))
     role = Column(Integer)
     is_banned = relationship("BannedUser", uselist=False, back_populates='users')

Banned user model:

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from sqlalchemy.orm import relationship

from .base import Base as BaseModel


class BannedUser(BaseModel, declarative_base()):
     __tablename__ = 'banned_users'

     id = Column(Integer, primary_key=True)
     user_id = Column(Integer, ForeignKey('users.id'))
     user = relationship('User', back_populates='banned_users')
     reason = Column(String)
     time_end = Column(DateTime)

I tried class directly instead of class string but that also doesn't work.

I tried 'User.id' instead of 'users.id', but the same thing happened.

I don't know what to do.

Thank you in advanced for the help.

Susannah
  • 3
  • 2
Jean Walrave
  • 191
  • 1
  • 2
  • 13

1 Answers1

1

On the back_populates (doc) you need to specify the property which is related on the other end of the relationship, while you specified the table name ... of the same entity ...

I would recommend doing it with back_ref (doc), which takes care of the other end related property (so you don't need to specify the user property on BannedUser, or the other way around), something like:

...

class User(BaseModel, declarative_base()):
    __tablename__ = 'users'

    ...
    is_banned = relationship("BannedUser", uselist=False, back_ref='user')
    ...

But if you still want to do it with back_populates, you should do something like this:

...

class User(BaseModel, declarative_base()):
    __tablename__ = 'users'

    ...
    is_banned = relationship("BannedUser", uselist=False, back_populates='user')
    ...

class BannedUser(BaseModel, declarative_base()):
    __tablename__ = 'banned_users'

    ...
    user = relationship('User', back_populates='is_banned')
    ...
creativeChips
  • 1,177
  • 9
  • 12
  • ah, sorry (its still a problem in your code i think). it looks related to the way you use the `declarative_base`. check this http://stackoverflow.com/questions/7478403/sqlalchemy-classes-across-files – creativeChips Sep 28 '16 at 19:56
  • found! I just add a Base = declarative_base() in my Database class, and extend it in my models – Jean Walrave Sep 28 '16 at 19:57