需要重复Flask形式,一种形式的多个实例class
need to repeat Flask form, multiple instances of one form class
注意:我知道我可以将表单代码重复 10 次来完成我想做的事情。我试图不重复代码并重复使用它 10 次,因为所有 10 种形式都是相同的。
我正在 raspberry pi 上构建一个带有烧瓶后端的自动化计时器到 运行,我这样做是为了能够像服务器一样访问 pi 并控制 pi。这是我正在尝试做的一个示例,我正在循环相同的代码并动态更改 10 个灌溉计时器中每一个的信息。
所以它是一个 html 页面,其中包含阀门 1 及其所有设置,然后是阀门 2....阀门3...等。 html 的示例在底部。
有一个构造函数并试图制作多个表单是行不通的,当我这样做时它一直在说
jinja2.exceptions.UndefinedError: 'webApp.forms.ValveForm object' has no attribute 'valveName
这是对我不起作用的示例
class ValveForm(FlaskForm):
def __init__(self, name):
valveName = StringField("Name", validators=[DataRequired(), Length(min=1, max=100)], default = name)
valveNotes = TextAreaField("Notes", validators=[Length(max=300)])
valveOnOff = SelectField("on/off", choices=[("True", "on"), ("False", "off")])
valveCycleIrrigate = SelectField("cycle or irrigate", choices=[("cycle", "Cycle"), ("irrigate", "Irrigate")])
valveIrrigationTime = TimeField("valveIrrigationTime")
valveTimeHour = StringField("valveTimeHour")
valveTimeMinute = StringField("valveTimeMinute")
#valveTimeSecond = StringField("valveTimeSecond")
cycleOnTimeHour = StringField("cycleOnTimeHour")
cycleOnTimeMinute = StringField("cycleOnTimeMinute")
cycleOnTimeSeconds = StringField("cycleOnTimeSecond")
cycleOffTimeHour = StringField("cycleOffTimeHour")
cycleOffTimeMinute = StringField("cycleOffTimeMinute")
cycleOffTimeSeconds = StringField("cycleOffTimeSecond")
blackoutStart = TimeField("blackoutStart")
blackoutStop = TimeField("blackoutStop")
selectAll = BooleanField("Select All")
monday = BooleanField("monday")
tuesday = BooleanField("tuesday")
wednesday = BooleanField("wednesday")
thursday = BooleanField("thursday")
friday = BooleanField("friday")
saturday = BooleanField("saturday")
sunday = BooleanField("sunday")
daysTuple = (selectAll, monday, tuesday, wednesday, thursday, friday, saturday, sunday)
它的工作原理如下,但当然这是行不通的。因为所有 10 个阀门都获得相同的信息。我正在尝试个性化每个信息。我需要在 class 中执行此操作,因为我需要为以前的设置插入默认值。通常人们不使用这样的表格,所以它给我带来了问题。
class ValveForm(FlaskForm):
valveName = StringField("Name", validators=[DataRequired(), Length(min=1, max=100)], default = "something")
valveNotes = TextAreaField("Notes", validators=[Length(max=300)])
valveOnOff = SelectField("on/off", choices=[("True", "on"), ("False", "off")])
valveCycleIrrigate = SelectField("cycle or irrigate", choices=[("cycle", "Cycle"), ("irrigate", "Irrigate")])
valveIrrigationTime = TimeField("valveIrrigationTime")
valveTimeHour = StringField("valveTimeHour")
valveTimeMinute = StringField("valveTimeMinute")
#valveTimeSecond = StringField("valveTimeSecond")
cycleOnTimeHour = StringField("cycleOnTimeHour")
cycleOnTimeMinute = StringField("cycleOnTimeMinute")
cycleOnTimeSeconds = StringField("cycleOnTimeSecond")
cycleOffTimeHour = StringField("cycleOffTimeHour")
cycleOffTimeMinute = StringField("cycleOffTimeMinute")
cycleOffTimeSeconds = StringField("cycleOffTimeSecond")
blackoutStart = TimeField("blackoutStart")
blackoutStop = TimeField("blackoutStop")
selectAll = BooleanField("Select All")
monday = BooleanField("monday")
tuesday = BooleanField("tuesday")
wednesday = BooleanField("wednesday")
thursday = BooleanField("thursday")
friday = BooleanField("friday")
saturday = BooleanField("saturday")
sunday = BooleanField("sunday")
daysTuple = (selectAll, monday, tuesday, wednesday, thursday, friday, saturday, sunday)
这是 html 用于循环的阀门
{%extends "layout.html"%}
{%block body_content%}
{% for i in range(10) %}
<h1>{{IrrigationValve.valveList[i].name}}</h1>
<form method="POST" action="">
{#{{ form.hidden_tag() }}#}
<table class="table table-striped table-bordered">
<tbody>
<tr>
<td>{{ formList[i].valveName.label(class="form-control-label") }} </td>
<td>
<div class="form-group">
{% if formList[i].valveName.errors %}
{{ formList[i].valveName(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in valve.valveName.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ formList[i].valveName(class="form-control form-control-lg") }}
{% endif %}
</div>
</td>
</tr>
<tr>
<td>Notes</td>
<td>
<div>
{{ formList[i].valveNotes(class="form-control form-control-lg") }}
</div>
</td>
</tr>
<tr>
<td>current state</td>
<td>{{IrrigationValve.valveList[i].currentStateOn | trueFalseIndicator()}}</td>
</tr>
<tr>
<td>on/off</td>
<td>
<div class="form-group">
{{ formList[i].valveOnOff(class="form-control form-control-lg", value=IrrigationValve.valveList[i].currentStateOn) }}
</div>
</td>
</tr>
<tr>
<td>testing</td>
<td>
<button type="submit" name="action" class="btn btn-danger" value="test">TEST</button>
</td>
</tr>
<tr>
<td>cycle or irrigate</td>
<td>
<div class="form-group">
{{ formList[i].valveCycleIrrigate(class="form-control form-control-lg", value=IrrigationValve.valveList[i].cycleOrIrrigate) }}
</div>
</td>
</tr>
<tr>
<td>irrigation times</td>
<td>
{% if not IrrigationValve.valveList[i].irrigationTimes %}
None
{% else %}
{% for key, value in IrrigationValve.valveList[i].irrigationTimes.items() %}
time: {{ key | strf_time_converter() }} duration: {{ value | deltaToHrMinSec() }}
<button type="submit" name="action" id="{{ key }}" value="irrigation-time-delete" class="btn btn-danger">Delete</button>
{% endfor %}
{% endif %}
<br><br>
<div class="form-group">
{{ formList[i].valveIrrigationTime() }}
<button type="submit" name="action" value="irrigation-time-add" class="btn btn-primary">Add</button>
</div>
</td>
</tr>
<tr>
<td>cycle on time</td>
<td>
{%if not IrrigationValve.valveList[i].cycleOnTime%}
None<br><br>
<div>
<label>Hours</label>
{{ formList[i].cycleOnTimeHour() }} <br>
<label>Minutes</label>
{{ formList[i].cycleOnTimeMinute }} <br>
<label>Seconds</label>
{{ formList[i].cycleOnTimeSeconds }} <br>
<button type="submit" name="action" value="cycle-on-time-add" class="btn btn-primary">Add</button>
</div>
{%else%}
{{IrrigationValve.valveList[i].cycleOnTime | HrMinSec()}}
<button type="submit" name="action" value="cycle-on-time-delete" class="btn btn-primary">delete</button>
{%endif%}
<br><br>
</td>
</tr>
<tr>
<td>cycle off time</td>
<td>
{%if not IrrigationValve.valveList[i].cycleOffTime%}
None<br><br>
<form>
<div>
<label>Hours</label>
{{ formList[i].cycleOffTimeHour }}<br>
<label>Minutes</label>
{{ formList[i].cycleOffTimeMinute }}<br>
<label>Seconds</label>
{{ formList[i].cycleOffTimeSeconds }}<br>
<button type="button" name="action" value="cycle-off-time-add" class="btn btn-primary">Add</button>
</div>
</form>
{%else%}
{{IrrigationValve.valveList[i].cycleOffTime | HrMinSec()}}
<button type="submit" name="action" value="cycle-off-time-delete" class="btn btn-primary">delete</button>
{%endif%}
<br><br>
</td>
</tr>
<tr>
<td>blackout start</td>
<td>
{%if not IrrigationValve.valveList[i].blackoutStart%}
None
<br><br>
{{ formList[i].blackoutStart }}
<button type="submit" name="action" value="blackout-start-add" class="btn btn-primary">Add</button>
{%else%}
{{IrrigationValve.valveList[i].blackoutStart | strftimeConverter()}}
<button type="submit" name="action" value="blackout-start-delete" class="btn btn-primary">delete</button>
{%endif%}
</td>
</tr>
<tr>
<td>blackout stop</td>
<td>
{%if not IrrigationValve.valveList[i].blackoutStop%}
None
<br><br>
{{ formList[i].blackoutStop }}
<button type="submit" name="action" value="blackout-stop-add" class="btn btn-primary">Add</button>
{%else%}
{{IrrigationValve.valveList[i].blackoutStop | strftimeConverter()}}
<button type="submit" name="action" value="blackout-stop-delete" class="btn btn-primary">delete</button>
{%endif%}
</td>
</tr>
<tr>
<td>days</td>
<td>
{{ formList[i].selectAll }}{{ formList[i].selectAll.label }}<br>
<br>
{{ formList[i].monday }}{{ formList[i].monday.label }}<br>
{{ formList[i].tuesday }}{{ formList[i].tuesday.label }}<br>
{{ formList[i].wednesday }}{{ formList[i].wednesday.label }}<br>
{{ formList[i].thursday }}{{ formList[i].thursday.label }}<br>
{{ formList[i].friday }}{{ formList[i].friday.label }}<br>
{{ formList[i].saturday }}{{ formList[i].saturday.label }}<br>
{{ formList[i].sunday }}{{ formList[i].sunday.label }}<br>
</td>
</tr>
</tbody>
</table>
<input class="btn-success btn-block btn-lg" type="submit" name="action" value="submit">
</form>
{% endfor %}
{%endblock%}
这是 app.py
的一部分
@app.route("/valves", methods=["GET", "POST"])
def irrigationValve():
formList = [ValveForm(IrrigationValve.valveList[i].name) for i in range(10)]
for i in range(10):
if formList[i].validate_on_submit():
formList[i].setValve(irrigationValve.valveList[i])
flash("changes saved", "success")
return render_template("valves.html", IrrigationValve=IrrigationValve, formList=formList)
这是动态 wtform 的另一个示例,SO 上有许多示例问题。
wtforms class 构造函数需要 class 级别的属性,而不是实例级别的属性,所以这有效:
class Form(FlaskForm):
attribute = StringField()
attribute2 = StringField()
虽然这不起作用:
class Form(FlaskForm):
attribute2 = StringField()
def __init__(self, arg):
self.attribute = StringField(arg)
解决方案是构建动态 class 构造函数,如下所示:
def Form(arg):
class TempForm(FlaskForm):
attribute2 = StringField()
setattr(TempForm, 'attribute', StringField(arg))
return TempForm()
此函数接受一个参数,然后以适当的格式动态构造 class 对象和 returns 它的实例,并在您的路由中以相同的方式使用:
form = Form(arg)
编辑问题
然后您创建表单列表:
arg_list = ['one', 'two', ..., 'ten']
form_list = [Form(arg=arg_list[i]) for i in range(10)]
只有一种形式 - 此答案中没有任何部分建议编码 10 个单独的形式。
注意:我知道我可以将表单代码重复 10 次来完成我想做的事情。我试图不重复代码并重复使用它 10 次,因为所有 10 种形式都是相同的。
我正在 raspberry pi 上构建一个带有烧瓶后端的自动化计时器到 运行,我这样做是为了能够像服务器一样访问 pi 并控制 pi。这是我正在尝试做的一个示例,我正在循环相同的代码并动态更改 10 个灌溉计时器中每一个的信息。 所以它是一个 html 页面,其中包含阀门 1 及其所有设置,然后是阀门 2....阀门3...等。 html 的示例在底部。
有一个构造函数并试图制作多个表单是行不通的,当我这样做时它一直在说
jinja2.exceptions.UndefinedError: 'webApp.forms.ValveForm object' has no attribute 'valveName
这是对我不起作用的示例
class ValveForm(FlaskForm):
def __init__(self, name):
valveName = StringField("Name", validators=[DataRequired(), Length(min=1, max=100)], default = name)
valveNotes = TextAreaField("Notes", validators=[Length(max=300)])
valveOnOff = SelectField("on/off", choices=[("True", "on"), ("False", "off")])
valveCycleIrrigate = SelectField("cycle or irrigate", choices=[("cycle", "Cycle"), ("irrigate", "Irrigate")])
valveIrrigationTime = TimeField("valveIrrigationTime")
valveTimeHour = StringField("valveTimeHour")
valveTimeMinute = StringField("valveTimeMinute")
#valveTimeSecond = StringField("valveTimeSecond")
cycleOnTimeHour = StringField("cycleOnTimeHour")
cycleOnTimeMinute = StringField("cycleOnTimeMinute")
cycleOnTimeSeconds = StringField("cycleOnTimeSecond")
cycleOffTimeHour = StringField("cycleOffTimeHour")
cycleOffTimeMinute = StringField("cycleOffTimeMinute")
cycleOffTimeSeconds = StringField("cycleOffTimeSecond")
blackoutStart = TimeField("blackoutStart")
blackoutStop = TimeField("blackoutStop")
selectAll = BooleanField("Select All")
monday = BooleanField("monday")
tuesday = BooleanField("tuesday")
wednesday = BooleanField("wednesday")
thursday = BooleanField("thursday")
friday = BooleanField("friday")
saturday = BooleanField("saturday")
sunday = BooleanField("sunday")
daysTuple = (selectAll, monday, tuesday, wednesday, thursday, friday, saturday, sunday)
它的工作原理如下,但当然这是行不通的。因为所有 10 个阀门都获得相同的信息。我正在尝试个性化每个信息。我需要在 class 中执行此操作,因为我需要为以前的设置插入默认值。通常人们不使用这样的表格,所以它给我带来了问题。
class ValveForm(FlaskForm):
valveName = StringField("Name", validators=[DataRequired(), Length(min=1, max=100)], default = "something")
valveNotes = TextAreaField("Notes", validators=[Length(max=300)])
valveOnOff = SelectField("on/off", choices=[("True", "on"), ("False", "off")])
valveCycleIrrigate = SelectField("cycle or irrigate", choices=[("cycle", "Cycle"), ("irrigate", "Irrigate")])
valveIrrigationTime = TimeField("valveIrrigationTime")
valveTimeHour = StringField("valveTimeHour")
valveTimeMinute = StringField("valveTimeMinute")
#valveTimeSecond = StringField("valveTimeSecond")
cycleOnTimeHour = StringField("cycleOnTimeHour")
cycleOnTimeMinute = StringField("cycleOnTimeMinute")
cycleOnTimeSeconds = StringField("cycleOnTimeSecond")
cycleOffTimeHour = StringField("cycleOffTimeHour")
cycleOffTimeMinute = StringField("cycleOffTimeMinute")
cycleOffTimeSeconds = StringField("cycleOffTimeSecond")
blackoutStart = TimeField("blackoutStart")
blackoutStop = TimeField("blackoutStop")
selectAll = BooleanField("Select All")
monday = BooleanField("monday")
tuesday = BooleanField("tuesday")
wednesday = BooleanField("wednesday")
thursday = BooleanField("thursday")
friday = BooleanField("friday")
saturday = BooleanField("saturday")
sunday = BooleanField("sunday")
daysTuple = (selectAll, monday, tuesday, wednesday, thursday, friday, saturday, sunday)
这是 html 用于循环的阀门
{%extends "layout.html"%}
{%block body_content%}
{% for i in range(10) %}
<h1>{{IrrigationValve.valveList[i].name}}</h1>
<form method="POST" action="">
{#{{ form.hidden_tag() }}#}
<table class="table table-striped table-bordered">
<tbody>
<tr>
<td>{{ formList[i].valveName.label(class="form-control-label") }} </td>
<td>
<div class="form-group">
{% if formList[i].valveName.errors %}
{{ formList[i].valveName(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in valve.valveName.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ formList[i].valveName(class="form-control form-control-lg") }}
{% endif %}
</div>
</td>
</tr>
<tr>
<td>Notes</td>
<td>
<div>
{{ formList[i].valveNotes(class="form-control form-control-lg") }}
</div>
</td>
</tr>
<tr>
<td>current state</td>
<td>{{IrrigationValve.valveList[i].currentStateOn | trueFalseIndicator()}}</td>
</tr>
<tr>
<td>on/off</td>
<td>
<div class="form-group">
{{ formList[i].valveOnOff(class="form-control form-control-lg", value=IrrigationValve.valveList[i].currentStateOn) }}
</div>
</td>
</tr>
<tr>
<td>testing</td>
<td>
<button type="submit" name="action" class="btn btn-danger" value="test">TEST</button>
</td>
</tr>
<tr>
<td>cycle or irrigate</td>
<td>
<div class="form-group">
{{ formList[i].valveCycleIrrigate(class="form-control form-control-lg", value=IrrigationValve.valveList[i].cycleOrIrrigate) }}
</div>
</td>
</tr>
<tr>
<td>irrigation times</td>
<td>
{% if not IrrigationValve.valveList[i].irrigationTimes %}
None
{% else %}
{% for key, value in IrrigationValve.valveList[i].irrigationTimes.items() %}
time: {{ key | strf_time_converter() }} duration: {{ value | deltaToHrMinSec() }}
<button type="submit" name="action" id="{{ key }}" value="irrigation-time-delete" class="btn btn-danger">Delete</button>
{% endfor %}
{% endif %}
<br><br>
<div class="form-group">
{{ formList[i].valveIrrigationTime() }}
<button type="submit" name="action" value="irrigation-time-add" class="btn btn-primary">Add</button>
</div>
</td>
</tr>
<tr>
<td>cycle on time</td>
<td>
{%if not IrrigationValve.valveList[i].cycleOnTime%}
None<br><br>
<div>
<label>Hours</label>
{{ formList[i].cycleOnTimeHour() }} <br>
<label>Minutes</label>
{{ formList[i].cycleOnTimeMinute }} <br>
<label>Seconds</label>
{{ formList[i].cycleOnTimeSeconds }} <br>
<button type="submit" name="action" value="cycle-on-time-add" class="btn btn-primary">Add</button>
</div>
{%else%}
{{IrrigationValve.valveList[i].cycleOnTime | HrMinSec()}}
<button type="submit" name="action" value="cycle-on-time-delete" class="btn btn-primary">delete</button>
{%endif%}
<br><br>
</td>
</tr>
<tr>
<td>cycle off time</td>
<td>
{%if not IrrigationValve.valveList[i].cycleOffTime%}
None<br><br>
<form>
<div>
<label>Hours</label>
{{ formList[i].cycleOffTimeHour }}<br>
<label>Minutes</label>
{{ formList[i].cycleOffTimeMinute }}<br>
<label>Seconds</label>
{{ formList[i].cycleOffTimeSeconds }}<br>
<button type="button" name="action" value="cycle-off-time-add" class="btn btn-primary">Add</button>
</div>
</form>
{%else%}
{{IrrigationValve.valveList[i].cycleOffTime | HrMinSec()}}
<button type="submit" name="action" value="cycle-off-time-delete" class="btn btn-primary">delete</button>
{%endif%}
<br><br>
</td>
</tr>
<tr>
<td>blackout start</td>
<td>
{%if not IrrigationValve.valveList[i].blackoutStart%}
None
<br><br>
{{ formList[i].blackoutStart }}
<button type="submit" name="action" value="blackout-start-add" class="btn btn-primary">Add</button>
{%else%}
{{IrrigationValve.valveList[i].blackoutStart | strftimeConverter()}}
<button type="submit" name="action" value="blackout-start-delete" class="btn btn-primary">delete</button>
{%endif%}
</td>
</tr>
<tr>
<td>blackout stop</td>
<td>
{%if not IrrigationValve.valveList[i].blackoutStop%}
None
<br><br>
{{ formList[i].blackoutStop }}
<button type="submit" name="action" value="blackout-stop-add" class="btn btn-primary">Add</button>
{%else%}
{{IrrigationValve.valveList[i].blackoutStop | strftimeConverter()}}
<button type="submit" name="action" value="blackout-stop-delete" class="btn btn-primary">delete</button>
{%endif%}
</td>
</tr>
<tr>
<td>days</td>
<td>
{{ formList[i].selectAll }}{{ formList[i].selectAll.label }}<br>
<br>
{{ formList[i].monday }}{{ formList[i].monday.label }}<br>
{{ formList[i].tuesday }}{{ formList[i].tuesday.label }}<br>
{{ formList[i].wednesday }}{{ formList[i].wednesday.label }}<br>
{{ formList[i].thursday }}{{ formList[i].thursday.label }}<br>
{{ formList[i].friday }}{{ formList[i].friday.label }}<br>
{{ formList[i].saturday }}{{ formList[i].saturday.label }}<br>
{{ formList[i].sunday }}{{ formList[i].sunday.label }}<br>
</td>
</tr>
</tbody>
</table>
<input class="btn-success btn-block btn-lg" type="submit" name="action" value="submit">
</form>
{% endfor %}
{%endblock%}
这是 app.py
的一部分@app.route("/valves", methods=["GET", "POST"])
def irrigationValve():
formList = [ValveForm(IrrigationValve.valveList[i].name) for i in range(10)]
for i in range(10):
if formList[i].validate_on_submit():
formList[i].setValve(irrigationValve.valveList[i])
flash("changes saved", "success")
return render_template("valves.html", IrrigationValve=IrrigationValve, formList=formList)
这是动态 wtform 的另一个示例,SO 上有许多示例问题。
wtforms class 构造函数需要 class 级别的属性,而不是实例级别的属性,所以这有效:
class Form(FlaskForm):
attribute = StringField()
attribute2 = StringField()
虽然这不起作用:
class Form(FlaskForm):
attribute2 = StringField()
def __init__(self, arg):
self.attribute = StringField(arg)
解决方案是构建动态 class 构造函数,如下所示:
def Form(arg):
class TempForm(FlaskForm):
attribute2 = StringField()
setattr(TempForm, 'attribute', StringField(arg))
return TempForm()
此函数接受一个参数,然后以适当的格式动态构造 class 对象和 returns 它的实例,并在您的路由中以相同的方式使用:
form = Form(arg)
编辑问题
然后您创建表单列表:
arg_list = ['one', 'two', ..., 'ten']
form_list = [Form(arg=arg_list[i]) for i in range(10)]
只有一种形式 - 此答案中没有任何部分建议编码 10 个单独的形式。