Neural Sync Active
Flask Forms — Handling User Input
Registry Synced
Flask Forms — Handling User Input
899 words
4 min read
Reading compass
Now · 🎯 Learning Objectives
Flask Forms — Handling User Input
🎯 Learning Objectives
- Handle GET and POST requests in Flask
- Access form data from
request.form - Validate form data and show error messages
- Use flash messages for user feedback
- Use WTForms for form validation
1. Handling Form Submissions
1.1 A Simple Contact Form
python# app.py from flask import Flask, render_template, request app = Flask(__name__) @app.route('/contact', methods=['GET', 'POST']) def contact(): if request.method == 'POST': name = request.form['name'] email = request.form['email'] message = request.form['message'] # Process the data (save to database, send email, etc.) print(f"Received from {name}: {message}") return render_template('thankyou.html', name=name) return render_template('contact.html')
html<!-- templates/contact.html --> <form method="POST" action="/contact"> <label for="name">Name:</label> <input type="text" id="name" name="name" required> <label for="email">Email:</label> <input type="email" id="email" name="email" required> <label for="message">Message:</label> <textarea id="message" name="message" rows="4" required></textarea> <button type="submit">Send</button> </form>
1.2 GET vs POST
- GET: Data in URL (
/search?q=flask). Use for searches, read-only queries. - POST: Data in request body. Use for mutations (create, update, delete).
python@app.route('/search') def search(): query = request.args.get('q', '') # GET parameters via request.args results = search_database(query) return render_template('results.html', results=results)
2. Flash Messages — User Feedback
pythonfrom flask import flash app.secret_key = 'your-secret-key-here' # Required for flash @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] if username == 'admin' and password == 'secret': flash('Login successful!', 'success') return redirect('/dashboard') else: flash('Invalid credentials!', 'error') return render_template('login.html')
html<!-- In base.html, display flash messages --> {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} <ul class="flashes"> {% for category, message in messages %} <li class="{{ category }}">{{ message }}</li> {% endfor %} </ul> {% endif %} {% endwith %}
3. Manual Form Validation
python@app.route('/register', methods=['GET', 'POST']) def register(): errors = [] if request.method == 'POST': username = request.form['username'].strip() password = request.form['password'] confirm = request.form['confirm_password'] # Validation if len(username) < 3: errors.append('Username must be at least 3 characters') if len(password) < 8: errors.append('Password must be at least 8 characters') if password != confirm: errors.append('Passwords do not match') if not errors: # Save user to database flash('Registration successful!', 'success') return redirect('/login') return render_template('register.html', errors=errors)
html{% if errors %} <ul class="errors"> {% for error in errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %}
4. WTForms — Advanced Form Handling
WTForms simplifies form definition, rendering, and validation.
python# pip install flask-wtf from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, BooleanField, SubmitField from wtforms.validators import DataRequired, Email, Length, EqualTo class RegistrationForm(FlaskForm): username = StringField('Username', validators=[ DataRequired(), Length(min=3, max=20) ]) email = StringField('Email', validators=[ DataRequired(), Email() ]) password = PasswordField('Password', validators=[ DataRequired(), Length(min=8) ]) confirm_password = PasswordField('Confirm Password', validators=[ DataRequired(), EqualTo('password') ]) submit = SubmitField('Sign Up') @app.route('/register', methods=['GET', 'POST']) def register(): form = RegistrationForm() if form.validate_on_submit(): # Form is valid — process data flash('Registration successful!', 'success') return redirect('/login') return render_template('register_wtf.html', form=form)
html<form method="POST" action=""> {{ form.hidden_tag() }} <!-- CSRF token --> <div> {{ form.username.label }} {{ form.username(size=20) }} {% for error in form.username.errors %} <span class="error">{{ error }}</span> {% endfor %} </div> <div> {{ form.email.label }} {{ form.email() }} </div> <div> {{ form.submit() }} </div> </form>
5. Common Pitfalls
Pitfall 1: Forgetting methods=['POST']
python@app.route('/login') # Default: only GET
Fix:
@app.route('/login', methods=['GET', 'POST'])Pitfall 2: Accessing form data before checking method
python@app.route('/submit', methods=['GET', 'POST']) # request.form['name'] raises BadRequestKeyError on GET
Fix: Check
request.method == 'POST' before accessing form data.Pitfall 3: Forgetting secret_key for flash/session
RuntimeError: The session is unavailable because no secret key was set.6. Practice Questions
Q1: How do you access GET parameters in Flask?Answer:request.args.get('key', 'default')for individual params.request.argsis an ImmutableMultiDict. Example:/search?q=flask&page=2→request.args.get('q')= "flask". Q2: How do you access POST data?Answer:request.form['field_name'](raises KeyError if missing) orrequest.form.get('field_name')(returns None if missing). Q3: What doesform.validate_on_submit()do in WTForms?Answer: Returns True if the form was submitted (POST) AND all validators pass. It runs all defined validators and populatesform.errorswith validation error messages. Q4: What is a CSRF token and why is it needed?Answer: Cross-Site Request Forgery token prevents malicious websites from submitting forms on behalf of an authenticated user. Flask-WTF generates and validates this token automatically. Useform.hidden_tag()in the template. Q5: How do you use flash messages?Answer: (1) Setapp.secret_key. (2)flash('Message', 'category')in routes. (3) In template, loopget_flashed_messages(with_categories=true). Categories help style different message types (success, error, info). Q6: What is the difference between request.form and request.args?Answer:request.formcontains POST data (form body).request.argscontains GET data (URL query string). Both are dictionary-like objects. Q7: Write a Flask route that accepts a search query and returns results.python@app.route('/search') def search(): query = request.args.get('q', '') results = Item.query.filter(Item.name.contains(query)).all() if query else [] return render_template('search.html', query=query, results=results)Q8: What does WTFormsEqualTovalidator check?Answer: It validates that the field's value equals the value of another field (e.g., confirm_password must match password). Usage:EqualTo('password', message='Passwords must match').
📐 Key Concepts
| Object | Content | Usage |
|---|---|---|
request.form | POST data | request.form['username'] |
request.args | GET query params | request.args.get('q') |
flash() | User messages | flash('Saved!', 'success') |
form.validate_on_submit() | WTForms validation | if form.validate_on_submit(): |