broken method declarations in widgets `clean()`
See original GitHub issueDescribe the bug
PR #479 changed the interface of the clean()
methods in widgets.py
to add the row
kwarg:
def clean(self, value, row=None, *args, **kwargs):
I believe this is broken because the kwarg ‘row’ appears before the arg list, therefore callers can never supply a list of args, they can only supply kwargs.
It seems like the fix could be one of two options:
- Change ‘row’ to be a mandatory arg.
- Drop ‘row’ and
*args
to leave justkwargs
(of which ‘row’ could be one of the kwargs).
‘row’ was originally added as an arg because in some cases you need to filter on more than one field to return a single row in a ForeignKeyWidget
lookup.
Since we are changing interfaces in release 3.0, that is probably the best time to try to fix this issue without causing too much disruption to callers who have overridden clean()
.
This issue may also be present in other areas in the code base, for example:
>>> from import_export import widgets
>>> w = widgets.ForeignKeyWidget("m", field='id', 2)
^
SyntaxError: positional argument follows keyword argument
Versions (please complete the following information):
- Django Import Export: 2.8.0
- Python 3.9
- Django 4.0
Additional context
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:8 (5 by maintainers)
Top GitHub Comments
Yes, I’m thinking that the following would be cleaner and simpler, and is what Bojan was referring to in the original discussion:
I’ll give it some more thought.
Apparently I was reading the wrong version of the PR 479 commit – in the initial version it used isinstance to determine whether to send the row data to the clean method or not. 😃 Then it got updated to just always send them (parent object model to render, and parent object row to clean).
What I was thinking was we could have whether the parent object data gets sent to those methods depend on a config parameter to Field, so it doesn’t always send them superfluously, but I guess that’s a fairly minor thing.
–
In the case of this instance, I wonder if we ought to remove the arg/kwargs from default implementations of clean (on all widgets). They are only used in a realy nasty way (to allow clean to pass random args/kwargs through to get_queryset). That type of stuff feels like should only be done for a good reason, and it doesn’t really add any value there except being confusing.
ForeignKeyWidget.clean passing args/kwargs down to Widget.Clean doesn’t really do anything (since Widget doesn’t do anything with args/kwargs.
Our design of clean/render is such that when you make a new widget and override clean, you can’t just go super().clean(*args, **kwargs) you have to specify the fields required (value, or value+row).
I could see the interface rule of clean/render being ‘the thing you want to clean or render, plus args/kwargs, and figure it out’ to make them very flexible at accepting the output of any customized Field as well.
(This is a bit of a problem with some init statements too, like we found in ForeignKeyWidget having kwargs before *args)