2015-10-02 14 views
7

Potrzebuję posta powiązanego z dwoma użytkownikami. Autor i moderator. Próbuję bezskutecznie ten kodJeden obiekt dwa klucze obce na tę samą tabelę

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) 

Error:

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

proszę pisać pełną błędzie traceback. –

+2

Rozwiązane na podstawie tego wątku https://www.reddit.com/r/flask/comments/2o4ejl/af_flask_sqlalchemy_two_foreign_keys_referencing/ – anvd

Odpowiedz

11

Jeden z tutejszych problemów jest to, że starają się obecnie używać kolumn tabeli w relacji foreign_keys zamiast atrybutów klasy.

Oznacza to, że zamiast używać posts.id, powinieneś używać Post.id. (W rzeczywistości, aby odnieść się do kolumny tabeli, musisz użyć posts.c.id).

Tak, to jest możliwe, że oryginalny kod będzie działać, jeśli go poprawić do:

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')  

Jeśli nie, to istnieje kilka innych opcji. Po pierwsze, możesz ustanowić te relacje w klasie Post, gdzie jest mniej niejednoznaczne dla sqlalchemy, aby znaleźć relację klucza obcego. Coś jak

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')  

Uwaga: W tej wersji nie musimy przekazać wartość foreign_keys jako ciąg znaków, możemy po prostu odwołać się bezpośrednio do kolumny w zakresie.

Ewentualnie, jeśli chcą ustanowić te relacje w Użytkownikiem, może trzeba dać sqlalchemy więcej informacji, za pomocą primaryjoin ... może coś takiego:

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

pierwszy przykład, ten sam typ błędu, który dostaję (oczekiwany obiekt wyrażenia oparty na kolumnach dla argumentu "klucze_docelowe"). drugi przykład relacja() otrzymała nieoczekiwany argument słowa kluczowego "primary_join" – anvd

+2

@anvd primary_join powinien być połączeniem podstawowym. Zauważyłem również, że używasz nazw tabel, a nie nazw klas w swoich 'obcych_kluczach' i odpowiednio poprawiłem swoją odpowiedź. Daj mi znać jak idzie! – donkopotamus

+3

Naprawdę nie dbam o twoją nagrodę, nie dbam również o to, aby całkowicie zreplikować strukturę tabeli i bazy danych, aby pomóc ci w rozsądnie prostym problemie. Próbuję tylko zapewnić wskaźniki ... wiesz, podejrzewam, że możesz być ** zdolny do robienia rzeczy takich jak przeglądanie dokumentacji **. Na przykład proste spojrzenie na api relacji powiedziałoby ci, że 'primary_join' miało być' primaryjoin' ... – donkopotamus

Powiązane problemy