36 votos

¿Cómo puedo crear una Django formulario en el que se muestra una casilla de verificación de la etiqueta a la derecha de la casilla?

Cuando defino una Django clase de forma similar a esta:

def class MyForm(forms.Form):
    check = forms.BooleanField(required=True, label="Check this")

Se expande a HTML que se parece a esto:

<form action="." id="form" method=POST>
<p><label for="check">Check this:</label> <input type="checkbox" name="check" id="check" /></p>
<p><input type=submit value="Submit"></p>
</form>

Me gustaría que la casilla de verificación elemento de entrada para tener una etiqueta que sigue la casilla de verificación, no la otra manera alrededor. Es allí una manera de convencer a Django para hacer eso?

[Editar]

Gracias por la respuesta de Jonas - todavía, mientras se soluciona el problema me preguntó acerca de (casilla de verificación de las etiquetas se representan a la derecha de la casilla de verificación) se introduce un nuevo problema (todos los widget de etiquetas se representan a la derecha de sus widgets...)

Me gustaría evitar primordial _html_output (), ya que, obviamente, no está diseñado para ello. El diseño me daría sería la de implementar un campo html método de salida en el Campo de las clases, anulan el uno para el campo Booleano y el uso de ese método en _html_output(). Lamentablemente, el Django desarrolladores decidieron ir de una manera diferente, y me gustaría trabajar dentro de los marcos existentes tanto como sea posible.

CSS suena como un decente, excepto que no sé lo suficiente de CSS para sacar esto adelante o incluso para decidir si me gusta este método o no. Además, prefiero marcado que todavía se asemeja a la salida final, al menos en el orden de procesamiento.

Además, ya que puede ser razonable para tener más de una hoja de estilo para cualquier marcado, haciendo esto en CSS podría significar tener que hacerlo varias veces para varios estilos, que bastante hace con CSS la respuesta equivocada.

[Editar]

Parece que estoy respondiendo a mi propia pregunta a continuación. Si alguien tiene una mejor idea de cómo hacerlo, no seas tímido.

32voto

romkyns Puntos 17295

He aquí una solución que he llegado con (Django v1.1):

{% load myfilters %}

[...]

{% for field in form %}
    [...]
    {% if field.field.widget|is_checkbox %}
      {{ field }}{{ field.label_tag }}
    {% else %}
      {{ field.label_tag }}{{ field }}
    {% endif %}
    [...]
{% endfor %}

Tendrás que crear una plantilla personalizada etiqueta (en este ejemplo en un "myfilters.py" archivo) que contiene algo como esto:

from django import template
from django.forms.fields import CheckboxInput

register = template.Library()

@register.filter(name='is_checkbox')
def is_checkbox(value):
    return isinstance(value, CheckboxInput)

Más información sobre etiquetas de plantilla personalizadas disponibles aquí.

Edit: en el espíritu de asker la propia respuesta:

Ventajas:

  1. No perdiendo el tiempo con CSS.
  2. El marcado termina buscando la manera que se supone que.
  3. Yo no hack Django interna. (pero tenía que mirar a un buen montón)
  4. La plantilla es buena, compacta y expresiones coloquiales.
  5. El código del filtro juega bonito, independientemente de los valores exactos de las etiquetas y nombres de campos de entrada.

Desventajas:

  1. Probablemente hay algo en algún lugar ahí fuera que lo hace mejor y más rápido.
  2. Poco probable que el cliente estará dispuesto a pagar por todo el tiempo invertido en esto solo para mover la etiqueta a la derecha...

15voto

Marco Puntos 947

Tomé la respuesta de romkyns y de hecho un poco más general

def field_type(field, ftype):
try:
    t = field.field.widget.__class__.__name__
    return t.lower() == ftype
except:
    pass
return False

De esta manera, usted puede comprobar el tipo de widget directamente con una cadena

 `{% si el campo|field_type:'checkboxinput' %}
 {{ field }} {{ field.etiqueta }}
 {% else %}
 {{ field.etiqueta }} {{ field }}
 {% endif %}`
 

12voto

Simon Steinberger Puntos 1787

Todo presentado soluciones implican modificaciones de la plantilla, que son en general bastante ineficiente relativa a la ejecución. Aquí es un widget personalizado que hace el trabajo:

from django import forms
from django.forms.fields import BooleanField
from django.forms.util import flatatt
from django.utils.encoding import force_text
from django.utils.html import format_html
from django.utils.translation import ugettext as _


class PrettyCheckboxWidget(forms.widgets.CheckboxInput):
    def render(self, name, value, attrs=None):
        final_attrs = self.build_attrs(attrs, type='checkbox', name=name)
        if self.check_test(value):
            final_attrs['checked'] = 'checked'
        if not (value is True or value is False or value is None or value == ''):
            final_attrs['value'] = force_text(value)
        if 'prettycheckbox-label' in final_attrs:
            label = _(final_attrs.pop('prettycheckbox-label'))
        else:
            label = ''
        return format_html('<label for="{0}"><input{1} /> {2}</label>', attrs['id'], flatatt(final_attrs), label)


class PrettyCheckboxField(BooleanField):
    widget = PrettyCheckboxWidget
    def __init__(self, *args, **kwargs):
        if kwargs['label']:
            kwargs['widget'].attrs['prettycheckbox-label'] = kwargs['label']
            kwargs['label'] = ''
        super(PrettyCheckboxField, self).__init__(*args, **kwargs)


# usage in form
class MyForm(forms.Form):
    my_boolean = PrettyCheckboxField(label=_('Some label'), widget=PrettyCheckboxWidget())

He PrettyCheckboxWidget y PrettyCheckboxField en un archivo extra, por lo que pueden ser importados en donde sea necesario. Si usted no necesita traducciones, se puede quitar el ugettext partes. Este código funciona en Django 1.5 y no se ha probado para versiones inferiores.

Ventajas:

  • Altamente eficiente, no necesita modificaciones de la plantilla
  • Fácil de usar como un widget personalizado

Desventajas:

  • "as_table" hace que la casilla de verificación + etiqueta dentro de la segunda columna
  • {{ field.etiqueta }} dentro de la plantilla está vacía. La etiqueta es lugar obligado para {{ field }}
  • Más trabajo de lo que había planeado hacer en un sábado ;-)

2voto

Ori Pessach Puntos 4957

He aquí lo que terminó haciendo. Escribí una plantilla personalizada stringfilter para cambiar las etiquetas. Ahora, mi código de plantilla se parece a esto:

{% load pretty_forms %}
<form action="." method="POST">
{{ form.as_p|pretty_checkbox }}
<p><input type="submit" value="Submit"></p>
</form>

La única diferencia de un simple Django plantilla es la adición de la {% carga %} etiqueta de plantilla y el pretty_checkbox filtro.

He aquí un funcional pero feo implementación de pretty_checkbox - este código no tiene ningún tipo de control de errores, se supone que el Django generado atributos en el formato de una manera muy específica, y sería una mala idea usar algo como esto en tu código:

from django import template
from django.template.defaultfilters import stringfilter
import logging

register=template.Library()

@register.filter(name='pretty_checkbox')
@stringfilter
def pretty_checkbox(value):
    # Iterate over the HTML fragment, extract <label> and <input> tags, and
    # switch the order of the pairs where the input type is "checkbox".
    scratch = value
    output = ''
    try:
        while True:
            ls = scratch.find('<label')
            if ls > -1:
                le = scratch.find('</label>')
                ins = scratch.find('<input')
                ine = scratch.find('/>', ins)
                # Check whether we're dealing with a checkbox:
                if scratch[ins:ine+2].find(' type="checkbox" ')>-1:
                    # Switch the tags
                    output += scratch[:ls]
                    output += scratch[ins:ine+2]
                    output += scratch[ls:le-1]+scratch[le:le+8]
                else:
                    output += scratch[:ine+2]
                scratch = scratch[ine+2:]
            else:
                output += scratch
                break
    except:
        logging.error("pretty_checkbox caught an exception")
    return output

pretty_checkbox explora su argumento de cadena, encuentra los pares de <label> y <input> etiquetas, y los interruptores de ellos en torno a si la etiqueta <input> de tipo "checkbox". También se elimina el último carácter de la etiqueta, que pasa a ser el ':' carácter.

Ventajas:

  1. No perdiendo el tiempo con CSS.
  2. El marcado termina buscando la manera que se supone que.
  3. Yo no hack Django interna.
  4. La plantilla es buena, compacta y expresiones coloquiales.

Desventajas:

  1. El código del filtro debe ser probado para el emocionante valores de las etiquetas y nombres de campos de entrada.
  2. Probablemente hay algo en algún lugar ahí fuera que lo hace mejor y más rápido.
  3. Más trabajo de lo que había planeado hacer en un sábado.

1voto

zihotki Puntos 4729

El orden de las entradas y las etiquetas se proporciona a través de normal_row parámetro de forma y no hay ninguna fila diferente de los patrones de casillas de verificación. Así que hay dos maneras de hacer esto (en versión 0.96 exactamente):
1. reemplazar _html_output de la forma
2. el uso de CSS para cambiar la posición de la etiqueta y la casilla de verificación

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X