Peewee - 使用ForeignKeyField('self')更新记录问题

时间:2018-05-01 10:51:05

标签: python-3.x peewee

我有一个数据库,我从pd.DataFrame填充。其中一个类有一个ForeignKeyField('self')。

    from peewee import SqliteDatabase, Model
    from peewee import IntegerField, CharField, ForeignKeyField, BooleanField
    import pandas as pd

    db = SqliteDatabase(':memory:', pragmas=(('foreign_keys', 'on'),))

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

    class Team(BaseModel):
        id = IntegerField(unique = True, primary_key = True)
        name = CharField()
        reserve_team = BooleanField()
        parent_team = ForeignKeyField('self', related_name = 'reserve_teams', null = True)
        class Meta:
            db_table = 'team_team'

    Team.create_table()

我填写的数据框看起来像这样

    df = pd.DataFrame({'ID': [1,2,3,4,5],
                       'Name': ['A','A2','B','C','C2'],
                       'Reserve': [False, True, False, False, True],
                       'Parent': [None, 'A', None, None, 'C']})

我使用以下代码填充表格。 parent_team设置为None,当表填满时,我打算返回并在适当的时候更新此字段。

    data = []
    for row in df.itertuples():
        data.append((row.ID,
                     row.Name,
                     row.Reserve == True,
                     None))
    fields = [Team.id,
              Team.name,
              Team.reserve_team,
              Team.parent_team]
    with db.atomic():
        Team.insert_many(data, fields = fields).execute()

我的问题是我不理解如何在不循环数据帧/表组合的情况下执行此操作。文档似乎很清楚,永远不应该这样做。

    for row in df.itertuples():
        if row.Reserve:
            r = row.ID
            p = row.Parent
            Team.update(parent_team = Team.get(Team.name == p)).where(Team.id == r).execute()

1 个答案:

答案 0 :(得分:0)

您可以对数据进行拓扑排序,然后直接将其与父ID一起插入。

至于循环和更新 - 一些想法:

  • 包装在交易中
  • 使用ValuesList()提供id-> parent id的映射并立即更新all
  • 插入ID - >父ID进入临时表并使用临时表(一次性全部)进行更新