如何将kwargs从Django import_export的Resource传至自定义Widget的clean方法
问题
使用Django import_export框架时,希望将kwargs从Resource传递到自定义Widget的clean方法中。现有代码如下:
resources.py
class UserResource(ModelResource): identifier = Field( column_name="identifier", attribute="identifier", widget=RegexWidget(), ) class Meta: model=User
widgets.py
class RegexWidget(CharWidget): def clean(self, value, row=None, **kwargs): regex = kwargs.get("regex", None) # 后续验证逻辑 ...
测试时尝试以下写法,但Widget的clean方法中获取到的kwargs为空字典:
UserResource.import_data(dataset, regex=r"U\{4}d\Z")
请问该如何实现需求?
解决方案
方法一:通过Resource实例传递参数
框架默认不会将import_data的参数传递到Widget的clean方法,因此需要通过Resource实例保存参数并传递给Widget:
- 修改
UserResource,添加初始化方法接收并传递regex参数:
class UserResource(ModelResource): identifier = Field( column_name="identifier", attribute="identifier", widget=RegexWidget(), ) def __init__(self, regex=None, **kwargs): super().__init__(**kwargs) self.regex = regex # 将regex传递给identifier字段的widget self.fields['identifier'].widget.regex = regex class Meta: model=User
- 调整
RegexWidget,直接使用实例属性获取regex:
class RegexWidget(CharWidget): def __init__(self, regex=None, **kwargs): super().__init__(**kwargs) self.regex = regex def clean(self, value, row=None, **kwargs): regex = self.regex if regex: # 执行正则验证逻辑,示例: import re if not re.fullmatch(regex, value): raise ValueError(f"值不符合正则规则:{regex}") # 调用父类clean方法处理基础逻辑 return super().clean(value, row, **kwargs)
- 调用时先实例化Resource再执行
import_data:
resource = UserResource(regex=r"U\{4}d\Z") resource.import_data(dataset)
方法二:重写Resource的clean方法传递参数
如果不想修改Widget的初始化逻辑,可以在Resource的clean方法中主动传递参数给Widget:
- 修改
UserResource,添加regex属性并重写clean方法:
class UserResource(ModelResource): identifier = Field( column_name="identifier", attribute="identifier", widget=RegexWidget(), ) def __init__(self, regex=None, **kwargs): super().__init__(**kwargs) self.regex = regex def clean(self, row, instance=None, **kwargs): # 先执行父类clean逻辑 row = super().clean(row, instance, **kwargs) # 针对identifier字段,调用widget的clean并传递regex参数 if 'identifier' in row: row['identifier'] = self.fields['identifier'].widget.clean( row['identifier'], row, regex=self.regex ) return row class Meta: model=User
- 调用方式同方法一:
resource = UserResource(regex=r"U\{4}d\Z") resource.import_data(dataset)
关键说明
直接调用UserResource.import_data()是类方法,框架不会将额外参数传递到Widget的clean流程中。必须通过实例化Resource并保存参数,再通过实例调用import_data,才能让Widget获取到所需参数。
内容的提问来源于stack exchange,提问作者malik
相关产品推荐
相关产品推荐

