Given the following models:
class ParentModel(models.Model):
name = models.CharField(max_length=255)
class ChildModel(models.Model):
name = models.CharField(max_length=255)
weight = models.FloatField()
parent = models.ForeignKey("ParentModel")
And the following ModelForm that has some extra fields for ChildModel:
class ChildBalancingForm(forms.ModelForm):
min_weight = forms.FloatField(min_value=0.0, max_value=1.0, required=True, label="Min Weight")
max_weight = forms.FloatField(min_value=0.0, max_value=1.0, required=True, label="Max Weight")
class Meta:
model = ChildModel
fields = []
I have a parent model that has many children. I need to use some math to balance the weights of the children (with some bounds on the minimum and maximum weight of each child). So, I am trying to create a formset that allows a user to enter a min and a max weight for each child to submit for rebalancing. I want to specify a default minimum weight, and a default maximum weight in said form. Thus, I have the following in my view:
# code to load up the parent whose children are being rebalanced..
# code to set a value for default_min_weight and default_max_weight
# code to get the number of children of said parent, num_children
initial_data = [{"min_weight": default_min_weight, "max_weight": default_max_weight},] * num_children
BalancingFormSet = modelformset_factory(ChildModel, form=ChildBalancingForm, extra=0, can_delete=False, min_num=num_children, max_num=num_children)
formset = BalancingFormSet(queryset=parent.childmodel_set.all(), initial=initial_data)
However when I output the form, the default values I specified for min_weight and max_weight do not show (the fields are just empty). What is the proper way to specify initial values for those extra fields in my formset?
The problem here is that ModelFormSet
s redefine the initial
parameter to apply to the extra forms. However, source-diving reveals that we can just re-add it under a different name:
# code to load up the parent whose children are being rebalanced..
# code to set a value for default_min_weight and default_max_weight
# code to get the number of children of said parent, num_children
initial_data = [{"min_weight": default_min_weight, "max_weight": default_max_weight},] * num_children
BalancingFormSetBase = modelformset_factory(ChildModel, form=ChildBalancingForm, extra=0, can_delete=False, min_num=num_children, max_num=num_children)
class BalancingFormSet(BalancingFormSetBase):
def __init__(self, *args, **kwargs):
initial_forms_initial = kwargs.pop("initial_forms_initial", None)
super(BalancingFormSet, self).__init__(*args, **kwargs)
if not initial_forms_initial is None:
self.initial = initial_forms_initial
formset = BalancingFormSet(queryset=parent.childmodel_set.all(), initial_forms_initial=initial_data)
I (sloppily) tested equivalent code on Django 1.8, and it didn't interfere with instance attributes - I didn't check what happens if you have extra
set to something that isn't 0
, though.
Starting with 1.9, overriding the new get_form_kwargs
method may be more robust as it doesn't assume that we can overwrite the initial
attribute without unwanted consequences.
Of course, if you have this pattern more than once, it might make sense to put this __init__
definition into a base class or a mixin - however, for clarity and simplicity, I'm not doing this here.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.