2010-12-31 150 views
10

Tôi có một mối quan hệ nhiều người đến nhiều người đến (nhà phát triển &) được mô hình hóa bằng cách sử dụng số của hiệp hội SA. Các bộ sưu tập (các nhà phát triển trên mỗi dự án & dự án cho mỗi nhà phát triển) hoạt động tốt, nhưng tôi cần phải lọc trên một thuộc tính của chính hiệp hội đó (trạng thái). Một cái gì đó như thế này (không hoạt động):lọc theo thuộc tính liên kết với SqlAlchemy association_proxy

activeDevelopers = s.query(Developer).filter_by(Developer.developerProjects.status == 'active').all() 

Tôi đang thiếu gì? Đây là mã kiểm tra hoàn chỉnh:

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' 

Trả lời

9

Sử dụng any() method của hiệp hội proxy:

s.query(Developer).filter(Developer.developerProjects.any(status='active')) 
+0

Cảm ơn, hoạt động tốt. – Hollister

+1

Làm thế nào để sử dụng 'like' cho phù hợp trong kịch bản này? –

4

Để thêm vào Denis của câu trả lời:

Khi chúng tôi thử phương pháp any(), tôi đã nhận lỗi này

sqlalchemy.exc.InvalidRequestError: 'any()' not implemented for scalar attributes. Use has(). 

Sử dụng has() thay vì any() đã hoạt động đối với tôi.

Có vẻ như any() là dành cho các mối quan hệ trong danh sách (trong trường hợp này Nhà phát triển có khả năng có nhiều dự án để Developer.developerProjects là danh sách). Trong khi đó, has() chỉ dành cho một mối quan hệ (ví dụ: nếu Developer có một liên kết Workplace được liên kết).

Đây là liên kết đến tài liệu: http://docs.sqlalchemy.org/en/latest/orm/internals.html#sqlalchemy.orm.properties.RelationshipProperty.Comparator.has

Các vấn đề liên quan