Hol*_*ter 12 sql many-to-many sqlalchemy
我有一个使用SA的association_proxy建模的多对多(开发人员和项目)关系.集合(每个项目的开发人员和每个开发人员的项目)工作正常,但我需要过滤关联本身的属性(状态).像这样的东西(不起作用):
activeDevelopers = s.query(Developer).filter_by(Developer.developerProjects.status == 'active').all()
Run Code Online (Sandbox Code Playgroud)
我错过了什么?这是完整的测试代码:
import logging
from sqlalchemy import create_engine, Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.orm import relation, mapper, sessionmaker
from sqlalchemy.sql import *
from sqlalchemy.ext.associationproxy import association_proxy
log = logging.getLogger('nm_test')
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s,%(msecs)03d %(levelname)s [%(filename)s.%(funcName)s @ %(lineno)d.%(thread)d] %(message)s')
engine = create_engine('sqlite:///:memory:', echo = False, echo_pool = False)
meta = MetaData()
meta.bind = engine
developer_table = Table('developer', meta,
Column('id', Integer, primary_key=True, autoincrement = False),
Column('name', String),
)
project_table = Table('project', meta,
Column('id', Integer, primary_key=True, autoincrement = True),
Column('name', String)
)
developer_project_table = Table('developer_project', meta,
Column('developer_id', Integer, ForeignKey('developer.id'), primary_key = True),
Column('project_id', Integer, ForeignKey('project.id'), primary_key = True),
Column('status', String)
)
class Developer(object):
projects = association_proxy('developerProjects', 'projects')
def __str__(self):
return 'Developer id:%i, name:%s' % (self.id, self.name)
class Project(object):
developers = association_proxy('developerProjects', 'developers')
def __str__(self):
return 'Project id:%i, name:%s' % (self.id, self.name)
class DeveloperProject(object):
def __str__(self):
return 'DeveloperProject developer:%s, project:%s, status:%s' % (self.developer_id, self.project_id, self.status)
mapper(Developer, developer_table, properties = {
'developerProjects':relation(DeveloperProject, backref = "developers")
})
mapper(Project, project_table, properties = {
'developerProjects':relation(DeveloperProject, backref = "projects")
})
mapper(DeveloperProject, developer_project_table)
meta.create_all(engine)
conn = engine.connect()
conn.execute(project_table.insert(),[
{'name':'stackoverflow'},
{'name':'superuser'},
])
conn.execute(developer_table.insert(),[
{'name':'John'},
{'name': 'TerryJ'},
{'name': 'TerryG'},
{'name': 'Eric'},
{'name': 'Graham'},
])
conn.execute(developer_project_table.insert(),[
{'developer_id':1, 'project_id':1, 'status':'active'},
{'developer_id':2, 'project_id':2, 'status':'inactive'},
{'developer_id':3, 'project_id':2, 'status':'active'},
{'developer_id':4, 'project_id':1, 'status':'active'},
{'developer_id':4, 'project_id':2, 'status':'active'},
{'developer_id':5, 'project_id':1, 'status':'active'},
{'developer_id':5, 'project_id':2, 'status':'inactive'},
])
Session = sessionmaker(bind=engine)
s = Session()
developers = s.query(Developer).all()
projects = s.query(Project).all()
for d in developers:
log.debug(d)
for p in d.projects:
log.debug(' %s' % p)
for p in projects:
log.debug(p)
for d in p.developers:
log.debug(' %s' % d)
# does not work
activeDevelopers = s.query(Developer).filter_by(Developer.developerProjects.status == 'active').all()
# AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute 'status'
Run Code Online (Sandbox Code Playgroud)
Den*_*ach 10
使用关联代理any()
方法:
s.query(Developer).filter(Developer.developerProjects.any(status='active'))
Run Code Online (Sandbox Code Playgroud)
添加丹尼斯的回答:
当我尝试这个any()
方法时,我收到了这个错误
sqlalchemy.exc.InvalidRequestError: 'any()' not implemented for scalar attributes. Use has().
Run Code Online (Sandbox Code Playgroud)
使用has()
而不是any()
为我工作.
它看起来像any()
列表关系(在这种情况下,开发人员可能有多个项目,因此Developer.developerProjects
是一个列表).而has()
对于单一关系(例如,如果Developer
有一个Workplace
关联).
以下是文档链接:http://docs.sqlalchemy.org/en/latest/orm/internals.html#sqlalchemy.orm.properties.RelationshipProperty.Comparator.has