我是Python和Django的新手。
我希望我的模型具有范围验证的浮点数。我从this answer写到:
class FloatRangeField (FloatField):
"""A FloatField constrained to a given range."""
def __init__ (self, minimum, maximum, **kwargs):
minmax = [MinValueValidator (minimum), MaxValueValidator (maximum)]
print ("\n\t\tFloatRangeField({},{})".format(minimum,maximum)) # (A)
FloatField.__init__ (self, validators = minmax, **kwargs)
print ("\t\tFINISHED\n")
这在python3 manage.py migrate
中引起错误,我将其范围缩小到clone()
调用。演示:
print ("HERE 1")
tmp1 = FloatRangeField (10, 20)
print ("HERE 2")
tmp2 = FloatRangeField (10, 20)
print ("HERE 3")
tmp3 = tmp1.clone () # (B)
print ("HERE 4")
它从第# (B)
行引发异常。奇怪的是,发生这种情况时, not 行# (A)
上的迹线未打印。输出如下:
HERE 1
FloatRangeField(10,20)
FINISHED
HERE 2
FloatRangeField(10,20)
FINISHED
HERE 3
Traceback (most recent call last):
File "manage.py", line 15, in <module>
execute_from_command_line(sys.argv)
File "/usr/local/lib/python3.5/dist-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
utility.execute()
[...snip...]
tmp3 = tmp1.clone ()
File "/usr/local/lib/python3.5/dist-packages/django/db/models/fields/__init__.py", line 470, in clone
return self.__class__(*args, **kwargs)
TypeError: __init__() missing 2 required positional arguments: 'minimum' and 'maximum'
# (A)
上什么都没打印出来,这与我在migrate
期间看到的错误不相同。如果我取出tmp1=...
的东西并运行migrate
,则回溯看起来像这样
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/django/db/migrations/state.py", line 411, in from_model
fields.append((name, field.clone()))
File "/usr/local/lib/python3.5/dist-packages/django/db/models/fields/__init__.py", line 470, in clone
return self.__class__(*args, **kwargs)
[...snip...]
FloatField.__init__ (self, validators = minmax, **kwargs)
TypeError: __init__() got multiple values for keyword argument 'validators'
为什么会这样?为什么我应该实现FloatRangeField
以便封装具有最小/最大验证器的子包?
答案 0 :(得分:2)
像写在documentation on custom model fields中一样:
如果添加新的关键字参数,则需要编写代码以自己将其值放入
kwargs
中(...)
因此,您还应该添加一个解构函数。这是必需的,例如在迁移文件中表示此字段:
class FloatRangeField (FloatField):
"""A FloatField constrained to a given range."""
def __init__ (self, minimum, maximum, **kwargs):
self.minimum = minimum
self.maximum = maximum
minmax = [MinValueValidator (minimum), MaxValueValidator (maximum)]
FloatField.__init__ (self, validators = minmax, **kwargs)
def deconstruct(self):
result = __, __, __, kwargs = super(FloatRangeField, self).deconstruct()
kwargs['minimum'] = self.minimum
kwargs['minimum'] = self.maximum
del kwargs['validators']
return result
请注意,最好不要使用validators = minmax
作为参数,因为这意味着如果用户将validator
的构造函数使用FloatRangeField
参数,则会发生参数冲突
例如,可以将我们的minmax
验证器追加到已经存在的验证器中,然后在我们想对其进行解构时将它们从验证器中弹出:
class FloatRangeField (FloatField):
"""A FloatField constrained to a given range."""
def __init__ (self, minimum, maximum, **kwargs):
self.minimum = minimum
self.maximum = maximum
old_validators = kwargs.get('validators', [])
minmax = [MinValueValidator (minimum), MaxValueValidator (maximum)]
kwargs['validators'] = minmax + old_validators
FloatField.__init__ (self, **kwargs)
def deconstruct(self):
result = __, __, __, kwargs = super(FloatRangeField, self).deconstruct()
kwargs['minimum'] = self.minimum
kwargs['minimum'] = self.maximum
kwargs['validators'] = kwargs['validators'][2:]
return result
因此在这里,我们在deconstruct(..)
函数中,删除了前两个验证器(在__init__(..)
函数中添加的验证器)。