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.