Weeknotes 2023-09-25

Anything worth doing is worth doing badly. — G. K. Chesterton

Worked on frontend stuff again last week. I think my favorite way to combine htmx with Alpine.js when you have to pass some parameters is to just use the htmx API like this:

<div
      {# fmt:off #}
      x-data="{
        value: false,
        toggle() {
          this.value = ! this.value;
          htmx.ajax(
            'GET',
            '{% url 'some-detail-url' pk=model.pk %}', {
              target: '#some_target_id',
              values: { toggle_state: this.value }
          });
        }
      }"
      {# fmt:on #}
    x-id="['toggle-label']"
>
    <!-- ... later on, you'll just have -->
    <button x-ref="toggle" @click="toggle()" type="button" role="switch" :aria-checked="value" :aria-labelledby="$id('toggle-label')">Toggle</button>
</div>

Didn't have much time for my own projects, but released django-cast 0.2.22 because I forgot to do this last week 😑. Then I noticed that I forgot to publish a TIL post about the new STORAGES setting in Django 4.2. Middle of the week I went to the Django Cologne meetup and had many interesting discussions with different people. Sarah talked a bit about the djangonaut.space project, which I'm also interested in, so it was a really nice evening.

Talking about doing things badly. I tried to upgrade an old project to pydantic > 2 and failed spectacularly. After upgrading I got this error message:

super().__init__(
File "../pydantic/main.py", line 165, in __init__
__pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)
pydantic_core._pydantic_core.ValidationError: 1 validation error for Settings
db_engine
Field required [type=missing, input_value={'database_url': 'postgre... 'services_development'}, input_type=dict]
For further information visit https://errors.pydantic.dev/2.3/v/missing

And somehow I misread this error message as being about the database_url field. But it was actually complaining that the db_engine field was missing. The problem was caused by a db_engine: typing.Any field that was None by default in pydantic < 2 and does not get a default value in pydantic > 2 as documented in the migration guide.

This took me far too long to fix, and it felt far too similar to the dread caused by updating old Javascript projects.