HTTP Methods & View Functions

Difficulty: Beginner

HTTP methods (also called HTTP verbs) indicate the desired action to be performed on a resource. Flask routes handle GET requests by default, but you can configure them to respond to any HTTP method. Understanding HTTP methods is essential for building REST APIs and handling form submissions.

The most common HTTP methods are GET, POST, PUT, PATCH, and DELETE. GET requests retrieve data and should not modify server state. POST requests submit data to create a resource. PUT requests replace an entire resource. PATCH requests partially update a resource. DELETE requests remove a resource. Flask also handles HEAD (like GET but without the response body) and OPTIONS (returns supported methods) automatically.

By default, a Flask route only responds to GET requests (and HEAD and OPTIONS, which Flask handles automatically). To allow other methods, pass the methods parameter to @app.route(). This parameter accepts a list of method strings. If a client sends a request with an unsupported method, Flask returns a 405 Method Not Allowed response.

Inside a view function, you can check which HTTP method was used via request.method. This is useful when a single route handles both GET (display a form) and POST (process the form submission). This pattern is common in traditional web applications where form pages handle both displaying and processing.

Flask also supports class-based views through the MethodView class from flask.views. With MethodView, you define separate methods for each HTTP verb (get, post, put, delete), and Flask dispatches to the correct method based on the request. This can be cleaner than a single function with if/elif blocks for each method. Class-based views are registered using app.add_url_rule() with the as_view() class method.

For REST APIs, it is common to have routes that support multiple methods with different behaviors. A '/api/users' route might support GET (list all users) and POST (create a user), while '/api/users/<id>' supports GET (get one user), PUT (update a user), and DELETE (delete a user). Flask's routing system makes this pattern straightforward.

Flask 2.0 introduced shortcut decorators: @app.get(), @app.post(), @app.put(), @app.delete(), and @app.patch(). These are syntactic sugar for @app.route(methods=['GET']), etc. They make route definitions more readable and explicit about which HTTP method a route handles.

Code examples

Handling Multiple HTTP Methods

from flask import Flask, request

app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        # Validate credentials...
        return f'Logging in {username}'
    # GET request - show login form
    return '''
        <form method="POST">
            <input name="username" placeholder="Username">
            <input name="password" type="password" placeholder="Password">
            <button type="submit">Login</button>
        </form>
    '''

This route handles both GET and POST. GET displays the login form, POST processes the submission. The request.method attribute tells you which HTTP method was used.

Shortcut Method Decorators (Flask 2.0+)

from flask import Flask, request

app = Flask(__name__)

@app.get('/items')
def list_items():
    return {'items': ['apple', 'banana', 'cherry']}

@app.post('/items')
def create_item():
    data = request.get_json()
    return {'created': data['name']}, 201

@app.delete('/items/<int:item_id>')
def delete_item(item_id):
    return {'deleted': item_id}

@app.put('/items/<int:item_id>')
def update_item(item_id):
    data = request.get_json()
    return {'updated': item_id, 'data': data}

Flask 2.0+ provides @app.get(), @app.post(), @app.put(), @app.delete(), and @app.patch() as shortcuts. They are clearer than using methods=['GET'] and make the HTTP method obvious at a glance.

Class-Based Views with MethodView

from flask import Flask, request
from flask.views import MethodView

app = Flask(__name__)

class UserAPI(MethodView):
    def get(self, user_id=None):
        if user_id is None:
            return {'users': ['alice', 'bob']}
        return {'user': f'user_{user_id}'}

    def post(self):
        data = request.get_json()
        return {'created': data}, 201

    def put(self, user_id):
        data = request.get_json()
        return {'updated': user_id, 'data': data}

    def delete(self, user_id):
        return {'deleted': user_id}

# Register the class-based view
user_view = UserAPI.as_view('user_api')
app.add_url_rule('/api/users', view_func=user_view, methods=['GET', 'POST'], defaults={'user_id': None})
app.add_url_rule('/api/users/<int:user_id>', view_func=user_view, methods=['GET', 'PUT', 'DELETE'])

MethodView dispatches to get(), post(), put(), delete() methods based on the HTTP method. You register it with as_view() and add_url_rule(). This keeps method handling organized in a class instead of if/elif chains.

Key points

Concepts covered

GET, POST, PUT, DELETE, PATCH, methods Parameter, Class-Based Views