The Page Doctype in Frappe is used to create custom pages or views within the Frappe Desk UI. These pages go beyond the standard form and list views of regular Doctypes, allowing developers to build unique user interfaces, dashboards, tools, or specialized applications directly within the Frappe framework.
- To enable the creation of custom, full-page user interfaces within the Frappe Desk.
- To provide a way to integrate custom HTML, client-side JavaScript, and server-side Python logic for specific functionalities.
- To build dashboards, custom reports with unique visualizations, specialized data entry forms, or any other view that doesn't fit the standard Doctype form/list paradigm.
- To organize these custom views within modules and control their access via roles.
page.json: Defines the metadata for the Page Doctype itself (e.g., page name, title, module, roles).page.py: The server-side Python controller for the Page Doctype. It handles creation, validation, export of standard page assets, and loading of these assets when a page is requested.page.js: The client-side JavaScript for the Page Doctype form (the form used to define a page), not for the custom page itself.README.md: Provides a brief overview of the Page Doctype.test_page.py: Contains unit tests for page logic.- For Standard Pages (where
standard= "Yes"):- A dedicated directory:
[app_name]/[module_name]/page/[page_name]/ [page_name].js: Client-side JavaScript for the custom page's functionality.[page_name].css(Optional): Custom CSS styles for the page.[page_name].html(Optional): HTML templates used by the page's JavaScript.[page_name].py(Optional, less common for page-specific logic, more often in Doctype controllers): Server-side Python specifically for this page, e.g., aget_contextmethod for Jinja templates.
- A dedicated directory:
This JSON file outlines the structure for each Page definition document.
- **
autoname: "field:page_name"andnaming_rule: "By fieldname"**: Thepage_name` field's value becomes the unique ID (name) of the Page document, which is also used in its URL route. document_type: "System": Classified as a system document.- Key Fields:
page_name(Data, Required, Unique, In List View): The unique internal name for the page (e.g., "custom-dashboard", "item-importer"). This forms part of its URL (e.g.,app/[page_name]).title(Data, In List View): The user-friendly title displayed in the browser tab, page header, and search results.module(Link to Module Def, Required): The Frappe module to which this page belongs, used for organization and packaging.icon(Data): An icon class (e.g., Font Awesome like "fa fa-tachometer") to represent the page in menus or lists.standard(Select, Required, Options: "Yes"/"No"):- "Yes": Indicates a standard page whose assets (JS, CSS, HTML) are stored in the filesystem within the app's module directory. These are typically part of an app's codebase.
- "No": Indicates a custom page created via the UI. The content for such pages might be stored differently (e.g., directly in fields, though this Doctype seems more geared towards standard pages).
system_page(Check, Default: 0): A flag, possibly to denote pages that are integral to the core Frappe system.restrict_to_domain(Link to Domain): Allows restricting the page's visibility to a specific domain in a multi-domain setup.roles(Table, Options: "Has Role", Depends ondoc.standard == 'Yes'): A child table to define which roles have default access to this page if it's a "Standard" page. For non-standard pages or for more granular control, permissions are often managed via "Role Permission for Page and Report" (which creates "Custom Role" records).
- Permissions (for the "Page" Doctype itself):
- "Administrator" and "System Manager" roles have permissions to create, modify, and delete Page definitions.
track_changes: 1: Changes to Page definitions are versioned.
The Python controller for the Page Doctype handles its lifecycle, asset management for standard pages, and permission checks.
Page(Document)Class:autoname(): Generates a URL-friendlynamefrom thepage_nameif not explicitly set.validate(): Ensures route conflicts don't occur and restricts creation/editing of standard pages to Administrators or when in developer mode.on_update(): For standard pages (standard == "Yes"), this method exports the Page definition to a.jsonfile in the module's page directory. If a corresponding.jsfile doesn't exist, it creates a boilerplate JS file with a basicfrappe.pages['page_name'].on_page_loadstructure.on_trash(): Prevents deletion if not in developer mode. Deletes associated "Custom Role" records and the page's asset folder from the filesystem for standard pages.is_permitted(): Checks if the current user has permission to view the page by comparing the user's roles against roles defined directly on the Page document (in itsrolestable) and any roles assigned via "Custom Role" records.load_assets(): This crucial method is called when a standard page is requested. It dynamically loads:- The content of
[page_name].jsintoself.script. - The content of
[page_name].cssintoself.style. - Any
.htmlfiles in the page's directory are read, converted into JavaScript template functions usinghtml_to_js_template, and added toself.script. If an HTML template contains<!-- jinja -->, it attempts to render it using aget_contextmethod (if defined for the page) before converting to a JS template. - It also loads JavaScript files specified via
page_jshooks in the app'shooks.py.
- The content of
delete_custom_role()(Global Function): A helper to remove "Custom Role" entries when a Page is deleted.
This script enhances the form used for defining/editing Page documents.
refresh(frm):- If not in developer mode and the user is not Administrator, makes the Page document form read-only.
- If the Page document is not new, adds a "Go to [Page Title] Page" button that navigates the user directly to the rendered page.
The README states that a Page is a view in the application for custom UIs, containing server-side and client-side code, with standard lifecycle events.
- Creation (Standard Page - Developer Mode):
- A developer creates a new "Page" document via the UI.
- They set
standardto "Yes" and specify themoduleandpage_name. - Upon saving, Frappe creates a directory:
[app]/[module]/page/[page_name]/. - A
[page_name].json(metadata) and a boilerplate[page_name].jsare created in this directory. - The developer then adds HTML, CSS, and custom JavaScript logic to these files to build the page's content and interactivity.
- Creation (Custom Page - UI):
- An Administrator can create a Page document and set
standardto "No". The content for such pages might be managed differently, potentially through fields on the Page Doctype itself if it were designed for that (though the current "Page" Doctype seems more focused on standard, file-based pages).
- An Administrator can create a Page document and set
- Access: When a user navigates to
app/[page_name]:- Frappe's routing mechanism loads the "Page" document.
- The
is_permitted()method checks access. - If permitted,
load_assets()gathers the JS, CSS, and HTML templates. - The client-side framework then renders the page, executing the loaded JavaScript (e.g., the
on_page_loadfunction in[page_name].js).
- Permissions: Access to pages is controlled by:
- Roles defined directly in the
rolestable of the Page document (for standard pages). - Roles assigned via "Role Permission for Page and Report" (which creates "Custom Role" records).
- Roles defined directly in the
Pages are essential for building custom applications, dashboards, and specialized tools within the Frappe Desk, offering a high degree of flexibility in UI and functionality.