Programming patterns¶
This is a list of programming patterns used in MedUX.
Forms pre-population with GET data¶
his is an often needed feature.
Just use a simple Mixin named PrepopulateFormViewMixin
:
# views.py
from django.views.generic import UpdateView
from medux.common.views.mixins import PrepopulateFormViewMixin
class PersonUpdateView(PrepopulateFormViewMixin, UpdateView):
model = ...
# or form_class = PersonUpdateForm
And you're done. Calling your FormView with e.g. /person/42/change/?first_name=James&last_name=Bond
will pre-populate the view with that values.
Forms with dependent fields¶
It's often needed in a Form to have a field dependent on another. MedUX uses HTMX and a few helpers to achieve that.
First, prepare your view, so that it accepts GET parameters that pre-populate your form. See Forms pre-population.
Now, inherit your form from DependencyFormMixin, and define a few attributes in Meta
, and a on_<field_name>_prepopulated()
method:
# forms.py
from django import forms
from django.urls import reverse
from medux.common.forms.mixins import DependencyFormMixin
class PersonUpdateForm(DependencyFormMixin, forms.ModelForm):
class Meta:
update_url = reverse("person:add")
field_dependencies = {"use_first_name": "#div_id_first_name"}
fields = ["first_name", "last_name"]
use_first_name = forms.BooleanField()
def on_changed_use_first_name(self, *args, **kwargs):
field = self.fields["first_name"]
field.disabled = True
# self.fields["friends"].queryset = Friend.objects.filter(
# tenant=self.instance.tenant
# )
The Mixin sets the correct HTMX attributes to your "use_first_name" field to dynamically update the #div_id_first_name
tag each
time the value of the checkbox changes. You define in the on_changed_<field_name>()
what should change.
Options e.g. would be disabling or hiding the field, or dynamically change select options (queryset).
Note
Keep in mind that if you are hiding a field using hidden_widget()
and re-render it using HTMX, the corresponding #id is removed from
the DOM, and you won't be able to hx-swap into it again.
Note
When you disable a required field, you might get problems with your validation logic. Make sure your form's clean() method deals with that.
The update_url
attribute can be dynamically created too by overriding the get_update_url()
method, e.g. for Create-/UpdateForm
s:
def get_update_url(self):
if self.instance.pk:
return reverse("person:update", args=(self.instance.pk,))
else:
return reverse("person:add")