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)
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.
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)
In case when you are using the UUID field instead of the default ID field, check self.pk field is a terrible idea because UUID is assigned as default before we go to the save method. Well, how to resolve it? The simplest and fastest solution is self._state.adding instead of self.pk
I hope you noticed an underscore before the "state" word, but don't worry, this method is completely legal and we do not call here a private variable.
Example:
def save(self, *args, **kwargs):
if self._state.adding: # will return true if obcject is newly created
# Object is a new instance
return super(Model, self).save(*args, **kwargs)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.