2013-07-19 21 views
14

Uygulamam için ilişkiler oluşturmak için Flask ile SQLAlchemy kullanıyorum. Benim modellerdeSQL Alchemy'deki ilişkilerimdeki sorun nedir?

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) 

Herhangi bir yardım mutluluk duyacağız Geçenlerde olursa olsun değiştirmek şeye ben hatayı almaya devam ilişkileri yeniden yazdım ve! aşağıdaki gibi

cevap

26

Bu hata:

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

SQLAlchemy ilişkide yabancı anahtar olarak kullanmak Enrollments uygun bir sütun bulamadığı anlamına gelir.

Yabancı anahtarı tanımladınız, ancak yanlış bir tablo adı kullandınız. tablo oluştururken Flask-SQLAlchemy camel_case için CamelCase sınıfları dönüştürür, böylece bunu değiştirmek gerekir: Varsayılan adlandırma kuralını geçersiz kılmak için

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

Eğer __tablename__ özelliğini kullanabilirsiniz: Buna

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

Flask-SQLAlchemy tarafından kullanılır.

+0

Bu gerçekten beni kızdırdı. Bunu neden yaptı? –

+2

Çünkü Flask, geliştiricinin bu kuralları açıkça üretmesine izin vermek yerine, sizin için isimler oluşturmanın hayatı kolaylaştırdığını düşünüyor. SQLAlchemy'nin kendisi hiçbir zaman hiçbir tür sözleşme yapmamak için kendi yolunun dışına çıkmaktadır, sadece kendinize ait araçları size sunar. – zzzeek

2

deneyin sizin CurriculumVersion sınıfında primaryjoin kullanmak:

Değişim

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

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

Notu: Sen de diğer sınıflar için bunu yapmak gerekebilir.

+0

Bu bana hata mesajını veriyor: "sqlalchemy.exc.NoReferencedTableError: 'enrollment.version_id' sütunuyla ilişkili yabancı anahtar 'id' sütununu hedefleyen bir yabancı anahtar oluşturmak için 'CurriculumVersion' tablosunu bulamadı. fikir? –

+0

örneğinde bu sorunu çözmek için eksik bir ayrıntı var - Örnekte ForeignKey 'curriculumversion.id' anlamına gelir ama bir nedenden dolayı "CurriculumVersion" adlı bir tablo arıyor - db.Model tam olarak ne yapıyor, '__tablename__' nedir , vb. ? – zzzeek