Skip to main content

TODO App Example

A simple TODO application built with Framework M.

DocType: Task

# apps/todo/src/doctypes/task/doctype.py
from __future__ import annotations

from datetime import date
from typing import ClassVar

from framework_m import DocType, Field


class Task(DocType):
"""A simple task/todo item."""

__doctype_name__: ClassVar[str] = "Task"

# Core fields
title: str = Field(description="Task title")
description: str = Field(default="", description="Task description")

# Status
status: str = Field(
default="Open",
description="Current status",
)
priority: str = Field(
default="Medium",
description="Priority level",
)

# Dates
due_date: date | None = Field(default=None, description="Due date")
completed_date: date | None = Field(default=None, description="Completed date")

class Meta:
naming_rule: ClassVar[str] = "autoincrement"
api_resource: ClassVar[bool] = True

Controller: TaskController

# apps/todo/src/doctypes/task/controller.py
from __future__ import annotations

from datetime import date

from framework_m import Controller

from .doctype import Task


class TaskController(Controller[Task]):
"""Business logic for Task."""

async def validate(self, context=None):
"""Validate task before save."""
if not self.doc.title.strip():
raise ValueError("Title is required")

async def before_save(self, context=None):
"""Auto-set completed date when status changes to Done."""
if self.doc.status == "Done" and not self.doc.completed_date:
self.doc.completed_date = date.today()

API Usage

# List all tasks
curl http://localhost:8000/api/v1/resource/Task

# Create a task
curl -X POST http://localhost:8000/api/v1/resource/Task \
-H "Content-Type: application/json" \
-d '{
"title": "Buy groceries",
"priority": "High",
"due_date": "2024-01-15"
}'

# Update task status
curl -X PUT http://localhost:8000/api/v1/resource/Task/1 \
-H "Content-Type: application/json" \
-d '{"status": "Done"}'

# Filter by status
curl "http://localhost:8000/api/v1/resource/Task?filters=[{\"field\":\"status\",\"operator\":\"eq\",\"value\":\"Open\"}]"

Quick Start

# Create the app
uv run m new:app todo

# Create the Task doctype
cd todo
uv run m new:doctype Task

# Edit doctype.py and controller.py as shown above

# Run migration
uv run m migrate init
uv run m migrate create "Add Task doctype" --autogenerate
uv run m migrate

# Start Studio
uv run m studio