2009-09-21 216 views
7

Estoy tratando de encontrar una forma sencilla de crear formularios que muestren fechas en el formato australiano (dd/mm/aaaa). Esta fue la única forma en que pude encontrar para hacerlo. Parece que debería haber una mejor solución.Creación de formularios Django.DateField show use formato de fecha local

A tener en cuenta:

  • Creado Un nuevo widget que hace valor de fecha en el formato dd/mm/aaaa
  • campo nueva fecha Creado para anteponer la cadena de fecha localizar formato de la lista de valores que intenta utilizar

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

¿Me falta 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() 
+2

Una alternativa simple es confiar en un widget de calendario de JavaScript para hacer la localización. Uno que usamos simplemente oculta mi campo de fecha y crea otro con el formato local especificado. – olivergeorge

+0

¿Alguna información sobre widgets particulares y conectar un widget? – dfrankow

+0

Supongo que debería consultar la pregunta sobre stackflow: http://stackoverflow.com/questions/114068/best-javascript-calendar-control. – dfrankow

Respuesta

10

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

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

Puede que no necesite crear su propio widget solo para representar la fecha en el formato correcto en la primera pantalla de formulario. Simplemente use el parámetro format para el widget DateInput y debería 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) 

usted podría utilizar formfield_callback (Véase la accepted answer para esta pregunta alejadas), que significa:

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 MyDateField clase, pero podría introducir - si desea que cada clase de formulario llame al customize_fields - la necesidad de un descendiente ModelForm, implementando 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, digamos que 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 
    

    está sobrescribiendo el campo de formulario devuelto por customize_fields, por lo que pierde completamente la personalización.

Creo que su enfoque es más legible.

+0

También, échele un vistazo a esto: http://code.djangoproject.com/ticket/7980 – cethegeek

6

He utilizado este enfoque simple antes: simplemente configure el atributo 'formato' del DateField.Widget en la inicialización 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'] 
0

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) 
2

todas las cosas widget personalizado pueden ser anuladas.

He aquí 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 según la configuración regional. Si está navegando desde los Estados Unidos, Django, de forma predeterminada, seleccionará 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 cambiar el formato es crear su propio módulo de formato, anulando el valor predeterminado de Django para la configuración regional en cuestión. Para eso, mira en FORMAT_MODULE_PATH. Si todo lo que intentas hacer es anular el formato de fecha predeterminado, te digo que te salves un poco de tiempo y un parche de mono. Agregué esto a mi archivo de configuración y todo parece funcionar espléndidamente con mi formato predeterminado preferido:

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