El Problema
Los campos de fecha en Django pueden comportarse inconsistentemente: a veces devuelven objetos datetime, a veces strings en formato localizado, y cuando hay errores de validación, no siempre se muestran correctamente en el template.
Solución Completa
1. Configuración Global (settings.py)
# settings.py
DATE_INPUT_FORMATS = ['%Y-%m-%d'] # Formato para parsear inputs
USE_L10N = False # Desactiva localización
DATE_FORMAT = 'Y-m-d' # Formato de visualización
2. Filtro Personalizado (templatetags/filters.py)
from django import template
import datetime
register = template.Library()
@register.filter
def to_date_input(value):
"""
Convierte cualquier valor a formato YYYY-MM-DD para inputs type="date"
"""
if not value:
return ''
# Si ya está en formato YYYY-MM-DD
if isinstance(value, str) and len(value) == 10 and value[4] == '-' and value[7] == '-':
return value
# Si es objeto date/datetime
if isinstance(value, (datetime.date, datetime.datetime)):
return value.strftime('%Y-%m-%d')
# Para cualquier otro caso
try:
return value.strftime('%Y-%m-%d')
except AttributeError:
return str(value)
3. Uso en el Template
{% load filters %}
<input type="date"
name="fecha_ingreso"
class="form-control"
value="{{ form.fecha_ingreso.value|to_date_input }}">
<!-- Debug opcional -->
<div style="background: #f0f0f0; padding: 10px; margin: 10px 0;">
<strong>DEBUG:</strong><br>
Valor original: "{{ form.fecha_ingreso.value }}"<br>
Valor convertido: "{{ form.fecha_ingreso.value|to_date_input }}"
</div>
¿Por qué esta solución funciona?
✅ Maneja todos los casos:
- Valores None o vacíos
- Strings en formato YYYY-MM-DD
- Objetos datetime/date
- Strings en otros formatos
✅ Mantiene la separación de concerns:
- La lógica de formato en el filtro
- La presentación en el template
- Configuración global en settings
⚠️ Importante: Recuerda reiniciar el servidor de Django después de crear o modificar los templatetags.
Estructura de Archivos
tu_app/
├── templatetags/
│ ├── __init__.py
│ └── filters.py # Filtros personalizados
├── templates/
│ └── tu_template.html
└── settings.py # Configuración global
Comentarios
Publicar un comentario