注意:我知道我可以将表单的代码重复10次以完成我想做的事情。我试图不重复代码并重复使用10次,因为所有10种形式都是相同的。
我正在构建一个带有烧瓶后端的自动化计时器,以便在树莓派上运行,我这样做是为了能够像服务器一样访问pi并控制pi。这是我要执行的操作的示例,我在循环相同的代码并动态更改10个灌溉计时器中的每个计时器的信息。 所以这是一个带有阀1的html页面,所有的设置都在这里,然后是valve2 .... valve3 ...等等。 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 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)
答案 0 :(得分:2)
这是动态wtforms的另一个示例,对此有大量关于SO的示例问题。
wtforms类构造函数需要在类级别而不是实例级别的属性,因此可以:
{
"baseUrl": "/",
"paths": {
"node_modules/localforage/dist/localforage.min": ["localforage"]
}
}
这不起作用:
class Form(FlaskForm):
attribute = StringField()
attribute2 = StringField()
解决方案是构建一个动态的类构造函数,如下所示:
class Form(FlaskForm):
attribute2 = StringField()
def __init__(self, arg):
self.attribute = StringField(arg)
此函数接受一个参数,然后以适当的格式动态构造类对象,并返回其实例,并在您的路由中以相同的方式使用:
def Form(arg):
class TempForm(FlaskForm):
attribute2 = StringField()
setattr(TempForm, 'attribute', StringField(arg))
return TempForm()
修改问题
,然后使用以下命令创建表单列表:
form = Form(arg)
只有一种形式-此答案的任何部分均不建议编码10种单独的形式。