Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Override model save()

In our project we use soft delete (is_deleted attribute on a model). Before creating a new model I want to first check if it was already exist and deleted and if so - set is_deleted=False and save the already exists model. So I decided to override the model 'save' method. (not the View Create since it should work not only for requests) The problem is that 'save()' is called for all actions (create, update, delete). Is there a way I can call the overridden method only on create?

class Model(BaseModel):
    title = models.CharField(max_length=200)
    identifier = models.CharField(max_length=15)

    def save(self, *args, **kwargs):
        try:                                               
            existing_model = Model.objects.active_and_deleted().get(                                                        identifier=self.identifier)

            if self.is_deleted is False:
                existing_model.is_deleted = False
                existing_model.title = self.title
                existing_model.created_at = self.created_at
                existing_model.updated_at = self.updated_at
                existing_model.created_by = self.created_by
                existing_model.deleted_at = None
                super(Model, existing_model).save(args, kwargs)
        except Model.DoesNotExist:
            # in case the Nodel wasn't already exist - continue
            pass
        super(Model, self).save(*args, **kwargs)
like image 789
user2880391 Avatar asked Apr 26 '18 19:04

user2880391


2 Answers

The answer to your question, "Is there a way I can call the overridden method only on create?" is this:

    def save(self, *args, **kwargs):

        if not self.id:
            # Object is a new instance

        return super(Model, self).save(*args, **kwargs)

But there are other issues here. Your model shouldn't be named "Model", for example.

like image 87
Rob L Avatar answered Oct 18 '22 18:10

Rob L


Check whether self.pk is None or not could do what you want, here is an example:

class ModelName(mdoels.Model):
    title = models.CharField(max_length=200)
    identifier = models.CharField(max_length=15)

    def save(self, *args, **kwargs):
        if self.pk is None:  # Adding of a new instance
            # let's say we compare instances by `title`
            # you can use other fields for the comparison
            possible_old_instance = Model.objects.filter(title__iexact=self.title)                                            
            if possible_old_instance.exists():
                existing_model = possible_old_instance.first()
                existing_model.is_deleted = False
                existing_model.title = self.title
                existing_model.created_at = self.created_at
                existing_model.updated_at = self.updated_at
                existing_model.created_by = self.created_by
                existing_model.deleted_at = None
                existing_model.save()
                # Nothing happens, we don't call save() method
            else:
                # in case the Model doesn't exist
                super(ModelName, self).save(*args, **kwargs)
        else:
            super(ModelName, self).save(*args, **kwargs)
like image 2
Lemayzeur Avatar answered Oct 18 '22 19:10

Lemayzeur