Opened 9 years ago
Closed 9 years ago
#27919 closed Bug (fixed)
Decide if attrs (and possibly others) are named or positional parameters in new widget rendering code
| Reported by: | Claude Paroz | Owned by: | Tim Graham |
|---|---|---|---|
| Component: | Forms | Version: | 1.11 |
| Severity: | Release blocker | Keywords: | |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Discussed on IRC:
claudep: in the new form widget rendering code, we often have attrs=None in signatures, but then passed as positional argument in various calls claudep: I wonder if this is a good practice claudep: this can lead to some issues when overriding methods and useing *args, or **kwargs claudep: thoughts? MarkusH: claudep: I didn't look at the code, but from what you say I can imagine that leading to issues
A concrete example:
class CustomSelect(Select):
def create_option(self, name, value, label, selected, index, attrs=None, **kwargs):
if 'somestring' in label:
if attrs is None:
attrs = {}
attrs['disabled'] = True
return super().create_option(name, value, label, selected, index, attrs=attrs, **kwargs)
leads to
...
File ".../django/forms/widgets.py", line 671, in get_context
context = super(Select, self).get_context(name, value, attrs)
File ".../django/forms/widgets.py", line 627, in get_context
context['widget']['optgroups'] = self.optgroups(name, context['widget']['value'], attrs)
File ".../django/forms/widgets.py", line 599, in optgroups
attrs=attrs,
TypeError: create_option() got multiple values for argument 'attrs'
Change History (15)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
Yes, I know the reason of the error. But when I read the method signature and see subindex=None, attrs=None, I'm interpreting those as keyword arguments, hence my wrong subclass implementation.
comment:3 by , 9 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
It looks like the calling code in ChoiceWidget.optgroups() should be self.create_option(..., subindex=subindex, ...) rather than passing subindex as a position argument. Would that solve the issue?
comment:4 by , 9 years ago
Yes, that was the question. I think this happens at several other places, with attrs and/or subindex. In my experience, it's better to always pass arguments with a default value as keyword arguments, but I didn't find yet any reference supporting that feeling.
comment:5 by , 9 years ago
My guess is the current code is the result of some refactoring along the way. As far as I saw, create_option() is only called in that one spot, so presumably subindex could be an arg instead, if there isn't a use case for calling the method without it. I would say use your best judgment and clean things up as you see fit.
comment:6 by , 9 years ago
Claude, do you plan to propose a patch before Monday's release candidate? If not, I'll look at this.
comment:7 by , 9 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:8 by , 9 years ago
| Has patch: | set |
|---|
PR -- possibly more could be done but I think that PR covers the public APIs.
comment:9 by , 9 years ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Thanks Tim, I'm sorry not being able to be more active at this stage of the 1.11 release.
comment:15 by , 9 years ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
Your method signature is missing the 6th positional argument
subindex. Instead you haveattrsas the 6th positional argument, so it receives both a positional argument (which should actually be thesubindexargument) and a keyword argument.