Hey,
Basically, I need to create a form (an inline formset actually), that contains 1 input field (a %) with an associated label/description (to help user), as well as some foreign keys. How many times, and what the description should be for each input field depends on another table. Some models.py pseudo-code to give an idea:
class MetaGroup(Model)
description = CharField(....)
< other irrelevant fields >
class Discounts(Model)
fk_metagroup = ForeignKey(MetaGroup, ...)
fk_client = ForeignKey(Client, ....)
percentage = Decimal(....)
The CONTENT of the MetaGroup
table is what determines the things on which discounts could be applied. So basically, an discount entry is related to a specific client (fk_client
) and to a specific MetaGroup (fk_metagroup
). The description comes from fk_metagroup.description
, and then the % determines what the discount is for that client with items from that MetaGroup. That all gets saved in the Discounts table, which is basically a list of all the discounts for on all the metagroups for all the clients. (I know this isn’t a very good structure to store that information, but that’s the way it’s been built and we’re not refactoring that now, so…)
For instance, the content of MetaGroup would look like:
In which case, my DiscountsForm
would display 3 rows, with Plastic cable, Led Lights, Actuator in the 1st column, and the input fields would be 1 decimal fields for each (the applicable discount on each of those group). In a separate form, the user can create a new group (say, pk=4, Description=Halogene Lights). In that case, my Discounts forms would need to offer another row for the new MetaGroup “Halogene Lights”, etc. The Discount formset actually appears within the ClientForm
as an inline_formset
of the ClientForm
, so setting the fk_client
is straightforward. I will have to manually set the fk_metagroup
manually when saving the form however.
I’m not sure what the best way to go about this is. Currently thinking something like:
class DiscountsForm(ModelForm):
class Meta:
model = Discount
fields = ["percentage"]
DiscountFormset = inlineformset_factory(Client, Discount,
form=DiscountForm,
extra=1,
can_delete=False)
However… a few issues:
-
extra=… isn’t a set number. I guess I could set it to some callback function (e.g.
extra=how_many_discounts
, withdef how_many_discounts():
defined above in forms.py, checking with the MetaGroup how many forms needs to be in the formset. -
I will need to put the associated descriptions (and the associated
metagroup.pk
so I can setfk_metagroup
when saving eachDiscountForm
instance) in the context for the template to build the table to display to the user somehow. I’m thinking an inclusion_tag could do that. But then I’m somewhat spreading out the logic for how that form works. Can I add a method to myDiscountForm
class and call that from the template to manage this?
Assume I get, say 4 discounts groups as per example above, along with 4 input fields from my DiscountsForm
, then I would iterate on that in the template with a for loop, building my table. When the user saves the Client form, I will have to manage adding fk_metagroup
to each new Discount instance (overriding form_valid()
or save()
or something like that the view… using a CreateView/Edit).
Any better ideas? Things I’m not seeing?