了解 wtforms StringField 实现

Understanding the wtforms StringField implementation

我正在使用 Flask 中的 wtforms,特别有兴趣了解 StringField 实现的某些方面 class。

所以我有以下用户定义 class:

from flask_wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired


class LoginForm(Form):

    username = StringField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired()])

现在我像这样实例化 class:

from flask import request
form = LoginForm(request.form)

现在当我这样做时:

form.username.data

我基本上指的是 data 对象的 username 成员(它是 StringField 的一个对象 class)。对吗?

现在我想了解这个 数据 来自哪里?

所以我继续实施 StringFiled class,我在以下位置找到了它:

site-packages/wtforms/fields/core.py

core.py文件比较大无法粘贴

现在 core.py StringField class 的实现是:

class StringField(Field):
    """
    This field is the base for most of the more complicated fields, and
    represents an ``<input type="text">``.
    """
    widget = widgets.TextInput()

    def process_formdata(self, valuelist):
        if valuelist:
            self.data = valuelist[0]
        else:
            self.data = ''

    def _value(self):
        return text_type(self.data) if self.data is not None else ''

现在在这个 class 中,data 成员出现的第一个位置(实际上已设置)在

行中
self.data = valuelist[0]

在 process_formdata() 中附加到调用对象(在我们的例子中是对象 用户名),然后它最终在 _value( ).

但是 process_formdata() 本身在整个 core.py 文件的任何地方都不会被调用,除了 1 个地方,即在 Field class 方法(StringField 继承)中进程()

但重点是,process() 方法本身并没有真正在整个 core.py 的任何地方被调用。

所以问题是:

当执行此操作的代码行根本没有达到时,self.data 究竟是如何设置的?我肯定错过了什么。请帮助我更好地理解这一点。

好的。凉爽的。通过学习如何使用 pycharm 调试 Flask 应用程序,然后单步执行 into/over 一些代码,得到了这个。调试中的一个技巧部分是配置调试设置以传递 运行 应用程序所需的参数。在我的例子中,应用程序是 运行 通过使用 flask_script 中的管理器模块作为:

from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from project import app, db

app.config.from_object('config.DevelopmentConfig')
migrate = Migrate(app, db)
manager = Manager(app)

manager.add_command('db', MigrateCommand)

if __name__ == '__main__':
    manager.run()

虽然 运行 以这种方式 运行server 需要作为参数给出,例如:

python manage.py runserver

所以这个 运行server 参数也需要在调试期间给出。 所以要这样做(在 form = LoginForm(request.form) 行中放置一个断点后,实际上一切都从这里开始):

  1. 转到主 运行 文件,即 manage.py,其中包含上述内容 代码。
  2. 转到主菜单中的运行 -> 调试
  3. 从弹出的window中,选择编辑配置选项
  4. 在 RHS 窗格中,在 Script Parameters 中将值设为 运行server
  5. 应用然后点击调试。

现在当您在浏览器中提交表单时,您会遇到上面设置的断点。现在您可以简单地单步执行 into/over 代码(根据需要)并按照执行流程跟踪实际调用方法的时间。

所以这里的 process() 基本上是从以下路径调用的:

site-packages/wtforms/forms.py

调用它的代码片段是:

    for name, field, in iteritems(self._fields):
        if obj is not None and hasattr(obj, name):
            field.process(formdata, getattr(obj, name))
        elif name in kwargs:
            field.process(formdata, kwargs[name])
        else:
            field.process(formdata)

由于用户定义文件中的这一行,上述文件出现在图片中,forms.py

from wtforms import StringField, PasswordField