首页 > 解决方案 > Peewee-async - 如何进行简单的 JOIN(或子查询/预取)

问题描述

我被困在一个peewee-async关于 JOIN 的非常简单的问题上,或者我可能需要使用子查询或预取......我无法弄清楚我需要做什么样的查询。

我有 2 个数据库表(父/子):

class Group(PeeweeModel):
    id = peewee.AutoField()

    name = peewee.TextField()


class Channel(PeeweeModel):
    id = peewee.AutoField()

    name = peewee.TextField()
    group = peewee.ForeignKeyField(Group, backref="channels")

我需要获取 1 个组对象,并且该对象有多个通道对象。

我试过了:

q = Group.select(Group, Channel).join(Channel)

但我backref的“频道”始终是一个ModelQuery实例,而不是实际的结果集。

完整代码

import asyncio

import peewee
import peewee_async
from peewee_async import Manager, PooledPostgresqlDatabase

database = PooledPostgresqlDatabase('test', max_connections=4, user='postgres', password='', host='127.0.0.1')
objects = peewee_async.Manager(database)


class PeeweeModel(peewee.Model):
    class Meta:
        database = database


class Group(PeeweeModel):
    id = peewee.AutoField()

    name = peewee.TextField()


class Channel(PeeweeModel):
    id = peewee.AutoField()

    name = peewee.TextField()
    group = peewee.ForeignKeyField(Group, backref="channels")


Group.create_table()
Channel.create_table()
database.set_allow_sync(False)


async def handler():
    # create 1 group object
    group = await objects.create(Group, name="TestGroup")

    # create 2 channel objects, assign to group
    await objects.create(Channel, name="TestName1", group=group)
    await objects.create(Channel, name="TestName2", group=group)

    # Query 1 group, and hopefully it will have the channels
    q = Group.select(Group, Channel).join(Channel)

    results = await objects.execute(q)
    for result in results:
        print(result.channels)  # problem: Channels is not a list of channel objects, but a `ModelSelect` instead

    with objects.allow_sync():
        Channel.drop_table(True)
        Group.drop_table(True)

loop = asyncio.get_event_loop()
loop.run_until_complete(handler())
loop.close()

标签: python-3.xpeewee

解决方案


我能够从专家那里获得帮助™,解决方案是使用prefetch()

async def handler():
    # create 1 group object
    group = await objects.create(Group, name="TestGroup")

    # create 2 channel objects, assign to group
    await objects.create(Channel, name="TestName", group=group)
    await objects.create(Channel, name="TestName", group=group)

    # Query 1 group, and hopefully it will have the channels
    q = Group.select(Group)

    groups = await objects.prefetch(q, Channel.select(Channel))
    for group in groups:
        print(group, group.channels)  # channels is a list of channels.

    with objects.allow_sync():
        Channel.drop_table(True)
        Group.drop_table(True)

Peewee 会自己找出关系(backref)。


推荐阅读