问题
I'm working on a flask app and using flask-wtf to help manage my forms.
There are 2 ways to register on my site - Either with or without an email token.
If the email has been confirmed the user gets an email containing:
http://127.0.0.1:5000/register/ImNsdWVtYXJpbmUzQG1haWxpbmF0b3IuY29tIg.Ca9oUQ.bRJmGYQ1wNqfcQFx1pYyoCEy2oM
Otherwise on the site itself the user could click on:
http://127.0.0.1:5000/register
The following code can handle both cases:
@blueprint.route("/register/", defaults={'token': ''}, methods=['GET', 'POST'])
@blueprint.route("/register/<token>", methods=['GET', 'POST'])
def register(token):
form = RegisterForm(request.form, csrf_enabled=False)
email = confirm_token(token)
if form.validate_on_submit():
new_user = User.create(username=form.username.data,
email=form.email.data,
password=form.password.data,
active=True)
return render_extensions('public/register.html', form=form , email=email)
My form class looks like:
class RegisterForm(Form):
username = StringField('Username', validators=[DataRequired(), Length(min=3, max=25)])
email = StringField('Email', validators=[DataRequired(), Email(), Length(min=6, max=40)])
password = PasswordField('Password', validators=[DataRequired(), Length(min=6, max=40)])
I have a jinja2 form template that looks like:
{% from "macros.html" import render_field %}
<div class="container-narrow">
<h1>Register</h1>
<br/>
<form id="registerForm" class="form form-register" method="POST" action="" role="form">
{{ form.hidden_tag() }}
{% for field in form %}
{% if field.label!='Email' or email=='False' %}
{{ render_field(field) }}
{% endif %}
{% endfor %}
<p><input class="btn btn-default btn-submit" type="submit" value="Register"></p>
</div>
{% endblock %}
and a jinja2 macro that looks like:
{% macro render_field(field)%}
<div class="form-group">
{# {{field.label}}#}
{{field(placeholder=field.label.text, class_="form-control")}}
</div>
{% endmacro %}
Right now this code works to display all the fields in the registerForm class. I'd like to modify/filter it so that if a token is used, I would like to display and validate only 2 form fields (username, password) . If no token - all 3 . How can this be done?
edit: switching
{% if field.label!='Email' or email=='False' %}
to
{% if field.label.text!='Email' or email=='False' %}
got it working
回答1:
One option would be to use inheritance, we'd define 2 form classes:
class TokenRegisterForm(Form):
username = StringField('Username',
validators=[DataRequired(), Length(min=3, max=25)])
password = PasswordField('Password',
validators=[DataRequired(), Length(min=6, max=40)])
class RegisterForm(TokenRegister):
email = StringField('Email',
validators=[DataRequired(), Email(), Length(min=6, max=40)])
Then we'd modify the view to choose a form to use based on the existence of a token:
def register(token):
"""Register a user"""
# Create the registration form based on the presence of a token. If the user
# has specified a valid token then we can use that to get retrieve their
# email address, if not we need to the registration form to ask it.
email = confirm_token(token)
if email:
form = TokenRegisterForm(request.form, csrf_enabled=False)
else
form = RegisterForm(request.form, csrf_enabled=False)
# Validate the user's submission
if form.validate_on_submit():
# Collate the details for the new user
user_details = form.data
user_details['active'] = True
if email:
user_details['email'] = email
# Create the new user
new_user = User.create(**user_details)
return render_extensions('public/register.html', form=form, email=email)
Finally we'd modify the Jinja2 template removing the loop (as it's such a short form):
{% from "macros.html" import render_field %}
<div class="container-narrow">
<h1>Register</h1>
<br/>
<form
class="form form-register"
id="registerForm"
method="POST"
role="form"
>
{{ form.hidden_tag() }}
{{ render_field(field.username) }}
{% if form.email %}
{{ render_field(field.email) }}
{% endif %}
{{ render_field(field.password) }}
<p>
<input
class="btn btn-default btn-submit"
type="submit"
value="Register">
</p>
</div>
来源:https://stackoverflow.com/questions/35636678/displaying-jinja2-form-fields-based-on-attribute-value