Pregunta

Estoy tratando de encontrar una manera fácil de construir formas que muestran fechas en el formato de Australia (dd / mm / aaaa). Esta era la única manera que pude encontrar para hacerlo. Parece que debe haber una mejor solución.

A tener en cuenta:

  • Creado un nuevo widget que hace valor de fecha en el formato dd / mm / aaaa
  • Se creó un nuevo campo de fecha para anteponer el formato de cadena de fecha localizar a la lista de valores que trata de utilizar

Me imagino que la solución ideal sería un datefield la que localiza automáticamente, pero eso no funcionó para mí (strftime no parecía ser Unicode amable, pero que no lo probamos muy duro)

Me estoy perdiendo algo? ¿Hay una solución más elegante? Es este un enfoque robusto?

from models import *
from django import forms
import datetime

class MyDateWidget(forms.TextInput):

    def render(self, name, value, attrs=None):

            if isinstance(value, datetime.date):
                    value=value.strftime("%d/%m/%Y")

            return super(MyDateWidget, self).render(name, value, attrs)


class MyDateField(forms.DateField):

    widget = MyDateWidget

    def __init__(self, *args, **kwargs):
            super(MyDateField, self).__init__(*args, **kwargs)
            self.input_formats = ("%d/%m/%Y",)+(self.input_formats)


class ExampleForm(ModelForm):
    class Meta: 
            model=MyModel
            fields=('name', 'date_of_birth')

    date_of_birth = MyDateField()
¿Fue útil?

Solución

Por supuesto, no estoy un Django / Python Jedi, pero ...

No creo que haya nada malo con su enfoque. Es una lectura limpia.

Es posible que no tenga que crear su propio widget sólo para hacer que la fecha en el formato adecuado en la primera pantalla de la forma. Sólo tiene que utilizar el parámetro format para el widget DateInput y que debe estar bien. Así que en su clase myDateField yo sólo haría:

class MyDateField(forms.DateField):

    widget = forms.DateInput(format="%d/%m/%Y")

    def __init__(self, *args, **kwargs):
        super(MyDateField, self).__init__(*args, **kwargs)
        self.input_formats = ("%d/%m/%Y",)+(self.input_formats)

Se puede usar formfield_callback (Véase aceptado respuesta para esta pregunta alejadas), es decir:

def customize_fields(f):
    if isinstance(f, DateTimeField):
        datetime_field=forms.DateTimeField(widget=
            forms.DateInput(format='%d/%m/%Y %h:%i'))
        date_field.input_formats = ("%d/%m/%Y %h:%i",)+
            (date_field.input_formats)
        return datetime_field
    elif isinstance(f, DateField):
        date_field=forms.DateField(widget=
            forms.DateInput(format='%d/%m/%Y'))
        date_field.input_formats = ("%d/%m/%Y",)+
            (date_field.input_formats)
        return date_field
    else:
        return f.formfield()

class MyModelForm(forms.ModelForm):
    formfield_callback = customize_fields

    class Meta:
        model = ...

Hacer que elimina completamente la necesidad de su clase MyDateField, pero podría introducir - si quieres todas las clases forma única para llamar customize_fields -. La necesidad de un descendiente ModelForm, implementar formfield_callback=customize_fields como la nueva base para todas sus clases de formulario

Mi problema con el uso del mecanismo de formfield_callback es doble:

  1. Es menos legible y se basa en el conocimiento de los mecanismos internos de ModelForms. No puedo encontrar documentación real en cualquier lugar formfield_callback ...

  2. Si alguna vez tiene que volver a definir un campo de modelo en un ModelForm, decir para que el campo no es obligatorio para esa instancia particular de la forma, de este modo:

       class MyModelForm(forms.ModelForm):
           formfield_callback = customize_fields
           foo = forms.DateField(required=false)
    
           class Meta:
               model = Bar
    

    va a sobrescribir el campo de formulario devuelto por customize_fields, por lo tanto, perder por completo la personalización.

Creo que su enfoque es más fácil de leer.

Otros consejos

He utilizado este enfoque simple antes: acaba de establecer el atributo 'formato' de la DateField.widget en el Init del formulario:

    class ExampleForm(ModelForm):

        class Meta:
            model = MyModel

        def __init__(self, *args, **kwargs):
            super(ModelForm, self).__init__(*args, **kwargs)
            self.fields['date_of_birth'].widget.format = '%d/%m/%Y'

            # at the same time, set the input format on the date field like you want it:
            self.fields['date_of_birth'].input_formats = ['%d/%m/%Y']

Todo el material widget personalizado pueden ser anuladas.

Aquí está un extracto de django/forms/widgets.py:

class DateInput(TextInput):
    def __init__(self, attrs=None, format=None):
        super(DateInput, self).__init__(attrs)
        if format:
            self.format = format
            self.manual_format = True
        else:
            self.format = formats.get_format('DATE_INPUT_FORMATS')[0]
            self.manual_format = False

Se dará cuenta de que el formato del widget se ajusta utilizando el módulo de formato. El módulo de formato se selecciona en función de la configuración regional. Si estás navegando desde los EE.UU., Django, por defecto, seleccione django.conf.formats.locale.en.formats.py. Aquí se encuentra el formato por defecto:

DATE_INPUT_FORMATS = (
    '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
    # '%b %d %Y', '%b %d, %Y',            # 'Oct 25 2006', 'Oct 25, 2006'
    # '%d %b %Y', '%d %b, %Y',            # '25 Oct 2006', '25 Oct, 2006'
    # '%B %d %Y', '%B %d, %Y',            # 'October 25 2006', 'October 25, 2006'
    # '%d %B %Y', '%d %B, %Y',            # '25 October 2006', '25 October, 2006'
)

Como se puede ver en el primer bloque de código, Django selecciona el primero de ellos. El enfoque completo para el cambio de formato es crear su propio módulo de formato, anulando por omisión de Django para la localidad en cuestión. Para eso, mira en FORMAT_MODULE_PATH . Si todo lo que estamos tratando de hacer es reemplazar el formato de fecha predeterminado, digo ahorrar un poco de tiempo y parche mono. He añadido esto a mi archivo de configuración y todo parece estar funcionando espléndidamente con mi formato preferido por defecto:

DATE_INPUT_FORMATS = ('%m/%d/%Y', '%m/%d/%y', '%Y-%m-%d',
                      '%b %d %Y', '%b %d, %Y', '%d %b %Y',
                      '%d %b, %Y', '%B %d %Y', '%B %d, %Y',
                      '%d %B %Y', '%d %B, %Y')
from django.conf.locale.en import formats
formats.DATE_INPUT_FORMATS = DATE_INPUT_FORMATS

En mi forma I'me usando:

def today():
    from datetime import date
    return date.today().strftime("%d.%m.%Y")

when = models.DateField(u'Когда', default=today)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top