使用案例:使用表格为学生注册的每门课程输入成绩。
型号:
使用SQLAlchemy,我定义了一个Student
对象,一个Course
对象和一个StudentCourse
关联对象,用于存储每个课程的每个学生的成绩。
class Student(Base):
__tablename__ = 'students'
id = Column(Integer, primary_key=True)
name = Column(Text)
courses = association_proxy('student_courses', 'grade',
creator=lambda k, v: StudentCourse(course_title=k, grade=v))
...
class Course(Base):
__tablename__ = 'courses'
id = Column(Integer, primary_key=True)
title = Column(Text, unique=True)
...
# Link students to courses and store grades
class StudentCourse(Base):
__tablename__ = 'student_courses'
student_id = Column(Integer, ForeignKey(Student.id), primary_key=True)
course_id = Column(Integer, ForeignKey(Course.id), primary_key=True)
grade = Column(Integer)
student = relationship(Student,backref=backref(
'student_courses',
collection_class=attribute_mapped_collection('course_title'),
cascade='all, delete-orphan'))
course = relationship(Course)
@property
def course_title(self):
if self.course is not None:
return self.course.title
else:
return self._course_title
...
查看:
我可以查询StudentCourses模型并构建相关表单,但我无法弄清楚 如何将查询中的数据作为对象传递/检索 。
def view(request):
student = Student.from_request(request)
student_courses = DBSession.query(StudentCourse).\
filter(StudentCourse.student_id == student.id).\
all()
class GradesForm(Form):
pass
# Add form field for each course the student is enrolled in
for c in student_courses:
setattr(GradesForm,
c.course_title,
IntegerField()
)
form = GradesForm(request.POST, obj=student_courses) # this doesn't populate the form
return {'form': form}
这会生成一个空白表单,因此我显然无法直接从Query
对象填充表单中的数据。但是,即使在为每门课程创建一个FormField
类型的表单时,我也没有成功填充任何类型的对象:
class StudentCourseForm(Form):
course_title = StringField()
grade = IntegerField()
def view(request):
...
class GradesForm(Form):
pass
# Add form field for each course
for c in student_courses:
setattr(GradesForm,
c.course_title,
FormField(StudentCourseForm)
)
form = GradesForm(request.POST, obj=student_courses)
return {'form': form}
如果可能,使用查询将是最简单的。根据{{3}},在会话中使用query()
方法会创建一个Query
对象。像我在控制器中那样迭代时,此对象是StudentCourse
个对象的列表。
[<app.models.StudentCourse object at 0x10875bd50>, <app.models.StudentCourse object at 0x10875bed0>]
......我的进步在这里结束。 感谢任何帮助!
答案 0 :(得分:1)
我能够填充这些动态创建的表单的唯一方法是传递** kwargs,所以我将发布此方法作为答案,直到其他人可以找出基于对象的解决方案。
填写表格:
def view(request):
...
data = {}
for c in student_courses:
data[c.course_title] = c.grade
# Populate form
form = GradesForm(request.POST, **data)
...
通过这种方式,我可以通过遍历字段在模板中呈现表单,并且在提交时,我将有一个dicts列表,然后我可以验证并使用它来更新我的数据库记录。
表单验证需要相同的方法:
def view(request):
...
# Validate and persist form data
if request.method == 'POST' and form.validate():
for c in student_courses:
student.courses[c.title] = form[c.title].data
这样可行,但如果我可以使用WTForms populate_obj()
方法,那就太棒了:
def view(request):
...
if request.method == 'POST' and form.validate():
form.populate_obj(student_courses)