Opened 2 years ago
Closed 2 years ago
#33995 closed Bug (fixed)
Rendering empty_form crashes when empty_permitted is passed to form_kwargs
Reported by: | claypooj21 | Owned by: | Bhuvnesh |
---|---|---|---|
Component: | Forms | Version: | 4.1 |
Severity: | Normal | Keywords: | formset, empty_form, empty_permitted, form |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | yes | UI/UX: | no |
Description
Issue
When explicitly setting form_kwargs = {'empty_permitted':True}
or form_kwargs = {'empty_permitted':False}
, a KeyError occurs when rendering a template that uses a formset's empty_form
.
Expected Behavior
empty_permitted
is ignored for formset.empty_form
since empty_permitted
is irrelevant for empty_form
, as empty_form
is not meant to be used to pass data and therefore does not need to be validated.
Steps to Reproduce
# views.py from django.shortcuts import render from .models import MyModel def test_view(request): context = {} ff = modelformset_factory(MyModel, fields = ['a_field']) context['formset'] = ff( queryset = MyModel.objects.none(), form_kwargs = {'empty_permitted':True} # or form_kwargs = {'empty_permitted':False} ) return render(request, 'my_app/my_model_formset.html', context) # urls.py from django.urls import path, include from .views import test_view urlpatterns = [ path('test', test_view) ] # my_model_formset.html {% extends "my_app/base.html" %} {% block content %} <form id="my-form" method="post"> {% csrf_token %} {{ formset }} <input type="submit" value="Save"> </form> {{ formset.empty_form }} {% endblock %}
Change History (6)
comment:1 by , 2 years ago
Easy pickings: | set |
---|---|
Summary: | Key Error 'empty_permitted' when rendering 'formset.empty_form' → Rendering empty_form crashes when empty_permitted is passed to form_kwargs |
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 2 years ago
The KeyError
is confusing here. It's raised because we're in the context of rendering the template:
>>> self.form(empty_permitted=True, **self.get_form_kwargs(None)) Traceback (most recent call last): File "/Users/carlton/Projects/Django/django/django/template/base.py", line 880, in _resolve_lookup current = current[bit] File "/Users/carlton/Projects/Django/django/django/forms/formsets.py", line 118, in __getitem__ return self.forms[index] TypeError: list indices must be integers or slices, not str During handling of the above exception, another exception occurred: Traceback (most recent call last): File "<console>", line 1, in <module> KeyError: 'empty_permitted'
The real exception is better seen using the formset directly:
>>> from ticket_33995.models import MyModel >>> from django.forms import modelformset_factory >>> ff = modelformset_factory(MyModel, fields=['name']) >>> formset = ff(queryset=MyModel.objects.none(), form_kwargs={'empty_permitted': True}) >>> formset.empty_form > /Users/carlton/Projects/Django/django/django/forms/formsets.py(262)empty_form() -> form_kwargs = self.get_form_kwargs(None) (Pdb) c Traceback (most recent call last): File "<console>", line 1, in <module> File "/Users/carlton/Projects/Django/django/django/forms/formsets.py", line 265, in empty_form form = self.form( TypeError: django.forms.widgets.MyModelForm() got multiple values for keyword argument 'empty_permitted'
That's expected:
>>> class Example: ... def __init__(self, a_kwarg=None): ... pass ... >>> Example(a_kwarg=True) <__main__.Example object at 0x102352950> >>> Example(a_kwarg=True, a_kwarg=False) File "<stdin>", line 1 SyntaxError: keyword argument repeated: a_kwarg >>> {"a":1, **{"a":2}} {'a': 2} >>> Example(a_kwarg=True, **{"a_kwarg": False}) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: __main__.Example() got multiple values for keyword argument 'a_kwarg'
Resolving the kwargs
before the constructor call, as per Mariusz' suggestion would resolve.
#21501 was on a similar topic.
comment:3 by , 2 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:5 by , 2 years ago
Patch needs improvement: | unset |
---|---|
Triage Stage: | Accepted → Ready for checkin |
Thanks for the report. It should be enough to change
form_kwargs
forempty_form
, e.g.django/forms/formsets.py
Would you like to prepare a patch? (a regression test is required)