Python peewee save() не работает должным образом

Я вставляю/обновляю объекты в базу данных MySQL, используя peewee ORM для Python . У меня есть такая модель:

class Person(Model):
    person_id = CharField(primary_key=True)
    name = CharField()

Я создаю объекты/строки с помощью цикла, и каждый раз в цикле есть словарь, например:

pd = {"name":"Alice","person_id":"A123456"}

Затем я пытаюсь создать объект и сохранить его.

po = Person()
for key,value in pd.items():
    setattr(po,key,value)
po.save()

Это занимает некоторое время для выполнения и выполняется без ошибок, но ничего не сохраняется в базе данных — записи не создаются.

Это работает:

Person.create(**pd)

Но также выдает ошибку (и завершает работу скрипта), когда первичный ключ уже существует. Прочитав руководство, я подумал, что функция save() Мне нужно было, чтобы эта крошка выполнила обновление или вставку по мере необходимости.

Не уверен, что мне нужно сделать здесь - попробовать сначала получить каждую запись? Отловить ошибки и попробовать обновить запись, если она не может быть создана? Я новичок в peewee и обычно пишу просто INSERT ... ON DUPLICATE KEY UPDATE или даже REPLACE.


person Martin Burch    schedule 04.05.2015    source источник


Ответы (3)


Person.save(force_insert=True)

Это задокументировано: http://docs.peewee-orm.com/en/latest/peewee/models.html#non-integer-primary-keys-composite-keys-and-other-tricks

person coleifer    schedule 04.05.2015
comment
Это не работает для меня. Он выдает ошибку, когда первичный ключ существует, как и Person.create(). Кажется, это эквивалентно Person.create(). - person Martin Burch; 14.05.2015
comment
Все предназначено для шуток: самый смешной вызов функции, который я видел на этой неделе. ХА. Я бы не хотел быть этим Person объектом! - person Mr_Spock; 14.05.2015
comment
Не логично ненавидеть мистера Спока :P - person Shayne; 28.01.2016

У меня была возможность повторно проверить свой ответ, и я думаю, что его следует заменить. Вот шаблон, который я могу сейчас порекомендовать; во-первых, используйте get_or_create() для модели, которая создаст строку базы данных, если она не существует. Затем, если он не создан (вместо этого объект извлекается из БД), установите все атрибуты из словаря данных и сохраните объект.

po, created = Person.get_or_create(person_id=pd["person_id"],defaults=pd)
if created is False:
    for key in pd:
        setattr(fa,key,pd[key])
    po.save()

Как и раньше, я должен упомянуть, что это две разные транзакции, поэтому это не следует использовать с многопользовательскими базами данных, требующими истинного upsert в одной транзакции.

person Martin Burch    schedule 14.05.2015
comment
Следует отметить, что это нормально только для однопользовательских баз данных, потому что это явно две транзакции. Если вы хотите правильно реплицировать upsert таким образом, чтобы он правильно обрабатывал параллелизм, вы должны использовать необработанные запросы peewee.readthedocs.org/en/latest/peewee/ - person Martin Burch; 14.05.2015
comment
избегайте sqlite в многопользовательских настройках - person axd; 09.03.2016

Я думаю, вы могли бы попробовать get_or_create()? http://peewee.readthedocs.org/en/latest/peewee/querying.html#get-or-create

person Jeremy Bowers    schedule 04.05.2015