frappe-doctype-development

Frappe DocType Development

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "frappe-doctype-development" with this command: npx skills add lubusin/agent-skills/lubusin-agent-skills-frappe-doctype-development

Frappe DocType Development

Build and modify DocTypes—the core data model abstraction in Frappe Framework.

When to use

  • Creating new DocTypes (standard, single, child table, submittable, tree)

  • Adding or modifying fields on existing DocTypes

  • Implementing controller logic (validate, before_save, on_submit, etc.)

  • Setting up naming series and auto-naming

  • Configuring permissions and workflows

  • Building child tables and parent-child relationships

Inputs required

  • Target app and module path

  • DocType name and type (standard/single/child/submittable/tree)

  • Field definitions (name, type, options)

  • Permission requirements by role

  • Whether workflow is needed

Procedure

  1. Verify environment

Ensure developer mode is enabled

bench --site <site> console

frappe.conf.developer_mode # Must be True

  1. Choose DocType type

Type Use Case Key Setting

Standard Multiple records Default

Single Config/settings (one record) issingle: 1

Child Table Rows in parent table istable: 1

Submittable Draft→Submit→Cancel workflow is_submittable: 1

Tree Hierarchical data is_tree: 1

Virtual External data source is_virtual: 1

  1. Create DocType

Option A: Via UI (recommended for new DocTypes)

  • Navigate to DocType List → New

  • Define fields, permissions, settings

  • Save (exports to app in developer mode)

Option B: Via code

Create DocType JSON in:

<app>/<module>/doctype/<doctype_name>/<doctype_name>.json

  1. Define fields

Common field patterns:

{ "fieldname": "customer", "fieldtype": "Link", "label": "Customer", "options": "Customer", "reqd": 1 }

See references/field-types.md for all field types.

  1. Implement controller

Create <doctype_name>.py alongside the JSON:

import frappe from frappe.model.document import Document

class MyDocType(Document): def validate(self): # Lightweight validation if not self.customer: frappe.throw("Customer is required")

def before_save(self):
    # Pre-save normalization
    self.full_name = f"{self.first_name} {self.last_name}"

def after_insert(self):
    # Post-create side effects
    frappe.publish_realtime("new_doc", {"name": self.name})

5) Set up naming

{ "autoname": "naming_series:", "fields": [ { "fieldname": "naming_series", "fieldtype": "Select", "options": "PRJ-.YYYY.-\nPRJ-.YYYY.-.###" } ] }

Options: field:fieldname , naming_series: , hash , format:PREFIX-{####}

  1. Configure permissions

Set in DocType → Permissions tab:

  • Role + Read/Write/Create/Delete/Submit/Cancel

  • User permissions for row-level filtering

  1. Add workflow (if needed)

Create Workflow DocType linking to your DocType with states and transitions.

Verification

  • DocType appears in list and can create new records

  • All fields save correctly

  • Controller hooks fire (check logs)

  • Permissions enforced for each role

  • Naming series generates correctly

  • Run: bench --site <site> migrate succeeds

Failure modes / debugging

  • DocType not found: Check module path and app installation

  • Controller not loading: Verify class name matches DocType name (PascalCase)

  • Fields not saving: Check fieldtype and options compatibility

  • Permission denied: Verify role permissions and User Permissions

Escalation

  • For complex permission logic, see references/permissions.md

  • For child table patterns, see references/child-tables.md

  • For Virtual DocTypes, see references/virtual-doctypes.md

References

  • references/field-types.md - All field types and options

  • references/controllers.md - Controller lifecycle hooks

  • references/child-tables.md - Parent-child patterns

  • references/naming.md - Naming patterns

Guardrails

  • Check developer_mode before schema changes: DocType modifications only export to files when developer_mode = 1 in site config

  • Verify naming series uniqueness: Ensure naming series prefixes don't conflict with existing DocTypes

  • Test child tables separately: Child tables have their own lifecycle; test them in isolation before parent integration

  • Always run migrate after changes: Schema changes require bench --site <site> migrate to apply

  • Validate fieldname conventions: Use snake_case, max 140 chars, no reserved SQL keywords

Common Mistakes

Mistake Why It Fails Fix

Missing reqd on mandatory fields Users can save incomplete data Set reqd: 1 on fields that must have values

Wrong fieldtype for data Data truncation or validation errors Match fieldtype to data (e.g., Currency for money, not Float )

Not running bench migrate

Schema changes not applied to database Always run bench --site <site> migrate after DocType changes

Circular Link dependencies DocType creation fails Use Dynamic Link or restructure relationships

Controller class name mismatch Controller methods not called Class name must be PascalCase of DocType name (e.g., SalesOrder for "Sales Order")

Missing in_list_view on key fields Fields not visible in list Set in_list_view: 1 on important fields

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

frappe-frontend-development

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

frappe-app-development

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

frappe-api-development

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

frappe-router

No summary provided by upstream source.

Repository SourceNeeds Review