构建 Django form/class 方法的正确方法
Proper way to build Django form/class method
我有一个 Django 表单 (Django non-rel v1.5.5),其中的 form/class 方法运行良好。但是,现在我已经开始为应用程序构建单元测试,我在测试 form/class 方法时遇到了问题。我假设 form/class 方法定义不正确。
forms.py
class TimeForm(forms.Form):
def build_choices(start, stop, incr=1):
# Form/class method that builds a list of tuples of identical i, i values for forms.ChoiceField
choice_list = []
temp_list = [i for i in range(start, stop, incr)]
for i in temp_list:
choice_list.append(('%02d' % i, '%02d' % i))
return choice_list
hour_choices = build_choices(1, 13) # E.g., [('01', '01'), ('02', '02') ... ]
minute_choices = build_choices(0, 60, 15)
hour = forms.ChoiceField(choices=hour_choices)
minute = forms.ChoiceField(choices=minute_choices)
上面的代码可以很好地生成表单,并为表单字段提供正确的选择。但是,当我尝试对 build_choices
方法进行单元测试时,我碰壁了。
一些测试
"""Testing the build_choices method."""
> form = TimeForm()
> form.build_choices(1, 10) # This will not work.
> *** TypeError: range() integer start argument expected, got TimeForm.
>
> TimeForm.build_choices(1, 10) # This will not work.
> *** TypeError: unbound method build_choices() must be called with TimeForm instance as first argument (got int instance instead)
>
> TimeForm.build_choices(form, 1, 10)
> *** TypeError: range() integer start argument expected, got TimeForm.
然而,
> TimeForm.hour_choices
> [('01', '01'), ('02', '02') ... ]
是否有更好的 way/proper 方法来定义不是实例方法的表单方法?例如,TimeForm(self, start, end, inc)
.
这是一些奇怪的设置。您有一个 class 方法,它会作为普通函数立即调用,直到 class 完成初始化。
我不是一个高深的 python 向导,但看起来功能仅在 class 设置后才转换为 class 方法。
底线:TimeForm.build_choices
是一种 class 方法。它的第一个参数总是 class 实例。
解决方案:
在 class.
之外定义 build_choices
通过TimeForm.hour_choices.__func__(1, 10)
测试函数对象本身
我觉得和富田一样,貌似在class初始化之前,build_choices
是一个函数,初始化之后就是一个实例方法。我认为另一种选择,而不是将 build_choices
放在 class 之外是:
class TimeForm(forms.Form):
def build_choices(self, start, stop, incr=1):
# Form/class method that builds a list of tuples of identical i, i values for forms.ChoiceField
choice_list = []
temp_list = [i for i in range(start, stop, incr)]
for i in temp_list:
choice_list.append(('%02d' % i, '%02d' % i))
return choice_list
hour_choices = build_choices(None, 1, 13) # E.g., [('01', '01'), ('02', '02') ... ]
minute_choices = build_choices(None, 0, 60, 15)
hour = forms.ChoiceField(choices=hour_choices)
minute = forms.ChoiceField(choices=minute_choices)
在这种情况下(就像在你的例子中一样)在测试中你将无法调用 build_choices
作为 class 方法(为此你需要使用装饰器 @classmethod 或 @staticmethod 但如果你这样做,你将无法从 class 属性中调用它。
你可以像这样在他的测试中调用它:
form = TimeForm()
form.build_choices(1, 10)
TimeForm.build_choices(TimeForm(), 1, 10)
TimeForm.build_choices(form, 1, 10)
我有一个 Django 表单 (Django non-rel v1.5.5),其中的 form/class 方法运行良好。但是,现在我已经开始为应用程序构建单元测试,我在测试 form/class 方法时遇到了问题。我假设 form/class 方法定义不正确。
forms.py
class TimeForm(forms.Form):
def build_choices(start, stop, incr=1):
# Form/class method that builds a list of tuples of identical i, i values for forms.ChoiceField
choice_list = []
temp_list = [i for i in range(start, stop, incr)]
for i in temp_list:
choice_list.append(('%02d' % i, '%02d' % i))
return choice_list
hour_choices = build_choices(1, 13) # E.g., [('01', '01'), ('02', '02') ... ]
minute_choices = build_choices(0, 60, 15)
hour = forms.ChoiceField(choices=hour_choices)
minute = forms.ChoiceField(choices=minute_choices)
上面的代码可以很好地生成表单,并为表单字段提供正确的选择。但是,当我尝试对 build_choices
方法进行单元测试时,我碰壁了。
一些测试
"""Testing the build_choices method."""
> form = TimeForm()
> form.build_choices(1, 10) # This will not work.
> *** TypeError: range() integer start argument expected, got TimeForm.
>
> TimeForm.build_choices(1, 10) # This will not work.
> *** TypeError: unbound method build_choices() must be called with TimeForm instance as first argument (got int instance instead)
>
> TimeForm.build_choices(form, 1, 10)
> *** TypeError: range() integer start argument expected, got TimeForm.
然而,
> TimeForm.hour_choices
> [('01', '01'), ('02', '02') ... ]
是否有更好的 way/proper 方法来定义不是实例方法的表单方法?例如,TimeForm(self, start, end, inc)
.
这是一些奇怪的设置。您有一个 class 方法,它会作为普通函数立即调用,直到 class 完成初始化。
我不是一个高深的 python 向导,但看起来功能仅在 class 设置后才转换为 class 方法。
底线:TimeForm.build_choices
是一种 class 方法。它的第一个参数总是 class 实例。
解决方案:
在 class.
之外定义build_choices
通过TimeForm.hour_choices.__func__(1, 10)
我觉得和富田一样,貌似在class初始化之前,build_choices
是一个函数,初始化之后就是一个实例方法。我认为另一种选择,而不是将 build_choices
放在 class 之外是:
class TimeForm(forms.Form):
def build_choices(self, start, stop, incr=1):
# Form/class method that builds a list of tuples of identical i, i values for forms.ChoiceField
choice_list = []
temp_list = [i for i in range(start, stop, incr)]
for i in temp_list:
choice_list.append(('%02d' % i, '%02d' % i))
return choice_list
hour_choices = build_choices(None, 1, 13) # E.g., [('01', '01'), ('02', '02') ... ]
minute_choices = build_choices(None, 0, 60, 15)
hour = forms.ChoiceField(choices=hour_choices)
minute = forms.ChoiceField(choices=minute_choices)
在这种情况下(就像在你的例子中一样)在测试中你将无法调用 build_choices
作为 class 方法(为此你需要使用装饰器 @classmethod 或 @staticmethod 但如果你这样做,你将无法从 class 属性中调用它。
你可以像这样在他的测试中调用它:
form = TimeForm()
form.build_choices(1, 10)
TimeForm.build_choices(TimeForm(), 1, 10)
TimeForm.build_choices(form, 1, 10)