【问题标题】:Many-to-one relation returns None object: SqlAlchemy多对一关系返回 None 对象:SqlAlchemy
【发布时间】:2013-10-14 08:38:36
【问题描述】:

我正在尝试编写包含如下记录的 Schedule 类: ...会话,基础,引擎声明在这里...

class Schedule(Base):
    __tablename__ = 'schedule'
    id = Column(Integer, primary_key=True)
    # and here i need ref to Station class
    station_id = Column(Integer, ForeignKey('station.id'))
    station = relationship('Station') # Also tried Station
    arr_time = Column(Time)

    def __init__(self, station_name, arrive_time):
         self.metadata.create_all()
         self.arrive_time = arrive_time

         # And now I'm trying to find station object by a given name
         # and add ref to it in self.station. 
         # The selection of a station works properly here:
         station = session.query(Station).filter(Station.name == station_name).first()
         # But on this statement I get an error: None object has no method 'append'
         self.station.append(station)
         session.add(self)
         session.commit()

之后我实现了类'Station'

class Station(Base):
    __tablename__ = 'stations'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    def __init__(self, name):
         self.name = name

所以,当我尝试添加新的计划记录时,我收到一个错误:

AttributeError: 'NoneType' object has no attribute 'append' 

一对多的情况(第一类中的外键和第二类中的关系)正常工作。

我的代码有什么问题?

更新: 还尝试了文档中的示例:

engine = create_engine('sqlite:///:memory:')
Base = declarative_base(engine)
session = sessionmaker(bind=engine)()

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    child_id = Column(Integer, ForeignKey('child.id'))
    child = relationship("Child")

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


if __name__ == '__main__':
    Base.metadata.create_all()
    parent = Parent()
    session.add(parent)
    child = Child()
    session.add(child)
    print(hasattr(Parent, 'child'))
    print(hasattr(parent, 'child'))
    print(type(Parent.child))
    print(type(parent.child))

我明白了:

 >>> True
 >>> True
 >>> <class 'sqlalchemy.orm.attributes.InstrumentedAttribute'>
 >>> <class 'NoneType'>

【问题讨论】:

  • 通过文档中的示例也得到此错误

标签: python sqlalchemy many-to-one


【解决方案1】:

我知道了)) 问题是关系构造函数中的默认uselist 标志设置为True。 但是 - 我真的不明白为什么它没有写在文档中 - 在多对一关系的情况下,这个标志设置为 False

所以,要解决我的问题,我只需要改变这个:

station = relationship("Station", uselist=True)

或在构造函数中使用:

self.station = station

这完全解决了我的问题。

【讨论】:

    【解决方案2】:

    我遇到了类似的问题。我认为问题在于,在您添加和提交之前,关系不会被触发。

    engine = create_engine('sqlite:///:memory:')
    Base = declarative_base(engine)
    session = sessionmaker(bind=engine)()
    
    class Parent(Base):
        __tablename__ = 'parent'
        id = Column(Integer, primary_key=True)
        child_id = Column(Integer, ForeignKey('child.id'))
        child = relationship("Child")
    
    class Child(Base):
        __tablename__ = 'child'
        id = Column(Integer, primary_key=True)
    
    
    if __name__ == '__main__':
        Base.metadata.create_all()
        parent = Parent()
        session.add(parent)
        child = Child()
        session.add(child)
        session.commit() # IMPORTANT: this is necessary for relationship to work
        print(hasattr(Parent, 'child'))
        print(hasattr(parent, 'child'))
        print(type(Parent.child))
        print(type(parent.child))
    

    我添加的唯一一行是

            session.commit() # IMPORTANT: this is necessary for relationship to work
    

    【讨论】:

      【解决方案3】:
      station = session.query(Station).filter(Station.name == station.name).first()
      

      self.station 是无....

      尝试使用调试器或只使用 print stationprint self.station

      编辑:类变量范围:

      类作用域变量有两种方式:

      1. 实例变量 - 使用 self 时,这称为实例变量,通过该类的每个实例,您将拥有该变量的副本。

      2. 类属性 - 在您的情况下,它是属于该类的 Schedule.station,而不是该类的实例。

      请参考Docs about namespace,它将解决您的问题。

      【讨论】:

      • 不,站不是无)))即使它是无,您也可以将其添加到任何列表中:x = []; x.append(None) 给出[None]。错误存在于relationsip,而不是站点本身。
      • 这是给出错误 self.station.append(station) 的行,不是吗?这就是我从 AttributeError 中了解到的:'NoneType' 对象没有属性 'append'
      • 对不起,我在这里的代码示例中有拼写错误。 Station.name == station_name,而不是 station.name。在我的代码中一切正常(我在这里输入了这段代码,没有复制)
      • np:) 只需编辑帖子,以便清楚。你也有self.station吗?它的内容是什么?
      • self.station - 据我了解,实际上是对 Schedule.station 成员的请求。用法不对吗?
      猜你喜欢
      • 2015-03-16
      • 2018-05-03
      • 2016-06-15
      • 2021-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多