我正在编写一个自定义表单窗口小部件,它会覆盖choice
method in django.forms.models.ModelChoiceIterator
:
class CustomIterator(ModelChoiceIterator):
def choice(self, obj):
return (self.field.prepare_value(obj),
self.field.label_from_instance(obj), obj)
以及_get_choices
method on django.forms.models.ModelChoiceField
:
class CustomField(ModelChoiceField):
def _get_choices(self):
if hasattr(self, '_choices'):
return self._choices
return ElfIterator(self)
choices = property(_get_choices, ChoiceField._set_choices)
(我按照this blog post上的例子)
我需要创建一个完全自定义的窗口小部件,根据例如HTML元素上data-selected
属性的值来选择对象。我已经能够使用上面添加的实例属性在表单上显示自定义HTML /样式:
from django.template.loader import render_to_string
class CustomWidget(Widget):
def render(self, name, value, attrs=None):
obj_list = [item[2] for item in self.choices]
obj_dict = [model_to_dict(obj) for obj in obj_list]
output = render_to_string('myapp/widgets/custom_widget.html',
{ 'obj_dict': obj_dict })
return mark_safe(output)
现在我试图在同一个类上覆盖value_from_datadict
方法,但是我不清楚,即使从阅读源代码,我如何能够基于一个返回选定的值没有Select小部件的任意HTML属性。
答案 0 :(得分:2)
我明白了!我将小部件名称传递给模板:
class CustomWidget(Widget):
class Media:
js = ('http://code.jquery.com/jquery-1.10.2.js', 'custom_widget.js')
def render(self, name, value, attrs=None):
instance_list = [item[2] for item in self.choices]
obj_dict_list = [model_to_dict(obj) for obj in obj_list]
output = render_to_string('myapp/widgets/custom_widget.html', {
'widget_name': name,
'obj_list': obj_dict_list,
})
return mark_safe(output)
在模板中创建一个隐藏的输入字段,指定name
attr的小部件名称:
<!-- myapp/widgets/custom_widget.html -->
<input type="hidden" name="{{ widget_name }}" value="some-initial-value" />
{% for obj in obj_list %}
{{ do_something_with_obj }}
{% endfor %}
<script>
// make {{ widget_name }} accessible to the included js on the widget
var widgetName = "{{ widget_name }}";
</script>
使用JavaScript / jQuery我更改了隐藏输入的value
attr:
// custom_widget.js
(function() {
var hiddenInput = $("input[name='" + widgetName + "']");
if (someCondition) {
hiddenInput.val(newVal);
}
)();
最后,在value_from_data
中,获取隐藏输入的值:
class CustomWidget(Widget):
...
def value_from_datadict(self, data, files, name):
return data.get(name, None)
答案 1 :(得分:0)
在模板的顶部,放置隐藏的div,其中包含{{widget.name}},例如:
<div id='widget-name-indicator' style="display: none">{{ widget.name }</div>
现在您可以在附加的js中选择它:
var widgetName = $('#widget-name-indicator').text();