AndrewIngram/django-extra-views

How do you pass variables as kwargs to formset forms?

coler-j opened this issue · 13 comments

If I have a View like this:

class CreateListingView(NamedFormsetsMixin, CreateWithInlinesView):
    model = MyModel
    form_class = MyModelForm
    inlines = [InlineFormsetInlineDerp1, InlineFormsetInlineDerp2]
    inlines_names = ['derp1', 'derp2']

Is there a function on that view like this:

def get_formset_kwargs(...):
    kwargs.update({'my_variable': some.variable})

So that in my FORM of the formset I can do this:

class Derp1Form(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.my_variable= kwargs.pop('my_variable', None)
        super().__init__(*args, **kwargs)
        .....

I have been hunting through this documentation and through the source, and haven't been able to do this yet, but this is a pretty common pattern. Almost thinking of going back to my FBV as I am wasting too much time on this library.

I feel kinda disgusted with this code, but I ended up doing the following to get the values I needed. Can someone please show me a better way?

In my form (within the formset) I only need the data for logic during POST / clean. This was only possible because the data that I needed was FROM the parent model instance:

class Derp1Form(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        post_data = kwargs.get('data', None)
        self.my_variable = None
        if post_data:
           self.my_variable = post_data.get('main-form-prefix-my_variable', None)
        super().__init__(*args, **kwargs)
        .....

Are you looking for Django's form_kwargs option? You can provide it to django extra views via the formset_kwargs dict, or via overriding the get_formset_kwargs method.

How would you do it with vanilla Django?

I meant how would you do it without Django extra views in the first place.

Since this library is mostly wrapping Django functions

@sdolemelipone maybe you understand better than me what's the question/problem here. I'm not sure what @coler-j is looking for.

Maybe you're looking for self.object or self.object_list which should be available in get_formset_kwargs.

Hi @coler-j, there is a function as you suggested but it's on the InlineFormSetFactory and not the view, like so:

InlineFormsetInlineDerp1(extra_views.InlineFormSetFactory):
    def get_formset_kwargs(self):
        kwargs = super().get_formset_kwargs()
        kwargs['form_kwargs'] = some.variable
        return kwargs

Note that the parent model instance, view, view kwargs and request are all available as attributes of the InlineFormSetFactory:

def __init__(self, parent_model, request, instance, view_kwargs=None, view=None):

Thanks! @sdolemelipone that is what I was looking for!

Thanks for it @sdolemelipone. You have been saved me! ❤️