Django动态小部件/表单字段表示
我有一个表格,里面包含了各种设置。我想在一个表单中以不同的方式显示和验证每个设置。例如,如果设置是整数或字符串,我希望有不同的处理方式。
这是我的模型:
class Setting(models.Model):
SETTING_TYPES = (
(u'1', u'Decimal'),
(u'2', u'Integer'),
(u'3', u'String'),
)
type = models..CharField(max_length=2, choices=SETTING_TYPES)
name = models.CharField(max_length=50, unique=True)
value = models.CharField(max_length=200)
所以如果类型是1,我想限制表单的输入,并验证我期待的是一个小数。但如果类型是3,我需要显示一个更大的输入框,并验证我期待的是一个字符串。
我看到几个可以实现这个的地方:
- 在一个自定义小部件中
- 通过重写BaseModelFormSet类,在初始化时更改字段属性(http://snippets.dzone.com/posts/show/7936)
- 使用自定义模板过滤器,评估类型,然后通过该设置类型的自定义模板手动渲染表单
- 将类型和值一起存储在一个json字段中,并使用类似于http://www.huyng.com/archives/django-custom-form-widget-for-dictionary-and-tuple-key-value-pairs/661/的方式,在一个地方更改设置值的显示和验证。
对于选项1,我不确定如果我在“值”字段上使用自定义小部件,它是否能够访问“类型”字段,以确定如何表示“值”。
我尝试了选项2,虽然我可以访问表单元素,但我无法访问表单值来确定设置的类型(可能它们还没有绑定?)。我觉得这条路可能是最简单的,但我需要访问表单值。
class BaseSettingFormset(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super(BaseSettingFormset, self).__init__(*args, **kwargs)
for form in self.forms:
# here i would access the type value and then change the widget propeties below
if form.fields['type'] == 3: # DOESN"T WORK :(
# change the widget and field properties
form.fields['value'].help_text='some text'
form.fields['value'].widget = CustomWidget() # or switch from decimal to string widgets..
def editProfile(request, strategy_id):
settingModelFormset = modelformset_factory(profile, formset=BaseSettingFormset)
... retrieve the values and show them..
(在发布这个的时候,我发现了一篇帖子,可能让我在初始化时绑定表单,从而访问值,见django - 如何在自定义小部件中访问表单字段)
选项3适合显示字段,但不适合验证任何数据。我觉得我需要将它与选项2结合起来,以便在保存时进行验证。
#Custom template filter
@register.filter(name='show_setting')
def show_setting(form):
setting = field_value(form['type']) # calls another function to retrieve value (works ok)
# render page using custom template that can alter the form to show a small field or text area etc.
# can also add js validations here.. (but no server validations)
if setting:
return render_to_string('setting-'+str(setting)+'.html', { 'form': form })
.
哪种方法最好(或者有没有其他方法),我该如何完成它?或者我是不是走错了方向,有没有更符合django的方式来解决我的问题?
1 个回答
0
我觉得你想要的是一个可以自定义的验证器,这个验证器可以放在CharField的构造函数里。
另外,根据具体情况,可能还有一种更优雅的解决方案,那就是自己创建一个字段类,继承CharField,并重写它的验证代码。