[英]How to populate lists of objects with WTForms?
使用案例:使用表格為學生注冊的每門課程輸入成績。
模型:
使用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}
如果可能,使用查詢將是最簡單的。 根據SQLAlchemy文檔 ,在會話上使用query()
方法可創建Query
對象。 像我在控制器中那樣迭代時,此對象是StudentCourse
對象的列表。
[<app.models.StudentCourse object at 0x10875bd50>, <app.models.StudentCourse object at 0x10875bed0>]
......我的進步在這里結束了。 任何幫助贊賞!
我能夠填充這些動態創建的表單的唯一方法是傳遞** 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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.