Django - Замена значений полей модели перед сохранением

На заметку: Я знаю о перезаписи метода Model's .save(), но мне это не подходит, как я объяснил в конце своего вопроса.

В одном из моих проектов у меня есть более 30 моделей баз данных, и каждая из этих моделей принимает несколько CharField для хранения персидских символов; однако могут быть случаи, когда пользователи используют арабские раскладки клавиатуры, где некоторые символы отличаются от персидских

Например:

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

Или даже в цифрах:

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

Мне нужно выборочно, выбрать набор этих полей и запустить функцию на их значении перед сохранением (при создании или обновлении), чтобы сопоставить эти символы, чтобы в итоге не получить две разные формы одного слова в моей базе данных.

Один из способов сделать это - перезаписать метод .save() в модели базы данных. Есть ли другой способ сделать это, чтобы мне не пришлось изменять все мои модели?

Звучит как хорошее использование Сигналов Django. С помощью сигналов вы можете вызвать функцию до или после сохранения одной или нескольких моделей.

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

Django включает в себя "диспетчер сигналов", который помогает разделенным приложениям получать уведомления о действиях, происходящих в других частях фреймворка. В двух словах, сигналы позволяют определенным отправителям уведомлять набор получателей о том, что произошло какое-то действие. Они особенно полезны, когда многие части кода могут быть заинтересованы в одних и тех же событиях.

.

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

.

Отправляется до или после вызова метода save() модели.

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

pre_save

django.db.models.signals.pre_save Этот сигнал отправляется в начале метода сохранения модели save().

Аргументы, отправляемые с этим сигналом:

отправитель Класс модели.

instance Фактический сохраняемый экземпляр.

raw Булево; True, если модель сохраняется именно в том виде, в котором она представлена (т.е. при загрузке фикстуры). Не следует запрашивать/изменять другие записи в базе данных, так как база данных может быть еще не в согласованном состоянии. использование Используемый псевдоним базы данных.

.

update_fields Набор полей для обновления, переданный в Model.save(), или None, если update_fields не был передан в save().

.

Вы можете подключить сигналы к одной, нескольким или всем моделям в вашем приложении.

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

В данном случае sender - это Модель, которая будет сохранена, instance - сохраняемый объект.

Вы можете создать полностью настраиваемое поле модели, однако в вашем случае действительно проще просто настроить CharField в Django:

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))

Замените ваши модели CharField на MyCharField.

И создайте .func_to_call() так, чтобы он делал все, что вам нужно для отображения значений:

def func_to_call(self, value):
    # Do whatever you want to map the values
    return value
Вернуться на верх