You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Dec 6, 2021. It is now read-only.
Traceback (most recent call last):
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/utils/jinja.py", line 84, in render_template
return get_jenv().from_string(template).render(context)
File "/home/frappe/benches/bench-version-13-f-16/env/lib/python3.6/site-packages/jinja2/environment.py", line 941, in from_string
return cls.from_code(self, self.compile(source), globals, None)
File "/home/frappe/benches/bench-version-13-f-16/env/lib/python3.6/site-packages/jinja2/environment.py", line 638, in compile
self.handle_exception(source=source_hint)
File "/home/frappe/benches/bench-version-13-f-16/env/lib/python3.6/site-packages/jinja2/environment.py", line 832, in handle_exception
reraise(*rewrite_traceback_stack(source=source))
File "/home/frappe/benches/bench-version-13-f-16/env/lib/python3.6/site-packages/jinja2/_compat.py", line 28, in reraise
raise value.with_traceback(tb)
File "<unknown>", line 357, in template
jinja2.exceptions.TemplateSyntaxError: expected token 'end of print statement', got ':'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/website/render.py", line 50, in render
data = render_page_by_language(path)
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/website/render.py", line 177, in render_page_by_language
return render_page(path)
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/website/render.py", line 193, in render_page
return build(path)
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/website/render.py", line 200, in build
return build_page(path)
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/website/render.py", line 218, in build_page
html = frappe.render_template(context.source, context)
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/utils/jinja.py", line 86, in render_template
throw(title="Jinja Template Error", msg="<pre>{template}</pre><pre>{tb}</pre>".format(template=template, tb=get_traceback()))
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/__init__.py", line 396, in throw
msgprint(msg, raise_exception=exc, title=title, indicator='red', is_minimizable=is_minimizable)
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/__init__.py", line 375, in msgprint
_raise_exception()
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/__init__.py", line 326, in _raise_exception
raise raise_exception(msg)
frappe.exceptions.ValidationError: <pre>{% extends "templates/doc.html" %}
{% block page_content %}<div class="from-markdown"><!-- add-breadcrumbs -->
<h1 id="hooks">Hooks</h1>
<!-- TODO: Add tables for quick reference -->
<p>Hooks are the duct tape of the Frappe system. Hooks allow you to "hook" in to
functionality and events of other parts of the Frappe system. Following are the
official hooks from Frappe.</p>
<h3 id="application-name-and-details">Application Name and Details</h3>
<ol>
<li><code>app_name</code> - slugified name with underscores e.g. "shopping_cart"</li>
<li><code>app_title</code> - full title name e.g. "Frappe"</li>
<li><code>app_publisher</code></li>
<li><code>app_description</code></li>
<li><code>app_version</code></li>
<li><code>app_icon</code> - font-awesome icon or image url</li>
<li><code>app_color</code> - hex colour background of the app icon</li>
</ol>
<h3 id="install-events">Install Events</h3>
<ol>
<li><code>before_install</code></li>
<li><code>after_install</code></li>
</ol>
<p>The above hooks are called before and after installation of the app they are in.
For example, <a href="/apps/erpnext">ERPNext</a>'s hooks contains a line,</p>
<pre><code>after_install = "erpnext.setup.install.after_install"
</code></pre>
<p>So, the function after_install is imported and called after ERPNext is installed.</p>
<p>Note, the <code>before_install</code> and <code>after_install</code> hooks are called with no arguments.</p>
<h3 id="boot-session">Boot Session</h3>
<p>After a successful login, the Frappe JS Client requests for a resource called
<code>bootinfo</code>. The <code>bootinfo</code> is available as a global in Javascript via
<code>frappe.boot</code>. By default, the <code>bootinfo</code> contains</p>
<ul>
<li>System defaults</li>
<li>Notification status</li>
<li>Permissions</li>
<li>List of icons on desktop</li>
<li>User settings</li>
<li>Language and timezone info</li>
</ul>
<p>If your app wants to modify bootinfo, it can declare a hook <code>boot_session</code>. The
value is assumed to be a dotted path to a function and is called with one
argument, bootinfo which it can modify and return.</p>
<p>Eg,</p>
<pre><code>boot_session = "erpnext.startup.boot.boot_session"
</code></pre>
<h3 id="notification-configurations">Notification configurations</h3>
<p>The notification configuration hook is expected to return a Python dictionary.</p>
<pre><code>{
"for_doctype": {
"Issue": {"status":"Open"},
"Customer Issue": {"status":"Open"},
},
"for_module_doctypes": {
"ToDo": "To Do",
"Event": "Calendar",
"Comment": "Messages"
},
"for_module": {
"To Do": "frappe.core.notifications.get_things_todo",
"Calendar": "frappe.core.notifications.get_todays_events",
"Messages": "frappe.core.notifications.get_unread_messages"
}
}
</code></pre>
<p>The above configuration has three parts,</p>
<ol>
<li><code>for_doctype</code> part of the above configuration marks any "Issue"
or "Customer Issue" as unread if its status is Open</li>
<li><code>for_module_doctypes</code> maps doctypes to module's unread count.</li>
<li><code>for_module</code> maps modules to functions to obtain its unread count. The
functions are called without any argument.</li>
</ol>
<h3 id="javascript-css-assets">Javascript / CSS Assets</h3>
<p>The following hooks allow you to bundle built assets to your app for serving.
There are two types of assets, app and web. The app assets are loaded in the
Desk and web assets are loaded in the website.</p>
<ol>
<li><code>app_include_js</code></li>
<li><code>app_include_css</code></li>
<li><code>web_include_js</code></li>
<li><code>web_include_css</code></li>
</ol>
<p>Eg,</p>
<pre><code>app_include_js = "assets/js/erpnext.min.js"
web_include_js = "assets/js/erpnext-web.min.js"
</code></pre>
<p>Note: to create an asset bundle (eg, assets/js/erpnext.min.js) the target file
should be in build.json of your app.</p>
<h3 id="customizing-web-forms">Customizing Web Forms</h3>
<blockquote>
<p>Introduced in Version 13</p>
</blockquote>
<p>In order to modify the client-side validations and stylesheets for existing web forms for a given DocType in the system, you can use the following hooks:</p>
<ol>
<li><code>webform_include_js</code></li>
<li><code>webform_include_css</code></li>
</ol>
<p>Eg,</p>
<pre><code>webform_include_js = {
"Issue": "public/js/issue.js",
"Address": "public/js/address.js"
}
</code></pre>
<h3 id="configuring-reports">Configuring Reports</h3>
<p>In the report view, you can force filters as per doctype using <code>dump_report_map</code>
hook. The hook should be a dotted path to a Python function which will be called
without any arguments. Example of output of this function is below.</p>
<pre><code>"Warehouse": {
"columns": ["name"],
"conditions": ["docstatus < 2"],
"order_by": "name"
}
</code></pre>
<p>Here, for a report with Warehouse doctype, would include only those records that
are not cancelled (docstatus < 2) and will be ordered by name.</p>
<h3 id="modifying-website-context">Modifying Website Context</h3>
<p>Context used in website pages can be modified by adding
a <code>update_website_context</code> hook. This hook should be a dotted path to a function
which will be called with a context (dictionary) argument.</p>
<h3 id="customizing-email-footer">Customizing Email footer</h3>
<p>By default, for every email, a footer with content, "Sent via Frappe" is sent.
You can customize this globally by adding a <code>mail_footer</code> hook. The hook should
be a dotted path to a variable.</p>
<h3 id="session-creation-hook">Session Creation Hook</h3>
<p>You can attach custom logic to the event of a successful login using
<code>on_session_creation</code> hook. The hook should be a dotted path to a Python
function that takes login_manager as an argument.</p>
<p>Eg,</p>
<pre><code>def on_session_creation(login_manager):
"""make feed"""
if frappe.session['user'] != 'Guest':
# log to timesheet
pass
</code></pre>
<h3 id="website-clear-cache">Website Clear Cache</h3>
<p>If you cache values in your views, the <code>website_clear_cache</code> allows you to hook
methods that invalidate your caches when Frappe tries to clear cache for all
website related pages.</p>
<h3 id="document-hooks">Document hooks</h3>
<h4 id="permissions">Permissions</h4>
<h4 id="query-permissions">Query Permissions</h4>
<p>You can customize how permissions are resolved for a DocType by hooking custom
permission match conditions using the <code>permission_query_conditions</code> hook. This
match condition is expected to be fragment for a where clause in an sql query.
Structure for this hook is as follows.</p>
<pre><code>permission_query_conditions = {
"{doctype}": "{dotted.path.to.function}",
}
</code></pre>
<p>The output of the function should be a string with a match condition.
Example of such a function,</p>
<pre><code>def get_permission_query_conditions():
return "(tabevent.event_type='public' or tabevent.owner='{user}'".format(user=frappe.session.user)
</code></pre>
<p>The above function returns a fragment that permits an event to listed if it's
public or owned by the current user.</p>
<h4 id="document-permissions">Document permissions</h4>
<p>You can hook to <code>doc.has_permission</code> for any DocType and add special permission
checking logic using the <code>has_permission</code> hook. Structure for this hook is,</p>
<pre><code>has_permission = {
"{doctype}": "{dotted.path.to.function}",
}
</code></pre>
<p>The function will be passed the concerned document as an argument. It should
True or a falsy value after running the required logic.</p>
<p>For Example,</p>
<pre><code>def has_permission(doc):
if doc.event_type=="Public" or doc.owner==frappe.session.user:
return True
</code></pre>
<p>The above function permits an event if it's public or owned by the current user.</p>
<h4 id="crud-events">CRUD Events</h4>
<p>You can hook to various CRUD events of any doctype, the syntax for such a hook
is as follows,</p>
<pre><code>doc_events = {
"{doctype}": {
"{event}": "{dotted.path.to.function}",
}
}
</code></pre>
<p>To hook to events of all doctypes, you can use the follwing syntax also,</p>
<pre><code> doc_events = {
"*": {
"on_update": "{dotted.path.to.function}",
}
}
</code></pre>
<p>The hook function will be passed the doc in concern as the only argument.</p>
<h5 id="list-of-events">List of events</h5>
<ul>
<li><code>validate</code></li>
<li><code>before_save</code></li>
<li><code>autoname</code></li>
<li><code>before_insert</code></li>
<li><code>after_insert</code></li>
<li><code>before_submit</code></li>
<li><code>before_cancel</code></li>
<li><code>before_update_after_submit</code></li>
<li><code>on_update</code></li>
<li><code>on_submit</code></li>
<li><code>on_cancel</code></li>
<li><code>on_update_after_submit</code></li>
<li><code>on_change</code></li>
<li><code>on_trash</code></li>
<li><code>after_delete</code></li>
</ul>
<p>Eg,</p>
<pre><code>doc_events = {
"Cab Request": {
"after_insert": "topcab.schedule_cab",
}
}
</code></pre>
<h3 id="scheduler-hooks">Scheduler Hooks</h3>
<p>Scheduler hooks are methods that are run periodically in background. Structure for such a hook is,</p>
<pre><code>scheduler_events = {
"{event_name}": [
"{dotted.path.to.function}"
],
}
</code></pre>
<h4 id="events">Events</h4>
<ul>
<li><code>daily</code></li>
<li><code>daily_long</code></li>
<li><code>weekly</code></li>
<li><code>weekly_long</code></li>
<li><code>monthly</code></li>
<li><code>monthly_long</code></li>
<li><code>hourly</code></li>
<li><code>all</code></li>
<li><code>cron</code></li>
</ul>
<p>The scheduler events require RQ and redis (or a supported and
configured broker) to be running. The events with suffix '_long' are for long
jobs. The <code>all</code> event is triggered everytime (as per the RQ interval).</p>
<p>Example,</p>
<pre><code>scheduler_events = {
"daily": [
"erpnext.accounts.doctype.sales_invoice.sales_invoice.manage_recurring_invoices"
],
"daily_long": [
"erpnext.setup.doctype.backup_manager.backup_manager.take_backups_daily"
],
"cron": {
"15 18 * * *": [
"frappe.twofactor.delete_all_barcodes_for_users"
],
"*/6 * * * *": [
"frappe.utils.error.collect_error_snapshots"
],
"annual": [
"frappe.utils.error.collect_error_snapshots"
]
}
}
</code></pre>
<p>The asterisk (*) operator specifies all possible values for a field. For example, an asterisk in the hour time field would be equivalent to every hour or an asterisk in the month field would be equivalent to every month.</p>
<h3 id="override-whitelisted-methods">Override Whitelisted Methods</h3>
<p>Override whitelisted Python functions (server-side functions that are available to the client-side) using the <code>override_whitelisted_methods</code> hook.</p>
<p>An overriden function will be triggered during the following events:</p>
<ul>
<li>direct API call</li>
<li>document mapping</li>
</ul>
<p>Example,</p>
<pre><code>override_whitelisted_methods = {{
"{dotted.path.to.whitelisted.frappe.function}": "{dotted.path.to.whitelisted.custom.function}"
}}
</code></pre>
<h3 id="jinja-customization">Jinja Customization</h3>
<p>Fetch custom methods and filters that are to be available globally in jinja environment.</p>
<h4 id="options">Options</h4>
<ul>
<li><code>methods</code></li>
<li><code>filters</code></li>
</ul>
<p>Example,</p>
<pre><code>jenv = {
"methods": [
"method_name:dotted.path.to.method_definition"
],
"filters": [
"filter_name:dotted.path.to.filter_function"
]
}
</code></pre>
<h3 id="exempt-doctypes">Exempt Doctypes</h3>
<p>Exempt documents of a specific DocType from being automatically cancelled on the cancellation of any linked documents.</p>
<p>Example,</p>
<pre><code>auto_cancel_exempted_doctypes = ["Payment Entry"]
</code></pre>
<p>In the above example, if any document that is linked with Payment Entry is cancelled, the system will skip the auto-cancellation of the linked Payment Entry document.</p>
</div>{% endblock %}</pre><pre>Traceback (most recent call last):
File "/home/frappe/benches/bench-version-13-f-16/apps/frappe/frappe/utils/jinja.py", line 84, in render_template
return get_jenv().from_string(template).render(context)
File "/home/frappe/benches/bench-version-13-f-16/env/lib/python3.6/site-packages/jinja2/environment.py", line 941, in from_string
return cls.from_code(self, self.compile(source), globals, None)
File "/home/frappe/benches/bench-version-13-f-16/env/lib/python3.6/site-packages/jinja2/environment.py", line 638, in compile
self.handle_exception(source=source_hint)
File "/home/frappe/benches/bench-version-13-f-16/env/lib/python3.6/site-packages/jinja2/environment.py", line 832, in handle_exception
reraise(*rewrite_traceback_stack(source=source))
File "/home/frappe/benches/bench-version-13-f-16/env/lib/python3.6/site-packages/jinja2/_compat.py", line 28, in reraise
raise value.with_traceback(tb)
File "<unknown>", line 357, in template
jinja2.exceptions.TemplateSyntaxError: expected token 'end of print statement', got ':'
</pre>
The text was updated successfully, but these errors were encountered:
ryuliantoro
changed the title
Docs at frappeframwork.
Docs at frappeframework website return Uncaught Server Exception
Jul 4, 2020
Trying to see the docs for hooks and gets Uncaught Server Exception.
at url --> https://frappeframework.staging.frappe.cloud/docs/user/en/guides/basics/hooks
The text was updated successfully, but these errors were encountered: