Ottieni il tipo di widget di forma Django dal modello

Sto iterando attraverso i campi di un modulo e per determinati campi voglio un layout leggermente diverso, che richiede HTML alterato.

Per farlo con precisione, ho solo bisogno di conoscere il tipo di widget. Il nome della class o qualcosa di simile. In Python standard, questo è facile! field.field.widget.__class__.__name__

Sfortunatamente, non ti è consentito accedere alle variabili di sottolineatura nei modelli. Grande!

Puoi testare field.field.widget.input_type ma questo funziona solo per i tipi text / password . Ho bisogno di più risoluzione per quello.

Per me, per quanto difficile possa sembrare, ha più senso farlo a livello di template. Ho esternalizzato il bit di codice che gestisce l’HTML per i campi in un modello separato che viene incluso nel ciclo di campo. Ciò significa che è coerente tra ModelForm e Form standard (qualcosa che non sarebbe vero se avessi scritto una class Form intermedia).

    Se riesci a vedere un approccio universale che non mi richiede di modificare i moduli di 20 cifre, fammelo sapere!

    A partire da Django 1.11, puoi semplicemente usare widget.input_type . Esempio:

     {% for field in form.visible_fields %}  {% endfor %} 

    Fare un tag modello potrebbe funzionare? Qualcosa come field.field.widget|widget_type

    Modifica da Oli: buon punto! Ho appena scritto un filtro:

     from django import template register = template.Library() @register.filter('klass') def klass(ob): return ob.__class__.__name__ 

    E ora {{ object|klass }} correttamente. Ora devo solo capire come usarlo all’interno dell’istruzione if un template.

    Modifica da Oli # 2: Avevo bisogno di usare il risultato di questo in un template statetario, quindi ho solo spostato tutta la logica nel templatetag. Magia. Grazie per avermi spinto nella giusta direzione.

    In seguito alla risposta accettata – il if tag potenziato if tag in Django 1.2 consente di utilizzare i filtri in if tag confronto di if tag . Quindi ora puoi fare la tua html / logica personalizzata nel modello in questo modo:

     
      {% for field in form.fields %}
    • {% if field.field.widget|klass == "Textarea" %}

      Text Areas are Special

      {% else %} {{ field.errors }} {{ field.label_tag }} {{ field }} {% endif %}
    • {% endfor %}

    Seguendo la risposta di Oli e rinti: ho usato questo e penso che sia un po ‘più semplice:

    codice modello: {{ field|fieldtype }}

    codice filtro:

     from django import template register = template.Library() @register.filter('fieldtype') def fieldtype(field): return field.field.widget.__class__.__name__ 

    Forse vale la pena di ricordare ai lettori contemporanei che django-widget-tweaks fornisce filtri modello field_type e widget_type per questo scopo, restituendo i rispettivi nomi di class in widget_type minuscole. Nell’esempio che segue mostro anche l’output della proprietà input_type sul widget campo (da Django 1.11), che può anche essere utile.

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

    Risultato:

     Your name text charfield textinput 

    Tra queste varie opzioni dovresti essere in grado di trovare la proprietà giusta da utilizzare per quasi ogni caso d’uso. Se è necessario acquisire l’output di uno di questi filtri da utilizzare nelle istruzioni if , è ansible utilizzare il tag with modello.