2012-07-03 1 views
2

у меня есть две модели в SQLAlchemy, имея много-ко-многимКак запросить те объекты, которые не присоединились (SQLAlchemy)

team_user_table = Table('team_user', Base.metadata, 
    Column('user_id', Integer, ForeignKey('users.id')), 
    Column('team_id', Integer, ForeignKey('teams.id')) 
) 

class User(Base): 
    """ The SQLAlchemy declarative model class for a User object. """ 
    __tablename__ = 'users' 
    id = Column(Integer, primary_key=True) 
    name = Column(String, unique=True) 

class Team(Base): 
    """ The SQLAlchemy declarative model class for a Team object. """ 
    __tablename__ = 'teams' 
    id = Column(Integer, primary_key=True) 
    name = Column(Text, unique=True) 
    members = relationship("User", 
     secondary=team_user_table, 
     backref="memberteams") 

Я хотел бы запросить тех пользователей, которые не являются членом конкретной команды.

В SQL (например):

SELECT u.id,u.name FROM users u WHERE u.id NOT IN (SELECT tu.user_id FROM team_user tu WHERE tu.team_id=?); 

Как я могу это сделать в SQLAlchemy?

ответ

2

Это делает то, что вы хотите:

team_id = 1 
query = session.query(User.id).filter(~User.memberteams.any(Team.id == team_id)) 

Это SQL выводит (на MySQL):

SELECT users.id AS users_id, users.name AS users_name 
FROM users 
WHERE NOT (EXISTS (SELECT 1 
FROM team_user, teams 
WHERE users.id = team_user.user_id AND teams.id = team_user.team_id AND teams.id = %s)) 

Это не совсем то, что ваш запрос выглядит сейчас, но я думаю, что это так оно и должно быть сделано. Проверьте the docs for this.

Я тестировал это на MySQL. Однако я думаю, что он должен работать на любом другом.

Чтобы получить точный запрос, вам может потребоваться ознакомиться с using subqueries в сочетании с инструкцией по фильтрации. Я думаю, вам понадобится прямая ссылка на таблицу team_user в вашем коде, чтобы она работала.

+0

Да, это работает (также на sqllite)! Благодаря! –

0

Я считаю, что это должно работать, и оно не использует подзапросы.

session.query(User).join(team_users_table).filter(team_users_table.team_id != OTHER_TEAM) 
+0

Этот запрос не работает. Сначала команда team_users_table является только таблицей и поэтому не имеет аргумента team_id. (Часть team_users_table.team_id). Во-вторых, это даст только людям, которые являются членами любой другой команды, даже те, кто являются членами первоначальной команды. –

+0

Я не думаю, что запрос будет делать то, что вы ожидаете, но чтобы он «работал», вам нужно использовать 'team_users_table.c.team_id' (обратите внимание на' .c', потому что вы получаете доступ к ** c ** olumn таблицы) для доступа к этому полю. – jadkik94

+0

Оба вы правы. Благодаря :). – Salil