Pre-populate an inline FormSet?

后端 未结 10 1513
自闭症患者
自闭症患者 2020-11-30 18:25

I\'m working on an attendance entry form for a band. My idea is to have a section of the form to enter event information for a performance or rehearsal. Here\'s the model

相关标签:
10条回答
  • 2020-11-30 19:14

    I ran into this question -6 years later- , and we are on Django 1.8 now.

    Still no perfectly clean , short answer to the question.

    The issue lies in the ModelAdmin._create_formsets() github ; My Solution is to override it, and inject the initial data i want somewhere around the highlighted lines in the github link .

    I also had to override the InlineModelAdmin.get_extra() in order "have room" for the initial data provided. Left default it will display only 3 of the initial data

    I believe there should be a more cleaner answer in the upcoming versions

    0 讨论(0)
  • 2020-11-30 19:14

    I'm having the same problem. I'm using Django 1.9, and I've tried the solution proposed by Simanas, overriding the property "empty_form", adding some default values in de dict initial. That worked but in my case I had 4 extra inline forms, 5 in total, and only one of the five forms was populated with the initial data.

    I've modified the code like this (see initial dict):

    class MyFormSet(forms.models.BaseInlineFormSet):
        model = MyModel
    
        @property
        def empty_form(self):
            initial = {'model_attr_name':'population_value'}
            if self.parent_obj:
                initial['name'] = self.parent_obj.default_child_name
            form = self.form(
                auto_id=self.auto_id,
                prefix=self.add_prefix('__prefix__'),
                empty_permitted=True, initial=initial
            )
            self.add_fields(form, None)
            return form    
    
    class MyModelInline(admin.StackedInline):
        model = MyModel
        formset = MyFormSet
    
        def get_formset(self, request, obj=None, **kwargs):    
            formset = super(HostsSpaceInline, self).get_formset(request, obj, **kwargs)
            formset.parent_obj = obj
            return formset
    

    If we find a way to make it work when having extra forms, this solution would be a good workaround.

    0 讨论(0)
  • 2020-11-30 19:17

    Using django 1.7 we ran into some issues creating an inline form with additional context baked into the model (not just an instance of the model to be passed in).

    I came up with a different solution for injecting data into the ModelForm being passed in to the form set. Because in python you can dynamically create classes, instead of trying to pass in data directly through the form's constructor, the class can be built by a method with whatever parameters you want passed in. Then when the class is instantiated it has access to the method's parameters.

    def build_my_model_form(extra_data):
        return class MyModelForm(forms.ModelForm):
            def __init__(self, *args, **kwargs):
                super(MyModelForm, self).__init__(args, kwargs)
                # perform any setup requiring extra_data here
    
            class Meta:
                model = MyModel
                # define widgets here
    

    Then the call to the inline formset factory would look like this:

    inlineformset_factory(ParentModel, 
                          MyModel, 
                          form=build_my_model_form(extra_data))
    
    0 讨论(0)
  • 2020-11-30 19:22

    Just override "save_new" method, it worked for me in Django 1.5.5:

    class ModelAAdminFormset(forms.models.BaseInlineFormSet):
        def save_new(self, form, commit=True):
            result = super(ModelAAdminFormset, self).save_new(form, commit=False)
            # modify "result" here
            if commit:
                result.save()
            return result
    
    0 讨论(0)
提交回复
热议问题