#27240: Docs - Passing custom parameters to formset forms in admin
-------------------------------------+-------------------------------------
     Reporter:  arogachev            |                    Owner:  nobody
         Type:  Uncategorized        |                   Status:  new
    Component:  contrib.admin        |                  Version:  1.10
     Severity:  Normal               |               Resolution:
     Keywords:  admin, form,         |             Triage Stage:
  formset, parameter                 |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by arogachev:

Old description:

> I have `Enterprise` model and related model `Attachment`. Attachments are
> managed using formsets in both frontend and backend.
>
> I use custom form to handle attachments, and it uses additional `user`
> kwarg:
>
> {{{#!python
> def __init__(self, *args, **kwargs):
>     self.user = kwargs.pop('user', None)
>     super(AttachmentForm, self).__init__(*args, **kwargs)
> }}}
>
> I need to fill this parameter with `request.user` value. In frontend I
> use the method recommended in
> [https://docs.djangoproject.com/en/1.9/topics/forms/formsets/#passing-
> custom-parameters-to-formset-forms docs] (code omitted for brevity).
>
> {{{#!python
> enterprise = Enterprise()
> AttachmentFormSet = generic_inlineformset_factory(Attachment,
> form=AttachmentForm, max_num=3, validate_max=True)
> if request.method == 'POST':
>     attachment_formset = AttachmentFormSet(request.POST, request.FILES,
> instance=enterprise, form_kwargs = {'user': request.user})
> else:
>     attachment_formset = AttachmentFormSet(instance=enterprise,
> form_kwargs = {'user': request.user})
> }}}
>
> But docs do not cover how achieve the same thing in backend using Django
> Admin.
>
> In admin I have:
>
> {{{#!python
> class AttachmentInline(GenericTabularInline):
>     model = Attachment
>     form = AttachmentForm
>
> class EnterpriseAdmin(MyCompareVersionAdmin):
>     inlines = [AttachmentInline]
>    # ...
> }}}
>
> It's unclear where and how we need to grab and pass `request.user`
> parameter to `AttachmentForm`. After some trial and error, I ended up
> with this workaround:
>
> {{{#!python
> class EnterpriseAdmin(MyCompareVersionAdmin):
>     inlines = [AttachmentInline]
>
>     def save_related(self, request, form, formsets, change):
>         AttachmentForm.user = request.user
>         super(MyCompareVersionAdmin, self).save_related(request, form,
> formsets, change)
> }}}
>
> Related modifications in `AttachmentForm`:
>
> {{{#!python
> user = None
>
> def __init__(self, *args, **kwargs):
>     user = kwargs.pop('user', None)
>     if user:
>         self.user = user
>         super(AttachmentForm, self).__init__(*args, **kwargs)
> }}}
>
> So I turned `user` to class attribute and set it from kwargs only if it's
> passed and it's not `None`.
>
> It works, but I don't like this approach and It looks like a hack for me.
>
> I think the solution on how to properly do it should be added to the docs
> in the same section along with frontend solution.

New description:

 I have `Enterprise` model and related model `Attachment`. Attachments are
 managed using formsets in both frontend and backend.

 I use custom form to handle attachments, and it uses additional `user`
 kwarg:

 {{{#!python
 def __init__(self, *args, **kwargs):
     self.user = kwargs.pop('user', None)
     super(AttachmentForm, self).__init__(*args, **kwargs)
 }}}

 I need to fill this parameter with `request.user` value. In frontend I use
 the method recommended in
 [https://docs.djangoproject.com/en/1.9/topics/forms/formsets/#passing-
 custom-parameters-to-formset-forms docs] (code omitted for brevity).

 {{{#!python
 enterprise = Enterprise()
 AttachmentFormSet = generic_inlineformset_factory(Attachment,
 form=AttachmentForm, max_num=3, validate_max=True)
 if request.method == 'POST':
     attachment_formset = AttachmentFormSet(request.POST, request.FILES,
 instance=enterprise, form_kwargs = {'user': request.user})
 else:
     attachment_formset = AttachmentFormSet(instance=enterprise,
 form_kwargs = {'user': request.user})
 }}}

 But docs do not cover how achieve the same thing in backend using Django
 Admin.

 In admin I have:

 {{{#!python
 class AttachmentInline(GenericTabularInline):
     model = Attachment
     form = AttachmentForm

 class EnterpriseAdmin(MyCompareVersionAdmin):
     inlines = [AttachmentInline]
 }}}

 It's unclear where and how we need to grab and pass `request.user`
 parameter to `AttachmentForm`. After some trial and error, I ended up with
 this workaround:

 {{{#!python
 class EnterpriseAdmin(MyCompareVersionAdmin):
     inlines = [AttachmentInline]

     def save_related(self, request, form, formsets, change):
         AttachmentForm.user = request.user
         super(MyCompareVersionAdmin, self).save_related(request, form,
 formsets, change)
 }}}

 Related modifications in `AttachmentForm`:

 {{{#!python
 user = None

 def __init__(self, *args, **kwargs):
     user = kwargs.pop('user', None)
     if user:
         self.user = user
         super(AttachmentForm, self).__init__(*args, **kwargs)
 }}}

 So I turned `user` to class attribute and set it from kwargs only if it's
 passed and it's not `None`.

 It works, but I don't like this approach and It looks like a hack for me.

 I think the solution on how to properly do it should be added to the docs
 in the same section along with frontend solution.

--

--
Ticket URL: <https://code.djangoproject.com/ticket/27240#comment:4>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/067.236e3710d5c7cd7066a46f5ab1da6af8%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to