自定义widg中的键/值对

2024-10-01 04:57:11 发布

您现在位置:Python中文网/ 问答频道 /正文

假设有一个简单的文本输入

<input class='employee_list' name='requestor' type='text' />

为了这个

^{pr2}$

并使用AJAX+JSON加载隐藏的输入值。问题是,if form.is_valid() is not True,那么如何创建一个自定义小部件来呈现这两个值?我想我可以做两个不同的领域,但这看起来很难看。我也可以定制表单渲染,但那更糟糕。也许表单可以将所有的POST数据传递给小部件,但似乎无法找到如何使其工作。在

一定有一个优雅的方法来实现这一点!在

from django import forms

class AjaxPickerWidget(forms.TextInput):
    def render(self, name, value, attrs=None):
        # ... now what?
        return super(AjaxPickerWidget, self).render(name, value, attrs=attrs)

我的解决方案

谢谢你的帮助,我采取了不同的方法。由于我严格地将其用于模型(因此需要一个键/值对),所以我让小部件直接与模型交互,并创建一个data-id属性,jQuery将捕捉该属性以移动到隐藏字段。在

from django import forms

class AjaxPickerModelWidget(forms.TextInput):
    def __init__(self, css_class, queryset, id_name, value_name, attrs={}):
        attrs['class'] = css_class
        self.queryset = queryset
        self.id_name = id_name
        self.value_name = value_name
        super(AjaxPickerModelWidget, self).__init__(attrs=attrs)

    def render(self, name, value, attrs={}):
        try:
            instance = self.queryset.get(**{self.id_name: value})
            attrs['data-id'] = value
            value = getattr(instance, self.value_name)
        except:
            value = ''
        return super(AjaxPickerModelWidget, self).render(name, value,
                                                         attrs=attrs)

Tags: nameselfid表单isvalue部件def
2条回答

好吧,我不知道这是否算优雅,但像这样的东西怎么样。这里我将搜索字符串存储为小部件上的一个属性,并从表单构造函数中的POST数据设置该属性。我还使用name=“foo_picker_text”来指示名为“foo”的相应输入的搜索输入。在

class AjaxPickerWidget(HiddenInput):
  search_text_suffix = "_picker_text"

  def __init__(self, **kwargs):
    super(AjaxPickerWidget, self).__init__(**kwargs)
    self.search_text = None

  def render(self, name, value, attrs=None):
    start = '<div name="%s" class="ajax_picker">' % (name) + \
             '<input class="search_box" name="%s%s" ' % (name, self.search_text_suffix)+ \
             'type="text" value="%s" />' % (self.search_text or "")
    end = super(AjaxPickerWidget, self).render(name, value, attrs=attrs) + '</div>'
    return '%s%s' % (start, end)

class MyForm(Form):
  requestor = CharField(widget = AjaxPickerWidget())

  def __init__(self, *args, **kwargs):
    super(MyForm, self).__init__(*args, **kwargs)
    # find picker text in POST data and tell the corresponding widget about it
    for name in self.data:
      if name.endswith(AjaxPickerWidget.search_text_suffix):
        field_name = name.split(AjaxPickerWidget.search_text_suffix)[0]
        self.fields[field_name].widget.search_text = self.data[name]

你可能需要稍微调整一下,让属性显示在你想要的地方,等等,但希望这基本上能满足你的需要?在

您可以创建一个自定义函数,而不是在窗体上调用is_valid()

from django import forms

class AjaxPickerWidget(forms.TextInput):
    def render(self, name, value, attrs=None):
        return super(AjaxPickerWidget, self).render(name, value, attrs=attrs)
    def validate(self):
        values = self.cleaned_data.items():
        # Modify the values to fit the original form (delete, change etc)
        return whateversleft.is_valid() # Perhaps with some additional checks

相关问题 更多 >