Skip to main content

Creating Your First Generic View

Class-based views in Flask provide an alternative to function-based views, allowing you to use inheritance and mixins to reuse code. By subclassing the base View class, you can organize your logic into methods and configure view behavior through class attributes.

In this tutorial, you will build a greeting view that handles multiple HTTP methods and uses decorators to modify the response.

Subclassing the View Class

To create a class-based view, you must subclass flask.views.View and implement the dispatch_request method. This method acts as the entry point for the request, similar to a standard view function.

Create a file named views.py and define your first view:

from flask.views import View

class GreetingView(View):
def dispatch_request(self, name="World"):
return f"Hello, {name}!"

The dispatch_request method receives any variables captured from the URL rule as keyword arguments. In this example, it takes an optional name argument.

Registering the View

You cannot pass the class itself to app.add_url_rule. Instead, you must convert it into a view function using the as_view class method. This method takes a string which serves as the name of the endpoint.

from flask import Flask
from views import GreetingView

app = Flask(__name__)

# Register the view for a static route
app.add_url_rule("/greet", view_func=GreetingView.as_view("greet"))

# Register the view for a dynamic route
app.add_url_rule("/greet/<name>", view_func=GreetingView.as_view("greet_user"))

When a request matches the route, Flask calls the function returned by as_view. By default, this function creates a new instance of GreetingView and calls its dispatch_request method.

Handling HTTP Methods

By default, a View only responds to GET requests. To handle other methods like POST or PUT, define the methods class attribute.

from flask import request
from flask.views import View

class Index(View):
methods = ["GET", "POST"]

def dispatch_request(self):
if request.method == "POST":
return "You sent a POST request"
return "You sent a GET request"

app.add_url_rule("/", view_func=Index.as_view("index"))

Flask uses this methods attribute when registering the route, ensuring that the view only receives the specified HTTP verbs.

Applying Decorators

If you want to apply decorators (such as authentication guards or logging) to your class-based view, you cannot use the standard @decorator syntax on the class itself. Instead, use the decorators class attribute, which accepts a list of decorators.

from flask import make_response
from flask.views import View

def add_header(f):
def wrapper(*args, **kwargs):
response = make_response(f(*args, **kwargs))
response.headers["X-Custom-Header"] = "Flask-Tutorial"
return response
return wrapper

class DecoratedView(View):
decorators = [add_header]

def dispatch_request(self):
return "Check my headers!"

app.add_url_rule("/decorated", view_func=DecoratedView.as_view("decorated"))

Decorators in the list are applied in order from top to bottom. This is equivalent to applying them from bottom to top in standard Python decorator syntax.

Optimizing with init_every_request

By default, Flask creates a new instance of your view class for every single request. This ensures that storing data on self is safe because it won't leak between requests. However, if your view doesn't store state on self, you can improve performance by setting init_every_request to False.

class FastView(View):
init_every_request = False

def __init__(self):
# This runs only once when as_view is called
print("View instance created")

def dispatch_request(self):
return "Efficient response"

app.add_url_rule("/fast", view_func=FastView.as_view("fast"))

When init_every_request is False, Flask creates one instance of the class when as_view is called and reuses it for every request.

Warning: If you set init_every_request = False, you must not store request-specific data on self (e.g., self.user = ...), as this data will persist across different users' requests. Use flask.g for request-global storage instead.

Next Steps

Now that you can create generic views, you might find that manually checking request.method inside dispatch_request becomes repetitive. To solve this, Flask provides MethodView, which automatically dispatches requests to methods named after the HTTP verbs (like get(), post(), and delete()).