Optimize your get_or_create blocks

Tue Sep 15, 2009

Was going through a code review, and saw something like this:

def some_function(user_id, bobj_id):
    user = User.objects.get(id=user_id)
    item, created = MyObject.objects.get_or_create(user=user, bobj=bobj)
    return item

But that is two hits to the database we don’t need since the id’s are passed in. Remember, if you have id’s then you can shortcut pulling the object from the ORM like this:

item, created = MyObject.objects.get_or_create(user__id=user_id, bobj__id=bobj_id) That will do the


just fine, but fails when it tries to


with this error:

psycopg2.IntegrityError: null value in column “user_id” violates not-null constraint

You got the error because


does not automatically use the query spec for the default. There’s probably an enhancement filed for that. Remember to send in the defaults explicitly:

item, created = MyObject.objects.get_or_create(user__id=user_id, bobj__id=bobj_id,
                defaults={'user_id':user_id, 'bobj_id':bobj_id})

Be sure you look for that in your api calls where you have mainly ids coming in and not object references.