Peewee - обновить проблему с записями с ForeignKeyField ('self') - PullRequest
0 голосов
/ 01 мая 2018

У меня есть база данных, которую я заполняю из 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 голосов
/ 01 мая 2018

Вы можете выполнить топографическую сортировку данных и затем вставить их непосредственно с родительскими идентификаторами.

Что касается циклов и обновлений - некоторые идеи:

  • Завершение транзакции
  • используйте ValuesList (), чтобы обеспечить отображение id-> родительского идентификатора и обновлять все сразу
  • вставка идентификатора -> родительского идентификатора во временную таблицу и обновление с использованием временной таблицы (все сразу)
...