В процесс фикса одного бага выяснилась интересная вещь, хочу вот поделиться...
Как написано
В
официальной документации написано, что если вдруг захочется создать кастомное поле, необходимо сделать следующие шаги:
1) создать класс
CustomObject(object), представляющего значение этого поля
2) создать класс поля
CustomField(django.db.models.Field)
3) определить в классе поля метод
to_python(), который из значения, полученного из БД или из пользовательского ввода, конструирует тот самый
CustomObject
4) определить в классе поля метод
get_prep_value(), противоположный по функции методу
to_python()
И все, но этого мало.
Как надо
Во-первых,
CustomField может получить на вход to_python строковое представление объекта
CustomObject, т.е. результат вызова
CustomObject.__unicode__() - который, по умолчанию, выведет только полное имя типа объекта.
Во-вторых, django при попытке сохранения модели проверяет, изменились ли значения ее полей. На практике, происходит сжатие методом
zip значения этого поля (
мы еще помним, что значением CustomField является CustomObject?). Метод
zip требует наличия у сжимаемого объекта
итератора, в придачу к которому нужен еще и метод
len().
Ну и факультативно...
Если итератор для объекта "ходит" по его текстовому представлению, то стоит его закэшировать и обновлять при изменении полей
CustomObject, участвующих в создании текстового представления. Для этого поля объекта превращаем в
свойства, в сеттерах которых выполняем обновление текстового представления.