2013-07-19 35 views
14

Tôi đang sử dụng SQLAlchemy với Flask để tạo mối quan hệ cho ứng dụng của tôi. Gần đây tôi đã viết lại các mối quan hệ, và, không có vấn đề gì tôi thay đổi, tôi tiếp tục nhận được lỗi:Điều gì là sai với các mối quan hệ của tôi trong SQL Alchemy?

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. 

Mở mô hình của tôi:

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) 

Bất kỳ trợ giúp sẽ được đánh giá cao!

Trả lời

26

lỗi này:

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

nghĩa là SQLAlchemy không thể tìm thấy một cột thích hợp trong Enrollments để sử dụng như phím nước ngoài trong mối quan hệ.

Bạn đã xác định khóa ngoại, nhưng bạn đã sử dụng tên bảng không chính xác. Flask-SQLAlchemy chuyển đổi CamelCase lớp học để camel_case khi tạo bảng, do đó bạn cần phải thay đổi điều này:

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

này:

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

Hoặc bạn có thể sử dụng thuộc tính __tablename__ để ghi đè các quy ước mặc định đặt tên được sử dụng bởi Flask-SQLAlchemy.

+0

Điều này thực sự làm tôi bực mình. Bất kỳ ý tưởng tại sao nó làm điều đó? –

+2

vì Flask nghĩ rằng việc tạo tên cho bạn, thay vì để nhà phát triển sản xuất rõ ràng các quy ước này, giúp cuộc sống trở nên dễ dàng hơn. Bản thân SQLAlchemy không thể tạo ra bất kỳ loại công ước nào, chỉ cung cấp cho bạn các công cụ để tạo ra các công cụ của riêng bạn. – zzzeek

2

Cố gắng sử dụng primaryjoin trong lớp CurriculumVersion của bạn như sau:

Thay đổi

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

để

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

Lưu ý: Bạn có thể cần phải làm điều này cho các lớp khác là tốt.

+0

Điều đó cho tôi thông báo lỗi: "sqlalchemy.exc.NoReferencedTableError: Khóa ngoại được kết hợp với cột 'enroll.version_id' không thể tìm thấy bảng 'CurriculumVersion' để tạo khóa ngoài để nhắm mục tiêu cột 'id'" ý tưởng? –

+0

có chi tiết còn thiếu trong ví dụ của bạn để sửa lỗi này - ForeignKey trong ví dụ đề cập đến 'curriculumversion.id' nhưng vì lý do nào đó, nó tìm kiếm một bảng có tên "CurriculumVersion" - chính xác thì db.Model làm gì, ở đâu '__tablename__' , v.v ...? – zzzeek

Các vấn đề liên quan