带有 JOIN 的混合 属性 表达式

Hybrid property expression with JOIN

我是 peewee 的新手,但对 SQLAlchemy(以及随之而来的所有恶习)有一定的了解。我正在尝试创建一个与第三个(甚至 N 个)table 相关的自定义混合表达式。我将尝试在示例(未测试)代码中进行演示:

class BaseModel(Model):
    class Meta:
        database = database


class Person(BaseModel):
    id = PrimaryKeyField(column_name="person_id")
    name = CharField(max_length=255, column_name="person_name")
    username = CharField(max_length=255, column_name="person_username")



class PersonTree(BaseModel):
    id = PrimaryKeyField(column_name="person_tree_id")
    name = CharField(max_length=255, column_name="person_tree_name")
    code = CharField(max_length=255, column_name="person_tree_code")

    person = ForeignKeyField(
        column_name="person_id",
        model=Person,
        field="id",
        backref="tree",
    )


class Article(BaseModel):
    id = PrimaryKeyField(column_name="article_id")
    name = CharField(max_length=255, column_name="article_name")

    branch = ForeignKeyField(
        column_name="person_tree_id",
        model=PersonTree,
        field="id",
        backref="articles",
    )

    @hybrid_property
    def username(self):
        """
        This gives me the possibility to grab the direct username of an article
        """
        return self.branch.person.username

    @username.expression
    def username(cls):
        """
        What if I wanted to do: Article.query().where(Article.username == "john_doe") ?
        """
        pass

使用 Article 上的 username hybrid_property,我可以使用 Article 获得与 Person 相关的 username PersonTree 作为相关性,到目前为止一切顺利,但是......如果我想 "create a shortcut" 查询由 "john_doe" Person 用户名创建的所有 Articles 怎么办,我每次进行查询时都没有声明 JOIN 并且不依赖 .filter(branch__person__username="john_doe")?我知道使用 SA 是可能的(在很大程度上),但我发现使用 peewee.

很难做到这一点

为了澄清,这里是 SQL 我希望能够构造:

SELECT
    *
FROM
    article a
    JOIN person_tree pt ON a.person_tree_id = pt.person_tree_id
    JOIN person p ON pt.person_id = p.person_id
WHERE
    p.username = 'john_doe';

提前致谢!

混合属性可用于允许将属性表示为模型实例的 属性 或 SQL 查询中的标量计算。

您尝试做的是通过 属性 添加多个连接和内容,使用混合属性是不可能的。

What if I wanted to "create a shortcut" to query all Articles created by the "john_doe" Person username

只需添加一个普通方法:

@classmethod
def by_username(cls, username):
    return (Article
            .select(Article, PersonTree, Person)
            .join(PersonTree)
            .join(Person)
            .where(Person.name == username))