110

I have a Django application that reads data from a web API and puts it in a database.
Is there a way to create a new object from a mode but prevent the duplicate exception if the object already exists?

In other words, is there a way to save an object, but to just do nothing if it already exists?

4 Answers 4

206

Model.objects.get_or_create()

4
  • 12
    making it a link to the docs adds some chars (and makes it a better answer i guess)
    – second
    Feb 3, 2013 at 9:39
  • 7
    This seems to make 2 queries. If I only want to save the object in case it doesn't exists, is there a way with only 1 query? I guess catching IntegrityError cause current transaction to abort and is not sufficient. Jan 24, 2015 at 11:13
  • you can catch the integrity error if you add a savepoint, e.g. using transaction.atomic (make sure you catch outside the atomic block, i.e. try: with acomic: create; except IntegrityError. It's also tricky to make sure you don't catch other integrity errors than the one you intend to
    – second
    Nov 27, 2016 at 8:47
  • 1
    If you are able to catch the IntegrityError, my testing shows that it cuts the execution time nearly in half when the record exists compared to get_or_create().
    – Ron
    Sep 2, 2018 at 6:27
52

In Django 1.7, you can also do:

Model.objects.update_or_create()

1
  • 3
    I could really use that over here in 1.6.
    – erewok
    Mar 18, 2014 at 16:50
6

It can be achieved using Model.objects.get_or_create()

Example

obj, created = Person.objects.get_or_create(
    first_name='John',
    last_name='Lennon',
    defaults={'birthday': date(1940, 10, 9)},
)

Any keyword arguments(here first_name and last_name) passed to get_or_create() — except an optional one called defaults — will be used to query in database(find the object) in database.

It returns a tuple, if an object is found, get_or_create() returns a tuple of that object and False.

Note: Same thing can also be achieved using try except statements
Example:

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()
2

Looks like in newer versions of Django the save() function does an UPDATE or INSERT by default. See here.

2
  • looks like it should choose well automatically, however in my db it is currently duplicating entries every time I run my script to populate the db. Aug 12, 2018 at 7:39
  • 2
    the save() method checks if the PK of the model has a value. The Author would have to query the DB in order to get the model instance with the correct PK in order to use this technique. The sole use of save() does not do the magic. Apr 27, 2019 at 9:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.