Django动态小部件/表单字段表示

2 投票
1 回答
2013 浏览
提问于 2025-04-16 09:40

我有一个表格,里面包含了各种设置。我想在一个表单中以不同的方式显示和验证每个设置。例如,如果设置是整数或字符串,我希望有不同的处理方式。

这是我的模型:

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,我需要显示一个更大的输入框,并验证我期待的是一个字符串。

我看到几个可以实现这个的地方:

  1. 在一个自定义小部件中
  2. 通过重写BaseModelFormSet类,在初始化时更改字段属性(http://snippets.dzone.com/posts/show/7936
  3. 使用自定义模板过滤器,评估类型,然后通过该设置类型的自定义模板手动渲染表单
  4. 将类型和值一起存储在一个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,并重写它的验证代码。

撰写回答