Opened 8 years ago
Closed 8 years ago
#27240 closed New feature (duplicate)
Allow passing custom parameters to formset forms in admin
Reported by: | Alexey Rogachev | Owned by: | nobody |
---|---|---|---|
Component: | contrib.admin | Version: | dev |
Severity: | Normal | Keywords: | admin, form, formset, parameter |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
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:
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 docs (code omitted for brevity).
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:
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:
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
:
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.
Change History (14)
comment:1 by , 8 years ago
Description: | modified (diff) |
---|
comment:2 by , 8 years ago
Description: | modified (diff) |
---|
comment:3 by , 8 years ago
Description: | modified (diff) |
---|
comment:4 by , 8 years ago
Description: | modified (diff) |
---|
comment:5 by , 8 years ago
Description: | modified (diff) |
---|
comment:6 by , 8 years ago
Version: | 1.10 → master |
---|
comment:7 by , 8 years ago
Component: | contrib.admin → Documentation |
---|---|
Description: | modified (diff) |
Summary: | Docs - Passing custom parameters to formset forms in admin → Passing custom parameters to formset forms in admin |
comment:8 by , 8 years ago
Description: | modified (diff) |
---|
comment:9 by , 8 years ago
comment:10 by , 8 years ago
@knbk I understand that approach with class attribute is not elegant. As for your soultion - I need to do it for formset form (AttachmentForm
), not admin form. Admin form is different in my case and called EnterpriseAdminForm
. Formset has no get_form
related method, only get_form_kwargs(self, index):
method. which has no reference to request
.
comment:11 by , 8 years ago
InlineModelAdmin
has a get_formset()
method in which you can do the same.
comment:12 by , 8 years ago
@knbk Thanks, I think this can be also done in def get_formsets_with_inlines(self, request, obj=None):
or def get_inline_formsets(self, request, formsets, inline_instances, obj=None):
in regular admin.ModelAdmin
.
comment:13 by , 8 years ago
Did you come up with a solution? If so, maybe you can submit a patch if you still think an example is needed?
comment:14 by , 8 years ago
Component: | Documentation → contrib.admin |
---|---|
Resolution: | → duplicate |
Status: | new → closed |
Summary: | Passing custom parameters to formset forms in admin → Allow passing custom parameters to formset forms in admin |
Type: | Uncategorized → New feature |
Closing as a duplicate of #26607 (see :ticket:26607#comment:3).
I'm currently using the following pattern to solve the same problem with forms:
Using a class attribute can suffer from thread-safety issues when handling concurrent requests.