#27240: Docs - Passing custom parameters to formset forms in admin
-----------------------------+---------------------------------------------
     Reporter:  arogachev    |      Owner:  nobody
         Type:               |     Status:  new
  Uncategorized              |
    Component:               |    Version:  1.10
  contrib.admin              |
     Severity:  Normal       |   Keywords:  admin, form, formset, parameter
 Triage Stage:  Unreviewed   |  Has patch:  0
Easy pickings:  0            |      UI/UX:  0
-----------------------------+---------------------------------------------
 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]

 {{{#!python
 enterprise = Enterprise()
 AttachmentFormSet = generic_inlineformset_factory(Attachment,
 form=AttachmentForm, max_num=3, validate_max=True)
 if request.method == 'POST':
     form = EnterpriseForm(request.POST, request.FILES,
 instance=enterprise, user=request.user)
     attachment_formset = AttachmentFormSet(request.POST, request.FILES,
 instance=enterprise, form_kwargs = {'user': request.user})
     # ...
 else:
     form = EnterpriseForm(instance=enterprise, user=request.user)
     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
     readonly_fields = ('is_image', 'user', 'created_at')
     max_num = 3

 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>
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/052.34a9dc5b510c237991c303e5993d2276%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to