Types of DocType in Frappe Framework (Version 15)
Introduction – What Are DocTypes in Frappe?
A DocType in the Frappe Framework represents both a database table and a form interface used to manage data.
Every document in Frappe whether a Customer, Sales Invoice, or Task — is modeled as a DocType.
Frappe provides multiple types of DocTypes to handle various data structures and business use cases.
Understanding these types is essential for designing scalable, modular, and efficient ERP applications.
Why Understanding DocType Types Matters
Each DocType type serves a unique role in data management and system architecture.
Knowing the difference helps developers:
- Choose the correct data storage strategy.
- Build reusable and relational models.
- Improve application performance and maintainability.
- Simplify permissions and workflow configurations.
Types of DocType in Frappe v15
In Frappe Version 15, DocTypes are broadly categorized into four types based on their structure, data storage behavior, and parent-child relationships:
- Standard DocType
- Single DocType
- Child Table DocType
- Custom DocType
Let’s explore each type in detail.
1. Standard DocType
A Standard DocType is the most common type — it stores multiple records in its own dedicated database table.
When created, Frappe automatically generates a MariaDB table named tab<DocType Name>.
For example, the Task DocType creates a table called tabTask.
Each record in a Standard DocType corresponds to one row in this table.
Key Features:
- Can store multiple records.
- Supports full CRUD operations (Create, Read, Update, Delete).
- Allows workflows, permissions, and submission logic.
- Ideal for transactional or master data (e.g., Sales Order, Item, Customer).
Example:
{
"doctype": "DocType",
"name": "Project",
"is_submittable": 1,
"fields": [
{"fieldname": "project_name", "fieldtype": "Data", "reqd": 1},
{"fieldname": "start_date", "fieldtype": "Date"}
]
}
Each field becomes a database column automatically.
2. Single DocType
A Single DocType holds only one record — it’s designed for global configuration or application settings.
Instead of creating a dedicated table, Frappe stores its data in a shared table called tabSingles.
Use Case Examples:
- System Settings
- Email Account
- Website Settings
Key Characteristics:
- Contains only one instance (no “New” button in the UI).
- Accessed via frappe.db.get_single_value() or frappe.db.set_value().
- Ideal for storing configuration data or global variables.
Example Usage:
# Fetch a setting
email_enabled = frappe.db.get_single_value("Email Account", "enable_outgoing")
# Update a single DocType value
frappe.db.set_value("System Settings", None, "enable_scheduler", 1)
Storage Example:
| doctype | field | value |
| System Settings | enable_scheduler | 1 |
| Email Account | default_sender | info@site.com |
3. Child Table DocType
A Child Table DocType is designed to exist within a parent DocType.
It doesn’t stand alone but acts as a one-to-many relational table.
For instance, a Sales Invoice (Parent) may contain multiple Sales Invoice Item (Child) entries.
Key Features:
- Exists only inside a parent record.
- Cannot be accessed independently via list view.
- Each child record links to the parent using a parent field.
- Displayed as an editable grid within the parent form.
Example Directory:
my_app/
└── my_app/
└── doctype/
├── sales_invoice/
└── sales_invoice_item/
Example Child Table JSON:
{
"doctype": "DocType",
"name": "Sales Invoice Item",
"istable": 1,
"fields": [
{"fieldname": "item_code", "fieldtype": "Link", "options": "Item"},
{"fieldname": "qty", "fieldtype": "Float"}
]
}
In the parent DocType (Sales Invoice), add:
{
"fieldname": "items",
"fieldtype": "Table",
"options": "Sales Invoice Item"
}
4. Custom DocType
Custom DocTypes are created from the Desk interface by users without modifying the codebase.
They are stored as metadata in the database rather than as JSON files in the filesystem.
When to Use:
- For user-defined modules.
- To add new data structures without app rebuilds.
- For quick prototyping or one-time configurations.
Limitations:
- Not version-controlled.
Can be overwritten during migrations if not exported to code using:
bench export-fixtures
Comparison of DocType Types
| Feature | Standard | Single | Child Table | Custom |
| Multiple Records | ✅ | ❌ | ✅ (within parent) | ✅ |
| Independent Access | ✅ | ❌ | ❌ | ✅ |
| Database Table | tab<DocType> | tabSingles | tab<Child DocType> | Database Metadata |
| Use Case | Transactions / Masters | Settings | Sub-Records | User Customization |
| Controlled via UI | ✅ | ✅ | ✅ | ✅ |
| Supports Workflow | ✅ | ❌ | ❌ | ✅ |
How Frappe Internally Manages DocType Types
When a new DocType is created, Frappe automatically identifies its type based on flags set in the JSON definition:
| Property | Type | Description |
| issingle | 1 | Marks a Single DocType |
| istable | 1 | Marks a Child Table DocType |
| None set | Standard DocType | |
| Custom Created in UI | Custom DocType |
Frappe dynamically routes CRUD operations accordingly:
- Standard → Creates new DB table.
- Single → Uses tabSingles.
- Child Table → Links through parent and parenttype fields.
Example — Mixed DocType Structure
Example scenario: Sales Invoice
| DocType | Type | Description |
| Sales Invoice | Standard | Parent document |
| Sales Invoice Item | Child Table | Line items |
| Selling Settings | Single | Configuration for selling module |
This hierarchy ensures modularity and data normalization in ERPNext applications.
Best Practices
- Use Single DocTypes only for global configurations.
- Always define Child Table DocTypes for repeated or nested data.
- Avoid using Custom DocTypes for core app logic; prefer standard DocTypes.
Enable Developer Mode when building new DocTypes for exportable metadata:
bench set-config developer_mode 1
bench restart
- For large datasets, use Standard DocTypes with indexing to optimize queries.
Troubleshooting & Common Mistakes
| Issue | Cause | Solution |
| Data not saving | Missing fieldname or incorrect fieldtype | Verify JSON schema |
| Child Table not displaying | Missing parent Table field link | Set options = Child DocType name |
| Single DocType missing in database | Not initialized properly | Open in Desk UI to auto-create record |
| Custom DocType lost after update | Not exported | Run bench export-fixtures before deployment |
Cross-References & Related Topics
- Create a DocType in Frappe Framework (v15)
- DocType Features in Frappe Framework (v15)
- Controller Methods in Frappe Framework (v15)
- Frappe Model and Database Architecture (GitHub v15)