mcpField
F
frappe-impl-website

frappe-impl-website

github.com/impertio-studio开发198108 次安装30 周前更新
代码仓库

关于 frappe-impl-website

面向 Frappe 开发者的网站与门户实施指南,涵盖页面、表单、博客、路由、主题和 SEO 配置,并提供访客访问安全建议。

主要功能

  1. 01创建静态页面与自定义门户页面
  2. 02配置 Web Form 和访客提交
  3. 03发布 DocType 网页与博客文章
  4. 04设置网站路由与主题样式
  5. 05添加 SEO 元数据并配置 Sitemap
  6. 06管理访客访问与安全设置

适用场景

  1. 01构建公开内容页或自定义门户
  2. 02收集外部用户提交的数据
  3. 03将 DocType 记录发布为网页
  4. 04设置博客、网站路由及搜索元数据

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/impertio-studio/frappe_claude_skill_package --skill frappe-impl-website

安装后在 Claude Code 中输入/frappe-impl-website确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
.gitkeep
anti-patterns.md
decision-tree.md
examples.md
generators.md
workflows.md

详细介绍

Frappe 网站与门户 — 实施工作流

构建网站、门户和面向公众页面的分步工作流。钩子语法请参阅 frappe-impl-hooks。Jinja 模板请参阅 frappe-impl-jinja。

版本:v14/v15/v16 | 注意:v15+ 使用 Bootstrap 5;v14 使用 Bootstrap 4。

快速判断:选择哪种页面类型?

WHAT do you need?
├── Static content page (About, Terms)     → Web Page DocType or www/ HTML
├── Data entry by external users           → Web Form
├── List of records visible on website     → has_web_view on DocType
├── Blog / news articles                   → Blog Post + Blog Category
├── Custom app with sidebar/toolbar        → Custom Portal Page (www/)
└── Dynamic route with parameters          → website_route_rules in hooks.py

完整决策树请参阅 references/decision-tree.md。

工作流 1:创建门户页面(www/)

门户页面位于应用的 www/ 目录中。文件名会成为 URL 路由。

  1. 创建 myapp/www/custom_page.html:
{% extends "templates/web.html" %}
{% block page_content %}
<h1>{{ title }}</h1>
<div>{{ content }}</div>
{% endblock %}
  1. 创建对应的控制器 myapp/www/custom_page.py:
import frappe

def get_context(context):
    context.title = "My Custom Page"
    context.content = "Hello World"
    context.no_cache = 1  # ALWAYS set for dynamic content
  1. 结果:页面可通过 /custom_page 访问

自动加载的文件类型:.html(模板)、.py(控制器)、.css(样式)、.js(脚本)。

子目录模式 — 用于嵌套路由:

myapp/www/
├── services/
│   ├── index.html        → /services
│   ├── index.py
│   ├── consulting.html   → /services/consulting
│   └── consulting.py
上下文变量参考
键类型效果
titlestr页面标题和浏览器标签页标题
no_cachebool禁用页面缓存
no_headerbool隐藏页面页眉
no_breadcrumbsbool移除面包屑导航
add_breadcrumbsbool根据文件夹结构自动生成
show_sidebarbool显示网站侧边栏
sitemapint0 = 从站点地图中排除,1 = 包含
metatagsdictSEO 元标签(参见工作流 7)

规则:对于包含用户专属或频繁变化内容的页面,始终设置 no_cache = 1。

工作流 2:创建 Web 表单

Web 表单允许外部用户提交数据并创建 Frappe 文档。

  1. 导航至 Web Form 列表 → New Web Form
  2. 设置 Title,选择目标 DocType,设置 Route(URL 别名)
  3. 添加字段——字段的 fieldname 始终要与目标 DocType 的字段名称一致
  4. 配置访问权限:
    • Login Required:取消勾选以允许访客提交
    • Allow Edit:允许用户编辑其提交内容
    • Allow Multiple:允许用户多次提交
  5. 保存并发布
访客提交
ALLOWING guest submissions?
├── YES → Uncheck "Login Required"
│        → Set "Guest Title" for the submission form
│        → ALWAYS add rate limiting in site_config:
│           "rate_limit": {"web_form": "5/hour"}
│        → ALWAYS validate server-side (guests can bypass JS)
└── NO  → Keep "Login Required" checked (default)
Web 表单自定义脚本(客户端)
frappe.web_form.on("after_load", function() {
    // Runs after form loads in browser
});

frappe.web_form.on("before_submit", function() {
    // Validate before submission — return false to cancel
    let val = frappe.web_form.get_value("email");
    if (!val) {
        frappe.throw("Email is required");
        return false;
    }
});

frappe.web_form.on("after_submit", function() {
    // Redirect or show message after success
    window.location.href = "/thank-you";
});
Web 表单自定义脚本(服务器端:Python)

在 Web Form 文档中添加 Python 脚本:

def get_context(context):
    # Add custom context variables for the template
    context.categories = frappe.get_all("Category", fields=["name", "title"])

规则:绝不能只信任 Web 表单的客户端验证。始终要在目标 DocType 的控制器或服务器脚本中进行验证。

工作流 3:在 DocType 上启用 has_web_view

这样可以将单个文档作为网页访问(例如 /articles/my-article)。

  1. 打开 DocType → 勾选 Has Web View 和 Allow Guest to View
  2. 设置 Route 字段前缀(例如 articles)
  3. 始终将以下字段添加到 DocType:
    • route(Data,隐藏)— 自动生成的 URL 别名
    • published(Check)— 控制可见性
  4. 在 DocType 目录中创建模板:
    • {doctype_name}.html — 单条记录模板
    • {doctype_name}_row.html — 列表项模板
  5. 在 hooks.py 中注册为网站生成器:
website_generators = ["Article"]
  1. 在控制器中实现 get_context:
class Article(WebsiteGenerator):
    website = frappe._dict(
        template="templates/generators/article.html",
        condition_field="published",
        page_title_field="title",
    )

    def get_context(self, context):
        context.related = frappe.get_all(
            "Article",
            filters={"published": 1, "name": ("!=", self.name)},
            fields=["title", "route"],
            limit=5,
        )

规则:始终包含 published 检查字段。绝不能向访客公开未发布的文档。

工作流 4:网站路由规则(hooks.py)

路由规则将 URL 模式映射到控制器或页面。

# hooks.py
website_route_rules = [
    # Map parameterized URL to a page
    {"from_route": "/projects/<name>", "to_route": "projects/project"},
    # Map URL prefix to DocType
    {"from_route": "/kb/<path:name>", "to_route": "knowledge-base"},
]

# Redirects (301/304)
website_redirects = [
    {"source": "/old-page", "target": "/new-page"},
    {"source": r"/docs(/.*)?", "target": r"https://docs.example.com\1"},
]

# Homepage for logged-in users (role-based)
role_home_page = {
    "Customer": "orders",
    "Supplier": "rfqs",
}

# Dynamic homepage
get_website_user_home_page = "myapp.utils.get_home_page"

主页的优先级顺序:get_website_user_home_page > role_home_page > Portal Settings > Website Settings。

工作流 5:博客设置

  1. 创建 Blog Category 文档(例如“新闻”“更新”)
  2. 创建 Blog Post 文档:
    • 选择分类,编写内容(Markdown 或富文本)
    • 设置 Published 和 Published On 日期
    • 博客路由会自动生成为 /blog/{slug}
  3. 在 Website Settings 中配置:
    • 设置博客标题
    • 启用/禁用评论

规则:始终设置 Published On 日期——没有日期的文章绝不会出现在 RSS 源中。

工作流 6:网站主题与自定义 CSS

通过 Website Theme DocType
  1. 导航至 Website Theme → New
  2. 配置:字体、颜色、导航栏样式、按钮圆角
  3. 在 Custom CSS 字段中添加自定义 CSS
  4. 在 Website Settings 中将其设为活动主题
通过 hooks.py
# Inject CSS/JS on all web pages
website_context = {
    "favicon": "/assets/myapp/images/favicon.png",
}

update_website_context = "myapp.overrides.website_context"

# Override base template
base_template = "myapp/templates/custom_base.html"

工作流 7:SEO:元标签、Open Graph 和站点地图

在门户页面中(frontmatter 或上下文)
def get_context(context):
    context.metatags = {
        "title": "My Page Title",
        "description": "Page description for search engines",
        "image": "/assets/myapp/images/og-image.png",
        "og:type": "website",
        "twitter:card": "summary_large_image",
    }
在 Web Page DocType 中

直接设置元数据字段:Meta Title、Meta Description、Meta Image。

站点地图
  • Frappe 会根据已发布的 Web Page 和 has_web_view 文档自动生成 /sitemap.xml
  • 排除页面:在上下文或 frontmatter 中设置 sitemap = 0
  • 自定义 robots.txt:在 site_config.json 中设置 robots_txt 路径

规则:公共页面必须始终设置 meta description。绝不能留空——搜索引擎会降低没有描述的页面的排名。

工作流 8:访客访问与安全性

# site_config.json — rate limiting
{
    "rate_limit": {
        "web_form": "5/hour",
        "api": "100/hour"
    },
    "allowed_referrers": ["https://mysite.com"],
    "allow_cors": "https://mysite.com"
}

安全规则:

  • 始终启用 CSRF 保护(默认设置)。生产环境中绝不能设置 ignore_csrf
  • 始终对访客可访问的端点实施速率限制
  • 始终清理 Web Forms 中的用户输入(Frappe 默认会清理标准字段)
  • 未设置访问控制时,绝不能在面向访客的 URL 中暴露内部 DocType 名称

反模式

反模式正确做法
在 get_context 中硬编码 HTML使用带上下文变量的 Jinja 模板
动态页面未设置 no_cache用户专属内容必须始终设置 no_cache = 1
访客 Web Form 未设置速率限制始终为访客表单配置速率限制
has_web_view 缺少 published 字段始终添加 published 检查以防止数据泄露
将 website_route_rules 用于简单重定向改用 website_redirects
将业务逻辑放入 www/ 控制器将业务逻辑放在 DocType 控制器中;www/ 用于呈现

参见 references/anti-patterns.md,了解包含示例的扩展反模式说明。

另请参阅

  • frappe-impl-hooks — Website hooks 详解
  • frappe-impl-jinja — Jinja 模板模式
  • frappe-impl-controllers — DocType 控制器(WebsiteGenerator)
  • frappe-syntax-clientscripts — Web Forms 的客户端 API
  • references/generators.md — 门户生成器、博客系统、自定义路由模式
  • references/workflows.md — 扩展工作流详解
  • references/examples.md — 完整代码示例
  • references/decision-tree.md — 页面类型完整决策树

评论

支持 Markdown