Home > Blockchain >  Django - Replace model fields values before save
Django - Replace model fields values before save

Time:11-15

Just to note: I know about overwriting Model's .save() method but it won't suit me as I explained it at the end of my question.

In one of my projects, I've got more than of 30 database Models and each one of these models accept multiple CharField to store store Persian characters; However there might be some case where users are using Arabic layouts for their keyboard where some chars are differ from Persian.

For example:

The name Ali in Arabic: علي
and in Persian: علی

Or even in numbers:

345 in Arabic: ٣٤٥
And in Persian: ۳۴۵

I need to selectively, choose a set of these fields and run a function on their value before saving them (On create or update) to map these characters so I won't end up with two different form of a single word in my database.

One way to do this is overwriting the .save() method on the database Model. Is there any other way to do this so I don't have to change all my models?

CodePudding user response:

Sounds like a good use of Django's Signals. With Signals you can call a function before or after save on one or more Models.

https://docs.djangoproject.com/en/3.2/topics/signals/

Django includes a “signal dispatcher” which helps decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events.

django.db.models.signals.pre_save & django.db.models.signals.post_save

Sent before or after a model’s save() method is called.

https://docs.djangoproject.com/en/3.2/ref/signals/#pre-save

pre_save

django.db.models.signals.pre_save This is sent at the beginning of a model’s save() method.

Arguments sent with this signal:

sender The model class.

instance The actual instance being saved.

raw A boolean; True if the model is saved exactly as presented (i.e. when loading a fixture). One should not query/modify other records in the database as the database might not be in a consistent state yet. using The database alias being used.

update_fields The set of fields to update as passed to Model.save(), or None if update_fields wasn’t passed to save().

You can connect signals to a Single, Multiple, or All models in your application.

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel

@receiver(pre_save)
def my_handler(sender, instance, **kwargs):
    # logic here

In this case sender is the Model that is about to be saved, instance will be the object being saved.

CodePudding user response:

You can create a completely custom model field however in your case it's really easier to just customize Django's CharField:

class MyCharField(models.CharField):
    def to_python(self, value):
        if isinstance(value, str) or value is None:
            return self.func_to_call(value)
        return self.func_to_call(str(value))

Replace your models CharField with MyCharField.

And create the .func_to_call() so it does whatever you need to map the values:

def func_to_call(self, value):
    # Do whatever you want to map the values
    return value
  • Related