Django & Flask Topic

Handling Forms with Flask's request Object

Accessing Form Data with request.form

In Flask, when a form is submitted via POST, the data is available in the request.form object, which behaves like a dictionary.

Basic Form Handling Example:

python

from flask import Flask, request, render_template

app = Flask(__name__)

# Display the form (GET request)
@app.route('/register', methods=['GET'])
def show_registration_form():
    return render_template('register.html')

# Handle form submission (POST request)
@app.route('/register', methods=['POST'])
def handle_registration():
    # Access form data using request.form
    username = request.form['username']
    email = request.form['email']
    password = request.form['password']
    
    # Process the data (in a real app, you'd save to database, etc.)
    print(f"Registering user: {username}, Email: {email}")
    
    return f'Registration successful for {username}!'

# Alternatively, handle both GET and POST in one function
@app.route('/contact', methods=['GET', 'POST'])
def contact():
    if request.method == 'POST':
        name = request.form['name']
        message = request.form['message']
        # Process the contact form
        return f'Thank you {name} for your message!'
    
    # GET request - show the form
    return render_template('contact.html')

Corresponding HTML Template (register.html):

html

<!DOCTYPE html>
<html>
<head>
    <title>Registration</title>
</head>
<body>
    <h2>Register</h2>
    <form method="POST" action="/register">
        <input type="text" name="username" placeholder="Username" required>
        <input type="email" name="email" placeholder="Email" required>
        <input type="password" name="password" placeholder="Password" required>
        <button type="submit">Register</button>
    </form>
</body>
</html>

Safe Form Data Access

Instead of using request.form['key'] which raises a KeyError if the key doesn't exist, use request.form.get('key') which returns None if the key is missing:

python

@app.route('/search', methods=['GET', 'POST'])
def search():
    if request.method == 'POST':
        # Safe way to access form data
        query = request.form.get('query', '')  # Default to empty string
        category = request.form.get('category')  # Returns None if not found
        
        if query:
            return f'Search results for: {query}'
        else:
            return 'Please enter a search term'
    
    return render_template('search.html')

Handling File Uploads with request.files

For file uploads, you need to:

  1. Set enctype="multipart/form-data" in your form

  2. Use request.files to access uploaded files

python

from flask import request, flash
import os

app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024  # 16MB max file size

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        # Check if the post request has the file part
        if 'file' not in request.files:
            return 'No file part in the request'
        
        file = request.files['file']
        
        # If user does not select file, browser submits empty file
        if file.filename == '':
            return 'No selected file'
        
        if file:
            # Save the file
            filename = file.filename
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return f'File {filename} uploaded successfully!'
    
    return '''
    <!DOCTYPE html>
    <html>
    <body>
        <h2>Upload File</h2>
        <form method="POST" enctype="multipart/form-data">
            <input type="file" name="file">
            <button type="submit">Upload</button>
        </form>
    </body>
    </html>
    '''

Handling Multiple Values (Checkboxes, Multi-select)

For form fields that can have multiple values (like checkboxes), use getlist():

python

@app.route('/preferences', methods=['POST'])
def save_preferences():
    # For checkboxes with same name
    selected_interests = request.form.getlist('interests')
    # For multi-select dropdown
    selected_categories = request.form.getlist('categories')
    
    return f'Selected interests: {", ".join(selected_interests)}'

Complete Form Handling Example

python

from flask import Flask, request, render_template, redirect, url_for, flash

app = Flask(__name__)
app.secret_key = 'your-secret-key'  # Needed for flashing messages

@app.route('/user/create', methods=['GET', 'POST'])
def create_user():
    if request.method == 'POST':
        # Get form data safely
        username = request.form.get('username', '').strip()
        email = request.form.get('email', '').strip()
        bio = request.form.get('bio', '')
        newsletter = request.form.get('newsletter') == 'on'  # Checkbox
        avatar = request.files.get('avatar')
        
        # Basic validation
        errors = []
        if not username:
            errors.append('Username is required')
        if not email:
            errors.append('Email is required')
        
        if errors:
            for error in errors:
                flash(error, 'error')
            return render_template('create_user.html')
        
        # Process successful form submission
        user_data = {
            'username': username,
            'email': email,
            'bio': bio,
            'newsletter': newsletter
        }
        
        # Handle file upload
        if avatar and avatar.filename:
            filename = f"{username}_{avatar.filename}"
            avatar.save(os.path.join('uploads', filename))
            user_data['avatar'] = filename
        
        flash('User created successfully!', 'success')
        return redirect(url_for('user_created'))
    
    return render_template('create_user.html')

Django Connection: Appreciating Django's Form System

The "Raw Mechanics" vs Django's Abstraction

What you learn in Flask is the raw, manual process of form handling:

  • Manually accessing request.POST and request.FILES

  • Writing validation logic by hand

  • Manually rendering form fields in templates

  • Handling file uploads manually

Django's Form Classes - The Automated Approach

Django abstracts all this manual work into Form and ModelForm classes:

Flask (Manual Approach):

python

# Flask - Everything manual
@app.route('/register', methods=['POST'])
def register():
    username = request.form.get('username')
    email = request.form.get('email')
    password = request.form.get('password')
    
    # Manual validation
    errors = []
    if not username:
        errors.append('Username is required')
    if not email or '@' not in email:
        errors.append('Valid email is required')
    if len(password) < 8:
        errors.append('Password must be at least 8 characters')
    
    if errors:
        return render_template('register.html', errors=errors)
    
    # Process data...

Django (Automated Approach):

python

# Django - forms.py
from django import forms

class RegistrationForm(forms.Form):
    username = forms.CharField(max_length=100)
    email = forms.EmailField()
    password = forms.CharField(widget=forms.PasswordInput, min_length=8)

# Django - views.py
from django.shortcuts import render, redirect
from .forms import RegistrationForm

def register(request):
    if request.method == 'POST':
        form = RegistrationForm(request.POST)
        if form.is_valid():  # Automatic validation!
            username = form.cleaned_data['username']
            email = form.cleaned_data['email']
            password = form.cleaned_data['password']
            # Process data...
            return redirect('success')
    else:
        form = RegistrationForm()
    
    return render(request, 'register.html', {'form': form})

Django's ModelForm - Even More Automation

Django can automatically create forms from your models:

python

# models.py
from django.db import models

class User(models.Model):
    username = models.CharField(max_length=100)
    email = models.EmailField()
    created_at = models.DateTimeField(auto_now_add=True)

# forms.py
from django.forms import ModelForm
from .models import User

class UserForm(ModelForm):
    class Meta:
        model = User
        fields = ['username', 'email']  # Auto-generates form fields

Key Benefits You'll Appreciate After Learning Flask's Manual Approach:

  1. Automatic Validation: Django forms handle validation automatically

  2. CSRF Protection: Built-in Cross-Site Request Forgery protection

  3. Security: Automatic HTML escaping and security measures

  4. Template Rendering: Easy form rendering in templates

  5. File Handling: Simplified file upload handling with ModelForms

  6. Data Cleaning: Automatic data normalization and cleaning

This foundational knowledge makes you appreciate Django's form system much more. You'll understand what Django is doing for you under the hood, rather than just treating it as magic. When you encounter form issues in Django, you'll be able to debug them effectively because you understand the underlying mechanics learned from Flask.

Comments (0)

No comments yet. Be the first to comment!

LecturreAI Assistant

Hello! I'm LecturreAI

What would you like to learn today?