# Django 3.2.11.dev 文档

# 简单页面应用

Django 自带一个可选的“简单页面”应用程序。它可以让你在数据库中存储“简单”的 HTML 内容，并通过 Django 的管理界面和 Python API 为你处理管理。

简单页面是一个有 URL、标题和内容的对象。它可以用于一次性的、特殊情况下的页面，比如“关于”或“隐私政策”页面，你想把这些页面存储在数据库中，但又不想开发一个自定义的 Django 应用。

一个简单页面可以使用自定义模板，也可以使用系统默认的简单页面模板。它可以与一个或多个网站关联。

如果你想把你的内容放在一个自定义模板中，内容字段可以选择留空。

## 安装

要安装简单页面应用，请按照以下步骤操作：

1. 安装 `站点框架`，在 `INSTALLED_APPS` 设置中添加 `'django.contrib.sites'`，如果还没有的话。

   同时确保你已经正确地设置 `SITE_ID` 为配置文件所代表的网站 ID。这通常是 `1` （即 `SITE_ID = 1`，但如果你使用网站框架来管理多个网站，它可能是不同网站的 ID。

2. 将 `'django.contrib.flatpages'` 添加到你的 `INSTALLED_APPS` 配置中。

那么无论是：

3. 在你的 URLconf 中添加一个条目。例如：

       urlpatterns = [
           path('pages/', include('django.contrib.flatpages.urls')),
       ]

或：

3. 将 `'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware'` 添加到你的 `MIDDLEWARE` 配置中。
4. 运行命令 `manage.py migrate`。

## 工作方式

`manage.py migrate` 在数据库中创建两个表。`django_flatpage` 和 `django_flatpage_sites`。`django_flatpage` 是一个查找表，将一个 URL 映射到标题和一堆文本内容。`django_flatpage_sites` 将一个简单页面与一个网站关联起来。

### 使用 URLconf

有几种方法可以在你的 URLconf 中包含简单页面。你可以为简单页面指定一个特定的路径：

    urlpatterns = [
        path('pages/', include('django.contrib.flatpages.urls')),
    ]

你也可以把它设置成一个“catchall”模式。在这种情况下，重要的是将该模式放在其他 urlpatterns 的最后：

    from django.contrib.flatpages import views

    # Your other patterns here
    urlpatterns += [
        re_path(r'^(?P<url>.*/)$', views.flatpage),
    ]

警告

如果你将 `APPEND_SLASH` 设置为 `False`，你必须删除 catchall 模式中的斜杠，否则没有尾部斜杠的简单页面将不会被匹配。

另一种常见的设置是对有限的已知页面集使用简单页面，并对网址进行硬编码，所以你可以用 `url` 模板标签来引用它们：

    from django.contrib.flatpages import views

    urlpatterns += [
        path('about-us/', views.flatpage, {'url': '/about-us/'}, name='about'),
        path('license/', views.flatpage, {'url': '/license/'}, name='license'),
    ]

### 使用中间件

`FlatpageFallbackMiddleware` 可以完成所有的工作。

class `FlatpageFallbackMiddleware`

  每当任何 Django 应用出现 404 错误时，这个中间件都会检查简单页面数据库中所请求的 URL，作为最后的手段。具体来说，它检查给定 URL 的简单页面，其网站 ID 对应于:setting:SITE_ID 配置。

  如果它找到了一个匹配，就按照这个算法：

  - 如果简单页面有自定义模板，它就加载该模板。否则，它会加载模板 `flatpages/default.html`。
  - 它给该模板传递了一个上下文变量 `flatpage`，也就是简单页面对象。它使用 `RequestContext` 来渲染模板。

  如果产生的 URL 指向有效的简单页面，中间件只会添加尾部的斜线和重定向（通过查看 `APPEND_SLASH` 配置）。重定向是永久性的（301 状态码）。

  如果没有找到匹配的请求，则继续照常处理。

  中间件只有在 404 时才会被激活——而不是 500 或任何其他状态码的响应。

简单页面不会应用视图中间件

因为 `FlatpageFallbackMiddleware` 只有在 URL 解析失败并产生 404 之后才会应用，所以它返回的响应不会应用任何 视图中间件 方法。只有通过正常 URL 解析成功路由到视图的请求才会应用视图中间件。

注意 `MIDDLEWARE` 的顺序很重要。一般来说，你可以把 `FlatpageFallbackMiddleware` 放在列表的最后。这意味着它将在处理响应时首先运行，并确保任何其他响应处理中间件看到的是真正的简单页面响应而不是 404。

关于中间件的更多内容，请阅读 中间件文档。

确保你的 404 模板工作

请注意 `FlatpageFallbackMiddleware` 只有在另一个视图成功产生 404 响应后才会介入。如果另一个视图或中间件类试图产生 404，但最后却引发了一个异常，那么响应将变成 HTTP 500（“内部服务器错误”），并且 `FlatpageFallbackMiddleware` 将不会试图服务一个简单页面。

## 如何添加、更改和删除简单页面

### 通过管理界面

如果你已经激活了 Django 的自动管理界面，你应该会在管理索引页上看到一个“简单页面”栏目。编辑简单页面就像编辑系统中的其他对象一样。

`FlatPage` 模型有一个 `enable_comments` 字段，`contrib.flatpages` 没有使用，但对你的项目或第三方应用程序可能有用。它不会出现在管理界面中，但你可以通过为 `FlatPage` 注册一个自定义的 `ModelAdmin` 来添加它：

    from django.contrib import admin
    from django.contrib.flatpages.admin import FlatPageAdmin
    from django.contrib.flatpages.models import FlatPage
    from django.utils.translation import gettext_lazy as _

    # Define a new FlatPageAdmin
    class FlatPageAdmin(FlatPageAdmin):
        fieldsets = (
            (None, {'fields': ('url', 'title', 'content', 'sites')}),
            (_('Advanced options'), {
                'classes': ('collapse',),
                'fields': (
                    'enable_comments',
                    'registration_required',
                    'template_name',
                ),
            }),
        )

    # Re-register FlatPageAdmin
    admin.site.unregister(FlatPage)
    admin.site.register(FlatPage, FlatPageAdmin)

### 通过 Python API

class `FlatPage`

  简单页面由一个标准的 Django 模型 来表示，它位于 django/contrib/flatpages/models.py 中。你可以通过 Django 数据库 API 来访问简单页面对象。

检查是否有重复的简单页面网址。

如果你通过自己的代码来添加或修改简单页面，你很可能要检查同一站点内是否有重复的简单页面 URL。管理中使用的简单页面表单可以执行这种验证检查，可以从 `django.contrib.flatpages.forms.FlatpageForm` 中导入，并在你自己的视图中使用。

## 简单页面模板

默认情况下，简单页面是通过模板 `flatpages/default.html` 来渲染的，但是你可以为某个特定的简单页面覆盖这个模板：在管理中，一个名为“高级选项”的折叠式字段集（点击可以展开）包含了一个指定模板名称的字段。如果你是通过 Python API 创建一个简单页面，你可以将模板名称设置为 `template_name` 对象上的字段 `FlatPage`。

创建 `flatpages/default.html` 模板是你的责任；在你的模板目录下，创建一个 `flatpages` 目录，其中包含一个文件 `default.html`。

简单模板被传递一个单一的上下文变量 `flatpage`，也就是简单页面对象。

下面是一个示例 `flatpages/default.html` 模板：

    <!DOCTYPE html>
    <html>
    <head>
    <title>{{ flatpage.title }}</title>
    </head>
    <body>
    {{ flatpage.content }}
    </body>
    </html>

由于你已经在管理页面中输入了原始 HTML，所以 `flatpage.title` 和 `flatpage.content` 都在模板中被标记为 不需要 自动 HTML 转义。

## 获取模板中的 `FlatPage` 对象列表

简单页面应用提供了一个模板标签，允许你在 :ref:`当前站点 <hooking-into-current-site-from-views>`上迭代所有可用的简单应用。

和所有的自定义模板标签一样，在使用它之前，你需要 加载其自定义标签库。加载库后，你可以通过 `get_flatpages` 标签来检索当前所有的简单页面。

    {% load flatpages %}
    {% get_flatpages as flatpages %}
    <ul>
        {% for page in flatpages %}
            <li><a href="{{ page.url }}">{{ page.title }}</a></li>
        {% endfor %}
    </ul>

### 显示 `registration_required` 简单页面

默认情况下，`get_flatpages` 模板标签只显示标记为 `registration_required = False` 的页面。如果你想显示受注册保护的页面，你需要使用 `for` 子句指定一个经过认证的用户。

例如：

    {% get_flatpages for someuser as about_pages %}

如果你提供了一个匿名用户， `get_flatpages` 将与你没有提供用户的行为相同——即，它将只向你显示公共的简单页面。

### 通过基础 URL 限制简单页面

一个可选的参数，`starts_with`，可以用来限制返回的页面以特定的基本 URL 开头。这个参数可以以字符串的形式传递，也可以以一个变量的形式从上下文中解析。

例如：

    {% get_flatpages '/about/' as about_pages %}
    {% get_flatpages about_prefix as about_pages %}
    {% get_flatpages '/about/' for someuser as about_pages %}

## 与 `django.contrib.sitemaps` 整合

class `FlatPageSitemap`

  `sitemaps.FlatPageSitemap` 类查看所有为当前 `SITE_ID` 定义的公开可见的 `flatpages` （参见 `站点文档`），并在站点地图中创建一个条目。这些条目只包括 `location` 属性——不包括 `lastmod`、 `changefreq` 或 `priority`。

### 例如

下面是一个使用 `FlatPageSitemap` 的 URLconf 的例子：

    from django.contrib.flatpages.sitemaps import FlatPageSitemap
    from django.contrib.sitemaps.views import sitemap
    from django.urls import path

    urlpatterns = [
        # ...

        # the sitemap
        path('sitemap.xml', sitemap,
            {'sitemaps': {'flatpages': FlatPageSitemap}},
            name='django.contrib.sitemaps.views.sitemap'),
    ]