Skip to main content
 首页 » 编程设计

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

2025年05月04日33youxin

我有一个包含各种类型设置的表格。我想以不同的方式显示和验证每个设置。例如,如果设置是针对整数还是字符串。

这是我的模型

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. 将类型和值一起存储在 jsonfield 中并使用类似 http://www.huyng.com/archives/django-custom-form-widget-for-dictionary-and-tuple-key-value-pairs/661/ 的东西在一处更改设置值的显示和验证。

对于选项 1,我不确定我是否在“值”字段上使用自定义小部件是否能够访问“类型”字段以确定如何表示“值”

我尝试了选项 2,虽然我可以访问表单元素,但我无法访问表单值以确定设置的类型(也许它们尚未绑定(bind)?)。我认为这条路线可能是最简单的,但我需要访问表单值..

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.. 

(在发布这篇文章时,我确实找到了一个帖子,可能允许我在初始化期间绑定(bind)表单,因此可以访问该值,请参阅 django - how can I access the form field from inside a custom widget)

选项 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 }) 

.

哪种方法最好(或者有其他方法),我该如何完成? 还是我以错误的方式解决这个问题,是否有更多的 djangoesc 方法来解决我的问题?

请您参考如下方法:

我相信您正在寻找的是 custom validator传递给 CharField 构造函数。

根据情况的不同,另一种可能更优雅的解决方案是创建您自己的字段类来扩展 CharField 并重载其验证代码。