Create or get
Peewee has one helper method for performing “get/create” type operations: Model.get_or_create()
, which first attempts to retrieve the matching row. Failing that, a new row will be created.
For “create or get” type logic, typically one would rely on a unique constraint or primary key to prevent the creation of duplicate objects. As an example, let’s say we wish to implement registering a new user account using the example User model. The User model has a unique constraint on the username field, so we will rely on the database’s integrity guarantees to ensure we don’t end up with duplicate usernames:
try:
with db.atomic():
return User.create(username=username)
except peewee.IntegrityError:
# `username` is a unique column, so this username already exists,
# making it safe to call .get().
return User.get(User.username == username)
You can easily encapsulate this type of logic as a classmethod
on your own Model
classes.
The above example first attempts at creation, then falls back to retrieval, relying on the database to enforce a unique constraint. If you prefer to attempt to retrieve the record first, you can use get_or_create()
. This method is implemented along the same lines as the Django function of the same name. You can use the Django-style keyword argument filters to specify your WHERE
conditions. The function returns a 2-tuple containing the instance and a boolean value indicating if the object was created.
Here is how you might implement user account creation using get_or_create()
:
user, created = User.get_or_create(username=username)
Suppose we have a different model Person
and would like to get or create a person object. The only conditions we care about when retrieving the Person
are their first and last names, but if we end up needing to create a new record, we will also specify their date-of-birth and favorite color:
person, created = Person.get_or_create(
first_name=first_name,
last_name=last_name,
defaults={'dob': dob, 'favorite_color': 'green'})
Any keyword argument passed to get_or_create()
will be used in the get()
portion of the logic, except for the defaults
dictionary, which will be used to populate values on newly-created instances.
For more details read the documentation for Model.get_or_create()
.