如何使用PeeWee而不使用ForeignKey进行左外部联接?

问题描述

sqlite的顶部使用peewee,我试图在两个没有 定义了ForeignKey关系的表之间进行左外部联接。如果右表中的项与左表中的项匹配,则可以获取数据,但是如果不匹配,则右表中的列不会将其放入返回的模型中。

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与“位置”中的某项匹配,则此方法有效,但是如果Household.location_id为“无”(空),那么我得到一个AttributeError: 'Household' object has no attribute 'location'

我希望可以在该位置显示,但是有效值为None。

如何在使用位置之前检查位置是否存在?我试图避免使用ForeignKey,Household.location_id和Location.location_key之间存在很多不匹配,而peewee真的很生气关于那个 ...

解决方法

我想我了解您在重新阅读后想要做什么。我建议在联接中使用Peewee的“ on”关键字参数,该参数可以将相关的Location(如果存在)修补到与“ location”不同的attr:

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)
,

找到了我自己的答案。在家庭模型中实现__getattr__(self),如果名称为“ location”,则返回None。仅当没有具有该名称的属性时,才会调用__getattr__(self)