所以我想说我有jQuery从这个
转换一个简单的文本输入<input class='employee_list' name='requestor' type='text' />
到这个
<div name='requestor' class='ajax_picker'>
<input class='search_box' class='employee_list' name='requestor_text' type='text'/>
<input class='id' name='requestor' type='hidden' value='' />
<div class='results'></div>
</div>
使用AJAX + JSON加载隐藏的输入值。问题是,if form.is_valid() is not True
,那我怎样才能创建一个可以呈现两个值的自定义Widget?我想我可以做两个不同的领域,但这看起来很难看。我也可以自定义表单渲染,但更糟糕的是。也许表单可以将所有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)
答案 0 :(得分:1)
嗯,我不知道这是否符合优雅,但是这样的事情怎么样。在这里,我将搜索字符串存储为窗口小部件上的属性,并在窗体构造函数中设置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]
您可能需要调整一下才能让属性显示在您想要的位置等等,但希望这基本上可以满足您的需求吗?
答案 1 :(得分:0)
您可以代替在表单上调用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