首页 > 解决方案 > Python - 基于 json 输入构建函数

问题描述

我在 Python 模块中有以下代码

    self.helper.layout = Layout(
        Fieldset( _('Basic Information'), Field('form_filler', css_class='enabler'), Div('form_filler_other', css_class='dependent'), 'child_dob','age', 'sex', Field('country', css_class='enabler'), Div('zip_code', css_class='dependent'),'birth_order', Field('multi_birth_boolean', css_class='enabler'), Div('multi_birth', css_class='dependent'), self.birth_weight_field, Field('born_on_due_date', css_class='enabler'), Div('early_or_late', 'due_date_diff', css_class='dependent')),
        Fieldset( _('Family Background'), Field('primary_caregiver', css_class='enabler'), Div('primary_caregiver_other', css_class='dependent'), 'mother_yob', 'mother_education',Field('secondary_caregiver', css_class='enabler'), Div('secondary_caregiver_other', css_class='dependent'), 'father_yob', 'father_education', 'annual_income'),
        Fieldset( _("Child's Ethnicity"),HTML("<p> " + ugettext("The following information is being collected for the sole purpose of reporting to our grant-funding institute, i.e.,  NIH (National Institute of Health).  NIH requires this information to ensure the soundness and inclusiveness of our research. Your cooperation is appreciated, but optional.") + " </p>"), 'child_hispanic_latino', 'child_ethnicity'),
        Fieldset( _("Caregiver Information"), 'caregiver_info'),
        Fieldset( _("Language Exposure"), Field('other_languages_boolean', css_class = 'enabler'), Div(Field('other_languages', css_class='make-selectize'),'language_from', 'language_days_per_week', 'language_hours_per_day', css_class='dependent')),
        Fieldset( _("Health"), 
            Field('ear_infections_boolean', css_class = 'enabler'), Div('ear_infections', css_class='dependent'),
            Field('hearing_loss_boolean', css_class = 'enabler'), Div('hearing_loss', css_class='dependent'),
            Field('vision_problems_boolean', css_class = 'enabler'), Div('vision_problems', css_class='dependent'),
            Field('illnesses_boolean', css_class = 'enabler'), Div('illnesses', css_class='dependent'),
            Field('services_boolean', css_class = 'enabler'), Div('services', css_class='dependent'),
            Field('worried_boolean', css_class = 'enabler'), Div('worried', css_class='dependent'),
            Field('learning_disability_boolean', css_class = 'enabler'), Div('learning_disability', css_class='dependent'),
        ),
    )

我想替换它并使用 JSON 输入文件构建它,所以我创建了这个文件(我只显示第一个字段集)。

[{
    "fieldset" : "Basic Information",
    "fields" : [
        {
            "field" : "form_filler",
            "div" : ["form_filler_other"]
        },{
            "field" : "child_dob"
        },{
            "field" : "age"
        },{
            "field" : "sex"
        },{
            "field" : "country", 
            "div" : ["zip_code"]
        },{
            "field" : "birth_order"
        }, {
            "field" : "multi_birth_boolean",
            "div" : ["multi_birth"]
        }, {
            "field" : "self.birth_weight_field"
        }, {
            "field" : "born_on_due_date", 
            "div" : ["early_or_late", "due_date_diff"]
        }

    ]
}
]

而这段代码:

    rows = []
    fieldsets = json.load(open(self.filename))
    for fieldset in fieldsets:
        fields = []
        for field in fieldset['fields']:
            if 'div' in field:
                this_field = Field(field['field'], css_class="enabler"), Div(lambda x,: x in field['div'], css_class="dependent"),
            else:
                this_field = field['field'],
            fields.append(this_field)

        rows.append(Fieldset(fieldset['fieldset'], lambda field: field in fields))
    x = lambda row,: row in rows
    self.helper.layout = Layout(x)

事后看来,这显然是行不通的,给出了这个错误:

WARNING:root:Could not resolve form field '<function <lambda> at 0x7f8f3acab668>'.

如何根据 json 输入动态构建此代码?

标签: pythonpython-2.7

解决方案


我认为您不了解 lambda 的作用。它正在创建一个动态生成的匿名函数。因此,您的代码正在创建一个函数以作为第一个参数传递给 Div。在其他地方,您似乎假设需要进行列表理解。

看起来您真正想要的只是展平 field['div'] 中的列表,以便将列表的每个成员作为后续位置参数传递给 Div,而不是将列表作为第一个参数传递给 Div。

考虑

>>> def f(a, b=None, c=None, d=None):
...     print(a)
...     print(b)
...     print(c)
...     print(d)
... 
>>> x = [1, 2, 3]
>>> f(lambda a,: a in x, d='a')
<function <lambda> at 0x7faee8124758>
None
None
a
>>> f(x, d='a')
[1, 2, 3]
None
None
a
>>> f(*x, d='a')
1
2
3
a
>>> 

最后一个是你想要的,所以替换

Div(lambda x,: x in field['div'], css_class="dependent")

只需

Div(*field['div'], css_class="dependent")

应该得到你的 Fieldset 参数。然后,您只需以类似的方式调用该列表上的 Fieldset。就像是:

rows = []
fieldsets = json.load(open(self.filename))
for fieldset in fieldsets:
    fields = []
    for field in fieldset['fields']:
        if 'div' in field:
            this_field = Field(field['field'], css_class="enabler"), Div(*field['div'], css_class="dependent"),
        else:
            this_field = field['field'],
        fields.append(this_field)

    rows.append(Fieldset(fieldset['fieldset'], *fields)
self.helper.layout = Layout(x)

唔。其实我觉得你还是有问题。这不会在您的第一个 Fieldset 参数上调用下划线函数,看起来您需要对某些字段值进行一些额外的工作,但这会让您摆脱 lambda 难题。

编辑

以上带我到了那里,这是可行的解决方案:

    rows = []
    fieldsets = json.load(open(self.filename))
    for fieldset in fieldsets:
        fields = []
        for field in fieldset['fields']:
            if 'div' in field:
                fields.append(Field(field['field'], css_class="enabler"))
                fields.append(Div(*field['div'], css_class="dependent"))
            else:
                fields.append(field['field'])

        rows.append(Fieldset(fieldset['fieldset'], *fields))
    self.helper.layout = Layout(*rows)

推荐阅读