Explain Codes LogoExplain Codes Logo

How to use "get_or_create()" in Django?

python
django
get_or_create
tuple
Alex KataevbyAlex Kataev·Oct 6, 2024
TLDR

get_or_create() is a "two birds with one stone" method in Django. It budgetly fetches an existing entry from your Django model, or elbows a new one if none matches. Back to you comes a tuple, (object, created), where object is your requested model instance and created is a cheeky flag winking if it had to create this instance (True) or if it already existed (False).

Imagine you're dealing with a Book model. Here's a succinct example:

from myapp.models import Book # Look ma, no duplicates! book, created = Book.objects.get_or_create(title='Efficient Django', defaults={'author': 'E. Developer'})

If a Book titled "Efficient Django" exists, book becomes that instance and created puts on a False face; if not, a new one is conjured with 'E. Developer' as author, and created shows its True colors.

Tuple return handling: Unwrap the gift carefully

Remember the comeback of the tuple in get_or_create()? Where object, created = Model.objects.get_or_create() is akin to opening a Christmas gift. If you ignore the wrapping (read: forget to unpack your tuple), you'll be stuck squinting at a mysterious box, instead of enjoying your brand spanking new object or created.

Default dict: It's not just another dictionary

The defaults dictionary is the excuse-free zone for non-unique fields. The fields defining uniqueness are VIPs—they stay outside of defaults. This helps prevent embarrassing blunders, like duplicate entries:

# Put non-unique fields in the corner object, created = Model.objects.get_or_create( unique_field='unique_value', defaults={'other_field': 'value'} )

Boolean blues: Ignoring can be bliss

You know the created flag from the get_or_create() method? If its fate doesn't affect your day, you can make like an ostrich, and stick the underscore _ in the sand:

# Some days, you just don't care if it was created or not object, _ = Model.objects.get_or_create(...)

Foreign Keys: Attach with care

Foreign keys and get_or_create() are like that couple from high school — when they're good, they're luminous. When they're bad, it's a hot mess. Assign the object — not the entire tuple — to the foreign key field:

# Fail to do this, and Django will give you the silent treatment customer.source, _ = Source.objects.get_or_create(...)

Special handling of existing objects: No one left behind

If you could care less about whether or not the object was created but JUST want that object, then you can skip the line and grab it directly:

# Don't unpack, just grab and go! result = Model.objects.get_or_create(...) object = result[0] # YOLO - object loaded!

A deep-dive into "get_or_create()"

get_or_create() has its share of quirks and delights. Let's explore a few:

Handling complexity (and headaches)

Complex queries with Q and F objects can spell trouble for get_or_create(). Wrap calls with try-except blocks to catch Exceptions:

# When get_or_create() starts playing hard to get try: obj = Model.objects.get_or_create(...) except Model.MultipleObjectsReturned: # So many objects, so little time

Getting defaults from a form

When using a form, you can pass the cleaned data from the form straight into the defaults:

# Take user input, make a sandwich, feed it to model form = MyModelForm(request.POST) if form.is_valid(): object, created = Model.objects.get_or_create(defaults=form.cleaned_data)