Cannot autopopulate date field in django template with widget_tweaks

I’m building a django app that basically is a service for legal guardians to automatically create invoices. For the necessary information about their patients that need to be printed on the invoice, I have a model Patient:

class Patient(models.Model):
    address_as = models.ForeignKey('AddressAs', on_delete=models.PROTECT)
    first_name = models.CharField('First Name', max_length=120)
    last_name = models.CharField('Last Name', max_length=120)
    birthday = models.DateField('Birthday')
    guardian = models.ForeignKey('Guardian', on_delete=models.CASCADE)
    court = models.ForeignKey(Court, related_name='patients', on_delete=models.PROTECT)
    record_number = models.CharField('Record Number', max_length=50)
    first_billing_date = models.DateField('Start of Legal Care', null=True, blank=True)
    billing_start = models.DateField('Start of Billing', null=True, blank=True)
    billing_end = models.DateField('End of Billing', null=True, blank=True)
    last_billing = models.DateField('Last Billing Date', null=True, blank=True)
    dutyscope_financial = models.BooleanField('Dutyscope Financial Care')
    is_wealthy = models.BooleanField('Patient is wealthy', default=False)
    taken_from_volunteer = models.BooleanField('Taken from Volunteer', default=False)
    given_to_volunteer = models.BooleanField('Given to Volunteer', default=False)

    def __str__(self):
        return f'{self.last_name}, {self.first_name}, geb. {self.birthday}'

and a very simple form class:

class PatientForm(forms.ModelForm):
    class Meta:
        model = Patient
        fields ='__all__'

and of course a view to create patients and a template.

So far, so good. Everything works. But now I want to add the possibility to edit the patient’s data. I created a new view for that:

def edit_patient(request, patient_id):
    patient = Patient.objects.get(id=patient_id)
    if request.method =='POST':
        form = PatientForm(request.POST or None, instance=patient)
        if form.is_valid():
            updated_patient = form.save()
            return HttpResponseRedirect(reverse('show-patients'))

    form = PatientForm(instance=patient)
    return render(request, 'edit-patient.html', {'form': form})

The corresponding template (with widget_tweaks and bootstrap):

{% extends 'base.html' %}

{% block content %}

{% load widget_tweaks %}

<h5 class="text-center">Einen Betreuten bearbeiten</h5>

<div class="container-xl">
    <form action="" method="POST">        
        {%csrf_token %}
        
        {% for hidden in form.hidden_fields %}
            {{ hidden }}
        {% endfor %}

        <label for="{{form.address_as.id_for_label }}">Anrede</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.address_as class+='form-control' %}
        </div>

        <label for="{{ form.first_name.id_for_label }}">Vorname</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.first_name placeholder='Vorname' class+='form-control' autocomplete='off' %}
        </div>

        <label for="{{ form.last_name.id_for_label }}">Nachname</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.last_name placeholder='Nachname' class+='form-control' autocomplete='off' %}
        </div>

        <label for="{{ form.birthday.id_for_label }}">Geburtsdatum</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.birthday type='date' class+='form-control' %}
        </div>
        
        <label for="{{ form.guardian.id_for_label }}">Betreuer</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.guardian placeholder='Betreuer' class+='form-control' %}
        </div>

        
        <label for="{{ form.court.id_for_label }}">Zuständiges Betreuungsgericht</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.court class+='form-control' %}
        </div>

        <label for="{{form.record_number.id_for_label }}">Aktenzeichen des Betreuungsgerichts</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.record_number placeholder='Aktenzeichen' class+='form-control' autocomplete='off' %}
        </div>

        <label for="{{form.first_billing_date.id_for_label }}">Erster Vergütungstag alter Betreuer</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.first_billing_date type='date' class+='form-control' %}
        </div>

        <label for="{{form.billing_start.id_for_label }}">Mein erster Vergütungstag</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.billing_start type='date' class+='form-control' %}
        </div>

        <label for="{{form.last_billing.id_for_label }}">ggf. Enddatum des letzten Vergütungszeitraums</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.last_billing type='date' class+='form-control' %}
        </div>

        <label for="{{form.billing_end.id_for_label }}">ggf. Enddatum der Betreuung</label>
        <div class="input-group mb-4">
            <span class="input-group-text">
                <i class="bi bi-person-fill"></i>
            </span>
            {% render_field form.billing_end type='date' class+='form-control' %}
        </div>


        <div class="form-check form-switch">
            {% render_field form.dutyscope_financial class+='form-check-input' type='checkbox' role='switch' id='checkbox-dutyscope-financial' %}
            <label for="checkbox-dutyscope-financial" class="form-check-label">Aufgabenkreis Vermögenssorge ist vorhanden (Für die Formulierung des Anschreibens)</label>
        </div>

        <div class="form-check form-switch">
            {% render_field form.taken_from_volunteer class+='form-check-input' type='checkbox' role='switch' id='checkbox-taken-from-volunteer' %}
            <label for="checkbox-taken-from-volunteer" class="form-check-label">Die Betreuung wurde von einem ehrenamtlichen Betreuer übernommen. (Zur Geltendmachung der gesonderten Pauschale nach §10 (2) VBVG bei der ersten Abrechnung)</label>
        </div>

        <div class="form-check form-switch">
            {% render_field form.given_to_volunteer class+='form-check-input' type='checkbox'role='switch' id='checkbox-given-to-volunteer' %}
            <label for="checkbox-given-to-volunteer" class="form-check-label">Die Betreuung wurde an einen ehrenamtlichen Betreuer abgegeben. (Zur Geltendmachung der gesonderten Pauschale nach §10 (3) VBVG bei Abgabe der Betreuung)</label>
        </div>

        <button type="submit" class="btn btn-success mt-3">Los gehts</button>
    </form>
</div>

{% endblock %}

But when I call edit_patient I get the template back without the birthday and the other dates filled in. All the other fields are rendered populated with the stored information.

What’s the problem with the dates?

I already asked the question on the django forum and got the hint to try the form without widget_tweaks. If I render it using {{ form.as_p }}, the date fields are populated. So... How do I get this to work with widget_tweaks?

OK, I figured it out after a lot of trial and error:

In my settings.py, I had LANGUAGE_CODE = 'de-de'

When the form was sent, it transmitted the data in the dd.mm.yyyy format, according to the set locale. This is the transmitted source of the page's input field:

<input type="date" name="birthday" value="10.04.2004" class="form-control" required="" id="id_birthday">

It seems that django or widget_tweaks don't play nice with locales here. According to W3 Schools, the HTML date input always needs the value in the format yyyy-mm-dd and only after that the browser renders the date according to it's locale.

I changed the locale in settings.py back to LANGUAGE_CODE = 'en-us' and everything works fine now:

<input type="date" name="birthday" value="2004-04-10" class="form-control" required="" id="id_birthday">

and also the form is rendered nicely.

Back to Top