簡體   English   中英

如何使用WTForms填充對象列表?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM