2015-10-02 6 views
7

Ich muss einen Beitrag für zwei Benutzer zugeordnet haben. Der Autor und der Moderator. Ich versuche, diesen Code ohne ErfolgEin Objekt zwei Fremdschlüssel für die gleiche Tabelle

class User(UserMixin, db.Model): 
    __tablename__ = 'users' 
    id = db.Column(db.Integer, primary_key=True) 
    ... 
    post = db.relationship('Post', foreign_keys=['posts.id'], backref='post_user', lazy='dynamic') 
    post_blame = db.relationship('Post', foreign_keys=['posts.moderated_by'], backref='post_blame', lazy='dynamic')  

class Post(db.Model): 
    __tablename__ = 'posts' 
    id = db.Column(db.Integer, primary_key=True) 
    ... 
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) 
    moderated_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) 

Fehler:

ArgumentError: Column-based expression object expected for argument 'foreign_keys'; got: 'posts.id', type <type 's 
+1

Bitte den vollständigen Fehler Zurückverfolgungs posten. –

+2

In diesem Thread gelöst https://www.reddit.com/r/flask/comments/2o4ejl/af_flask_sqlalchemy_two_foreign_keys_referencing/ – anvd

Antwort

11

Eines der Probleme dabei ist, dass Sie gerade versuchen, Tabellenspalten in der Beziehung foreign_keys, anstatt Klassenattribute zu verwenden.

Das heißt, anstelle von posts.id sollten Sie Post.id verwenden. (Um auf eine Tabellenspalte zu verweisen, müssten Sie posts.c.id verwenden).

So ist es möglich, dass Ihre ursprüngliche Code funktioniert, wenn Sie es zu korrigieren:

class User(UserMixin, db.Model): 
    __tablename__ = 'users' 
    id = db.Column(db.Integer, primary_key=True) 
    ... 
    post = db.relationship('Post', foreign_keys='Post.id', backref='post_user', lazy='dynamic') 
    post_blame = db.relationship('Post', foreign_keys='Post.moderated_by', backref='post_blame', lazy='dynamic')  

Wenn dies nicht der Fall, dann gibt es einige andere Optionen. Zunächst können Sie diese Beziehungen in der Klasse Post einrichten, in der es für sqlalchemy weniger zweideutig ist, die Fremdschlüsselbeziehung zu finden. So etwas wie

class Post(db.Model): 
    __tablename__ = 'posts' 
    id = db.Column(db.Integer, primary_key=True) 
    ... 
    author_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) 
    moderated_by = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) 
    post_user = db.relationship(User, foreign_keys=author_id, backref='post', lazy='dynamic') 
    post_blame = db.relationship(User, foreign_keys=moderated_by, backref='post_blame', lazy='dynamic')  

Hinweis in dieser Version, wir brauchen nicht den foreign_keys Wert als String zu übergeben, können wir direkt auf die Säule in ihrem Umfang beziehen sich nur.

Alternativ, wenn Sie diese Beziehungen innerhalb Benutzer etablieren möchten, können Sie Sie benötigen sqlalchemy mehr Informationen zu geben, die von primaryjoin mit ... vielleicht so etwas wie:

class User(UserMixin, db.Model): 
    __tablename__ = 'users' 
    id = db.Column(db.Integer, primary_key=True) 
    ... 
    post = db.relationship('Post', primaryjoin='User.id == Post.id', backref='post_user', lazy='dynamic') 
    post_blame = db.relationship('Post', foreign_keys='User.id == Post.moderated_by', backref='post_blame', lazy='dynamic')  
+1

ersten Beispiel, gleiche Art von Fehler, die ich bekomme (Column-basierte Ausdruck Objekt für Argument 'Foreign_keys' erwartet). Das zweite Beispiel relation() hat ein unerwartetes Schlüsselwort argument 'primary_join' – anvd

+2

@anvd primary_join sollte primärer Join sein. Hab auch gerade gemerkt, dass du Tabellennamen verwendest, keine Klassennamen in deinen 'fremden_Tasten' und ich meine Antwort entsprechend überarbeitet habe. Lass mich wissen wie es geht! – donkopotamus

+3

Ich kümmere mich nicht wirklich um Ihre Kopfgelder, es ist mir auch nicht besonders wichtig, Ihre Tabellen- und Datenbankstruktur vollständig zu replizieren, um Ihnen bei einem relativ einfachen Problem zu helfen. Ich versuche nur, Hinweise zu geben ... Wissen Sie, ich vermute, dass Sie ** in der Lage sein könnten, Dinge zu tun, wie Dokumentation nachzuschlagen **. Zum Beispiel, ein einfacher Blick auf die Beziehung api hätte dir gesagt, dass 'primary_join' eigentlich' primaryjoin' sein sollte ... – donkopotamus