update_or_create only if filed is empty

Hi All,

Do you know if it is possible to update an object with field data but only if the field value is Null or None ?
The goal is NOT erase data ever set in this field with another one
For example :
obj, created = Person.objects.update_or_create( first_name='John', last_name='Lennon', defaults={ 'first_name': 'Bob'. #IF first_name is None or first_name is Null }, )

One idea is to merge both data but it is not very cool no ?
For example :
obj, created = Person.objects.update_or_create( first_name='John', last_name='Lennon', defaults={ 'first_name': first_name + 'Bob' }, )

Thanks for your help


Yes, it is possible.

Precisely how you would do this depends upon the circumstances of when you want to do this.
Do you want this:

  • To always be the case?
  • Only when certain forms are submitted?
  • Only in particular views?
  • Only in the admin? (Only when not in the admin?)

Each one of those cases are likely to lead you toward different solutions.

Hi Ken,

Thanks for your help.
I think in my case, the best choice is number 3 : In particular view for a a specific object

To be clear (I hope), in a views, there is a fonction and when this function is called, it take a json file and update or create the object. This is in this case that I want to do this test, append, merge …

I don’t see where there’s going to be a particularly “clean” way of doing this while using the update_or_create, because you want to check the existing values of the object before changing their values with the submitted JSON object - but there isn’t a “current object” if this is going to be a create.

If I were handling this, I’d break this down into two parts. One for the create case and one for the update case. The create is easy - build the object from the submitted JSON.
For the update, you’ll need to retrieve the existing object and assign the fields based on the value in that existing object.

If you have a Person object named a_person, you can do something like:
a_person.first_name = a_person.first_name or json_data['first_name']
(repeated for each field).

Or, if the thought of assigning a value to itself bothers your esthetically, you could write:
if not a_person.first_name: a_person.first_name = json_data['first_name']

(This is just a starting point. It can get a lot more intricate than that depending upon the number and types of fields involved and the number of fields supplied in the json object being used to update this.)

Thanks Ken, it is working find.
I was loooking for a solution with update_or_create but yours is really good :wink: