DocTypes & the Data Model
A DocType is the central building block of every Frappe app. A single DocType definition gives you four things at once:
- Schema: the fields and their types, stored as JSON.
- Database table: a real SQL table generated from the schema.
- Model and controller: a Python class (a
Documentsubclass) with lifecycle hooks for validation and business logic. - UI: an auto-generated form, list view, filters and reports in the Desk.
You define the DocType once, and Frappe takes care of the table, the REST API, the form, permissions and search.
A DocType is a table
Every standard DocType maps to one SQL table named tab<DocType>. A DocType called Task lives in the table tabTask, and each field becomes a column.
SELECT name, subject, status FROM `tabTask`;
A row in that table is a document (or "doc"). In Python you work with documents, not rows:
import frappe
# Create and save a new document (a new row in tabTask)
doc = frappe.new_doc("Task")
doc.subject = "Write docs"
doc.status = "Open"
doc.insert()
# Load an existing document
doc = frappe.get_doc("Task", "TASK-0001")
print(doc.subject)
See Document API for the full set of CRUD methods.
Anatomy of a DocType
A DocType is made up of:
- Fields: each field has a
fieldtype(Data, Link, Select, Currency, Table, and more), afieldname(the column and property name) and alabel. See Fields. - Naming rule: how the primary key (
name) is generated. See Naming. - Permissions: role-based rules controlling who can read/write/submit. See Permissions.
- A controller:
<doctype>.pywith aDocumentsubclass holding validation and lifecycle logic. See Controllers & Lifecycle. - A client script:
<doctype>.jsfor form behaviour in the browser. See Form API.
Standard fields
Every document gets a set of standard fields automatically. You never declare them. The most important is name, the primary key.
| Field | Type | Description |
|---|---|---|
name |
string | Primary key, unique per DocType. How you load a doc. |
owner |
Link (User) | User who created the document. |
creation |
Datetime | When it was created. |
modified |
Datetime | Last modified timestamp (used for concurrency checks). |
modified_by |
Link (User) | User who last modified it. |
docstatus |
Int | 0 Draft, 1 Submitted, 2 Cancelled. See Docstatus. |
idx |
Int | Sort/row index. |
These are defined in frappe/model/__init__.py as default_fields. Child table rows also carry parent, parenttype and parentfield (see Child Tables).
Where a DocType lives
A DocType is owned by a module inside an app. Its files live on disk under that module's folder:
your_app/your_app/<module>/doctype/<doctype>/
├── <doctype>.json # schema (fields, permissions, naming)
├── <doctype>.py # controller (Document subclass)
├── <doctype>.js # client script
└── test_<doctype>.py
The JSON is the source of truth; it is synced into the database table on bench migrate. See Modules & App Structure.
Special kinds of DocTypes
Most DocTypes are standard table-backed types, but a few flags change their behaviour:
- Child table (
istable): rows embedded in a parent document. See Child Tables. - Single (
issingle): exactly one record, for settings pages. See Single DocTypes. - Virtual (
is_virtual): no SQL table; you supply the backend. See Virtual DocTypes. - Submittable (
is_submittable): has the Draft, Submit, Cancel flow. See Docstatus.
Next steps
- Fields: every field type and its key properties.
- Naming: how the
nameprimary key is generated. - Controllers & Lifecycle: where your business logic goes.
- Document API: reading and writing documents in code.