私は読み取り専用のフォームフィールドを作成する方法を探していましたが、この件に関して見つけたすべての記事には、「これは悪い考えです」という記述が付いています。これで、個々のフォームについて、問題を解決する他の方法があることは理解できますが、モデルフォームセットで読み取り専用フォームフィールドを使用することは、完全に自然な考えのようです。
教師が1回の送信ですべての学生(複数の学生に注意)の成績を入力できるようにしたい教師の成績表アプリケーションについて考えてみます。モデルフォームセットは、学生名が読み取り専用で、成績が編集可能なフィールドになるように、すべての学生の成績を反復処理できます。モデルフォームセットで得られるエラーチェックとエラーレポートのパワーと利便性は気に入っていますが、そのようなフォームセットで学生名を編集可能なままにしておくのはおかしいです。
専門家Djangoコンセンサスは、読み取り専用のフォームフィールドは悪い考えであるということなので、標準のDjangoベストプラクティスは、例の学生にとって何であるか疑問に思いました-上記のグレードの例?
これを行わない理由は、誰かが無効なフィールドを有効に変更してからフォームを送信できるためです。 「無効」データを挿入しないように、保存機能を変更する必要があります。
これを行う標準的な方法は、名前を入力に入力するのではなく、テキストとして表示することです。
<form>
<div>
<label>Name</label>
<p>Johnny Five</p>
</div>
<div>
....
これはDjangoでは不可能です。
私はあなたが本当にあなたのユーザーベースが物事を「混乱」させないことを信頼しているならそれを選びなさい、しかしそれが可能性のある機密データを持っている公開されているウェブサイトなら遠ざけてください。
私があなたの状況を見る限り、これは理想的な答えです:
https://stackoverflow.com/a/2242468/1004781
つまり、テンプレートにモデル変数を出力するだけです。
{{ form.instance.LastName }}
無効なフィールドを使用する場合、フォームが検証に失敗した場合でも、フィールドが正しく入力されたままであることを確認する必要があります。送信されたデータを変更する悪意のある試みも処理する私の方法は次のとおりです。
class MyForm(forms.Form):
MY_VALUE = 'SOMETHING'
myfield = forms.CharField(
initial=MY_VALUE,
widget=forms.TextInput(attrs={'disabled': 'disabled'})
def __init__(self, *args, **kwargs):
# If the form has been submitted, populate the disabled field
if 'data' in kwargs:
data = kwargs['data'].copy()
self.prefix = kwargs.get('prefix')
data[self.add_prefix('myfield')] = MY_VALUE
kwargs['data'] = data
super(MyForm, self).__init__(*args, **kwargs)
学生/成績の例として、学生は編集不可能なフィールドであり、必要に応じて成績を編集および更新できるソリューションを考え出しました。 このようなもの
Zip関数を使用して、view.pyのgrade_editクラスの成績の学生オブジェクトとフォームセットを組み合わせています。
def grade_edit(request, id):
student = student.objects.get(id=id)
grades = grades.objects.filter(studentId=id)
gradeformset = GradeFormSet(request.POST or None)
if request.POST:
gradeformset = GradeFormSet(request.POST, request.FILES, instance=student)
if gradeformset.is_valid():
gradeformset.save()
grades = grades.objects.filter(studentId=id)
return render(request, 'grade_details.html', {'student': student, 'grades': grades})
else:
gradeformset = GradeFormSet(instance=student)
grades = grades.objects.filter(studentId=id)
zips = Zip(grades, gradeformset)
return render(request, 'grade_edit.html', {'zips': zips, 'student': student, 'gradeformset': gradeformset })
私のテンプレートは次のようになります
<table>
<tr>
{% for field in gradeformset.forms.0 %}
{% if not field.is_hidden %}
<th>{{ field.label }}</th>
{% endif %}
{% endfor %}
</tr>
{% for f in gradeformset.management_form %}
{{ f }}
{% endfor %}
{% for student, gradeform in zips %}
<tr>
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<td> {{ student.name }} </td>
<td> {{ gradeform.gradeA }} </td>
<td> {{ gradeform.gradeB }} </td>
</tr>
{% endfor %}
</table>
Django formset here http://whoisnicoleharris.com/2015/01/06/implementing-Django-formsets.html について詳しく読むことができます