WTForms:同一页面上的两个表单? [英] WTForms: two forms on the same page?

查看:29
本文介绍了WTForms:同一页面上的两个表单?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个动态网页,它应该处理两种表单:登录表单注册表单.我正在使用 WTForms 来处理这两个表单,但我在使其工作时遇到了一些麻烦,因为这两个表单都被渲染到同一页面.

I have a dynamic web-page that should process two forms: a login form and a register form. I am using WTForms to process the two forms but I am having some trouble making it work, since both forms are being rendered to the same page.

以下是我的网页登录表单的代码:

The following is the code for the login form of my webpage:

PYTHON:
class Login(Form):
    login_user = TextField('Username', [validators.Required()])
    login_pass = PasswordField('Password', [validators.Required()])

@application.route('/index', methods=('GET', 'POST'))
def index():
    l_form = Login(request.form, prefix="login-form")
    if request.method == 'POST' and l_form.validate():
        check_login = cursor.execute("SELECT * FROM users WHERE username = '%s' AND pwd = '%s'"
        % (l_form.login_user.data, hashlib.sha1(l_form.login_pass.data).hexdigest()))
        if check_login == True:
            conn.commit()
            return redirect(url_for('me'))
    return render_template('index.html', lform=l_form)


HTML:
<form name="lform" method="post" action="/index">
    {{ lform.login_user }}
    {{ lform.login_pass }}
    <input type="submit" value="Login" />
</form>

以下是我的网页注册表单的代码:

The following is the code for the register form of my webpage:

PYTHON:
class Register(Form):
    username = TextField('Username', [validators.Length(min=1, max = 12)])
    password = PasswordField('Password', [
        validators.Required(),
        validators.EqualTo('confirm_password', message='Passwords do not match')
    ])
    confirm_password = PasswordField('Confirm Password')
    email = TextField('Email', [validators.Length(min=6, max=35)])

@application.route('/index', methods=('GET','POST'))
def register():
    r_form = Register(request.form, prefix="register-form")
    if request.method == 'POST' and r_form.validate():
        check_reg = cursor.execute("SELECT * FROM users WHERE username = '%s' OR `e-mail` = '%s'"
        % (r_form.username.data, r_form.email.data))

        if check_reg == False:
            cursor.execute("INSERT into users (username, pwd, `e-mail`) VALUES ('%s','%s','%s')"
            % (r_form.username.data, hashlib.sha1(r_form.password.data).hexdigest(), check_email(r_form.email.data)))
            conn.commit()
            return redirect(url_for('index'))
    return render_template('index.html', rform=r_form)


HTML:
<form name="rform" method="post" action="/index">
    {{ rform.username }}
    {{ rform.email }}
    {{ rform.password }}
    {{ rform.confirm_password }}
    <input type="submit" value="Register />
</form>

当我继续加载网页时出现以下错误:

I get the following error when I go ahead and load the webpage:

    Traceback (most recent call last):
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflaskapp.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflaskapp.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflaskapp.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflaskapp.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflaskapp.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflaskapp.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflaskapp.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflaskapp.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "C:UsersHTVal_000DesktopinnoCMSmain.py", line 36, in index
    return render_template('index.html', lform=l_form)
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflask	emplating.py", line 128, in render_template
    context, ctx.app)
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesflask	emplating.py", line 110, in _render
    rv = template.render(context)
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesjinja2environment.py", line 969, in render
    return self.environment.handle_exception(exc_info, True)
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesjinja2environment.py", line 742, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "C:UsersHTVal_000DesktopinnoCMS	emplatesdefaultindex.html", line 52, in top-level template code
    {{ rform.username }}
  File "C:UsersHTVal_000DesktopinnoCMSvirtualenvlibsite-packagesjinja2environment.py", line 397, in getattr
    return getattr(obj, attribute)
UndefinedError: 'rform' is undefined

据我所知,表格之间存在冲突,因为根据回溯:

From what I understand, there is a conflict between the forms because according to the traceback:

return render_template('index.html', lform=l_form)

返回以下错误:

UndefinedError: 'rform' is undefined

当脚本看到:

{{ rform.username }}
{{ rform.email }}
{{ rform.password }}
{{ rform.confirm_password }}

但它完全忽略了:

{{ lform.login_user }}
{{ lform.login_pass }}

可能有点混乱,我也很困惑,我希望有人以前遇到过这个问题,这样我也可以解决它.

It might be a little confusing, I am confused loads as well, and I hope that someone has faced this problem before so that I could solve it too.

推荐答案

这有点混乱,因为你在 index() 和 register() 上渲染 index.html,并且都注册了相同的路由 (@application.route('/index')).当您将表单提交到 /index 时,只会调用其中之一.你可以

This is a bit confusing, because you render index.html on both index() and register(), and both register the same route (@application.route('/index')). When you submit your form to /index, only one of them only ever get called. You can either

  • 将所有逻辑放在一个索引函数中,看看哪种形式(如果有)是有效的.
  • 分离你的逻辑,只提交相关的表单

通常,您希望将逻辑分开,即使您希望在同一页面上同时显示登录和注册.所以我会尝试向你展示正确的方向:-)

Generally, you want to separate the logic, even if you want to show both the login and signup on the same page. So I'll try to show you in the right direction :-)

例如,首先将您的登录视图和注册视图分开,现在只会检查与它们相关的表单的逻辑:

For example, first separate your login and register views, which will now only check the logic for the form that concerns them:

class Login(Form):
    login_user = TextField('Username', [validators.Required()])
    login_pass = PasswordField('Password', [validators.Required()])

class Register(Form):
    username = TextField('Username', [validators.Length(min=1, max = 12)])
    password = PasswordField('Password', [
        validators.Required(),
        validators.EqualTo('confirm_password', message='Passwords do not match')
    ])
    confirm_password = PasswordField('Confirm Password')
    email = TextField('Email', [validators.Length(min=6, max=35)])

@application.route('/login', methods=['POST'])
def index():
    l_form = Login(request.form, prefix="login-form")
    if l_form.validate():
        check_login = cursor.execute("SELECT * FROM users WHERE username = '%s' AND pwd = '%s'"
            % (l_form.login_user.data, hashlib.sha1(l_form.login_pass.data).hexdigest()))
        if check_login == True:
            conn.commit()
            return redirect(url_for('me'))
    return render_template('index.html', lform=l_form, rform=Register())

@application.route('/register', methods=['POST'])
def register():
    r_form = Register(request.form, prefix="register-form")
    if r_form.validate():
        check_reg = cursor.execute("SELECT * FROM users WHERE username = '%s' OR `e-mail` = '%s'"
            % (r_form.username.data, r_form.email.data))

        if check_reg == False:
            cursor.execute("INSERT into users (username, pwd, `e-mail`) VALUES ('%s','%s','%s')"
                % (r_form.username.data, hashlib.sha1(r_form.password.data).hexdigest(), check_email(r_form.email.data)))
            conn.commit()
            return redirect(url_for('index'))
    return render_template('index.html', lform=Login(), rform=r_form)

@application.route('/index')
def index():
    # If user is logged in, show useful information here, otherwise show login and register
    return render_template('index.html', lform=Login(), rform=Register())

然后,创建一个显示两个表单的 index.html 并将它们发送到正确的方向.

Then, create a index.html that shows both forms and send them in the right direction.

<form name="lform" method="post" action="{{ url_for('login') }}">
    {{ lform.login_user }}
    {{ lform.login_pass }}
    <input type="submit" value="Login" />
</form>

<form name="rform" method="post" action="{{ url_for('register') }}">
    {{ rform.username }}
    {{ rform.email }}
    {{ rform.password }}
    {{ rform.confirm_password }}
    <input type="submit" value="Register" />
</form>

该代码未经测试,因此可能存在错误,但我希望它能够为您指明正确的方向.请注意,我们在对 render('index.html', ...) 的所有调用中都传递了 lform 和 rform.

The code is untested, so there might be bugs, but I hope it sends you in the right direction. Notice that we pass both lform and rform in all calls to render('index.html', ...).

更简单的改进/重构方法:使用函数检查现有用户(您的 SELECT 语句)并使用 Jinja2 的包含或宏来处理模板中的各个表单.

Further easy ways to improve/refactor: use a function to check for an existing user (your SELECT statement) and use Jinja2's includes or macros for the individual forms in the templates.

这篇关于WTForms:同一页面上的两个表单?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆