Harry
Harry

Reputation: 13329

Django admin model save - Update existing object

This seems really simple.

On my model save() I want to basically do a get_or_create(). So I want to update the model if it exists or create a new one if not.

This seems like a super simple problem, but I am not getting it right!

class StockLevel(models.Model):
    stock_item = models.ForeignKey(StockItem)
    current_stock_level = models.IntegerField(blank=True, default=0)

    def save(self):
        try:
            # it exists
            a = StockLevel.objects.get(stock_item=self.stock_item)
            a.current_stock_level = self.current_stock_level
            a.save()

        except:
            # is does not exist yet
            # save as normaly would.
            super(StockLevel, self).save()

OR

def save(self):
    stock_level_item , created = StockLevel.objects.get_or_create(stock_item=self.stock_item)
    stock_level_item.current_stock_level = self.current_stock_level
    stock_level_item.save()

This would also go into a infinite loop.

This would just put the save() in an infinite loop. But that is the basic idea of how it should work.

Upvotes: 1

Views: 4963

Answers (3)

So this is how i solved a similar situation just yesterday, I created a duplicate model to store the updated information.

let's call the new model "StockLevelUpdates".

I then used signals to insert the saved data from the original model.

I will use your model above as the original model to explain further.

class StockLevelUpdates(models.Model):
    stock_item = models.ForeignKey(StockItem)
    current_stock_level = models.IntegerField(blank=True, default=0)

@receiver(signals.post_save, sender=StockLevel)
def update_info(sender, instance, **kwargs):

    try:
        # if it exists
        a = StockLevelUpdates.objects.get(stock_item=instance.stock_item)
        a.current_stock_level = instance.current_stock_level
        a.save()

    except:
        # if it does not exist yet
        # save the new instance
        obj = StockLevelUpdates(stock_item=instance.stock_item,
                                current_stock_level = instance.current_stock_level)
        obj.save()  

This worked well for me, and you can get all your update reports from the duplicate model.

Perhaps there is a better way to do this kind of thing but this was a quick way out of a sticky situation.

Upvotes: 0

gagamil
gagamil

Reputation: 119

Django uses the same save() method for both creating and updating the object. User code doesn't need to determine whether to create or update the object, since this is done by the method itself.

Furthermore you can force the save() method to create or update the object by using the methods optional arguments.

This is covered in the Django docs.

Upvotes: 5

Daniel Roseman
Daniel Roseman

Reputation: 600041

This really doesn't sound like the best way to do this. The save method is meant for saving the current instance, not magically querying for an existing one. You should take care of this in the form or view code.

Upvotes: 1

Related Questions