简体   繁体   English

使用 Jinja2 Flask 渲染具有可编辑 WTForms 字段列表和不可编辑值的 HTML 表

[英]Render HTML Table with Editable WTForms FieldList and Non-Editable Values Using Jinja2 Flask

I'm using Flask and Jinja2 and I need to make an attendance table that includes both editable and non-editable fields.我正在使用 Flask 和 Jinja2 并且我需要制作一个包含可编辑和不可编辑字段的出勤表。 I referred to other posts such as here and here which got me to this point.我提到了其他帖子,例如这里这里,这让我明白了这一点。 The table successfully displays the editable fields using FieldList.该表使用 FieldList 成功显示可编辑字段。 However, I have not been able to render the non-editable fields.但是,我无法呈现不可编辑的字段。

This is what the table should look like:表格应该是这样的: 在此处输入图像描述

The only fields which should be editable are "attendance code" and "comment".唯一可以编辑的字段是“出席代码”和“评论”。 Unfortunately, I have not found a way to include the other fields (class name, start time, end time, first name, last name) as simple text fields.不幸的是,我还没有找到将其他字段(类名、开始时间、结束时间、名字、姓氏)包含为简单文本字段的方法。

I have tried using the read-only attribute for WTForms.我尝试使用 WTForms 的只读属性。 While this is functional, it displays the text in text boxes which don't look appealing.虽然这是功能性的,但它会在看起来不吸引人的文本框中显示文本。

My latest attempt shown below defines a WTForms class called updateStudentAttendanceForm that inherits the fields from another class called attendanceLogClass that includes instance variables for the desired fields.下面显示的我的最新尝试定义了一个名为updateStudentAttendanceForm的 WTForms class,它继承了另一个 class 的字段,该class包含所需字段的实例变量。 I assign the values to the form class in the routes.py file.我将值分配给 routes.py 文件中的 class 表格。 However, when I reference these variables in the html file, they result in blank fields.但是,当我在 html 文件中引用这些变量时,它们会导致空白字段。 I have used a print statement to verify the variable assignments are working properly.我使用了打印语句来验证变量分配是否正常工作。 I cannot figure out why the variables do not display properly when included in the html template.我无法弄清楚为什么当包含在 html 模板中时变量无法正确显示。

forms.py forms.py

class attendanceLogClass:
    def __init__(self):
        self.classAttendanceLogId = int()
        self.className = str()
        self.firstName = str()
        self.lastName = str()
        self.startTime = datetime()
        self.endTime = datetime()

    def __repr__(self):
        return f"attendanceLogClass('{self.classAttendanceLogId}','{self.className}','{self.firstName}','{self.lastName}','{self.startTime}','{self.endTime}')"


class updateStudentAttendanceForm(FlaskForm, attendanceLogClass):
    attendanceCode = RadioField(
        "Attendance Code",
        choices=[("P", "P"), ("T", "T"), ("E", "E"), ("U", "U"), ("Q", "?"),],
    )
    comment = StringField("Comment")
    submit = SubmitField("Submit Attendance")


class updateClassAttendanceForm(FlaskForm):
    title = StringField("title")
    classMembers = FieldList(FormField(updateStudentAttendanceForm))

routes.py路线.py

@app.route("/classattendancelog")
def displayClassAttendanceLog():
    classAttendanceForm = updateClassAttendanceForm()
    classAttendanceForm.title.data = "My class"
    for studentAttendance in ClassAttendanceLog.query.all():
        studentAttendanceForm = updateStudentAttendanceForm()
        studentAttendanceForm.className = studentAttendance.ClassSchedule.className
        studentAttendanceForm.classAttendanceLogId = studentAttendance.id
        studentAttendanceForm.className = studentAttendance.ClassSchedule.className
        studentAttendanceForm.startTime = studentAttendance.ClassSchedule.startTime
        studentAttendanceForm.endTime = studentAttendance.ClassSchedule.endTime
        studentAttendanceForm.firstName = (
            studentAttendance.ClassSchedule.Student.firstName
        )
        studentAttendanceForm.lastName = (
            studentAttendance.ClassSchedule.Student.lastName
        )
        studentAttendanceForm.attendanceCode = studentAttendance.attendanceCode
        studentAttendanceForm.comment = studentAttendance.comment
        # The following print statement verified that all of the variables are properly defined based on the values retrieved from the database query
        print(studentAttendanceForm)
        classAttendanceForm.classMembers.append_entry(studentAttendanceForm)

    return render_template(
        "classattendancelog.html",
        title="Class Attendance Log",
        classAttendanceForm=classAttendanceForm,
    )

classattendancelog.html:上课记录.html:

{% extends 'layout.html'%}
{% block content %}
<h1> Class Attendance </h1>
<form method="POST" action="" enctype="multipart/form-data">
  {{ classAttendanceForm.hidden_tag() }}
  <table class="table table-sm table-hover">
    <thead class="thead-light">
      <tr>
        <th scope="col">Class Name</th>
        <th scope="col">Start Time</th>
        <th scope="col">End Time</th>
        <th scope="col">First Name</th>
        <th scope="col">Last Name</th>
        <th scope="col">Attendance Code</th>
        <th scope="col">Comment</th>
      </tr>
    </thead>
    <tbody>

      {% for studentAttendanceForm in classAttendanceForm.classMembers %}
      <tr>
        <td> {{ studentAttendanceForm.className }}</td>
        <td> {{ studentAttendanceForm.startTime }}</td>
        <td> {{ studentAttendanceForm.endTime }}</td>
        <td> {{ studentAttendanceForm.firstName }}</td>
        <td> {{ studentAttendanceForm.lastName }} </td>
        <td>
          {% for subfield in studentAttendanceForm.attendanceCode %}
          {{ subfield }}
          {{ subfield.label }}
          {% endfor %}
        </td>
        <td>
          {{ studentAttendanceForm.comment(class="form-control form-control-sm") }}
        </td>
      </tr>
      {% endfor %}
    </tbody>
  </table>

  {% endblock content %}

Note: I haven't yet written the code to handle the form response.注意:我还没有编写处理表单响应的代码。

I solved the problem by using the zip function to iterate simultaneously through two lists: one list with the FormField data and a second list with the non-editable "fixed field" data.我通过使用 zip function 同时遍历两个列表来解决该问题:一个包含 FormField 数据的列表和另一个包含不可编辑的“固定字段”数据的列表。

To use "zip" in the HTML template, I followed the instructions here and added this line to my init .py要在 HTML 模板中使用“zip”,我按照此处的说明将这一行添加到我的init .py

app.jinja_env.globals.update(zip=zip)

updated forms.py (eliminated attendanceLogClass with fixed field variables):更新了 forms.py(使用固定字段变量消除了出席日志类):

class updateStudentAttendanceForm(FlaskForm):
    attendanceCode = RadioField(
        "Attendance Code",
        choices=[("P", "P"), ("T", "T"), ("E", "E"), ("U", "U"), ("Q", "?"),],
    )
    comment = StringField("Comment")
    submit = SubmitField("Submit Attendance")


class updateClassAttendanceForm(FlaskForm):
    title = StringField("title")
    classMembers = FieldList(FormField(updateStudentAttendanceForm))

updated routes.py (added new variable for fixed fields called classAttendanceFixedFields):更新了 routes.py(为名为 classAttendanceFixedFields 的固定字段添加了新变量):

@app.route("/classattendancelog")
def displayClassAttendanceLog():
    classAttendanceFixedFields = ClassAttendanceLog.query.all()
    classAttendanceForm = updateClassAttendanceForm()
    classAttendanceForm.title.data = "My class"

    for studentAttendance in ClassAttendanceLog.query.all():
        studentAttendanceForm = updateStudentAttendanceForm()
        studentAttendanceForm.attendanceCode = studentAttendance.attendanceCode
        studentAttendanceForm.comment = studentAttendance.comment
        classAttendanceForm.classMembers.append_entry(studentAttendanceForm)

    return render_template(
        "classattendancelog.html",
        title="Class Attendance Log",
        classAttendanceForm=classAttendanceForm,
        classAttendanceFixedFields=classAttendanceFixedFields,
    )

updated classattendancelog.html (incorporated zip function in the for loop to simultaneously iterate through the editable fields and fixed fields).更新了 classattendancelog.html(在 for 循环中合并了 zip function 以同时迭代可编辑字段和固定字段)。

{% extends 'layout.html'%}
{% block content %}
<h1> Class Attendance </h1>
<form method="POST" action="" enctype="multipart/form-data">
  {{ classAttendanceForm.hidden_tag() }}
  <table class="table table-sm table-hover">
    <thead class="thead-light">
      <tr>
        <th scope="col">Class Name</th>
        <th scope="col">Start Time</th>
        <th scope="col">End Time</th>
        <th scope="col">First Name</th>
        <th scope="col">Last Name</th>
        <th scope="col">Attendance Code</th>
        <th scope="col">Comment</th>
      </tr>
    </thead>
    <tbody>

      {% for studentAttendanceForm, studentFixedFields in zip(classAttendanceForm.classMembers, classAttendanceFixedFields) %}
      <tr>
        <td> {{ studentFixedFields.ClassSchedule.className }}</td>
        <td> {{ studentFixedFields.ClassSchedule.startTime.strftime('%-I:%M') }}</td>
        <td> {{ studentFixedFields.ClassSchedule.endTime.strftime('%-I:%M') }}</td>
        <td> {{ studentFixedFields.ClassSchedule.Student.firstName }}</td>
        <td> {{ studentFixedFields.ClassSchedule.Student.lastName }} </td>
        <td>
          {% for subfield in studentAttendanceForm.attendanceCode %}
          {{ subfield }}
          {{ subfield.label }}
          {% endfor %}
        </td>
        <td>
          {{ studentAttendanceForm.comment(class="form-control form-control-sm") }}
        </td>
      </tr>
      {% endfor %}
    </tbody>
  </table>

  {% endblock content %}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM