次のSQLAlchemyマップクラスがあります。
class User(Base):
__table= 'users'
email = Column(String, primary_key=True)
name = Column(String)
class Document(Base):
__table= "documents"
name = Column(String, primary_key=True)
author = Column(String, ForeignKey("users.email"))
class DocumentsPermissions(Base):
__table= "documents_permissions"
readAllowed = Column(Boolean)
writeAllowed = Column(Boolean)
document = Column(String, ForeignKey("documents.name"))
user.email = "[email protected]"
に対して次のようなテーブルを取得する必要があります。
email | name | document_name | document_readAllowed | document_writeAllowed
SQLAlchemyの1つのクエリリクエストを使用してどのように作成できますか?以下のコードは私には機能しません:
result = session.query(User, Document, DocumentPermission).filter_by(email = "[email protected]").all()
おかげで、
これを試して
q = (Session.query(User,Document,DocumentPermissions)
.filter(User.email == Document.author)
.filter(Document.name == DocumentPermissions.document)
.filter(User.email == 'someemail')
.all())
良いスタイルは、いくつかの関係とパーミッションの主キーを設定することです(実際、通常はintegerすべてのプライマリキーを設定するのが良いスタイルですが、何でも):
class User(Base):
__table= 'users'
email = Column(String, primary_key=True)
name = Column(String)
class Document(Base):
__table= "documents"
name = Column(String, primary_key=True)
author_email = Column(String, ForeignKey("users.email"))
author = relation(User, backref='documents')
class DocumentsPermissions(Base):
__table= "documents_permissions"
id = Column(Integer, primary_key=True)
readAllowed = Column(Boolean)
writeAllowed = Column(Boolean)
document_name = Column(String, ForeignKey("documents.name"))
document = relation(Document, backref = 'permissions')
次に、結合を使用して簡単なクエリを実行します。
query = session.query(User, Document, DocumentsPermissions).join(Document).join(DocumentsPermissions)
@letitbeeが言ったように、主キーをテーブルに割り当て、適切なORMクエリを可能にするために関係を適切に定義することがベストプラクティスです。言われていること...
次の行に沿ってクエリを作成することに興味がある場合:
SELECT
user.email,
user.name,
document.name,
documents_permissions.readAllowed,
documents_permissions.writeAllowed
FROM
user, document, documents_permissions
WHERE
user.email = "[email protected]";
次に、次のようなものに行く必要があります。
session.query(
User,
Document,
DocumentsPermissions
).filter(
User.email == Document.author
).filter(
Document.name == DocumentsPermissions.document
).filter(
User.email == "[email protected]"
).all()
代わりに、次のようなことをしたい場合:
SELECT 'all the columns'
FROM user
JOIN document ON document.author_id = user.id AND document.author == User.email
JOIN document_permissions ON document_permissions.document_id = document.id AND document_permissions.document = document.name
次に、次の行に沿って何かを行う必要があります。
session.query(
User
).join(
Document
).join(
DocumentsPermissions
).filter(
User.email == "[email protected]"
).all()
それについての1つのメモ...
query.join(Address, User.id==Address.user_id) # explicit condition
query.join(User.addresses) # specify relationship from left to right
query.join(Address, User.addresses) # same, with explicit target
query.join('addresses') # same, using a string
詳細については、 docs をご覧ください。
Abdulの答えを拡張すると、列を結合することにより、行の個別のコレクションの代わりに KeyedTuple
を取得できます。
q = Session.query(*User.__table__.columns + Document.__table__.columns).\
select_from(User).\
join(Document, User.email == Document.author).\
filter(User.email == 'someemail').all()
この関数は、タプルのリストとして必要なテーブルを作成します。
def get_documents_by_user_email(email):
query = session.query(User.email, User.name, Document.name,
DocumentsPermissions.readAllowed, DocumentsPermissions.writeAllowed,)
join_query = query.join(Document).join(DocumentsPermissions)
return join_query.filter(User.email == email).all()
user_docs = get_documents_by_user_email(email)