2015-05-04 1 views
3

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

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 выполнил бы обновление или вставку по мере необходимости.

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

ответ

1

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

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 в одной транзакции.

+0

Следует отметить, что это только ОК для однопользовательских баз данных, потому что это, очевидно, две транзакции. Если вы хотите правильно реплицировать upsert, чтобы правильно обрабатывать параллелизм, вы должны использовать необработанные запросы http://peewee.readthedocs.org/en/latest/peewee/querying.html?highlight=upsert#sql-functions-subqueries -and-raw-expressions –

+0

избежать использования sqlite в многопользовательских настройках – axd

5
+0

Это не работает для меня. Он выдает ошибку, когда первичный ключ существует, как и 'Person.create()'. Кажется, это эквивалентно 'Person.create()'. –

+0

Все анекдоты предназначались: funniest invocation, которые я видел на этой неделе. HA. Я бы не хотел быть тем «Человеческим» объектом! –

+0

Нелогично «ненавидеть» мистера Спок: P – Shayne