Skip to main content

Hooks in Frappe Framework v15

What are Hooks in Frappe?

Hooks are a declarative configuration mechanism in hooks.py that allow developers to extend, override, or inject functionality into Frappe and ERPNext without editing the core code. Hooks enable custom applications to connect logic to framework events such as DocType events, scheduled tasks, API endpoints, UI assets, and more.
In Frappe v15, hooks are the primary mechanism for integration, used to implement business logic, add custom controllers, and register services inside a modular app.

How do Hooks work in Frappe?

Frappe loads hooks.py from every installed app at startup.
During runtime, when Frappe reaches a hook point (e.g., document event, scheduler time, page load), it resolves registered methods and executes them.

Hook entries follow this structure:

# content example (simplified)
doc_events = {
"Sales Invoice": {
"validate": "my_app.api.validate_invoice"
}
}

Here, when Sales Invoice.validate event triggers, Frappe will call the method defined in the hook.

Why use Hooks instead of modifying core?

Hooks enable:

  • Zero core modification (upgrade-safe)
  • Clean modular architecture
  • Event-driven custom logic
  • Central configuration of integrations
  • Ability to override framework behavior
  • Ability to register routes and scheduler jobs

Hooks are the preferred customization method in production systems.

Structure of hooks.py in Frappe Apps

Every app created using:

bench new-app my_app

contains a default hooks.py file at:

my_app/my_app/hooks.py

This file defines all configuration entries used to integrate that app into the Frappe environment.

Core Hook Categories in Frappe v15

There are multiple hook types grouped by functionality.
Below are the standard classes of hooks.

1. DocType Event Hooks

What are DocType Hooks?

DocType Hooks allow you to register functions that are triggered during the lifecycle of a document, including:

  • validate
  • before_save
  • on_update
  • on_submit
  • on_cancel
  • on_trash

Use this to implement business logic:

doc_events = {
"Purchase Order": {
"validate": "my_app.api.validate_po"
}
}

2. Scheduled (Cron-like) Hooks

Hooks allow you to register background jobs that run on time intervals.

scheduler_events = {
"daily": [
"my_app.tasks.cleanup_old_logs"
],
"hourly": [
"my_app.tasks.pull_data"
],
}

Supported intervals include:

  • all
  • daily
  • hourly
  • weekly
  • monthly
  • cron (custom)

This enables automated workflows like reconciliation, cleanup jobs, and integrations.

3. Website & Web Page Hooks

Hooks allow registering pages and web forms without modifying core routing.

website_route_rules = [
{"from_route": "/shop", "to_route": "Shop Home"}
]

You can also define website assets in hooks for CSS/JS bundling.

4. REST API Whitelisting Hooks

To expose Python functions as HTTP APIs:

override_whitelisted_methods = {
"frappe.desk.doctype.event.event.get_events": "my_app.api.get_custom_events"
}

Or whitelist your own method:

api_methods = [
"my_app.api.get_data"
]

When whitelisted, methods can be called via:

/api/method/my_app.api.get_data

5. Override Core Logic

You can override framework classes or controller logic, allowing deep customization.

override_doctype_class = {
"Item": "my_app.overrides.CustomItem"
}

This approach lets you customize ERPNext DocType behavior at class level.

6. Fixtures & Custom Fields Injection

Hooks can define exportable fixtures such as:

  • Custom Fields
  • Property Setters
  • Print Formats

fixtures = [
"Custom Field",
"Property Setter"
]

This allows migration of UI settings from development to production.

7. Asset Bundling Hooks

To include JS/CSS into Desk:

app_include_js = "/assets/my_app/js/custom.js"
app_include_css = "/assets/my_app/css/style.css"

Useful for UI customization.

8. Document Creation Hooks

You can define default values or field transformations using hooks.

before_install = "my_app.install.before_install"
after_install = "my_app.install.after_install"

How to Implement Hooks (Step-by-Step)

Step 1: Create a Frappe App

bench new-app my_app
bench install-app my_app

Step 2: Open hooks.py

cd apps/my_app/my_app
nano hooks.py

Step 3: Add Hook Configuration

Example: DocType validate event

doc_events = {
"Sales Order": {
"validate": "my_app.api.validate_so"
}
}

Step 4: Create the Python Function

# my_app/api.py
import frappe
def validate_so(doc, method):
# business logic here
if not doc.items:
frappe.throw("Items required")

Step 5: Reload and Test

bench restart
bench --site site1.local execute my_app.api.validate_so

Best Practices for Hooks in Frappe v15

 1. Use fully qualified import paths
Always use full paths: “my_app.api.validate_so”.

2. Avoid heavy logic inside Document events
Offload heavy tasks to background jobs when possible.

3. Keep hooks.py clean
Organize logic in files, not inside the hook definition.

4. Use Scheduler for integrations
Instead of calling APIs on every save, use cron hooks.

5. Avoid overriding core when possible
Use events instead of override class unless necessary.

6. Test hooks under load
Especially scheduled jobs.

7. Always log exceptions
Use frappe.log_error() inside hooks for traceability.

 

Troubleshooting Common Hook Issues

Hooks not triggering?

  • Ensure the app is installed on the site.
  • Use bench restart after changes.
  • Confirm spelling of DocType.

Review error logs using:

bench --site site1.local logs

Scheduler not running?

  • Ensure Redis Queue is running.

Enable scheduler:

bench enable-scheduler

API override not applying?

  • Verify the correct dotted path.
  • Confirm the original API is safe to override.

Recommended Use Cases

Hooks are ideal when:

  • You need to insert business rules into DocType lifecycle
  • You want to schedule background integrations
  • You want to expose custom APIs
  • You are building module extensions for ERPNext
  • You want to auto-create data or enrich fields
  • You want to override print formats
  • You want system-wide UI customization

Industry Relevance & Why It Matters

Companies implementing ERPNext often need:

  • Validation rules (e.g., stock check)
  • Auto-create transactions (e.g., delivery on submit)
  • Payment gateway integration
  • 3rd-party API sync (CRM, HRIS, POS)
  • Automated reports
  • Extended accounting logic

Hooks allow all of this without touching ERPNext core, supporting upgrade safety and modular deployments.

Target Audience

  • ERPNext implementation teams
  • Frappe backend developers
  • Integration engineers
  • System architects
  • Consultants designing custom workflows

Technical Prerequisites

  • Familiarity with Python
  • Frappe app development basics
  • Understanding of DocType lifecycle
  • Ability to run commands via Bench

Cross-References

To fully understand Hooks, explore these related concept guides:

  • Frappe Routing API
  • Background Jobs API
  • Frappe Response API
  • Server Scripts vs Hooks
  • Scheduler Events
  • Document Lifecycle Events
Click to rate this post!
[Total: 0 Average: 0]