需要重复Flask表单,一个表单类的多个实例

时间:2018-08-12 21:42:18

标签: python python-3.x flask raspberry-pi flask-wtforms

注意:我知道我可以将表单的代码重复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)

1 个答案:

答案 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种单独的形式。