AndrewIngram / django-extra-views

Django's class-based generic views are awesome, let's have more of them.
MIT License
1.38k stars 172 forks source link

How do you pass variables as kwargs to formset forms? #179

Closed coler-j closed 5 years ago

coler-j commented 5 years ago

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.

coler-j commented 5 years ago

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)
        .....
jonashaag commented 5 years ago

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.

coler-j commented 5 years ago

But i need to get info from the instance. The kwargs dict only seems to let you pass statically defined variables. Can you show an example?

On Sun, Nov 11, 2018, 7:32 AM Jonas Haag <notifications@github.com wrote:

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

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/AndrewIngram/django-extra-views/issues/179#issuecomment-437666438, or mute the thread https://github.com/notifications/unsubscribe-auth/AHeff7De4CZp7MiKBv0f49nttG6wb2VGks5uuBjsgaJpZM4YYEX8 .

jonashaag commented 5 years ago

How would you do it with vanilla Django?

coler-j commented 5 years ago

I have an example in my original question.

On Sun, Nov 11, 2018, 12:45 PM Jonas Haag <notifications@github.com wrote:

How would you do it with vanilla Django?

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/AndrewIngram/django-extra-views/issues/179#issuecomment-437689731, or mute the thread https://github.com/notifications/unsubscribe-auth/AHeff99OeoKSmVNOufJ5IwLR9jZa3NTsks5uuGJQgaJpZM4YYEX8 .

jonashaag commented 5 years ago

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

jonashaag commented 5 years ago

Since this library is mostly wrapping Django functions

coler-j commented 5 years ago

In a FBV where I init the formset I would do the following (sorry for formatting im on my phone). Passing to form of formset with form_kwargs:

MyInlineFormSet(request.POST, instance=listing, prefix="nested", 
    form_kwargs={'related_schedule_type': post_schedule_type})
jonashaag commented 5 years ago

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

jonashaag commented 5 years ago

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

sdolemelipone commented 5 years ago

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: https://github.com/AndrewIngram/django-extra-views/blob/52d9f7a8a79142d307d9ea87ca55a6cb811b89ba/extra_views/advanced.py#L19

coler-j commented 5 years ago

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

jjpaulo2 commented 1 year ago

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