6

この多対多の関係を考えると:

tagmap = db.Table('tagmap', db.Model.metadata,
    db.Column('post_id', db.Integer, db.ForeignKey('posts.id'),
    db.Column('tag_id', db.Integer, db.ForeignKey('tags.id'),)

class Post(db.Model):
    __tablename__ = 'posts'
    id    = db.Column(db.Integer, primary_key=True)
    text  = db.Column(db.Text)
    tags  = db.relationship('Tag', secondary=tagmap, backref='posts')

class Tag(db.Model):
    __tablename__ = 'tags'
    id    = db.Column(db.Integer, primary_key=True)
    name  = db.Column(db.String)

関連するタグ オブジェクトの反復可能なリストを含むすべての投稿を選択するクエリをどのように作成しますか?

望ましいクエリ結果の構造:

[ <Post 1, "Blah",      [<Tag "Goober">, <Tag "Mexico">]>,
  <Post 2, "Daft Punk", [<Tag "French">]>,
  <Post 3, "Slurpee",   [<Tag "Diabetes">, <Tag "Tasty">, <Tag "Sugary">]>,
  <Post 4, "Lasers",    []> ]

Jinja テンプレートでの望ましい結果の使用例:

{% for post in posts %}
    {{ post.text }}
    <hr>
    {% for tag in post.tags %}
        {{ tag.name }}, 
    {% endfor %}
{% endfor %}

編集

クエリを拡張しようとすると、タグが含まれなくなります。以下の失敗したクエリを参照してください。

Post.query.join(User)\
    .options(db.joinedload(Post.tags))\
    .order_by(Post.create_date.desc()).limit(5)\
    .values(User.name.label('author'),
            Post.create_date,
            Post.text,)

編集2

したがって、このクエリはうまく機能します。

posts = db.session.query(Post, User.name.label('author')).join(User)\
            .options(db.joinedload(Post.tags))\
            .order_by(Post.created.desc()).limit(5)

しかし、投稿の列を選択したい場合は、次を選択します。

# I only need the post text, nothing else
posts = db.session.query(Post.text, User.name.label('author')).join(User)\
            .options(db.joinedload(Post.tags))\
            .order_by(Post.created.desc()).limit(5)

それはすぐにバラバラになり始めます:

ArgumentError: Query has only expression-based entities - can't find property named 'tags'.

だから私はタグを追加しようとします:

# Yes, I know this is wrong
posts = db.session.query(Post.text, Post.tags, User.name.label('author'))\
            .join(User)\               
            .options(db.joinedload(Post.tags))\
            .order_by(Post.created.desc()).limit(5)

それでも失敗します。

親オブジェクト (Post) の特定の列のみが必要な場合、式のどこで「タグが必要ですか」と言うのでしょうか?

今はそれほど重要ではありませんが、知っておくと便利だと思いました。または、それが不可能であることさえ知っています。

4

2 に答える 2

7

リレーションシップに熱心な読み込みを使用したいと思います。またはlazyとの関係でキーワード引数を設定することで、それを実現できます。'joined''subquery'

class Post(db.Model):
    # ...
    tags = db.relationship('Tag', secondary=tagmap, backref='posts',
                           lazy='joined')    # Or lazy='subquery'

または、クエリごとに設定できます。

q = Post.query.options(db.joinedload(Post.tags)).all()
# Or db.subqueryload(Post.tags)

詳細については、ORM チュートリアルのEager Loadingの部分とRelationship Loading Techniquesを参照してください。

于 2013-01-16T12:06:11.890 に答える
0

SQLAlchemy は、post.tagsアクセス時にプロパティを自動ロードするため、必要なすべての投稿をロードするだけで済みます。

db.Column('tag_id', db.Integer, db.ForeignKey('quotes.id'),)

それquotes.idはタイプミスですか?

于 2013-01-16T07:04:17.697 に答える