web-dev-qa-db-ja.com

テンプレート内からDjangoフォームウィジェットのタイプを取得します

フォームのフィールドを繰り返し処理しており、特定のフィールドについては、少し異なるレイアウトが必要で、HTMLを変更する必要があります。

これを正確に行うには、ウィジェットのタイプを知る必要があります。そのクラス名またはそれに似たもの。標準のpythonでは、これは簡単です。 field.field.widget.__class__.__name__

残念ながら、テンプレート内のアンダースコア変数へのアクセスは許可されていません。 素晴らしい!

あなたできるテストfield.field.widget.input_typeしかし、これはテキスト/パスワードに対してのみ機能します<input ../> タイプ。それ以上の解決策が必要です。

私には、どのように見えても難しいかもしれませんが、これをテンプレートレベルで行うのが最も理にかなっています。フィールドのHTMLを処理するコードの一部を、フィールドループに含まれる別のテンプレートに外部委託しました。これは、ModelFormsと標準のFormsの間で一貫していることを意味します(中間のFormクラスを記述した場合、これは当てはまりません)。

20奇数フォームの編集を必要としない普遍的なアプローチを見つけたなら、私にも知らせてください!

43
Oli

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 %}
16
Ivan Ogai

テンプレートタグを作成するとうまくいくかも?何かのようなもの 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ステートメントで使用する必要があったので、そのすべてのロジックをテンプレートタグにシフトしました。マジック。私を正しい方向に向けてくれてありがとう。

43
rinti

受け入れられた回答のフォローアップ-拡張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>
35
zlovelady

Oliとrintiからの回答に続いて、私はこれを使用しましたが、少し簡単だと思います。

テンプレートコード:{{ field|fieldtype }}

フィルターコード:

from Django import template
register = template.Library()

@register.filter('fieldtype')
def fieldtype(field):
    return field.field.widget.__class__.__name__
19

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 テンプレートタグを使用できます。

0
BigglesZX

フォームを管理するすべてのビューに、テンプレートに必要なメタデータをコンテキストにロードするカスタムの汎用ビューから継承させることができます。一般的なフォームビューには、次のようなものが含まれている必要があります。

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のデバッガーを使用すると、フィールドタイプ以外に必要なものがあれば、使用可能なすべてのメタデータを表示できます。

0
Gregorio