Search code examples
djangodjango-formsbootstrap-datepicker

Django ModelForm - Bootstrap DateTimePicker


I'm having some problems for processing DjangoModelForm and bootstrap-datepicker to select a specific month

First of all I get this error when I access the form

The specified value "01/04/2023" does not conform to the required format.  The format is "yyyy-MM" where yyyy is year in four or more digits, and MM is 01-12

And after selecting manually the month I get

periodo: Enter a valid date.
limite_retroactividad: Enter a valid date.

I tried to handle it with a javascript script but it's working just for the initial dates but not for saving the data.

This is what I have:

forms.py

class RegistroGestionForm(ModelForm):
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super().__init__(*args, **kwargs)

    def clean(self):
        cleaned_data = super().clean()
        periodo = cleaned_data.get('periodo')
        limite_retroactividad = cleaned_data.get('limite_retroactividad')

        if periodo and limite_retroactividad:
            if periodo < limite_retroactividad:
                # Add validation error
                self.add_error('limite_retroactividad', 'El periodo no puede ser menor al límite de retroactividad')
        return cleaned_data

    class Meta:
        model = RegistroGestion
        fields = ['periodo', 'estado', 'limite_retroactividad']
        widgets = {
            'limite_retroactividad': DateInput(
                attrs={
                    'type': "month",
                    'class': "form-select mb-3"
                }
            ),
            'periodo': DateInput(
                attrs={
                    'type': "month",
                    'class': "form-select mb-3"
                }
            ),
        }

views.py

class RegistroGestionUpdateView(UpdateView):
    model = RegistroGestion
    form_class = RegistroGestionForm
    context_object_name = 'registro_gestion'
    template_name = 'esquema_liquidacion/registro_gestion_form.html'

    def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
        context = super().get_context_data(**kwargs)
        context['update'] = True
        return context

    def get_success_url(self):
        return reverse('registro-gestion-list')

    def form_valid(self, form):
        if form.is_valid():
            # Perform custom actions if needed
            return super().form_valid(form)
        else:
            # Handle the case where the form is not valid
            # You can add debugging output or log errors here
            return self.render_to_response(self.get_context_data(form=form))

form.html

{% extends "sitio/base.html" %}
{% load static %}
{% load tz %}

{% block site_title %}
Editar Registro Gestión {{ registro_gestion.division_personal_empresa.division_personal }} - {{ registro_gestion.division_personal_empresa.empresa }}
{% endblock site_title%}

{% block extra_head %}
<!-- Bootstrap Date-Picker Plugin -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.4.1/js/bootstrap-datepicker.min.js"></script>
<script src="{% static 'lib/bootstrap-datepicker/bootstrap-datepicker.min.js' %}"></script>
<link rel="stylesheet" href="{% static 'lib/bootstrap-datepicker/bootstrap-datepicker3.css' %}"/>
{% endblock extra_head %}

{% block site_content %}

<div class="container my-3">
    {% if form.errors %}
    <div class="alert alert-danger">
        <strong>Errores observados</strong>
        <ul>
            {% for k, error in form.errors.items %}
            <li>
                <b>{{k}}</b>: {{ error.0 }}
            </li>
            {% endfor %}
        </ul>
    </div>
    {% endif %}
    <div class="row">
        <div class="col-12">
        <p class="h3 text-center mb-5">
            Editar Registro Gestión <b>{{ registro_gestion.division_personal_empresa.division_personal }} - {{ registro_gestion.division_personal_empresa.empresa }}</b>
        </p>
        <form method="POST" class="mb-3">
        {% csrf_token %}
            <div class="row">
                <div class="col-4">
                    {{ form.periodo.label_tag }}
                    {{ form.periodo }}
                </div>
                <div class="col-4">
                    {{ form.estado.label_tag }}
                    {{ form.estado }}
                </div>
                <div class="col-4">
                    {{ form.limite_retroactividad.label_tag }}
                    {{ form.limite_retroactividad }}
                </div>
            </div>
            <br>
            <div class="payroll-form-action-buttons text-center">
                <button class="btn btn-primary">Actualizar Registro Gestión</button>
            </div>
        </form>
        </div>
    
{% endblock site_content %}

I appreciate any help


Solution

  • It was finally solved just adding format='%Y-%m' to the form

    It's working now this way:

    class Meta:
            model = RegistroGestion
            fields = ['periodo', 'estado', 'limite_retroactividad']
            widgets = {
                'limite_retroactividad': DateInput(
                    format='%Y-%m',
                    attrs={
                        'type': "month",
                        'class': "form-select mb-3"
                    }
                ),
                'periodo': DateInput(
                    format='%Y-%m',
                    attrs={
                        'type': "month",
                        'class': "form-select mb-3"
                    }
                ),
            }