【问题标题】:flask sqlalchemy.exc.NoForeignKeysError NoForeignKeysError: Could not determine join conditionflask sqlalchemy.exc.NoForeignKeysError NoForeignKeysError:无法确定加入条件
【发布时间】:2018-11-20 18:10:46
【问题描述】:

这是调试器中的异常跟踪

sqlalchemy.exc.NoForeignKeysError

NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Department.employees - there are no foreign keys linking these tables. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.

这是我的 models.py,我正在使用现有架构的反射。

    from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime, Date, Time
    from sqlalchemy.orm import relationship, backref

    #make sure we get the right base
    from database import ProbeDB_Base, DB

    class Location(ProbeDB_Base):
        __tablename__ = u'Location'
        __table_args__ = {u'schema': u'probedb'}

        LocationID = Column(Integer, primary_key=True)
        LocationName = Column(String(100))
        controllers = relationship("Controller", backref="Location")

    class Controller(ProbeDB_Base):
        __tablename__ = u'Controller'
        __table_args__ = {u'schema': 'probedb'}

        ControllerID = Column(Integer, primary_key=True)
        ControllerName = Column(String(100))
        ControllerNo = Column(Integer)
        SlaveNo = Column(Integer)
        IPAddress = Column(String(20))
        Port = Column(Integer)
        CommunicationType = Column(Integer)
        Enable = Column(Integer)
        ResponseTime = Column(Integer)
        LocationID = Column(Integer, ForeignKey('Location.LocationID'), index=True)
        #LocationID = relationship(Location, primaryjoin='Controller.LocationID == DB.Location.LocationID')
        MaxChannels = Column(Integer)
        #Location_id = relationship(u'Location')
        transactions = relationship("Transaction", backref="Controller")

    class Department(ProbeDB_Base):
        __tablename__ = u'Department'
        __table_args__ = {u'schema': 'probedb'}

        DepartmentID = Column(Integer, primary_key=True)
        Name = Column(String(100))
        employees = relationship("Employee", backref="Department")

    class Designation(ProbeDB_Base):
        __tablename__ = u'Designation'
        __table_args__ = {u'schema': 'probedb'}

        DesignationID = Column(Integer, primary_key=True)
        Name = Column(String(100))
        employees = relationship("Employee", backref="Designation")

    class Employee(ProbeDB_Base):
        __tablename__ = u'Employee'
        __table_args__ = {u'schema': 'probedb'}

        EmployeeID = Column(Integer, primary_key=True)
        EmployeeCode = Column(String(15), index=True)
        LocationID = Column(Integer)
        Name = Column(String(50))
        CardNo = Column(Integer)
        DepartmentID = Column(Integer, ForeignKey('Department.DepartmentID'), index=True)
        #DepartmentID = relationship(Department, primaryjoin='Employee.DepartmentID == DB.Department.DepartmentID')
        DesignationID = Column(Integer, ForeignKey('Designation.DesignationID'), index=True)
        #DesignationID = relationship(Designation, primaryjoin='Employee.DesignationID == DB.Designation.DesignationID')
        EnrollDate = Column(DateTime)
        ExpDate = Column(DateTime)
        #Department_id = relationship(u'Department')
        #Designation_id = relationship(u'Designation')

    class Event(ProbeDB_Base):
        __tablename__ = u'Event'
        __table_args__ = {u'schema': 'probedb'}

        EventID = Column(Integer, primary_key=True)
        Name = Column(String(100))

        transactions = relationship("Transaction", backref="Event")

    class Transaction(ProbeDB_Base):
        __tablename__ = u'Transaction'
        __table_args__ = {u'schema': 'probedb'}

        TransactionID = Column(Integer, primary_key=True)
        DateTime = Column(DateTime)
        Date = Column(Date)
        Time = Column(Time)
        CardNo = Column(Integer)
        Channel = Column(Integer)
        EventID = Column(Integer, ForeignKey('Event.EventID'), index=True)
        #EventID = relationship(Event, primaryjoin='Transaction.EventID == DB.Event.EventID')
        AccessType = Column(String(4))
        ReadPtr = Column(Integer)
        ControllerID = Column(Integer, ForeignKey('Controller.ControllerID'), index=True)
        #ControllerID = relationship("Controller", primaryjoin='Transaction.ControllerID == Controller.ControllerID')
        IPAddress = Column(String(20))
        #Controller_id = relationship(u'Controller')
        #Event_id = relationship(u'Event')

    class User(ProbeDB_Base):
        __tablename__ = u'users'
        __table_args__ = {u'schema': 'probedb'}

        uid = Column(Integer, primary_key=True)
        firstname = Column(String(100), nullable=False)
        lastname = Column(String(100), nullable=False)
        email = Column(String(120), nullable=False, index=True)
        pwdhash = Column(String(100), nullable=False)

我确实为事务表指定了一个外键,并在控制器表中指定了一个反向引用,但无法弄清楚我哪里出错了

这是表格的create.sql

    /*
    ProbeDB 
    This is the setup SQL for probedb
    */

    CREATE TABLE IF NOT EXISTS Location(
    LocationID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    LocationName varchar(100)
    )
    ;
    CREATE TABLE IF NOT EXISTS Controller(
    ControllerID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    ControllerName varchar(100),
    ControllerNo int,
    SlaveNo int,
    CONSTRAINT SlaveNo_Ck CHECK (SlaveNo BETWEEN 1 AND 128),
    IPAddress varchar(20),
    Port int,
    CommunicationType int,
    CONSTRAINT CommunicationType_Ck CHECK (CommunicationType BETWEEN 1 AND 2),
    /* 
    1 TCP
    2 UDP
    */
    Enable int, 
    CONSTRAINT Enable_Ck CHECK (Enable BETWEEN 0 AND 1),
    /* 
    0 Enable
    1 Disable
    */
    ResponseTime int,
    LocationID int,
    CONSTRAINT fk_LocationReference FOREIGN KEY (LocationID) REFERENCES Location(LocationID),
    MaxChannels int
    )
    ;
    CREATE TABLE IF NOT EXISTS Department(
    DepartmentID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    Name varchar(100)
    )
    ;
    CREATE TABLE IF NOT EXISTS Designation(
    DesignationID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    Name varchar(100)
    )
    ;
    CREATE TABLE IF NOT EXISTS Employee(
    EmployeeID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    EmployeeCode varchar(15) UNIQUE,
    LocationID int,
    Name varchar(50),
    CardNo int,
    DepartmentID int,
    CONSTRAINT fk_DepartmentReference FOREIGN KEY (DepartmentID) REFERENCES Department(DepartmentID),
    DesignationID int,
    CONSTRAINT fk_DesignationReference FOREIGN KEY (DesignationID) REFERENCES Designation(DesignationID),
    EnrollDate datetime,
    ExpDate datetime
    )
    ;
    CREATE TABLE IF NOT EXISTS Event(
    EventID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    Name varchar(100)
    )
    ;
    CREATE TABLE IF NOT EXISTS Transaction(
    TransactionID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    DateTime datetime,
    Date date,
    Time time,
    CardNo int,
    Channel int,
    EventID int,
    CONSTRAINT fk_EventReference FOREIGN KEY (EventID) REFERENCES Event(EventID),
    AccessType varchar(4),
    ReadPtr int,
    ControllerID int,
    CONSTRAINT fk_ControllerReference FOREIGN KEY (ControllerID) REFERENCES Controller(ControllerID),
    IPAddress varchar(20)
    )
    ;
    CREATE TABLE users (
    uid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    firstname VARCHAR(100) NOT NULL,
    lastname VARCHAR(100) NOT NULL,
    email VARCHAR(120) NOT NULL UNIQUE,
    pwdhash VARCHAR(100) NOT NULL
    );
    /*
    END
    */

我做错了什么?

根据 Miguel 修改后已编辑

    from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime, Date, Time
    from sqlalchemy.orm import relationship, backref

    #make sure we get the right base
    from database import ProbeDB_Base, DB

    class Location(ProbeDB_Base):
        __tablename__ = u'Location'
        __table_args__ = {u'schema': u'probedb'}

        LocationID = Column(Integer, primary_key=True)
        LocationName = Column(String(100))
        controllers = relationship("Controller", backref="Location")

    class Controller(ProbeDB_Base):
        __tablename__ = u'Controller'
        __table_args__ = {u'schema': 'probedb'}

        ControllerID = Column(Integer, primary_key=True)
        ControllerName = Column(String(100))
        ControllerNo = Column(Integer)
        SlaveNo = Column(Integer)
        IPAddress = Column(String(20))
        Port = Column(Integer)
        CommunicationType = Column(Integer)
        Enable = Column(Integer)
        ResponseTime = Column(Integer)
        LocationID = Column(Integer, ForeignKey('Location'), index=True)
        #LocationID = relationship(Location, primaryjoin='Controller.LocationID == DB.Location.LocationID')
        MaxChannels = Column(Integer)
        #Location_id = relationship(u'Location')
        transactions = relationship("Transaction", backref="Controller")

    class Department(ProbeDB_Base):
        __tablename__ = u'Department'
        __table_args__ = {u'schema': 'probedb'}

        DepartmentID = Column(Integer, primary_key=True)
        Name = Column(String(100))
        employees = relationship("Employee", backref="Department")

    class Designation(ProbeDB_Base):
        __tablename__ = u'Designation'
        __table_args__ = {u'schema': 'probedb'}

        DesignationID = Column(Integer, primary_key=True)
        Name = Column(String(100))
        employees = relationship("Employee", backref="Designation")

    class Employee(ProbeDB_Base):
        __tablename__ = u'Employee'
        __table_args__ = {u'schema': 'probedb'}

        EmployeeID = Column(Integer, primary_key=True)
        EmployeeCode = Column(String(15), index=True)
        LocationID = Column(Integer)
        Name = Column(String(50))
        CardNo = Column(Integer)
        DepartmentID = Column(Integer, ForeignKey('Department'), index=True)
        #DepartmentID = relationship(Department, primaryjoin='Employee.DepartmentID == DB.Department.DepartmentID')
        DesignationID = Column(Integer, ForeignKey('Designation'), index=True)
        #DesignationID = relationship(Designation, primaryjoin='Employee.DesignationID == DB.Designation.DesignationID')
        EnrollDate = Column(DateTime)
        ExpDate = Column(DateTime)
        #Department_id = relationship(u'Department')
        #Designation_id = relationship(u'Designation')

    class Event(ProbeDB_Base):
        __tablename__ = u'Event'
        __table_args__ = {u'schema': 'probedb'}

        EventID = Column(Integer, primary_key=True)
        Name = Column(String(100))

        transactions = relationship("Transaction", backref="Event")

    class Transaction(ProbeDB_Base):
        __tablename__ = u'Transaction'
        __table_args__ = {u'schema': 'probedb'}

        TransactionID = Column(Integer, primary_key=True)
        DateTime = Column(DateTime)
        Date = Column(Date)
        Time = Column(Time)
        CardNo = Column(Integer)
        Channel = Column(Integer)
        EventID = Column(Integer, ForeignKey('Event'), index=True)
        #EventID = relationship(Event, primaryjoin='Transaction.EventID == DB.Event.EventID')
        AccessType = Column(String(4))
        ReadPtr = Column(Integer)
        ControllerID = Column(Integer, ForeignKey('Controller'), index=True)
        #ControllerID = relationship("Controller", primaryjoin='Transaction.ControllerID == Controller.ControllerID')
        IPAddress = Column(String(20))
        #Controller_id = relationship(u'Controller')
        #Event_id = relationship(u'Event')

    class User(ProbeDB_Base):
        __tablename__ = u'users'
        __table_args__ = {u'schema': 'probedb'}

        uid = Column(Integer, primary_key=True)
        firstname = Column(String(100), nullable=False)
        lastname = Column(String(100), nullable=False)
        email = Column(String(120), nullable=False, index=True)
        pwdhash = Column(String(100), nullable=False)

我得到了这个异常

sqlalchemy.exc.NoForeignKeysError

NoForeignKeysError: Could not determine join condition between parent/child tables on relationship Designation.employees - there are no foreign keys linking these tables. Ensure that referencing columns are associated with a ForeignKey or ForeignKeyConstraint, or specify a 'primaryjoin' expression.

【问题讨论】:

  • ForeignKey 的参数是表名,而不是表的主键名。尝试 ForeignKey('Department') 而不是 ForeignKey('Department.DepartmentID')。
  • 将所有外键语句更改为指向表名。但是我将如何设置特定列与特定列的关系?我是 SQL 新手,如果我听起来很愚蠢,请多多包涵
  • 在我的主帖下方添加一个带有新错误的编辑。还是不行
  • 如果我没记错的话,你需要将模型中的关系与外键引用分开。所以控制器会有location = relationship("Location", backref="Controller"),它会以同样的方式行动。
  • 不幸的是,将 CamelCase 烧瓶到 camel_case 是恶魔,受害者是我

标签: python database sqlalchemy flask


【解决方案1】:

这应该教我正确地使用 RTFM flask 在数据库表名中强制执行 CamelCase

在我从the manual 弄明白之前,我挠了两天的头。 有人应该在该页面上将其加粗或突出或其他内容。

    from sqlalchemy import Table, Column, Integer, ForeignKey, String, DateTime, Date, Time
    from sqlalchemy.orm import relationship, backref
    from database import ProbeDB_Base, DB

    #make sure your models are setup right for reflection of an existing schema
    #convert all CamelCase table names - if you SQL table name is MyName, then change it to my_name
    #make sure you add backrefs and primaryjoin relationships for each ForeignKey constraint
    #make sure you escape all ' like this - \' in your relationship statements

    class Location(ProbeDB_Base):
        __tablename__ = u'location'
        __table_args__ = {u'schema': u'probedb'}

        location_id = Column(Integer, primary_key=True)
        Locationname = Column(String(100))
        controllers = relationship("u'controller'", backref="u'location'")

    class Controller(ProbeDB_Base):
        __tablename__ = u'lontroller'
        __table_args__ = {u'schema': 'probedb'}

        controller_id = Column(Integer, primary_key=True)
        controller_name = Column(String(100))
        controller_no = Column(Integer)
        slave_no = Column(Integer)
        ip_address = Column(String(20))
        port = Column(Integer)
        communicationType = Column(Integer)
        enable = Column(Integer)
        responseTime = Column(Integer)
        #location_id = Column(Integer, ForeignKey('location.location_id'), index=True)
        location_id = relationship(Location, primaryjoin='u\'controller\'.location_id == u\'location\'.location_id')
        max_channels = Column(Integer)
        #Location_id = relationship(u'Location')
        transactions = relationship("u'transaction'", backref="u'controller'")


    class Department(ProbeDB_Base):
        __tablename__ = u'department'
        __table_args__ = {u'schema': 'probedb'}

        department_id = Column(Integer, primary_key=True)
        name = Column(String(100))
        employees = relationship("u'employee'", backref="u'department'")

    class Designation(ProbeDB_Base):
        __tablename__ = u'designation'
        __table_args__ = {u'schema': 'probedb'}

        designation_id = Column(Integer, primary_key=True)
        name = Column(String(100))
        employees = relationship("u'employee'", backref="u'designation'")

    class Employee(ProbeDB_Base):
        __tablename__ = u'employee'
        __table_args__ = {u'schema': 'probedb'}

        employee_id = Column(Integer, primary_key=True)
        employee_code = Column(String(15), index=True)
        location_id = Column(Integer)
        name = Column(String(50))
        CardNo = Column(Integer)
        #department_id = Column(Integer, ForeignKey('Department.department_id'), index=True)
        department_id = relationship(u'department', primaryjoin='u\'employee\'.department_id == u\'department\'.department_id')
        #designation_id = Column(Integer, ForeignKey('Designation.designation_id'), index=True)
        designation_id = relationship(u'designation', primaryjoin='u\'employee\'.designation_id == u\'designation\'.designation_id')
        enroll_date = Column(DateTime)
        exp_date = Column(DateTime)
        #department_id = relationship(u'department')
        #designation_id = relationship(u'designation')

    class Event(ProbeDB_Base):
        __tablename__ = u'event'
        __table_args__ = {u'schema': 'probedb'}

        event_id = Column(Integer, primary_key=True)
        name = Column(String(100))

        transactions = relationship("u'transaction'", backref="u'event'")

    class Transaction(ProbeDB_Base):
        __tablename__ = u'transaction'
        __table_args__ = {u'schema': 'probedb'}

        transaction_id = Column(Integer, primary_key=True)
        date_time = Column(DateTime)
        date = Column(Date)
        time = Column(Time)
        card_no = Column(Integer)
        channel = Column(Integer)
        #event_id = Column(Integer, ForeignKey('event.event_id'), index=True)
        event_id = relationship(u'event', primaryjoin='u\'transaction\'.event_id == u\'event\'.event_id')
        accessType = Column(String(4))
        read_ptr = Column(Integer)
        #controller_id = Column(Integer, ForeignKey(controller.controller_id'), index=True)
        controller_id = relationship(u'controller', primaryjoin='u\'transaction\'.controller_id == u\'controller\'.controller_id')
        ip_address = Column(String(20))
        #Controller_id = relationship(u'Controller')
        #Event_id = relationship(u'Event')

    class User(ProbeDB_Base):
        __tablename__ = u'users'
        __table_args__ = {u'schema': 'probedb'}

        uid = Column(Integer, primary_key=True)
        firstname = Column(String(100), nullable=False)
        lastname = Column(String(100), nullable=False)
        email = Column(String(120), nullable=False, index=True)
        pwdhash = Column(String(100), nullable=False)

这是有效的代码,如果你最初像我一样使用 sqlacodegen 制作你的 model.py,如果你想使用 tablename

【讨论】:

猜你喜欢
  • 2017-11-26
  • 2016-03-18
  • 1970-01-01
  • 2021-07-18
  • 2021-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-02
相关资源
最近更新 更多