Creating and modifying Frappe DocTypes, fields, and naming rules.
DocTypes are the core data model in Frappe. Each DocType becomes a database table and gets auto-generated CRUD APIs, forms, and list views.
Create the JSON definition file. Frappe creates the folder structure on bench migrate.
Do NOT mkdir DocType directories. Write the JSON file and let migrate handle it.
File path: apps/<app>/<app>/<module>/doctype/<doctype_name>/<doctype_name>.json
Minimal example:
{
"name": "Expense",
"module": "Expense Tracker",
"doctype": "DocType",
"engine": "InnoDB",
"fields": [
{
"fieldname": "title",
"fieldtype": "Data",
"label": "Title",
"reqd": 1
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"label": "Amount",
"reqd": 1
},
{
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
"options": "Draft\nApproved\nRejected",
"default": "Draft"
}
],
"autoname": "format:EXP-{####}",
"naming_rule": "Expression",
"is_submittable": 0,
"permissions": [
{
"role": "System Manager",
"read": 1,
"write": 1,
"create": 1,
"delete": 1
}
]
}
Also create an empty __init__.py alongside the JSON:
apps/<app>/<app>/<module>/doctype/<doctype_name>/__init__.py
| fieldtype | Use for |
|---|---|
| Data | Short text (140 chars) |
| Small Text | Multi-line text |
| Text Editor | Rich text (HTML) |
| Int | Integer |
| Float | Decimal |
| Currency | Money amounts |
| Date | Date only |
| Datetime | Date + time |
| Select | Dropdown (options separated by \n) |
| Link | Foreign key to another DocType |
| Table | Child table (one-to-many) |
| Check | Boolean (0/1) |
| Attach | File attachment |
autoname: "format:EXP-{####}" — sequential (EXP-0001, EXP-0002)autoname: "field:title" — use field value as nameautoname: "hash" — random hashautoname: "naming_series:" — user-configurable seriesautoname: "prompt" — user enters name manuallyFor one-to-many relationships (e.g. Expense Items inside an Expense):
"istable": 1Table field in the parent pointing to it:{
"fieldname": "items",
"fieldtype": "Table",
"label": "Items",
"options": "Expense Item"
}
Child DocType must have "istable": 1 and no permissions (inherits from parent).
Always run:
bench --site <site> migrate
{
"sort_field": "modified", // default sort column for list view
"sort_order": "DESC", // ASC or DESC
"track_changes": 1, // enable version history / timeline
"is_submittable": 1 // enables Submit → Cancel → Amend workflow
}
Submittable DocTypes get a docstatus field automatically: 0 = Draft, 1 = Submitted, 2 = Cancelled. Users cannot edit submitted documents — they must cancel and amend.
Do NOT add creation, modified, owner, modified_by, or docstatus as fields — Frappe creates these automatically.