2013-10-29 59 views
1

我正在寫一個自定義表單控件,它覆蓋choice method in django.forms.models.ModelChoiceIteratorDjango:如何從自定義小部件中獲取選定的值?

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屬性返回所選值。

回答

1

我想通了!我通過窗口小部件名稱模板:

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) 
+0

出現如下錯誤:'未捕獲的ReferenceError:widgetName未定義'在'custom_widget.js'中。 – Dipak

0

在模板的頂部,將隱藏的div其中有{{widget.name}},例:

<div id='widget-name-indicator' style="display: none">{{ widget.name }</div> 

現在你可以在你的附加JS選擇它:

var widgetName = $('#widget-name-indicator').text(); 
相關問題