Python peewee save() doesn't work as expected

Question:

I’m inserting/updating objects into a MySQL database using the peewee ORM for Python. I have a model like this:

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

I create the objects/rows with a loop, and each time through the loop have a dictionary like:

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

Then I try creating an object and saving it.

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

This takes a while to execute, and runs without errors, but it doesn’t save anything to the database — no records are created.

This works:

Person.create(**pd)

But also throws an error (and terminates the script) when the primary key already exists. From reading the manual, I thought save() was the function I needed — that peewee would perform the update or insert as required.

Not sure what I need to do here — try getting each record first? Catch errors and try updating a record if it can’t be created? I’m new to peewee, and would normally just write INSERT ... ON DUPLICATE KEY UPDATE or even REPLACE.

Asked By: Martin Burch

||

Answers:

I’ve had a chance to re-test my answer, and I think it should be replaced. Here’s the pattern I can now recommend; first, use get_or_create() on the model, which will create the database row if it doesn’t exist. Then, if it is not created (object is retrieved from db instead), set all the attributes from the data dictionary and save the object.

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

As before, I should mention that these are two distinct transactions, so this should not be used with multi-user databases requiring a true upsert in one transaction.

Answered By: Martin Burch

You may do something like:

po = Person()
for key,value in pd.items():
    setattr(po,key,value)
updated = po.save()
if not updated:
    po.save(force_insert=True)
Answered By: David Lador
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.