1👍
For those that might come across this, here is my current solution (also open to improvements):
forms.py
class ItemAspectForm(forms.ModelForm):
class Meta:
model = ItemAspect
exclude = ("item",)
views.py
class ItemAspectCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = ItemAspectForm
form_class = ItemAspectForm
template_name = "inventory/item_aspect_form.html"
success_message = _("Item aspect successfully created")
def get_context_data(self, **kwargs):
item = Item.objects.get(id=self.kwargs["id"])
aspects = [Aspect(**aspect) for aspect in get_item_aspects_for_category(item)["aspects"]]
context = super().get_context_data()
ItemAspectFormSet = modelformset_factory(
model=ItemAspect,
form=ItemAspectForm,
can_delete=True,
extra=len(aspects)
)
if self.request.POST:
context["formset"] = ItemAspectFormSet(self.request.POST)
else:
context["formset"] = ItemAspectFormSet()
for aspect, form in zip(aspects, context["formset"]):
if aspect.has_values:
form.fields["value"] = forms.ChoiceField(
choices=((value, value) for value in aspect.values)
)
form.fields["value"].required = aspect.is_required
form.fields["value"].label = aspect.name
form.fields["name"].initial = aspect.name
form.fields["name"].widget = forms.HiddenInput()
return context
def form_valid(self, form):
assert (
self.request.user.is_authenticated
) # for mypy to know that the user is authenticated
context = self.get_context_data()
formset = context["formset"]
item = Item.objects.get(id=self.kwargs["id"])
if formset.is_valid():
aspect_forms = formset.save(commit=False)
for aspect_form in aspect_forms:
aspect_form.item = item
aspect_form.save()
return super().form_valid(form)
item_aspects_create = ItemAspectCreateView.as_view()
Source:stackexchange.com