#27240: Passing custom parameters to formset forms in admin
-------------------------------------+-------------------------------------
Reporter: arogachev | Owner: nobody
Type: Uncategorized | Status: new
Component: Documentation | Version: master
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
-------------------------------------+-------------------------------------
Changes (by arogachev):
* component: contrib.admin => Documentation
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(admin.ModelAdmin):
> inlines = [AttachmentInline]
>
> def save_related(self, request, form, formsets, change):
> AttachmentForm.user = request.user
> super(EnterpriseAdmin, 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(admin.ModelAdmin):
inlines = [AttachmentInline]
def save_related(self, request, form, formsets, change):
AttachmentForm.user = request.user
super(EnterpriseAdmin, 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.
I'm not sure If I can't find the proper way to do that or it's really not
implemented for admin.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/27240#comment:7>
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 [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/067.59af14ee834798b578854d53dd6a798b%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.