【问题标题】:What is wrong with my relationships in SQL Alchemy?我在 SQLAlchemy 中的关系有什么问题?
【发布时间】:2013-07-19 04:28:30
【问题描述】:

我正在使用带有 Flask 的 SQLAlchemy 为我的应用程序创建关系。我最近重写了这些关系,无论我改变什么,我都会不断收到错误:

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

在我的模型上:

class User(db.Model, AuthUser):
    id = db.Column(db.Integer, primary_key=True)
    tf_login = db.Column(db.String(255), unique=True, nullable=False) # can assume is an email
    password = db.Column(db.String(120), nullable=False)
    salt = db.Column(db.String(80))
    role = db.Column(db.String(80)) # for later when have different permission types
    zoho_contactid = db.Column(db.String(20), unique=True, nullable=False)
    created_asof = db.Column(db.DateTime, default=datetime.datetime.utcnow)
    enrollments = db.relationship('Enrollment', backref='enrollment', lazy='dynamic')
    firstname = db.Column(db.String(80))
    lastname = db.Column(db.String(80))


    def __repr__(self):
        return '#%d tf_login: %s, First Name: %s Last Name: %s created_asof %s' % (self.id, self.tf_login, self.firstname, self.lastname, self.created_asof)

    def __getstate__(self):
        return {
            'id': self.id,
            'tf_login': self.tf_login,
            'firstname': self.firstname,
            'lastname': self.lastname,
            'role': self.role,
            'created_asof': self.created_asof,
        }

    @classmethod
    def load_current_user(cls, apply_timeout=True):
        data = get_current_user_data(apply_timeout)
        if not data:
            return None
        return cls.query.filter(cls.email==data['email']).one()
        return '#%d Course Name: %s, Course Version: %s, Closing Date: %s' %(self.id, self.course_name, self.course_version, self.closing_date)

class Enrollment(db.Model, AuthUser):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    version_id = db.Column(db.Integer, db.ForeignKey('curriculumversion.id'))
    cohort_id = db.Column(db.Integer, db.ForeignKey('cohort.id'))

    def __repr__(self):
        return '#%d User ID: %d Version ID: %d, Cohort ID: %d' %(self.id, self.user_id, self.version_id, self.cohort_id)

class Cohort(db.Model, AuthUser):
    id = db.Column(db.Integer, primary_key=True)
    days_to_completion = db.Column(db.String(20))
    course_id = db.Column(db.Integer, db.ForeignKey('course.id'))
    enrollments = db.relationship('Enrollment', backref='enrollment', lazy='dynamic')

    def __repr__(self):
        return '#%d Days To Completion: %s' %(self.id, self.days_to_completion)


class CurriculumVersion(db.Model, AuthUser):
    id = db.Column(db.Integer, primary_key=True)
    version_number = db.Column(db.String(6))
    date_implemented = db.Column(db.DateTime)
    course_id = db.Column(db.Integer, db.ForeignKey('course.id'))
    enrollments = db.relationship('Enrollment', backref='enrollment', lazy='dynamic')

    def __repr__(self):
        return '#%d Version Number: %s, Date Implemented: %s' %(self.id, self.version_number, self.date_implemented)

class Course(db.Model, AuthUser):
    id = db.Column(db.Integer, primary_key=True)
    course_code = db.Column(db.String(20))
    course_name = db.Column(db.String(50))
    versions = db.relationship('CurriculumVersion', backref='version', lazy='dynamic')
    cohorts = db.relationship('Cohort', backref='cohort', lazy='dynamic')


    def __repr__(self):
        return '#%d Course Code: %s, Course Name: %s' %(self.id, self.course_code, self.course_name)

任何帮助将不胜感激!

【问题讨论】:

    标签: database sqlalchemy flask flask-sqlalchemy


    【解决方案1】:

    这个错误:

    Could not determine join condition between parent/child tables on relationship CurriculumVersion.enrollments 
    

    表示 SQLAlchemy 无法在 Enrollments 中找到合适的列来用作关系中的外键。

    您定义了外键,但使用了不正确的表名。 Flask-SQLAlchemy 在创建表时会将CamelCase 类转换为camel_case,所以你需要改变这个:

    class Enrollment(db.Model, AuthUser):
        # ...
        version_id = db.Column(db.Integer, db.ForeignKey('curriculumversion.id'))
        #...
    

    到这里:

    class Enrollment(db.Model, AuthUser):
        # ...
        version_id = db.Column(db.Integer, db.ForeignKey('curriculum_version.id'))
        #...
    

    或者,您可以使用 __tablename__ 属性来覆盖 Flask-SQLAlchemy 使用的默认命名约定。

    【讨论】:

    • 这真的让我很生气。知道为什么会这样吗?
    • 因为 Flask 认为为您创建名称,而不是让开发人员明确生成这些约定,可以让生活更轻松。 SQLAlchemy 本身竭尽全力从不产生任何约定,只是为您提供制作自己的工具。
    【解决方案2】:

    尝试在您的 CurriculumVersion 类中使用 primaryjoin,如下所示:

    改变

    enrollments = db.relationship('Enrollment', backref='enrollment', lazy='dynamic')
    

    enrollments = db.relationship('Enrollment', backref='enrollment', lazy='dynamic', primaryjoin="Enrollment.version_id==CurriculumVersion.id")
    

    注意:您可能也需要对其他类执行此操作。

    【讨论】:

    • 这给了我错误消息:“sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'enrollment.version_id' 找不到表 'CurriculumVersion' 用于生成目标列的外键'id'" 有什么想法吗?
    • 您的示例中缺少详细信息来解决此问题 - 示例中的 ForeignKey 指的是“curriculumversion.id”,但由于某种原因,它正在寻找一个名为“CurriculumVersion”的表 - db.Model 究竟做了什么做,__tablename__等在哪里?
    猜你喜欢
    • 1970-01-01
    • 2019-11-24
    • 2013-08-17
    • 2020-03-11
    • 1970-01-01
    • 2015-01-09
    • 2020-02-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多