Issue
I have been working on implementing WTForms Dynamic Fields. Linked: https://pypi.org/project/WTForms-Dynamic-Fields/
I am getting the error: AttributeError: 'Request' object has no attribute 'post'
I understand I am doing something wrong, but I am not entirely sure what, exactly.
My code is:
@app.route("/create", methods=["POST", "GET"])
@login_required
def create():
if request.method == "POST":
name = request.form.get('name')
phone = request.form.get('phone')
email = request.form.get('email')
company = request.form.get('company')
frequency = request.form.get('frequency')
datefc = datetime.strptime(request.form.get('date'), "%Y-%m-%d")
adate = datetime.today()
if frequency == "Weekly":
nContactTime = datefc + timedelta(days=7)
elif frequency == "Monthly":
nContactTime = datefc + timedelta(days=30)
elif frequency == "Quarterly":
nContactTime = datefc + timedelta(days=90)
people.insert_one({"name": name, "phone": phone, "email": email, "company": company, "frequency": frequency,
"parentrecord": current_user.user_json['_id'], "dateadded": adate.strftime("%x"),
"datefc": datefc, "nextContact": nContactTime})
flash('Your record has been entered successfully.')
return redirect(url_for('profile'))
elif request.method == "GET":
cfv = customfields.find({"_id": current_user.user_json['_id']})
dynamic = WTFormsDynamicFields()
for value in cfv:
print(value['fieldName'] + value['fieldType'])
if value['fieldType'] == "Text Field":
dynamic.add_field(value['fieldName'], value['fieldName'], StringField)
form = dynamic.process(CreateRecord, request.post)
return render_template('create.html', form=form, auth=current_user.is_authenticated)
My form class is:
class CreateRecord(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
phone = StringField('Phone')
email = StringField('Email')
company = StringField('Company', validators=[DataRequired()])
frequency = SelectField('Follow-up Frequency',
choices=[('Weekly', 'Weekly'), ('Monthly', 'Monthly'), ('Quarterly', 'Quarterly')])
date = DateField('First Date To Contact', validators=[DataRequired()])
submit = SubmitField('Create Record')
My goal is to simply have the new fields show up on the rendered page which for testing purposes I have kept the code simple at:
{% for field in form %}
{{ field() }}
{% endfor %}
Solution
In order to register new fields, you must pass a dictionary containing the fields you'll like to pick out from your WTFormsDynamicFields
object to be available in your form.
For example, if one wants to add an email field dynamically that is required.
One must provide a MutableDict
that includes the email field.
templates/index.html
{% for field in form %}
{{ field.label }} {{ field() }}
{% endfor %}
app.py
from flask import Flask, request, render_template
from wtforms import Form, TextField
from wtforms.validators import InputRequired
from wtforms_dynamic_fields import WTFormsDynamicFields
from werkzeug.datastructures import ImmutableMultiDict
app = Flask(__name__)
class PersonalFile(Form):
""" A personal file form. """
first_name = TextField('First name', validators=[InputRequired()])
last_name = TextField('Last name', validators=[InputRequired()])
class Dict:
'''Wrapper klass because iteritems no longer available in Python3.7 dict'''
def __init__(self, mapping):
self.mapping = ImmutableMultiDict(mapping)
def iteritems(self):
return self.mapping.items()
def __getattr__(self, attr):
return getattr(self.mapping, attr)
def __iter__(self):
return dict.__iter__(self.mapping)
@app.route('/', methods=['GET', 'POST'])
def index():
dynamic = WTFormsDynamicFields()
dynamic.add_field('email', 'Email address', TextField)
dynamic.add_validator('email', InputRequired, message='This field is required')
dynamic.add_field('subject', 'Subject', TextField)
post = request.form.copy() # making a mutable dict copy
# add email in post mapping to declare
# that we are going to want this field in the form
post.add('email', '')
post = Dict(post) # Wrapping the mutable dict as immutable
# augumenting form with email field.
# Note that if we want to show the subject field,
# we must add the 'subject' key in the post mapping.
form = dynamic.process(PersonalFile, post)
if request.method == "POST":
return request.form
if request.method == 'GET':
return render_template('index.html', form=form)
if __name__ == '__main__':
app.run(debug=True)
Answered By - Oluwafemi Sule
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.