2015-10-02 2 views
7

Мне нужно, чтобы сообщение было связано с двумя пользователями. Автор и модератор. Я пытаюсь без успеха этого кодаОдин объект два внешних ключа к одной таблице

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) 

Ошибка:

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

Пожалуйста, пост полных отслеживающих ошибок. –

+2

Исправлено на основе этой темы https://www.reddit.com/r/flask/comments/2o4ejl/af_flask_sqlalchemy_two_foreign_keys_referencing/ – anvd

ответ

11

Одна из проблем здесь является то, что вы в настоящее время пытаетесь использовать столбцы таблицы в отношениях foreign_keys, а не атрибуты класса.

То есть, вместо использования posts.id, вы должны использовать Post.id. (На самом деле, чтобы ссылаться на столбец таблицы, вам нужно будет использовать posts.c.id).

Таким образом, вполне возможно, что ваш исходный код будет работать, если вы исправите его:

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

Если это не произойдет, то есть несколько других вариантов. Во-первых, вы можете установить эти отношения в классе Post, где для sqlalchemy менее двусмысленно найти отношение внешнего ключа. Что-то вроде

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

Примечания в этой версии, нам не нужно, чтобы передать значение foreign_keys в виде строки, можно просто обратиться непосредственно к колонку в области.

В качестве альтернативы, если вы хотите установить эти отношения в пользователе, вы можете вы должны дать sqlalchemy больше информации, используя primaryjoin ... возможно, что-то вроде:

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

первый пример, тот же тип ошибки, который я получаю (объект выражения на основе столбцов, ожидаемый для аргумента 'foreign_keys'). второй пример отношения() получил неожиданный аргумент ключевого слова 'primary_join' – anvd

+2

@anvd primary_join должно быть основным соединением. Также заметили, что вы использовали имена таблиц, а не имена классов в ваших 'foreign_keys', и я соответствующим образом пересмотрел свой ответ. Дайте мне знать, как это происходит! – donkopotamus

+3

Меня не волнует ваша щедрость, я также не особо забочусь о том, чтобы полностью воспроизвести таблицу и структуру базы данных, чтобы помочь вам в достаточно простой проблеме. Я просто пытаюсь предоставить указатели ... вы знаете, я подозреваю, что вы могли бы делать так, как искать документацию **. Например, простой взгляд на отношения api сказал бы вам, что «primary_join» должен был быть «primaryjoin» ... – donkopotamus

Смежные вопросы