【问题标题】:Django: How to get the selected value from a custom widget?Django:如何从自定义小部件中获取选定的值?
【发布时间】:2013-11-08 19:12:56
【问题描述】:

我正在编写一个覆盖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 方法,但是我不清楚,即使从阅读源代码来看,我如何能够基于任意 HTML 返回选定的值没有选择小部件的属性。

【问题讨论】:

    标签: django django-forms django-widget


    【解决方案1】:

    在模板的顶部,放置具有{{widget.name}}的隐藏div,例如:

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

    现在您可以在附加的 js 中选择它:

    var widgetName = $('#widget-name-indicator').text();
    

    【讨论】:

      【解决方案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)
      

      【讨论】:

      • 出现如下错误:Uncaught ReferenceError: widgetName is not defined in custom_widget.js.
      猜你喜欢
      • 2021-04-30
      • 2015-08-27
      • 2012-03-28
      • 1970-01-01
      • 2013-09-13
      • 2017-09-13
      • 1970-01-01
      • 2012-10-29
      • 2013-01-20
      相关资源
      最近更新 更多