0

それで、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では、両方の値をレンダリングするカスタムウィジェットを作成するにはどうすればよいですか?私は2つの異なる分野を行うことができると思っていますが、それは醜いようです。フォームのレンダリングをカスタマイズすることもできますが、それはさらに悪いことです。フォームはすべての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)
4

2 に答える 2

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]

属性を必要な場所に表示するために少し調整する必要があるかもしれませんが、うまくいけば、これは基本的にあなたが望むことをしますか?

于 2012-12-09T23:53:56.993 に答える
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
于 2012-12-10T12:18:40.740 に答える