フォームのフィールドを繰り返し処理しており、特定のフィールドについては、少し異なるレイアウトが必要で、HTMLを変更する必要があります。
これを正確に行うには、ウィジェットのタイプを知る必要があります。そのクラス名またはそれに似たもの。標準のpythonでは、これは簡単です。 field.field.widget.__class__.__name__
残念ながら、テンプレート内のアンダースコア変数へのアクセスは許可されていません。 素晴らしい!
あなたできるテストfield.field.widget.input_type
しかし、これはテキスト/パスワードに対してのみ機能します<input ../>
タイプ。それ以上の解決策が必要です。
私には、どのように見えても難しいかもしれませんが、これをテンプレートレベルで行うのが最も理にかなっています。フィールドのHTMLを処理するコードの一部を、フィールドループに含まれる別のテンプレートに外部委託しました。これは、ModelForm
sと標準のForm
sの間で一貫していることを意味します(中間のFormクラスを記述した場合、これは当てはまりません)。
20奇数フォームの編集を必要としない普遍的なアプローチを見つけたなら、私にも知らせてください!
Django 1.11以降、widget.input_type
。例:
{% for field in form.visible_fields %}
<input type="{{ field.field.widget.input_type }}"
id="{{ field.id_for_label }}"
name="{{ field.html_name }}"
placeholder="{{ field.label }}"
maxlength="{{ field.field.max_length }}" />
{% endfor %}
テンプレートタグを作成するとうまくいくかも?何かのようなもの field.field.widget|widget_type
オリから編集:良い点!私はフィルターを書いたところです:
from Django import template
register = template.Library()
@register.filter('klass')
def klass(ob):
return ob.__class__.__name__
そして今 {{ object|klass }}
は正しくレンダリングされます。これで、テンプレートのif
ステートメント内でそれを使用する方法を理解する必要があります。
Oli#2からの編集:その結果をテンプレート内のifステートメントで使用する必要があったので、そのすべてのロジックをテンプレートタグにシフトしました。マジック。私を正しい方向に向けてくれてありがとう。
受け入れられた回答のフォローアップ-拡張if tag
in Django 1.2では、if tag
比較。したがって、次のようにテンプレートでカスタムhtml/logicを実行できます。
<ul>
{% for field in form.fields %}
<li>
{% if field.field.widget|klass == "Textarea" %}
<!-- do something special for Textarea -->
<h2>Text Areas are Special </h2>
{% else %}
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
{% endif %}
</li>
{% endfor %}
</ul>
Oliとrintiからの回答に続いて、私はこれを使用しましたが、少し簡単だと思います。
テンプレートコード:{{ field|fieldtype }}
フィルターコード:
from Django import template
register = template.Library()
@register.filter('fieldtype')
def fieldtype(field):
return field.field.widget.__class__.__name__
Django-widget-tweaks
がこの目的でfield_type
およびwidget_type
テンプレートフィルターを提供し、それぞれのクラス名を小文字で返すことを、現代の読者に指摘する価値があるかもしれません。以下の例では、フィールドウィジェットのinput_type
プロパティの出力も示しています(Django 1.11以降))。これも役立つ場合があります。
forms.py
:
class ContactForm(forms.Form):
name = forms.CharField(
max_length=150,
required=True,
label='Your name'
)
template.html
:
{% load widget_tweaks %}
{% for field in form.visible_fields %}
{{ field.label }}
{{ field.field.widget.input_type }}
{{ field|field_type }}
{{ field|widget_type }})
{% endfor %}
結果:
Your name
text
charfield
textinput
これらのさまざまなオプションの間で、ほぼすべてのユースケースでターゲットにする適切なプロパティを見つけることができるはずです。これらのフィルターのいずれかの出力をif
ステートメントで使用するためにキャプチャする必要がある場合は、 with
テンプレートタグを使用できます。
フォームを管理するすべてのビューに、テンプレートに必要なメタデータをコンテキストにロードするカスタムの汎用ビューから継承させることができます。一般的なフォームビューには、次のようなものが含まれている必要があります。
class CustomUpdateView(UpdateView):
...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
...
for f, value in context["form"].fields.items():
context["form"].fields[f].type = self.model._meta.get_field(f).get_internal_type()
...
return context
テンプレートでは、field.fieldを通じてこれらのカスタムプロパティにアクセスできます。
{% if field.field.type == 'BooleanField' %}
<div class="custom-control custom-checkbox">
...
</div>
{% endif %}
PyCharmまたはVisual Studio Codeのデバッガーを使用すると、フィールドタイプ以外に必要なものがあれば、使用可能なすべてのメタデータを表示できます。