13

モデルフォームにドロップダウンがあり、ユーザーは選択した値を変更できないはずです。私は、adisabledが必要なことを正確に実行することを発見しました。ただし、これには奇妙な点があります。

フォームを初めて開いたとき(GET)に値が選択され、ユーザーは値を変更できません。これは素晴らしいです:

ここに画像の説明を入力してください

ただし、で検証エラーが発生しunrelated field、POSTによってユーザーが同じフォームに戻されるとすぐに、以前の情報は失われます。無効にされた外部キードロップダウンには値が含まれなくなり、非常に苛立たしくなります。

ここに画像の説明を入力してください

私はいくつかの調査を行い、stackoverflowで何かを見つけましたが、外部キードロップダウンウィジェットが無効になっていると、データがまったく返送されないようです。ここでの3番目の回答で説明されているように、検証をオーバーライドして、ドロップダウンフィールドにエラーをスローしないようにすることができます。ただし、他の無関係なフィールドがエラーをスローした場合、無効にされたドロップダウンが最初にPOSTにデータを送信したことがないため、データは失われます。

トリッキーな状況です。

ビュー内のデータをrequest.POSTに渡す方法はありますか?またはあなたは何を提案しますか?readonlyの代わりに使用することもできますdisabledが、ユーザーがドロップダウンを変更することもできます。これもイライラします。

何か案は?どうもありがとう

編集:

小さな修正:データが完全に失われることはありません。むしろ、selectが誤って初期ダミー値に設定されています。

    <select id="id_form-0-deal_type" name="form-0-deal_type" disabled="disabled">
      <option selected="selected" value="">---------</option>
      <option value="1">deal 1</option>
      <option value="2">deal 2</option>
    </select>

アップデート:

フランシスの解決策は非常に有望に見えます。そこで、彼の2番目の提案を試し、htmlに非表示の入力フィールドを追加して、正しい値をPOSTに渡しました。

問題は今、どのように進めるかです。フォームセットのフォームのquerydictに次のように不足しているエントリを追加しようとしました(正しいドロップダウン値を設定するため)

formset.forms[0].data['form-0-deal_type'] = formset.forms[0].data['form-0-hiddenfield'] 

しかし、それは言いますThis QueryDict instance is immutable

それを行う他の唯一の方法は、通常のフォームセットでイニシャルを介して設定することです。残念ながら、既存のフォームのイニシャルをサポートしていないmodelformsetsを使用しています。

他に解決策がない場合は、モデルフォームセットを通常のフォームセットにリファクタリングし始めます。まだアイデアを開いています...

最終更新+解決策:

modelformsetを通常のfomsetにリファクタリングする必要はありません。実際、それ自体に他の問題をもたらすので、そうすることは強くお勧めしません。modelformsetsはすべてを処理し、不足している部分を埋めます。

実際の問題は、QueryDictが不変であるという事実ですが、これはそれらをコピーすることで簡単に解決できます。

formset = deal_formset(request.POST, queryset=formset_query)        
if formset.is_valid():
  pass
else:
  new_post = request.POST.copy()
  deal_types = dict()
  for k,v in new_post.items():
     if k.startswith('hidden'):
        deal_types[k[7:]]= v
  for k,v in deal_types.iteritems():
     new_post[k] = v
  formset = deal_formset(new_post, queryset=formset_query)

これに加えて、フランシスの解決策:

{{ formset.management_form }}
  {% for fs in formset %}  
     {{ fs.id }} 
     <input type="hidden" name="hidden-{{ fs.prefix }}-deal_type" value="{{fs.deal_type.value}}" />
   {{fs.deal_type}}
{% endfor %}
{% endif %}

ただ驚異的に動作します...お楽しみください:)

4

3 に答える 3

18

それはdjangoのものではなく、HTMLのものです。無効にされたフォーム要素はフォームによって送信されません。

[要素]はユーザー入力を受け取ることができず、その値はフォームで送信されません。

http://www.w3.org/TR/html401/interact/forms.html#h-17.12.1&http://www.w3schools.com/tags/att_input_disabled.asp _ _

readonlyテキスト/テキストエリア http://www.w3schools.com/tags/att_input_readonly.aspにある場合に使用できます

他にできることは、値をプレーンテキストで表示し、それを非表示フィールドとして送信することです。

{{ form.field_name.label_tag }}
{{ form.field_name.value }}
<input type="hidden" name="field_name" value="{{form.field_name.value}}" />

あまりエレガントではありませんが、そこにたどり着くことができます。

さらに一歩進んで、無効な要素を探し、その要素の名前と値を後に追加するJSを作成することもできます。

いくつかのサンプルJQuery:

//Untested, but you get the gist
$(':disabled').each(
    function()
    {
        $(this).after('<input type="hidden" name="' + $(this).attr('name') + '" value="' + $(this).val() + '" />');
    }
);
于 2012-07-31T21:27:14.570 に答える
1

ビューのフォームセットを使用してフォームを作成し、テンプレートに非表示のプロパティを持つ要素を設定できます。

{{form.field.as_hidden}}

ビュー内では、問題がデータ損失である場合、外部キーであるため、モデル構造に適したフィールドの初期値をいつでも設定できます。もちろん、フォームをコミットする前にフォームを検証する必要があります。フォームが有効でない場合は、常に入力する必要のあるフィールドに初期値を使用してフォームをレンダリングできます。

于 2012-07-31T22:03:17.953 に答える
0

これはDjangoではなくHTMLの問題だと思います。無効にしたフォームフィールドは値をポストバックしないため、値が失われます。

検証が失敗した場合、値をフィールドに再バインドすることは可能ですか?あなたは次のようなことを試すことができます

if form.is_valid(): # All validation rules pass
    #save form, redirect, etc.
else:
    form.disabled_field = my_value
return render(request, 'contact.html', {'form': form,})

明らかに、フィールド名と値をモデルの正しいデータに置き換える必要があります。

于 2012-07-31T21:27:38.907 に答える