Django: Как получить выбранное значение из пользовательского виджета?

Я пишу собственный виджет формы, который переопределяет choice метод в 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 для 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)

(Я следовал примеру из этой записи в блоге)

Мне нужно создать полностью настраиваемый виджет, который выбирает объекты на основе, скажем, значения атрибута data-selected в элементе HTML. Мне удалось отобразить пользовательский 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 без виджета Select .


person 3cheesewheel    schedule 29.10.2013    source источник


Ответы (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:

<!-- 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 скрытого ввода:

// 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)
person 3cheesewheel    schedule 29.10.2013
comment
Получил следующую ошибку: Uncaught ReferenceError: widgetName is not defined в custom_widget.js. - person Dipak; 06.04.2016

В верхней части шаблона поместите скрытый div с {{widget.name}}, например:

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

Теперь вы можете выбрать его в добавленных js:

var widgetName = $('#widget-name-indicator').text();
person Bert Kiv    schedule 23.09.2017