Juanvulcano
Juanvulcano

Reputation: 1396

Django - Create object if field not in database

I want to create an object only if there's no other object with the same ID already in the database. The code below would create the same item if one the parameters below like the State was modified.

returns = Return.objects.all()
for ret in returns:
    obj, created = Return.objects.get_or_create(ItemID="UUID", 
                          ItemName="Hodaddy", State="Started")
    obj.save()

Upvotes: 0

Views: 936

Answers (3)

neomanic
neomanic

Reputation: 366

get_or_create works off all the arguments provided to find the object.

What you need to do instead is use the special defaults argument to provide the new value for a field that you don't want to filter on.

In your case, you only want the UUID field to be unique, and so you provide the other two members as defaults.

obj, created = Return.objects.get_or_create(ItemID="UUID", 
               defaults={ItemName:"Hodaddy", State:"Started"})

Then you can make further decisions based on the value of created. I am not sure why you're iterating over all the Returns in the original question?

Upvotes: 2

gallen
gallen

Reputation: 1292

If you know the id, you can query for it:

In your question, you have:

returns = Return.objects.all()
for ret in returns:
   return_in_database = Return.objects.filter(ItemId="UUID").exists()
   if not return_in_database:
       obj, created = Return.objects.get_or_create(ItemID="UUID", 
                      ItemName="Hodaddy", State="Started")
       obj.save() 

This can be done as:

if not Return.objects.filter(ItemId="UUID").exists():
    obj, created = Return.objects.get_or_create(ItemID="UUID", 
                      ItemName="Hodaddy", State="Started")
    obj.save()

As you can see, I've removed the for loop, as you were not using the variable ret anywhere, so no need to iterate over all Return objects. The above is functionally equivalent to what you had. :)

OR:

You can write your own manager with a create_or_update method inside your models.py

class ReturnManager(models.Manager): 
    def create_or_update(self, **kwargs):
        new_return = Return(**kwargs)
        existing = Return.objects.filter(ItemId=new_returns.ItemID).first()
        if existing:
            new_return.pk  = existing.pk
            new_return.id = existing.id
        new_return.save()
        return new_return

You would then assign this to your Return model

class Return(model.Models):
    # your object fields here

    objects = ReturnManager()

Upvotes: 2

Raunak Agarwal
Raunak Agarwal

Reputation: 7228

You need to change the param in the query, to just constraint the object lookup on ItemID. Once, a new object is returned you can update the ItemName and State

obj, created = Return.objects.get_or_create(ItemID="UUID")
if created:
    obj.ItemName="<item-name>"
    obj.State="<Started>"
    obj.save()

Upvotes: 1

Related Questions