Skip to main content

Python Dialog API (frappe.ui.py_dialog) in Frappe v15

What is a Python Dialog in Frappe?

frappe.ui.py_dialog is a server-side API that allows Python code to render and control UI dialogs dynamically in the Desk.
It is used to show interactive popups with form fields, custom UI actions, and callback logic directly from backend logic.
Unlike the JavaScript Dialog API, the Python Dialog allows the server to display UI dialogs triggered by server events, such as:

  • DocType events (validate, before_save)
  • Custom server scripts
  • Background job interaction
  • Server actions in workflow

When Should You Use the Python Dialog API?

Use frappe.ui.py_dialog when:

  • The dialog should open from server-side execution
  • Data validation requires user input
  • You want a modal UI flow controlled by Python
  • You need user confirmation before saving
  • Dynamic UI needs backend computation

It is not intended for normal form rendering.

For client-side UI, use frappe.ui.Dialog (JS).

How to Create a Python Dialog in Frappe v15

Basic Example

import frappe
from frappe.ui.py_dialog import Dialog
def show_dialog():
dialog = Dialog(
title="Confirm Action",
fields=[
{"label": "Reason", "fieldname": "reason", "fieldtype": "Small Text"},
],
primary_action_label="Submit",
primary_action=on_submit
)
dialog.show()
def on_submit(values):
frappe.msgprint(f"You entered: {values.reason}")

How it Works

  • Dialog class defines UI
  • show() renders dialog on the user’s screen
  • primary_action(values) receives user input

Python Dialog Constructor

Dialog Structure

Dialog(
title: str,
fields: list,
primary_action_label: str,
primary_action: callable,
size: str = "small",
secondary_action_label: str = None,
secondary_action: callable = None
)

Parameters

Parameter Type Description
title string Dialog header title
fields list List of field definitions
primary_action_label string Button label
primary_action function Callback executed on primary button click
size string Dialog size (small, large, extra-large)
secondary_action_label string Optional secondary action label
secondary_action function Secondary callback

Supported Field Types

The dialog supports all standard Frappe field types:

Examples:

  • Data
  • Small Text
  • Select
  • Link
  • Date
  • Int
  • Float
  • Check
  • Table (Inline Table)
  • Column Break
  • Section Break

Example field definition:

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

Full Example with Multiple Fields

import frappe
from frappe.ui.py_dialog import Dialog
def dialog_example():
dialog = Dialog(
title="Create Meeting",
fields=[
{"label": "Subject", "fieldname": "subject", "fieldtype": "Data", "reqd": 1},
{"label": "Date", "fieldname": "date", "fieldtype": "Date"},
{"label": "Participants", "fieldname": "participants", "fieldtype": "Table", "options": "Meeting Participant"},
],
primary_action_label="Create",
primary_action=create_meeting
)
dialog.show()
def create_meeting(values):
meeting = frappe.get_doc({
"doctype": "Meeting",
"subject": values.subject,
"date": values.date,
})
meeting.insert()
frappe.msgprint("Meeting Created")

Dialog Actions & Event Handling

Primary Action Callback

Action executed after clicking the main action button.

def on_submit(values):
frappe.msgprint(values.get("reason"))

The values argument is a dictionary mapping fieldname → value.

Secondary Action Example

Dialog(
...,
secondary_action_label="Cancel",
secondary_action=lambda values: frappe.msgprint("Cancelled")
)

Showing Dialog from DocType Events

Python dialogs can be invoked from document events:

Example in DocType Controller

def validate(self):
if not self.approved:
from frappe.ui.py_dialog import Dialog
dialog = Dialog(
title="Approval Required",
fields=[
{"label": "Approver Comments", "fieldname": "remarks", "fieldtype": "Small Text"}
],
primary_action_label="Approve",
primary_action=self.on_approve
)
dialog.show()

Rendering Options

Set Dialog Size

Dialog(size="large")

Values:

  • small (default)
  • large
  • extra-large

Return Values and Data Binding

The dialog returns all field values in a Python dictionary:

{
"subject": "Weekly Sync",
"date": "2025-12-08",
"participants": [...]
}

You can use returned data to create records or perform logic.

Best Practices

Recommended Usage

  • Use Python dialog only when UI must originate from the backend.
  • Keep dialogs small and focused.
  • Use JavaScript dialogs for rich UI flows.
  • Avoid heavy computation inside action callback.
  • Validate data inside callback.

Avoid

  • Complex layouts in Python dialogs.
  • Large tables inside dialogs.
  • Long-running tasks (use background jobs).
  • Excessive dialog creation inside loops.

Troubleshooting

Dialog Not Showing

  • Ensure method is called from a Desk context.
  • Python dialog does not work in REST API.
  • Import path must be correct:

from frappe.ui.py_dialog import Dialog

Missing Input Data

  • Check fieldname spelling.
  • Use values.get(“fieldname”).

Cross-References

For related topics:

  • JavaScript Dialog (frappe.ui.Dialog)
  • Python Response API
  • Server Script
  • REST API
  • Form Events (validate, before_save)
  • Background Jobs
  • Permissions in Dialog Actions
  • Dynamic Link Fields
Click to rate this post!
[Total: 0 Average: 0]