静态资产

本指南帮助您了解 Frappe Framework 中静态资源的提供方式。

assets 文件夹

静态文件从 frappe-bench/sites/assets 文件夹中提供。当您
为生产环境部署 Frappe 时,nginx 会直接提供该文件夹的内容。所有
静态文件的 URL 始终以 /assets 开头。位于
frappe-bench/sites/assets/hero.png 的文件可以通过 URL
/assets/hero.png 公开访问。

public 文件夹

每个应用都有自己的 public 文件夹,用于提供静态资源。
该文件夹会通过符号链接到 frappe-bench/sites/assets/[appname]。以下是
在 assets 文件夹上执行 tree 命令的输出结果。

~/frappe-bench
$ tree sites/assets -L 1
sites/assets
├── erpnext -> ~/frappe-bench/apps/erpnext/erpnext/public
└── frappe -> ~/frappe-bench/apps/frappe/frappe/public

这意味着,如果 [appname]/public/images/favicon.png 处存在文件,那么它
也会以符号链接的形式存在于 assets/[appname]/images/favicon.png,并且
可以通过 URL /assets/[appname]/images/favicon.png 公开访问。

打包资源

打包资源生成于
assets/[appname]/dist/js 和 assets/[appname]/dist/css。因此,它们
可以通过 URL /assets/[appname]/dist/js/main.bundle.[hash].js 访问。

站点资源

除了应用提供的静态文件外,每个站点还可以拥有自己的静态
文件,这些文件可能来自用户上传或站点备份。

用户上传

用户上传的公开文件存储在
frappe-bench/sites/[sitename]/public/files。存储在
frappe-bench/sites/[sitename]/public/files/profile.png 的文件可以通过
URL /files/profile.png 公开访问。

用户上传的私有文件存储在
frappe-bench/sites/[sitename]/private/files。存储在
frappe-bench/sites/[sitename]/private/files/profile.png 的文件可以通过
URL /private/files/profile.png 访问。私有文件仅在
用户获得授权后才能查看。

备份

为站点生成的任何本地备份都存储为
frappe-bench/sites/[sitename]/private/backups/20210502_182223-[sitename]-database.sql.gz。
它可以通过 URL
/backups/20210502_182223-[sitename]-database.sql.gz 访问,并且仅当用户
获得授权后才能下载。

以下是 ls 命令的输出结果:

~/frappe-bench
$ ls -l sites/site1.test/private/backups
total 6160
-rw-r--r-- 1 farisansari staff 2429268 May 2 18:22 20210502_182223-site1_test-database.sql.gz
-rw-r--r-- 1 farisansari staff 278 May 2 18:22 20210502_182223-site1_test-site_config_backup.json

资产捆绑

本指南旨在帮助您理解 Frappe Framework 中静态资源打包的工作原理。

Frappe 自带一个富管理界面,可通过 /app 访问,这是一个使用现代 JavaScript 语法编写的单页应用(SPA),其样式使用 SASS(.scss)文件编写。这些文件无法被浏览器直接理解,因此在发送到浏览器解析和执行之前,需要先进行编译。

Frappe 自带一个资源打包器,可以编译客户端资源,例如:

  • .js (使用 import 和 export 的现代语法)
  • .ts (TypeScript 文件)
  • .vue (Vue 单文件组件)
  • .css (使用 PostCSS 处理的 CSS)
  • .scss (SASS 文件)
  • .sass (使用缩进语法的 SASS 文件)
  • .styl (Stylus 文件)
  • .less (Less 文件)

这些文件根据类型被编译为 .js 或 .css 格式,然后发送到浏览器。

构建资源

要使用资源打包器编译资源,您需要在 frappe-bench 文件夹下运行以下命令:

$ bench build

您也可以通过指定 --apps 选项来为特定应用运行该命令。

# build only frappe assets
$ bench build --apps frappe

# build only frappe and erpnext assets
$ bench build --apps frappe,erpnext

监听模式

当您使用打包文件时,每次修改源文件后都需要重新运行构建命令。资源打包器提供了监听模式,它会监听文件系统的变化,并在文件发生更改时自动重新构建。

运行以下命令将启动一个长时间运行的进程,它会监听您的文件并在文件变化时重新构建。每次重新构建时,它都会记录一行包含“Compiled changes…”文本的日志。

$ bench watch
Watching for changes...
1:17:28 PM: Compiled changes...

您也可以通过指定 --apps 选项来为特定应用运行该命令。

# watch only erpnext assets
$ bench watch --apps erpnext

从版本 14 开始,如果在监听模式下资源被重新构建,Desk 将自动重新加载。此行为可以通过设置 LIVE_RELOAD 环境变量,或更改 common_site_config.json 中的 live_reload 值来切换。

打包文件

打包文件是资源打包器进行编译的资源入口点。例如,如果您的应用 public 文件夹中有一个名为 main.bundle.js 的文件,它将被打包器自动拾取并编译到 /assets/[app]/dist/js/main.bundle.[hash].js。根据输出内容计算出的唯一哈希值也会附加到文件名中,这对于浏览器中的缓存失效非常有用。

类似地,如果 public 文件夹中有一个名为 style.bundle.scss 的文件,它将被编译到 /assets/[app]/dist/css/style.bundle.css。请注意,扩展名从 .scss 变为了 .css,因为浏览器可以理解 CSS 文件,但不能理解 SASS 文件。打包文件可以存在于 public 文件夹中的任何嵌套级别,但它们始终会根据类型编译到 dist/js 或 dist/css 目录中。这意味着如果存在一个位于 public/main.bundle.js 的文件和另一个位于 public/src/main.bundle.js 的文件,后者的编译输出将覆盖前者。打包器也会对此类冲突打印警告。

更多打包输入和输出的示例:

输入 输出
[app]/public/main.bundle.js /assets/dist/[app]/js/main.bundle.[hash].js
[app]/public/src/main.bundle.js /assets/dist/[app]/js/main.bundle.[hash].js
[app]/public/src/utils/utils.bundle.js /assets/dist/[app]/js/utils.bundle.[hash].js
[app]/public/main.bundle.ts /assets/dist/[app]/js/main.bundle.[hash].js
[app]/public/main.bundle.css /assets/dist/[app]/css/main.bundle.[hash].css
[app]/public/styles/main.bundle.css /assets/dist/[app]/css/main.bundle.[hash].css
[app]/public/main.bundle.scss /assets/dist/[app]/css/main.bundle.[hash].css
[app]/public/main.bundle.sass /assets/dist/[app]/css/main.bundle.[hash].css
[app]/public/main.bundle.styl /assets/dist/[app]/css/main.bundle.[hash].css
[app]/public/main.bundle.less /assets/dist/[app]/css/main.bundle.[hash].css

从 npm 导入库

如果您熟悉现代 Web 开发,您可能需要从 npm 安装第三方库并在项目中使用。

假设您想在应用中使用 dayjs 库来处理日期和时间。首先,您需要在应用文件夹的根目录下运行以下命令,通过 yarn 安装它。

$ cd frappe-bench/apps/myapp
$ yarn add dayjs

现在,您可以像这样在源文件中导入它:

myapp/public/main.bundle.js

import * as dayjs from 'dayjs';

console.log(dayjs())

在 HTML 中包含打包资源

当打包文件被编译时,输出文件包含一个唯一的哈希值。因此,您不能硬编码文件的路径,因为下次您修改该文件时,哈希值会发生变化。Frappe 提供了一些辅助方法来解决这个问题。

在自定义 HTML 文件中包含资源

Jinja 方法 include_script 和 include_style 将分别输出包含 .js 和 .css 文件 HTML 标记的正确文件路径。

index.html



My App

 {{ include_style('style.bundle.css') }}

 {{ include_script('main.bundle.js') }}

index.html(渲染后)



My App

 <script type="text/javascript" src="/assets/myapp/dist/js/main.bundle.BYJXV4LB.js"></script>

在 app.html 中包含资源

如果您想从您的应用中包含打包资源到 /app 中,您可以使用
app_include_js 和 app_include_css 将它们加载到 app.html 中。

[app]/hooks.py

app_include_js = ['main.bundle.js']
app_include_css = ['style.bundle.css']

获取打包资源路径

如果由于某些原因您只需要打包资源的路径,您可以使用
bundled_asset Jinja 方法来生成它。

Jinja

{{ bundled_asset('main.bundle.js') }}

渲染结果

/assets/myapp/dist/js/main.bundle.BYJXV4LB.js

Python API

这些 API 在 Python 中也可用。您可以从 jinja_globals.py 中导入它们。

from frappe.utils.jinja_globals import bundled_asset, include_script, include_style

bundled_asset('main.bundle.js')

在 /app 中延迟包含打包资源

如果您想在管理界面(/app)中延迟加载打包资源,您可以使用
frappe.require 方法。

frappe.require('main.bundle.js').then(() => {
 // main.bundle.js is now loaded
})

当您想根据某些条件加载代码时,这种方法非常有用。
首次页面加载不会受到影响,并且对性能更有利。

生产模式

当您将应用部署到生产环境时,您可以在生产模式下构建您的资源。在这种模式下,打包器会压缩您的打包最终输出,
从而减小文件大小。

要在生产模式下构建您的资源,请运行以下命令:

$ bench build --production

用户与权限

Frappe 自带用户认证系统。它处理用户账户、基于角色的权限以及基于 Cookie 的用户会话。

Frappe 中的用户认证系统开箱即用地提供了许多功能:

  1. 用户
  2. 角色
  3. DocType 权限
  4. 权限级别
  5. 角色权限管理器
  6. 用户权限
  7. 限制视图和表单
  8. 密码哈希
  9. 密码强度检查
  10. 登录尝试限流
  11. 第三方认证,如 OAuth、Google、Facebook 等

用户和角色

用户记录代表一个经过认证的用户,可以在系统中执行授权操作。一个用户可以分配多个角色。角色描述了一个用户可以对某个 DocType 执行哪些操作。

用户角色

例如,博客作者角色对 博客文章 DocType 具有读取、写入和创建权限,但对 博客分类 只有读取权限。

博客作者角色

DocType 权限

当您安装应用时,DocType 可以有一组默认的角色。要为 DocType 配置角色,您必须在 DocType 的权限表中添加它们。

DocType 权限

如果您展开该行,您会看到更多可以配置的选项。 DocType 权限

以下是这些选项及其说明的列表:

选项 说明
级别 分配给此角色的权限级别
如果用户是所有者 仅当用户是创建该文档的人时,限制才会生效
读取 允许读取文档
写入 允许编辑文档
创建 允许创建文档
删除 允许用户删除文档
提交 允许用户提交文档
取消 允许用户取消文档
修订 允许用户修订文档
报表 允许用户查看报表视图
导出 允许用户以 Excel/CSV 格式导出记录
导入 允许用户使用数据导入工具导入记录
设置用户权限 允许用户为其他用户应用用户权限
共享 允许用户与其他用户共享文档
打印 允许用户打印文档或生成 PDF
电子邮件 允许用户为该文档发送电子邮件

权限级别

权限级别可用于对文档中的字段进行分组,并为每个级别应用单独的角色。默认情况下,所有字段的权限级别都设置为 0。

权限级别

角色权限管理器

角色权限管理器是一个用于管理角色权限的用户工具。默认的权限集显示在这里,并且可以被覆盖。

用户权限

用户权限是可以按用户应用的另一组规则。它可用于限制包含特定链接字段值的文档。

例如,要限制用户 John 只能查看由他创建的博客文章,即博客作者 John。应创建具有以下值的用户权限记录。

用户权限记录

创建用户权限配置后,当用户登录查看博客文章列表时,他将只能看到由他创建的博客文章的受限视图。

受限的博客文章列表

自动角色

某些角色会自动对用户隐藏,这简化了编写需要全面权限的 DocType。以下是自动角色:

  1. “访客” – 此角色分配给所有人,包括未认证的用户。
  2. “所有” – 此角色分配给所有注册用户。这包括网站用户。
  3. “管理员” – 此角色仅分配给默认创建的 Administrator 用户。
  4. “后台用户” – [v15 新增] 此角色分配给所有用户类型为“系统用户”的用户,即他们是系统用户而非网站用户。

限制视图和表单

Frappe 框架允许您配置哪些模块、DocType 和视图对用户可见。要配置向用户显示哪些模块,请转到用户表单的允许模块部分。

要隐藏用户的 DocType,请使用角色权限管理器从角色中移除读取权限。

要控制页面和报表的权限,请使用页面和报表的角色权限工具。

密码哈希

Frappe 内置了密码哈希处理功能。密码会被加密并保存在一个名为 __Auth 的独立数据库表中。

MariaDB [_baa0f26509a564b6]> select * from __Auth;
+---------+------------------+-----------+-----------------------------------------------
| doctype | name             | fieldname | password
+---------+------------------+-----------+-----------------------------------------------
| User    | Administrator    | password  | $pbkdf2-sha256$29000$Xss5pxSC8F5rDSHEOEdo7Q$in
| User    | [email protected] | password  | $pbkdf2-sha256$29000$y7mXMoZQau09RwiBsLaWsg$h.
+---------+------------------+-----------+-----------------------------------------------

密码策略

Frappe 还支持密码强度检查。可以在系统设置的“安全”部分启用该功能。“最低密码评分”字段用于验证密码应达到的强度等级。

密码策略

登录尝试

Frappe 允许您配置在锁定账户之前允许的连续登录尝试次数,以及锁定的时间长度。

第三方认证

Frappe 支持第三方登录提供商。要设置登录提供商,您需要配置一个社交登录密钥。点击此处了解更多信息。

理解文档类型

  1. 简介

  2. 模块

  3. DocField

  4. 命名

  5. 控制器

    • 控制器方法
    • 控制器钩子
  6. 子 DocType

  7. 单例 DocType

  8. 虚拟 DocType

  9. 操作与链接

  10. 自定义 DocType

简介

DocType 是基于 Frappe 框架的任何应用程序的核心构建块。它描述了数据的模型和视图。它包含数据存储了哪些字段,以及这些字段如何相互关联。它还包含数据的命名方式信息。此外,它还启用了丰富的对象关系映射(ORM)模式,我们将在本指南的后续部分讨论。当您创建 DocType 时,会生成一个 JSON 对象,该对象进而创建一个数据库表。

ORM 只是一种无需编写显式 SQL 语句即可在数据库中读取、写入和更新数据的简便方法。

约定

为了支持快速应用程序开发,Frappe 框架遵循一些标准约定。

  1. DocType 始终使用单数形式。如果您想在数据库中存储文章列表,应将 doctype 命名为 Article。
  2. 表名以 tab 为前缀。因此,Article doctype 的表名为 tabArticle。

创建 DocType 的标准方法是在 Desk 的搜索栏中输入 new doctype。

ToDo DocType

DocType 不仅存储字段,还存储有关数据在系统中如何行为的其他信息。我们称之为元数据。由于这些元数据也存储在数据库表中,因此无需编写大量代码即可轻松地动态更改元数据。了解更多关于元数据的信息。

DocType 本身也是一个 DocType。这意味着我们将元数据作为数据的一部分进行存储。

创建 DocType 后,Frappe 可以立即提供许多开箱即用的功能。如果您访问 /app/todo,您将被路由到 Desk 中的列表视图。

ToDo 列表

同样,您可以在路由 /app/todo/000001 处获得表单视图。该表单用于创建新文档并查看它们。

ToDo 表单

站点

Frappe 是一个多租户平台,每个租户被称为一个“站点”。每个站点都有自己独立的数据库。站点位于名为 sites 的目录中,该目录在执行 bench 命令时被视为当前工作目录。

站点目录

站点目录 frappe-bench/sites 存放着此 bench 的所有站点。该目录还包含一些其他文件和目录,下面将逐一说明。

apps.txt

此文件包含 Frappe 应用的列表。一个应用必须先在此文件中列出,才能被安装到站点上。当运行 bench get-app 命令或 bench new-app 命令时,该文件会自动更新。

common_site_config.json

所有站点通用的配置可以放在此文件中。了解更多关于站点配置的信息。

assets

assets 目录包含需要提供给客户端浏览器使用的文件,通常包括 *.js、*.css 和图片文件。该目录通过 bench build 命令自动生成。在生产环境中,此目录由 Nginx 提供服务。

创建新站点

要创建新站点,请在 frappe-bench 目录下运行以下命令:

$ bench new-site mysite.localhost

Installing frappe...
Updating DocTypes for frappe        : [========================================]
Updating country info               : [========================================]
*** Scheduler is disabled ***

现在,mysite.local 目录将在 sites 目录中被创建。

目录结构

sites/mysite.localhost
├── locks
├── private
│   ├── backups
│   └── files
├── public
│   └── files
├── site_config.json
└── task-logs

locks

此目录供调度器使用,通过文件锁机制来同步各种任务。

private

此目录包含需要身份验证才能访问的文件,例如私有文件和备份。可以通过 URL:/private/files/private-file.png 访问这些文件。

public

此目录包含可公开访问的文件。可以通过 URL:/files/public-file.png 访问这些文件。

site_config.json

此文件包含站点特定的配置信息。

站点配置

每个站点目录下都有一个名为 site_config.json 的文件,用于存储该站点特定的配置。这些配置值会以字典的形式保存在 frappe.conf 局部变量中。

site_config.json 示例:

{
    "db_name": "test_frappe",
    "db_password": "test_frappe",
    "admin_password": "admin",
}

要了解更多关于管理站点或 Bench 级别配置的信息,请查阅这份综合文档。

站点解析

在处理 HTTP 请求时,系统会根据以下条件自动选择一个站点:

  • HTTP 请求中的 Host 头信息与某个站点匹配
  • HTTP 请求中的 X-Frappe-Site-Name 头信息与某个站点匹配

也可以通过以下命令启动开发服务器,强制其服务于特定站点:

bench --site mysite.localhost serve

将某个站点设置为当前站点

要强制将某个站点设为默认站点,请运行以下命令:

bench use mysite.localhost

运行此命令后,执行站点特定命令时无需再添加 --site 参数。

例如,无需运行:

bench --site mysite.localhost migrate

只需运行:

bench migrate

应用

Frappe 应用是一个使用 Frappe 框架的 Python 包。Frappe 应用位于
apps 目录下的 frappe-bench 目录中。

默认应用 frappe 是一个 Frappe 应用,它充当所有应用的基础框架。
每个 Frappe 应用都必须在 apps.txt 中有一个条目。

创建应用

Frappe 自带一个新应用的模板。要创建新应用,请在 frappe-bench 目录下
运行以下命令。

$ bench new-app custom_app
INFO:bench.app:creating new app custom_app
App Title (default: Custom App):
App Description: Custom Frappe App
App Publisher: John Doe
App Email: [email protected]
App Icon (default 'octicon octicon-file-directory'):
App Color (default 'grey'):
App License (default 'MIT'):
'custom_app' created at /Users/johndoe/frappe-bench/apps/custom_app
INFO:bench.app:installing custom_app
INFO:bench.utils:./env/bin/pip install -q -e ./apps/custom_app

现在,custom_app 目录将在 apps 目录中创建。它
也会被添加到 apps.txt 中。

目录结构

应用的目录结构大致如下:

apps/custom_app
├── MANIFEST.in
├── README.md
├── custom_app
│ ├── __init__.py
│ ├── config
│ │ ├── __init__.py
│ │ ├── desktop.py
│ │ └── docs.py
│ ├── custom_app
│ │ └── __init__.py
│ ├── hooks.py
│ ├── modules.txt
│ ├── patches.txt
│ ├── public
│ │ ├── css
│ │ └── js
│ ├── templates
│ │ ├── __init__.py
│ │ └── includes
│ └── www
├── license.txt
├── requirements.txt
├── dev-requirements.txt
├── package.json
└── setup.py

requirements.txt

此文件存储 Python 依赖项列表。安装此应用时,
其依赖项也会一并安装。

dev-requirements.txt [可选]

此文件存储 Python 开发依赖项列表。此文件的语法与
requirements.txt 相同。如果启用了开发者模式,那么
安装应用时也会安装其开发依赖项。

package.json

此文件用于跟踪 Node 依赖项。在此处了解更多信息。

customapp

这是存储源文件的目录。

customapp/customapp

当您创建新应用时,会在应用内部创建一个同名的模块。
此目录即对应于该模块。

customapp/hooks.py

此文件用于挂钩 Frappe 事件,并扩展或覆盖 Frappe 的
标准行为。

了解更多关于 hooks 的信息。

customapp/modules.txt

每个 Frappe 应用都组织为不同的模块。每个 DocType 都属于某个
模块。这些模块都列在此文件中。

了解更多关于模块的信息。

customapp/patches.txt

此文件用于存储数据库迁移过程中运行的补丁引用。
这些补丁按顺序运行,并且每个补丁只运行一次。

了解更多关于数据库迁移的信息。

customapp/public

public 文件夹是一个静态文件夹,在生产环境中可以由 nginx 提供服务。
放在这里的文件可以通过 URL /assets/custom_app/**/* 访问。

例如,文件 public/img/logo.png 可以通过 URL
/assets/custom_app/img/logo.png 访问。

此文件夹用于存储直接在客户端使用的静态资源,
如 JS、CSS 和图片。

customapp/templates

templates 文件夹用于编写和管理 Jinja 模板。您可以按照
任何方式组织它们。当您在 Jinja 模板中使用它们时,
此目录会被直接扫描。

例如,当您包含一个局部模板 {% include "templates/navbar/navbar.html" %} 时,
它会首先扫描此目录,然后回退到其他应用。

customapp/www

此目录中的文件直接映射到门户页面,URL 与
目录结构相匹配。

了解更多关于门户页面的信息。

将应用安装到站点

要使用应用,必须将其安装到站点上。将应用安装到站点意味着
将应用捆绑的模型创建到站点中,也就是说,
在站点数据库中创建数据库表。

要将应用安装到站点,请运行以下命令:

$ bench --site site_name install-app custom_app

Installing custom_app...

要检查应用是否安装正确,请运行以下命令:

$ bench --site site_name list-apps
frappe
custom_app

目录结构

当你初始化一个新的 frappe-bench 目录时,你会得到一个类似如下的目录结构:

.
├── apps
 ├── frappe
├── config
 ├── redis_cache.conf
 ├── redis_queue.conf
 └── redis_socketio.conf
├── env
├── logs
├── Procfile
└── sites
 ├── apps.txt
 ├── assets
 ├── common_site_config.json
 └── site1.local
 ├── private
 ├── public
 └── site_config.json

apps(应用)

frappe 应用和其他基于 frappe 的应用都存放在此目录中。当你运行 bench new-app app_name 命令时,应用会在此目录中被初始化。你的自定义应用也存放在这里,你应该在此处进行编辑和开发。

了解更多关于应用的信息。

sites(站点)

站点从此目录中提供服务。当你运行 bench new-site site_name 命令时,站点会在此目录中被创建。站点根据其目录名称进行区分。

了解更多关于站点的信息。

logs(日志)

此目录用于存放来自各种进程的日志文件。每个日志文件根据其来源进程进行命名。

config(配置)

Frappe 使用 3 个 Redis 实例来管理缓存、任务队列和 socketio 通信。所有这些配置都存放在此目录中。

env(环境)

Python 虚拟环境存放在此目录中。基于 Frappe 的应用和 Python 包依赖都安装在这里。

Procfile(进程文件)

Frappe 使用基于 Procfile 的进程管理方式。默认的 Procfile 内容如下所示:

redis_cache: redis-server config/redis_cache.conf
redis_socketio: redis-server config/redis_socketio.conf
redis_queue: redis-server config/redis_queue.conf
web: bench serve --port 8000

socketio: /usr/bin/node apps/frappe/socketio.js

watch: bench watch

schedule: bench schedule
worker_short: bench worker --queue short --quiet
worker_long: bench worker --queue long --quiet
worker_default: bench worker --queue default --quiet

让我们看看每个进程的用途。

redis_cache:

用于内存缓存的 Redis。

redis_socketio:

用作 web 和 socketio 进程之间实时通信的发布/订阅(pub/sub)Redis。

redis_queue:

用于管理后台任务队列的 Redis。

web:

基于 Werkzeug 的 Python Web 服务器。

socketio:

用于与浏览器建立 socketio 连接以实现实时通信的 Node 服务器。

watch:

使用 Rollup 打包 JS/CSS 资源的 Node 服务器。它也会在文件变更时重新构建文件。

schedule:

使用 Python RQ 的作业调度器。

worker_short:

超时时间(短)为 300 秒的 Python 工作进程。

worker_long:

超时时间(长)为 1500 秒的 Python 工作进程。

worker_default:

超时时间为 300 秒的 Python 工作进程。

架构

Frappe 框架是一个全栈式的基于 Web 的框架,它包含了将站点部署到生产环境所需的全部
工具。当你设置一个 Frappe 站点时,数据库、缓存、后台
任务、实时通知等都会被自动配置好。

Frappe 框架基于 Python,因此它使用 virtualenv 来为多个 Python 版本设置
隔离的环境。你也可以用它来部署不同 Frappe 版本的站点。

下图大致展示了 frappe-bench 的目录结构
及其与整个技术栈不同部分的交互方式。


架构

要设置一个基于 Frappe 的站点,你首先需要安装 Bench。如果你还没有
安装它,请查看“安装”
页面。

你可以通过运行以下命令来创建一个新的 frappe-bench 环境:

bench init frappe-bench

该命令将执行以下操作:

  1. 创建一个名为 frappe-bench 的目录,并在其中创建 frappe-bench/sites 和 frappe-bench/apps 目录。
  2. 在 frappe-bench/env 下设置一个 Python 虚拟环境。
  3. 创建一个 frappe-bench/config 文件夹,用于存放 Redis 配置文件。
  4. 下载 frappe 应用并 pip install 它。
  5. 安装 Node 包。
  6. 构建 JS/CSS 资源文件。

每个 frappe-bench 环境都会启动它自己的 Web、Redis 和 Node 进程。

为什么选择Frappe框架?

Frappe 的诞生是为了驱动我们的旗舰产品 ERPNext。
Frappe 的核心理念是尽可能少写代码。我们更倾向于
配置而非代码。如果一个功能是通用的并且我们需要它,我们就会把它直接
集成到框架中。

这使得我们能够用一个小型开发团队构建并维护像 ERP 这样
拥有数千个功能的复杂应用。

快速应用开发

搭建好 Frappe 框架后,你可以迅速进入高效工作状态。创建
模型、编写控制器代码以及更新视图,这些都由框架
自动处理。

功能齐全,开箱即用

现代 Web 应用可能需要的一切,框架中很可能
已经内置了。PDF 生成、邮件、短信、网页……
应有尽有。如果 Frappe 框架中缺少了什么,我们可能
现在就已经在开发它了 :)

易于部署

Bench 是管理 Frappe 所有事务的一体化工具。它负责应用
更新、数据库迁移、生成 nginx 和 supervisor 的配置、
搭建新应用以及更多功能。

多租户支持

Bench 原生支持多租户。这意味着你可以在同一套代码基础上
启动多个应用实例,并各自使用独立的数据库。它还支持
基于端口的多租户模式,你可以为不同版本的应用
设置多个 bench 环境。

可扩展架构

通过创建你自己的应用,可以在 Frappe 之上构建强大的扩展。应用可以
自带模型,也可以修改 Frappe 中现有的模型。

什么是Frappe框架?

Frappe 是一个用 Python 和 Javascript 编写的全栈式 Web 框架,功能全面,开箱即用。

它是驱动 ERPNext 的底层框架。该框架非常通用,可用于构建数据库驱动的应用程序。

元数据驱动

在 Frappe 中,元数据是一等公民。它用于生成数据库表、设计表单以及配置许多功能。元数据存储在一个称为 DocType 的模型中。

我们以名为 ToDo 的 DocType 为例。它将包含诸如 status、date 和 description 之类的字段。

以下是 todo.json 可能的样子:

{
 "name": "ToDo",
 "module": "Desk",
 "field_order": [
  "status",
  "date",
  "description"
 ],
 "fields": [
  {
   "default": "Open",
   "fieldname": "status",
   "fieldtype": "Select",
   "in_global_search": 1,
   "in_list_view": 1,
   "in_standard_filter": 1,
   "label": "Status",
   "options": "Open
Closed"
  },
  {
   "fieldname": "date",
   "fieldtype": "Date",
   "in_standard_filter": 1,
   "label": "Due Date"
  },
  {
   "fieldname": "description",
   "fieldtype": "Text Editor",
   "in_global_search": 1,
   "label": "Description",
   "reqd": 1
  }
 ]
}

这样的配置将生成一个数据库表,其表结构可能如下所示:

MariaDB [_baa0f26509a564b6]> desc tabToDo;
+-----------------------+--------------+------+-----+---------+-------+
| Field                 | Type         | Null | Key | Default | Extra |
+-----------------------+--------------+------+-----+---------+-------+
| name                  | varchar(140) | NO   | PRI | NULL    |       |
| creation              | datetime(6)  | YES  |     | NULL    |       |
| modified              | datetime(6)  | YES  | MUL | NULL    |       |
| modified_by           | varchar(140) | YES  |     | NULL    |       |
| owner                 | varchar(140) | YES  |     | NULL    |       |
| docstatus             | int(1)       | NO   |     | 0       |       |
| idx                   | int(8)       | NO   |     | 0       |       |
| status                | varchar(140) | YES  |     | Open    |       |
| description           | longtext     | YES  |     | NULL    |       |
| date                  | date         | YES  |     | NULL    |       |
+-----------------------+--------------+------+-----+---------+-------+

丰富的管理界面

Frappe 不仅管理后端,还附带了一个功能丰富的管理界面,称为 Desk。当您在 Frappe 中创建 DocType 时,系统会为其生成多个视图。以下是其中一些视图:

列表视图支持分页、筛选、排序和批量编辑记录。

列表视图

用于编辑记录的表单视图还支持文件附件、PDF 格式、评论、电子邮件等功能。

表单视图

报表生成器支持添加列、分组、筛选、排序,并将其保存为配置。

报表生成器

用户、角色和权限

Frappe 内置了用户和角色管理功能。用户是指可以登录系统并执行授权操作(如创建、更新或删除记录)的人。角色是对 DocType 及其允许执行的操作的映射。

Python、JS 和 MariaDB

Frappe 框架使用 Python 作为后端。它附带了一个简单而强大的 ORM,作为对 CRUD 操作的抽象。默认数据库是 MariaDB。Postgres 支持目前处于测试阶段。

doc = frappe.new_doc('ToDo')
doc.description = 'Buy Eggs'
doc.insert()

前端是使用 Javascript(jQuery)构建的单页应用程序(SPA)。

实时功能

Frappe 还支持使用 NodeJS 和 socketio 实现实时发布/订阅事件。

# server
frappe.publish_realtime('update_progress', {
    'progress': 42,
    'total': 100
})

# client
frappe.realtime.on('update_progress', (data) => {
    console.log(data)
});

后台任务

Frappe 还支持基于 Python RQ 的后台任务队列。

frappe.enqueue('frappe.job.run_job', arg1='Test', arg2='Test2')

电子邮件

Frappe 支持发送和接收电子邮件,这些邮件也可以关联到单个文档。

打印

Frappe 支持基于 Jinja 模板生成 PDF 打印格式。它还附带了一个拖放式的打印格式生成器。

打印预览

打印格式生成器

功能全面,开箱即用

Frappe 拥有构建现代复杂应用所必需的众多功能。这里仅介绍了基本功能。本指南的其余部分将更详细地介绍这些功能以及其他高级功能,请务必通读全文。