如何在没有外键的情况下使用 PeeWee 进行左外连接?

How to do left outer join with PeeWee and no ForeignKey?

在 SQLite 之上使用 PeeWee,我试图在两个 table 之间进行左外连接,这两个 没有 定义了外键关系。如果右侧 table 与左侧 table 匹配的条目,我可以获得数据,但如果没有匹配,右侧 table 中的列不会进入返回的模型.

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

class Location(BaseModel):
    location_key = CharField(primary_key=True)
    lat = FloatField(null = False)
    lon = FloatField(null = False)


class Household(BaseModel):
    name = CharField(null=True)
    location_id = CharField(null=True)

我正在尝试做类似的事情:

    for h in Household.select(Household,Location).join(Location, on=(Household.location_id == Location.location_key), join_type=JOIN.LEFT_OUTER):
        print(type(h), h, h.location, h.location.lat)

如果 Household.location_id 与 Location 中的某些内容匹配,但如果 Household.location_id 是 None(空),那么我会得到一个 AttributeError: 'Household' object has no attribute 'location'

我希望位置存在,但有效 None。

如何在使用前检查位置是否存在? 我试图避免使用 ForeignKey,Household.location_id 和 Location.location_key 而 PeeWee 真的很生气 ...

找到我自己的答案。在 Household 模型中实现 __getattr__(self),如果名称为 'location',则实现 return None。 __getattr__(self) 只有在没有 属性 的情况下才会被调用。

我想我明白你在 re-reading 之后想要做什么。我的建议是在连接中使用 Peewee 的“on”关键字参数,它可以将相关位置(如果存在)修补到与“位置”不同的属性上:

query = (HouseHold
         .select(HouseHold, Location)
         .join(Location, on=(HouseHold.location_id == Location.location_key),
               attr='location_obj', join_type=JOIN.LEFT_OUTER))

然后您可以勾选“location_obj”来检索相关对象。

for house in query:
    # if there was a match, get the location obj or None.
    location_obj = getattr(house, 'location_obj', None)
    # the location_id is still present.
    print(house.location_id, location_obj)