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