Если честно, я бы просто разделил комплексное число на два поля с плавающей запятой / десятичное поле и добавил свойство для чтения и записи в виде одного комплексного числа.
Я придумал это настраиваемое поле, которое заканчивается как поле разделения на фактической модели и также вводит вышеупомянутое свойство.
contribute_to_class
называется глубоко в механизме модели Джанго для всех полей, которые объявлены в модели. Как правило, они могут просто добавить само поле в модель и, возможно, дополнительные методы, такие как get_latest_by_...
, но здесь мы угоняем этот механизм, чтобы вместо этого добавить два поля, в которых мы строим, а не само поле «себя» вообще , поскольку он не должен существовать как столбец базы данных. (Это может что-то сломать, кто знает ...) Часть этого механизма объясняется здесь в вики Django.
Класс ComplexProperty
является дескриптором свойства , который позволяет настраивать то, что происходит, когда свойство, к которому он «присоединен», обращается к экземпляру (осуществляется чтение или запись). (То, как работают дескрипторы, немного выходит за рамки этого ответа, но в документации по Python есть руководство .)
NB: я сделал не проверяйте это за пределами бегущих миграций, так что все может сломаться неожиданным образом, но, по крайней мере, теория обоснована. :)
from django.db import models
class ComplexField(models.Field):
def __init__(self, **kwargs):
self.field_class = kwargs.pop('field_class', models.FloatField)
self.field_kwargs = kwargs.pop('field_kwargs', {})
super().__init__(**kwargs)
def contribute_to_class(self, cls, name, private_only=False):
for field in (
self.field_class(name=name + '_real', **self.field_kwargs),
self.field_class(name=name + '_imag', **self.field_kwargs),
):
field.contribute_to_class(cls, field.name)
setattr(cls, name, ComplexProperty(name))
class ComplexProperty:
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
if not instance:
return self
real = getattr(instance, self.name + '_real')
imag = getattr(instance, self.name + '_imag')
return complex(real, imag)
def __set__(self, instance, value: complex):
setattr(instance, self.name + '_real', value.real)
setattr(instance, self.name + '_imag', value.imag)
class Test(models.Model):
num1 = ComplexField()
num2 = ComplexField()
num3 = ComplexField()
Миграция для этого выглядит как
migrations.CreateModel(
name="Test",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("num1_real", models.FloatField()),
("num1_imag", models.FloatField()),
("num2_real", models.FloatField()),
("num2_imag", models.FloatField()),
("num3_real", models.FloatField()),
("num3_imag", models.FloatField()),
],
)
, так что, как вы можете видеть, три ComplexField
разбиты на шесть FloatField
с. [1119 ]
Почему не может Вы твердый код версия в postinst сценарий в упаковочное время?