Class-Based Views (MethodView)
A MethodView is a Flask class where each HTTP method — get , post , put , delete — becomes its own method, grouping the logic for one resource into a single tidy class.
Learn Class-Based Views (MethodView) in our free Flask course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick…
Part of the free Flask course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll build a MethodView , register it with add_url_rule and as_view , share helper logic across methods, and learn exactly when a class beats a plain view function.
A class-based view turns the usual "one function per route" pattern on its head. You subclass MethodView and write a method named after each HTTP verb you want to support: a get method for GET requests, a post method for POST, and so on.
Flask handles the routing for you. When a request arrives, it looks at request.method and dispatches to the matching method automatically — GET calls get() , POST calls post() . There's no if request.method == "POST" branching to write or maintain.
To connect the class to a URL you call MyView.as_view("name") , which converts the class into a normal view function, and hand that to add_url_rule . The "name" string is the endpoint that url_for uses, so it must be unique across your app.
Notice there is no method-checking code — Flask sent the GET to get() and the POST to post() on its own. That automatic dispatch is the heart of a MethodView .
URL parameters work exactly as they do with function views: declare them in the rule with <int:user_id> and accept them as arguments on the matching method, like def get(self, user_id) .
Here's where a class starts to pay off. Because every method lives on the same class, they can share helper methods . A private _serialize method can format a resource once, and both get and a future put can call it — no duplicated logic scattered across separate functions.
You can also restrict which verbs a rule accepts by passing methods=["GET"] to add_url_rule , which is useful when one view function backs several rules.
The _serialize helper centralizes how a user is formatted. As you add put or delete , they call the same helper instead of repeating the dictionary — that is the structural advantage of a class.
A real resource often lives at two URLs: /users for the collection (list all, create new) and /users/<id> for a single item. A single MethodView can serve all of them by registering the same view function on multiple rules.
The trick is defaults= . By giving /users a default of user_id=None , the get method can detect "no id was supplied" and return the whole list; when an id is present it returns one record. The post method creates a new user and returns a 201 Created status by returning a (body, status) tuple.
This is the classic REST shape: GET /users lists, POST /users creates, and GET /users/<id> fetches one — all from a single, cohesive class.
Rule of thumb: one resource with several HTTP methods, shared setup, or inheritance across endpoints → a MethodView . A single simple route → a plain @app.route function.
Complete the class-based view below. Replace each ___ so it subclasses MethodView , handles GET, and registers on /ping .
❌ Forgetting as_view (passing the class itself)
Passing view_func=MyView instead of view_func=MyView.as_view("name") hands Flask a class, not a callable view, and routing breaks. Always call as_view("unique_name") first — it returns the actual view function Flask expects.
A 405 means the verb isn't served here. Either the matching method (for example post ) isn't defined on the class, or your explicit methods=[...] list left it out. Define the method and include its verb in the rule's methods list.
Build a TaskAPI class-based view that lists tasks and adds new ones.
Lesson complete — you can structure views like a pro!
You can now subclass MethodView , write a method per HTTP verb, register classes with as_view and add_url_rule , share helpers across methods, and recognize when a class beats a plain function.
🚀 Up next: Checkpoint — A Dynamic Web App — put everything together into a real, working application.
Practice quiz
What base class do you subclass for a class-based view?
- flask.Blueprint
- flask.Resource
- flask.ClassView
- flask.views.MethodView
Answer: flask.views.MethodView. Class-based views subclass flask.views.MethodView.
In a MethodView, which method handles a GET request?
- A method named get()
- A method named handle_get()
- A method named on_get()
- A method named GET()
Answer: A method named get(). Flask dispatches GET to the get() method automatically.
What converts a MethodView class into a usable view function?
- as_route()
- MyView.as_view("name")
- register_view()
- view_func()
Answer: MyView.as_view("name"). MyView.as_view("name") returns a view function you give to add_url_rule.
Which method registers the view on a URL?
- app.route_class()
- app.bind_view()
- app.add_url_rule()
- app.connect()
Answer: app.add_url_rule(). app.add_url_rule("/path", view_func=...) connects the view to a URL.
How does Flask decide which method to call?
- Alphabetical order
- The first method defined
- Random selection
- It dispatches based on request.method
Answer: It dispatches based on request.method. Flask inspects request.method and calls the matching method, e.g. POST -> post().
What is the main structural advantage of a MethodView?
- Methods share helper logic on the same class
- It is always faster than functions
- It needs no URL rule
- It disables HTTP methods
Answer: Methods share helper logic on the same class. Grouping verbs in one class lets them share helpers like a private _serialize method.
How do you declare a URL parameter for a MethodView rule?
- With request.args only
- With <int:user_id> in the rule and a matching method argument
- By naming the class after it
- It is not possible
Answer: With <int:user_id> in the rule and a matching method argument. Declare <int:user_id> in the rule and accept it as def get(self, user_id).
What does the string passed to as_view("name") become?
- The HTTP method
- The template name
- The endpoint name used by url_for
- The class docstring
Answer: The endpoint name used by url_for. It is the endpoint name, so it must be unique across the app.
How can one view function back several URL rules?
- By renaming the class each time
- It cannot, you need separate classes
- By disabling routing
- By calling add_url_rule multiple times with the same view function
Answer: By calling add_url_rule multiple times with the same view function. You can register the same as_view function on multiple rules.
How does a post() method return a 201 Created status?
- By returning a (body, status) tuple, e.g. jsonify(...), 201
- By raising Created()
- By setting self.status = 201
- By naming the method create()
Answer: By returning a (body, status) tuple, e.g. jsonify(...), 201. Returning a (body, 201) tuple sets the status code.