Python MVC Pattern Example (Model-View-Controller)

A minimal, runnable Model-View-Controller (MVC) example in pure Python that separates data, presentation, and logic.

Easy Python 3.9+ Aug 9, 2026 System design patterns 14 views 0 copies

Python code

43 lines
Python 3.9+
class Model:
    def __init__(self):
        self.data = {"title": "Initial Title", "content": "Initial Content"}

    def get_data(self):
        return self.data

    def update_data(self, title=None, content=None):
        if title:
            self.data["title"] = title
        if content:
            self.data["content"] = content


class View:
    def render(self, data):
        print("=" * 30)
        print(f"Title: {data['title']}")
        print(f"Content: {data['content']}")
        print("=" * 30)


class Controller:
    def __init__(self, model, view):
        self.model = model
        self.view = view

    def display(self):
        data = self.model.get_data()
        self.view.render(data)

    def update(self, title=None, content=None):
        self.model.update_data(title=title, content=content)
        self.display()


if __name__ == "__main__":
    model = Model()
    view = View()
    controller = Controller(model, view)

    controller.display()
    controller.update(title="Updated Title", content="New content here")

Output

stdout
==============================
Title: Initial Title
Content: Initial Content
==============================
==============================
Title: Updated Title
Content: New content here
==============================

How it works

Model owns the data and all mutations to it. View is only responsible for formatting/printing that data, with zero knowledge of the model's internals. Controller acts as the middle layer — it reads from the model, passes data to the view, and triggers updates. Running the script first calls display, then update, which internally calls display again after mutating the model. This separation keeps concerns isolated so you can swap views or models without touching the controller logic.

Common mistakes

  • Letting the View directly access or mutate the Model's data — it should only receive data passed by the Controller.
  • Putting business rules in the View instead of the Model, which breaks the separation of concerns.
  • Forgetting to call `display()` after an update, so the user never sees the new state.

Variations

  1. Use a `Property` or `Event` system in the Model to auto-notify views on change instead of an explicit update call.
  2. Implement View as a function (e.g. `render_html`) instead of a class when your rendering logic is trivial.

Real-world use cases

  • Structuring a desktop GUI app (e.g. tkinter or PyQt) where UI widgets refresh from a central data model.
  • Separating API routes (controller) from database objects (model) and JSON serializers (view) in a small Flask/FastAPI service.
  • Powering a web framework's command-line tool that prints report data without coupling business logic to output format.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from System design patterns

Related tutorials and quizzes for this topic.