相关文章推荐
阳刚的青蛙  ·  K8S ...·  1 年前    · 
豁达的枇杷  ·  如何评价 Visual Studio ...·  1 年前    · 
睿智的椰子  ·  归一化评分-掘金·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am very new to SQLAlchemy. I am having some difficulty setting up a one to many relationship between two models in my application. I have two models User `Photo'. A user has only one role associated with it and a role has many users associated with it.

This is the code that I have in my data_generator.py file:

# coding=utf-8
from sqlalchemy import Column, Integer, String, BigInteger,Date, Enum, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
import time
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, relationship
import datetime
Base = declarative_base()
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer(), primary_key=True)
    username = Column(String(30), unique=True, nullable=False)  
    password = Column(String, default='123456', nullable=False) 
    name = Column(String(30), nullable=False) 
    grade = Column(String(30))  
    emp_no = Column(BigInteger, unique=True, nullable=False) 
    roles = relationship('Role', back_populates='users')
class Scene(Base):
    __tablename__ = 'scenes'
    id = Column(Integer, primary_key=True)
    scene_name = Column(String(30), nullable=False) 
    life_time = Column(Date, nullable=False,
                       default=datetime.datetime.strptime(
                       time.strftime("%Y-%m-%d", time.localtime(time.time() + (12 * 30 * 24 * 3600))),'%Y-%m-%d').date())  
    scene_description = Column(String(150), default="")  
class Gateway(Base):
    __tablename__ = 'gateways'
    id = Column(Integer, primary_key=True)
    gateway_name = Column(String(30), nullable=False) 
    gateway_api_key = Column(String(100), nullable=False, unique=True) 
    gateway_type = Column(Enum('up', 'down', 'soft', name="gateway_type"), nullable=False)
class Role(Base):
    __tablename__ = 'roles'
    id = Column(Integer, primary_key=True)
    role_name = Column(String(30), unique=True, nullable=False)
    users = relationship('User', back_populates='roles')
    def __repr__(self):
        return self.role_name
engine = create_engine('sqlite:///memory:')
Session = sessionmaker()
Session.configure(bind=engine)
session = Session()
Base.metadata.create_all(engine)
ed_user = User(name='ed', username='jack', password='123', emp_no=1, grade='1', roles=1)
example_scene = Scene(scene_name='example_1', scene_description='example_description')
example_gateway = Gateway(gateway_name='example_1',gateway_api_key='11111',gateway_type='up')
# session.add(example_gateway)
# session.commit()
def init_user(flag, number):
    while number >= 1:
        if flag == 1:
            ed_user = User(name='ed', username='jack', password='123', emp_no=1, grade='1')
        if flag == 2:
            # TODO admin
        if flag == 3:
            # TODO teacher
        number -= 1
def init_scene(number):
    while number >= 1:
        number -= 1
        # TODO scene
def init_gateway(api_key, number):
    # TODO gateway
if __name__ == '__main__':
    with session.no_autoflush:
        c = session.query(Gateway).all()
    print c[0].id

The error that I keep encountering is shown below:

/usr/bin/python2.7 /home/pajamas/PycharmProjects/untitled5/data_generator.py
Traceback (most recent call last):
  File "/home/pajamas/PycharmProjects/untitled5/data_generator.py", line 73, in <module>
    ed_user = User(name='ed', username='jack', password='123', emp_no=1, grade='1', roles=1)
  File "<string>", line 2, in __init__
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", line 347, in _new_state_if_none
    state = self._state_constructor(instance, self)
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/util/langhelpers.py", line 764, in __get__
    obj.__dict__[self.__name__] = result = self.fget(obj)
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/instrumentation.py", line 177, in _state_constructor
    self.dispatch.first_init(self, self.class_)
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/event/attr.py", line 256, in __call__
    fn(*args, **kw)
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 3088, in _event_on_first_init
    configure_mappers()
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2984, in configure_mappers
    mapper._post_configure_properties()
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1810, in _post_configure_properties
    prop.init()
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/interfaces.py", line 184, in init
    self.do_init()
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1658, in do_init
    self._setup_join_conditions()
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1733, in _setup_join_conditions
    can_be_synced_fn=self._columns_are_mapped
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 1991, in __init__
    self._determine_joins()
  File "/home/pajamas/.local/lib/python2.7/site-packages/sqlalchemy/orm/relationships.py", line 2096, in _determine_joins
    "specify a 'primaryjoin' expression." % self.prop)
sqlalchemy.exc.NoForeignKeysError: Could not determine join condition between parent/child tables on relationship User.roles - there are no foreign keys linking these tables.  Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.
Process finished with exit code 1

Can someone assist me with this? Help would be greatly appreciated.

  • One to One(One user has only one Role)
  • Many to One(One user has many roles)
  • Many to Many(Many user has many roles)
  • For One to One:

    class Role(Base):
        id = Column(Integer, primary_key=True)
        # ...
        user_id = Column(Integer, ForeignKey("user.id"))
    class User(Base):
        id = Column(Integer, primary_key=True)
        # ...
        role = relationship("Role", back_populates="user", uselist=False)
    

    For Many to One:

    class Role(Base):
        id = Column(Integer, primary_key=True)
        # ...
        user_id = Column(Integer, ForeignKey("user.id"))
    class User(Base):
        id = Column(Integer, primary_key=True)
        # ...
        roles = relationship("Role", back_populates="user")
    

    For Many to Many:(In this relation, we need a associate table)

    roles_users = Table("roles_users", 
    Column("role_id", Integer, ForeignKey("role.id")), 
    Column("user_id", Integer, ForeignKey("user.id")))
    class Role(Base):
        id = Column(Integer, primary_key=True)
        # ...
    class User(Base):
        id = Column(Integer, primary_key=True)
        # ...
        roles = relationship("Role", back_populates="users", secondary=roles_users)
                    Thank you very much!  I have to enrich my fundamental knowledge.But is there should be a  users = relationship("User", back_populates="roles", secondary=roles_users) in many to many relationship, isn't it?
    – Saige Zhang
                    Jul 31, 2017 at 2:21
                    Actually, You can remove relationship define in all relation(One2One, Many2One, Many2Many). I think relationship is convenient when you code.
    – stamaimer
                    Jul 31, 2017 at 2:29
                    Should your first example have "uselist=False" instead of "userlist=False"?  Also, for the reference of others landing at this question, here are the API docs: docs.sqlalchemy.org/en/latest/orm/relationship_api.html
    – jcadcell
                    Mar 28, 2019 at 20:20
    

    I made a low-level mistake because of my lack of database and SQL alchemy. First of all, this is a typical "one to many" problem.Relationship connects two rows from two tables by users' foreign key. The role_id is defined as the foreign key, which builds the connections. The parameter "roles.id" in "ForeignKey()" clarified this column is the id of Role's rows.
    relationship() 's backref specialized the role model.

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.