我试图在达詹戈确定一个习俗领域,我希望用一个助手来开始。 外地班级接受助手的直径,并在内部储存。 想这样做:
# define helper class
class Foo:
# ...
# instance of helper class
myFoo = Foo()
# model with field accepting helper class
class MyModel(models.Model):
foo = FooManagedField(foo=myFoo)
This seems to me like a pretty reasonable thing to do.
But in practice, it completely breaks migration tooling.
我看到的是: 一旦任何模型都利用了这个领域,Django就认为它总是处于变化状态(我假定它不考虑不同的物体)。 因此,它登记的变化总是需要新的移民。
Is there any way to solve this, any way to indicate that the definition is consistent? Or is it a blanket restriction that a custom field can only be initialized with primitives?
Or maybe there s a reason I m not seeing that passing object instances into a custom Field implementation is a bad idea and I shouldn t want to do it?
Walkthrough and Detail
I m 界定一个简单的习俗Django领域如下:
class FooManagedField(CharField):
def __init__(self, foo : Foo, *args, **kwargs) -> None:
self.foo : Foo = foo
super().__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
kwargs["foo"]=self.foo
return name, path, args, kwargs
<代码>Foo为简单目标,例如:
class Foo:
def __init__(self, n):
self.n=n
def __repr__(self):
return f"Foo({self.n})"
现在,我把这一新的领域添加到一种模式中(为支持移徙提供书面支持类别<代码>FooSerializer——以下支持代码):
from django.db import models
from .utils.foo_field import Foo, FooManagedField
fooA = Foo(1)
fooB = Foo(2)
class MyModel(models.Model):
n1 = models.IntegerField() # preexisting field
n2 = models.IntegerField() # preexisting field
foo1 = FooManagedField(foo=fooA) # new FooManagedField
foo2 = FooManagedField(foo=fooB) # new FooManagedField
运行<条码> 移民条码>按预期会产生移民档案:
operations = [
migrations.AddField(
model_name= mymodel ,
name= foo1 ,
field=myproject.utils.foo_field.FooManagedField(foo=Foo(1)),
),
migrations.AddField(
model_name= mymodel ,
name= foo2 ,
field=myproject.utils.foo_field.FooManagedField(foo=Foo(2)),
),
]
但随后,运行<条码>,再制作
operations = [
migrations.AlterField(
model_name= mymodel ,
name= foo1 ,
field=myproject.utils.foo_field.FooManagedField(foo=Foo(1)),
),
migrations.AlterField(
model_name= mymodel ,
name= foo2 ,
field=myproject.utils.foo_field.FooManagedField(foo=Foo(2)),
),
]
Question
这在Django是否是一种硬性限制? 是否有办法提供同我一样的阶级?
而且,我是否希望从这一建筑开始,这是我在法典设计中犯错误的标志吗? 我以错误的方式来到这里——难道不宜把一些可改观的逻辑归纳为界定实地的助手类别?
References
- Infinite AlterField Migrations due to default callable object mismatch is an existing ticket which helped me figure out what the immediate issue was (though I m still missing the rationale and a workaround, or else to understand why this shouldn t be worked around)
non_db_attrs
is a relatively new property which lets you mark "attributes of a field that don’t affect a column definition". Is this helpful in any way to this situation? I tried adding this and saw no improvement, but maybe I misunderstood usage.
Supporting code
Foo序列izer(参考here):
from django.db.migrations.serializer import BaseSerializer
from django.db.migrations.writer import MigrationWriter
class FooSerializer(BaseSerializer):
def serialize(self):
return repr(self.value), {"from myproject.utils.foo_field import Foo"}
MigrationWriter.register_serializer(Foo, FooSerializer)