webentwicklung-frage-antwort-db.com.de

Ruft den Typ des Django-Formular-Widgets aus der Vorlage ab

Ich durchlaufe die Felder eines Formulars und für bestimmte Felder möchte ich ein etwas anderes Layout, das geändertes HTML erfordert.

Um dies genau zu tun, muss ich nur den Widget-Typ kennen. Sein Klassenname oder etwas ähnliches. In Standard-Python ist das einfach! field.field.widget.__class__.__name__

Leider können Sie in Vorlagen keine Unterstreichungsvariablen verwenden. Großartig!

Sie können can test field.field.widget.input_type, dies funktioniert jedoch nur für Text/Passwort <input ../>-Typen. Ich brauche mehr Auflösung als das.

So schwierig es auch aussehen mag, es ist für mich am sinnvollsten, dies auf Vorlagenebene zu tun. Ich habe den Code, der HTML für Felder behandelt, in eine separate Vorlage ausgelagert, die in die Feldschleife aufgenommen wird. Dies bedeutet, dass es über ModelForms und Standard Forms hinweg konsistent ist (etwas, das nicht wahr wäre, wenn ich eine intermediäre Formularklasse schrieb).

Wenn Sie einen universellen Ansatz sehen, bei dem ich nicht mehr als 20 Formulare bearbeiten muss, lassen Sie es mich auch wissen!

40
Oli

Ab Django 1.11 können Sie einfach widget.input_type verwenden. Beispiel:

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

Das Erstellen eines Vorlagen-Tags könnte funktionieren. So etwas wie field.field.widget|widget_type

Edit from Oli: Guter Punkt! Ich habe gerade einen Filter geschrieben:

from Django import template
register = template.Library()

@register.filter('klass')
def klass(ob):
    return ob.__class__.__name__

Und jetzt wird {{ object|klass }} richtig dargestellt. Jetzt muss ich nur noch herausfinden, wie man das in der if-Anweisung einer Vorlage verwendet.

Edit from Oli # 2: Ich musste das Ergebnis davon in einer if-Anweisung in-template verwenden, also habe ich all diese Logik in den Templatetag verschoben. Zauber. Danke, dass Sie mich in die richtige Richtung stoßen.

43
rinti

Nach der akzeptierten Antwort - mit dem erweiterten if tag in Django 1.2 können Sie Filter in if tag-Vergleichen verwenden. Sie können jetzt Ihre benutzerdefinierte HTML/Logik in der Vorlage wie folgt erstellen:

<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

Nach der Antwort von Oli und Rinti: Ich habe diese verwendet und finde es etwas einfacher:

vorlagencode: {{ field|fieldtype }}

filtercode: 

from Django import template
register = template.Library()

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

Vielleicht ist es für zeitgenössische Leser wichtig, darauf hinzuweisen, dass Django-widget-tweaks für diesen Zweck Vorlagenfilter field_type und widget_type bereitstellt, wobei die jeweiligen Klassennamen in Kleinbuchstaben zurückgegeben werden. Im folgenden Beispiel zeige ich auch die Ausgabe der input_type-Eigenschaft im Feld-Widget (seit Django 1.11), was ebenfalls nützlich sein kann.

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 %}

Ergebnis:

Your name
text
charfield
textinput

Zwischen diesen verschiedenen Optionen sollten Sie in der Lage sein, für fast jeden Anwendungsfall die richtige Eigenschaft zu finden. Wenn Sie die Ausgabe eines dieser Filter für die Verwendung in if-Anweisungen erfassen müssen, können Sie das Tag with template verwenden.

0
BigglesZX