wagtail的数据模型和渲染
文章目录
- 前言
- 页面数据模型
- 数据库字段部分
- 搜索部分
- 编辑面板
- 基础面板
- 结构化面板
- 父页面/子页面类型规则
- 页面URLs
- 自定义页面模型的URL模式
- 获取页面实例的URL
- 模板渲染
- 为页面模型添加模板
- 模板上下文
- 自定义模板上下文
- 更改模板
- 动态选择模板
- Ajax 模板
- 内联模型
- 在多个页面类型之间重用内联模型
- 使用页面
前言
Wagtail中的每种页面类型(也称为内容类型)都由Django模型表示。所有页面模型都必须继承自 wagtail.models.Page 类。
正如所有页面类型都是Django模型一样,您可以使用Django提供的任何字段类型。请参阅Django模型字段参考获取可用字段类型的完整列表。此外,Wagtail还提供了 wagtail.fields.RichTextField,该字段提供了一个所见即所得的编辑器,用于编辑富文本内容。
页面数据模型
一个页面的数据模型包括如下基本内容
from django.db import modelsfrom modelcluster.fields import ParentalKeyfrom wagtail.models import Page, Orderable
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel, MultiFieldPanel, InlinePanel
from wagtail.search import indexclass BlogPage(Page):# 数据库字段body = RichTextField()date = models.DateField("Post date")feed_image = models.ForeignKey('wagtailimages.Image',null=True,blank=True,on_delete=models.SET_NULL,related_name='+')# 搜索索引配置,body和date可被搜索search_fields = Page.search_fields + [index.SearchField('body'),index.FilterField('date'),]# 管理界面编辑面板配置content_panels = Page.content_panels + [FieldPanel('date'),FieldPanel('body'),InlinePanel('related_links', heading="Related links", label="Related link"),]promote_panels = [MultiFieldPanel(Page.promote_panels, "Common page configuration"),FieldPanel('feed_image'),]# 父页面 / 子页面类型规则parent_page_types = ['blog.BlogIndex']subpage_types = []class BlogPageRelatedLink(Orderable):page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='related_links')name = models.CharField(max_length=255)url = models.URLField()panels = [FieldPanel('name'),FieldPanel('url'),]
包括以下几个部分
数据库字段部分
每个 Wagtail页面是一个Django数据模型,在数据库中表示一个独立的表。
Wagtail 也提供了一些它自己的类:
RichTextField - For rich text contentStreamField - A block-based content field (see: Freeform page content using StreamField)
对于标签tag Wagtail 完全支持django的标签系统。
搜索部分
搜索字段定义了哪些哪些字段被添加到了搜索索引,是如何被索引的。
search_fields = Page.search_fields + [index.SearchField('body'),index.FilterField('date'),]
编辑面板
定义了页面的字段是如何通过面板被展示在编辑接口的。
content_panels - 用于内容展示,如,文本等promote_panels - 用于 metadata, 比如 tags, thumbnail image and SEO titlesettings_panels - 用户设置, 比如发布日期
又分为基础的和结构型的
基础面板
编辑数据字段,字段面板会选择合适的wideget来适配这些字段。比如富文本会选择富文本小组件。图片选择小组件选择一个外键指向一个图片模型。
FieldPanelPageChooserPanel
结构化面板
用于结构化字段
MultiFieldPanelInlinePanelFieldRowPanel
父页面/子页面类型规则
这两个属性允许您控制页面类型在站点中的使用位置。它们允许您定义诸如“博客条目只能在博客索引下创建”之类的规则。
parent_page_types 和 subpage_types 都接受模型类或模型名称的列表。模型名称的格式为 app_label.ModelName。如果省略了 app_label,则假定为相同的应用程序。
parent_page_types 限制了可以在此类型下创建哪些页面类型。
subpage_types 限制了可以在此类型下创建哪些页面类型。
默认情况下,任何页面类型都可以在任何页面类型下创建,如果这是期望的行为,则不需要设置这些属性。
将 parent_page_types 设置为空列表是防止特定页面类型在编辑界面中被创建的一种好方法。
页面URLs
检索页面URL的最常见方法是使用 {% pageurl %} 或 {% fullpageurl %} 模板标签。由于它是从模板中调用的,这些标签会自动包含下面提到的优化。
页面模型还包括一些用于覆盖或访问页面URL的低级方法。
自定义页面模型的URL模式
Page.get_url_parts(request) 方法通常不会直接调用,但可以被覆盖以为给定的页面模型定义自定义的URL路由。它应该返回一个元组 (site_id, root_url, page_path),这些由 get_url 和 get_full_url(见下文)用于构建给定类型的页面URL。
在覆盖 get_url_parts() 时,应该接受 *args, **kwargs:
def get_url_parts(self, *args, **kwargs):
并在调用 super 上的 get_url_parts 时传递它们(如果适用),例如:
super().get_url_parts(*args, **kwargs)
虽然您可以仅传递 request 关键字参数,但将所有参数原样传递确保了对这些方法签名的任何未来更改的兼容性。
有关更多信息,请参阅 wagtail.models.Page.get_url_parts()。
获取页面实例的URL
您可以在需要页面URL时调用 Page.get_url(request) 方法。如果它确定页面在当前站点上(通过请求中的主机名),它将默认返回本地URL(不包括协议或域);否则,它将返回包括协议和域的完整URL。在可能的情况下,应包括可选的 request 参数,以启用每个请求的站点级URL信息的缓存,并促进本地URL的生成。
get_url(request) 的一个常见用例是在项目中包含用于生成导航菜单的任何自定义模板标签中调用。在编写这样的自定义模板标签时,请确保它包括 takes_context=True 并使用 context.get(‘request’) 来安全地传递请求,或者如果上下文中不存在请求,则传递 None。
有关更多信息,请参阅 wagtail.models.Page.get_url()。
要检索完整的URL(包括协议和域),请使用 Page.get_full_url(request)。在可能的情况下,应包括可选的 request 参数,以启用每个请求的站点级URL信息的缓存。
有关更多信息,请参阅 wagtail.models.Page.get_full_url()。
模板渲染
每个页面模型都可以被分配一个 HTML 模板,当用户在站点前端浏览到页面时,该模板将被呈现。这是将 Wagtail 内容传递给最终用户的最简单和最常见的方式之一(但不是唯一的方式)。
为页面模型添加模板
Wagtail会根据应用标签和模型类名自动选择模板的名称。
格式: <app_label>/<model_name(蛇形命名)>.html例如,上述博客页面的模板将是: blog/blog_page.html
你只需在可以使用这个名称访问的位置创建一个模板。
模板上下文
Wagtail通过将页面变量绑定到正在渲染的页面实例来呈现模板。使用这个变量来访问页面的内容。例如,要获取当前页面的标题,请使用 {{ page.title }}。上下文处理器提供的所有变量也都可用。
自定义模板上下文
所有页面都有一个 get_context 方法,每当模板被渲染时都会调用该方法,并返回一个要绑定到模板中的变量字典。
要向模板上下文添加更多变量,您可以覆盖此方法:
class BlogIndexPage(Page):...def get_context(self, request, *args, **kwargs):context = super().get_context(request, *args, **kwargs)# Add extra variables and return the updated contextcontext['blog_entries'] = BlogPage.objects.child_of(self).live()return context
然后,这些变量可以在模板中使用:
{{ page.title }}{% for entry in blog_entries %}{{ entry.title }}
{% endfor %}
更改模板
将模板属性设置在类上,以使用不同的模板文件:
class BlogPage(Page):...template = 'other_template.html'
动态选择模板
可以通过在页面类上定义 get_template 方法,以在每个实例基础上动态更改模板。该方法在每次渲染页面时都会被调用:
class BlogPage(Page):...use_other_template = models.BooleanField()def get_template(self, request, *args, **kwargs):if self.use_other_template:return 'blog/other_blog_page.html'return 'blog/blog_page.html'
在这个例子中,拥有设置了 use_other_template 布尔字段的页面将使用 blog/other_blog_page.html 模板。所有其他页面将使用默认的 blog/blog_page.html 模板。
Ajax 模板
如果您想要向页面添加 AJAX 功能,例如在页面上直接更新而不是触发完整的页面重新加载的分页列表,您可以设置 ajax_template 属性来指定在通过 AJAX 调用请求页面时使用的替代模板(由 X-Requested-With: XMLHttpRequest HTTP 头指示):
class BlogPage(Page):...ajax_template = 'other_template_fragment.html'template = 'other_template.html'
对页面渲染的更多控制
所有页面类都有一个 serve() 方法,内部调用 get_context 和 get_template 方法,并呈现模板。这个方法类似于一个 Django 视图函数,接受一个 Django Request 对象,并返回一个 Django Response 对象。
这个方法也可以被覆盖,以完全控制页面的渲染。
例如,下面是使页面以其自身的 JSON 表示响应的一种方法:
from django.http import JsonResponseclass BlogPage(Page):...def serve(self, request):return JsonResponse({'title': self.title,'body': self.body,'date': self.date,# Resizes the image to 300px width and gets a URL to it'feed_image': self.feed_image.get_rendition('width-300').url,})
内联模型
Wagtail 允许在页面内嵌套其他模型。这对于创建重复字段,如相关链接或在轮播中显示的项目,非常有用。内联模型的内容也与页面的其余部分一起进行版本控制。
每个内联模型都需要以下内容:
必须继承自 wagtail.models.Orderable。
必须具有到父模型的 ParentalKey。
模型内联功能由 django-modelcluster 提供,ParentalKey 字段类型必须从该模块导入:
from modelcluster.fields import ParentalKey
ParentalKey 是 Django 的 ForeignKey 的子类,并接受相同的参数。
例如,以下内联模型可用于向 BlogPage 模型添加相关链接(名称、URL 对的列表):
from django.db import models
from modelcluster.fields import ParentalKey
from wagtail.models import Orderableclass BlogPageRelatedLink(Orderable):page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='related_links')name = models.CharField(max_length=255)url = models.URLField()panels = [FieldPanel('name'),FieldPanel('url'),]
要将这个添加到管理员界面中,请使用 InlinePanel 编辑面板类:
content_panels = [...InlinePanel('related_links', label="Related links"),
]
第一个参数必须与 ParentalKey 的 related_name 属性的值匹配。有关 InlinePanel 接受的参数的简要描述,请参阅 InlinePanel。
在多个页面类型之间重用内联模型
在上面的例子中,相关链接被定义为 BlogPage 页面类型上的子对象。通常,相同类型的内联子对象将出现在多个页面类型上,在这些情况下,重复整个模型定义是不可取的。可以通过将共同的字段重构为抽象模型来避免这种情况:
from django.db import models
from modelcluster.fields import ParentalKey
from wagtail.models import Orderable# The abstract model for related links, complete with panels
class RelatedLink(models.Model):name = models.CharField(max_length=255)url = models.URLField()panels = [FieldPanel('name'),FieldPanel('url'),]class Meta:abstract = True# The real model which extends the abstract model with a ParentalKey relation back to the page model.
# This can be repeated for each page type where the relation is to be added
# (for example, NewsPageRelatedLink, PublicationPageRelatedLink and so on).
class BlogPageRelatedLink(Orderable,RelatedLink):page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='related_links')
或者,如果 RelatedLink 将出现在您项目中定义的大量页面类型上,将一个单独的 RelatedLink 模型设置为指向基础的 wagtailcore.Page 模型可能更合适:
class RelatedLink(Orderable):page = ParentalKey("wagtailcore.Page", on_delete=models.CASCADE, related_name='related_links')name = models.CharField(max_length=255)url = models.URLField()panels = [FieldPanel('name'),FieldPanel('url'),]
然后,related_links 将作为跨所有页面类型的关联可用,尽管它仍然只能在包含了 InlinePanel 在其面板定义中的页面类型上进行编辑。对于其他页面类型,相关链接集将保持为空。
使用页面
Wagtail 使用 Django 的多表继承功能,允许在同一树中使用多个页面模型。
每个页面都被添加到 Wagtail 内置的 Page 模型和用户定义的模型(例如之前创建的 BlogPage 模型)。
页面可以以两种形式存在于 Python 代码中,即 Page 的实例或页面模型的实例。
在处理多个页面类型时,通常会使用 Wagtail 的 Page 模型的实例,这不会让你访问任何特定于其类型的字段。
# Get all pages in the database
>>> from wagtail.models import Page
>>> Page.objects.all()
[<Page: Homepage>, <Page: About us>, <Page: Blog>, <Page: A Blog post>, <Page: Another Blog post>]
在处理单个页面类型时,可以使用用户定义模型的实例。这样可以访问 Page 中的所有字段,以及该类型的任何用户定义字段。
# Get all blog entries in the database
>>> BlogPage.objects.all()
[<BlogPage: A Blog post>, <BlogPage: Another Blog post>]
可以使用 .specific 属性将 Page 对象转换为其更具体的用户定义等效项。这可能会导致额外的数据库查找。
>>> page = Page.objects.get(title="A Blog post")
>>> page
<Page: A Blog post># Note: the blog post is an instance of Page so we cannot access body, date or feed_image>>> page.specific
<BlogPage: A Blog post>
相关文章:
wagtail的数据模型和渲染
文章目录 前言页面数据模型数据库字段部分搜索部分编辑面板基础面板结构化面板父页面/子页面类型规则页面URLs自定义页面模型的URL模式获取页面实例的URL 模板渲染为页面模型添加模板模板上下文自定义模板上下文更改模板动态选择模板Ajax 模板 内联模型在多个页面类型之间重用内…...

OpenHarmony4.0适配LVDS屏幕驱动
1.概述 手头有一块RK3568的开发板OK3568-C,但是还没有适配OpenHarmony,用的还是LVDS屏幕,但是官方和网上好像还没有OpenHarmony4.0的LVDS屏幕驱动的通用实现,所以决定尝试了一下适配该开发板,完成LVDS屏幕驱动的适配&…...
【playwright】新一代自动化测试神器playwright+python系列课程01-playwright驱动浏览器
Playwright驱动浏览器 安装 Playwright 时,Playwright默认自动安装了三种浏览器(Chromium、Firefox 和 WebKit)。我们可以驱动这三种浏览器中的任意一种。 使用with上下文管理器 启动chromium浏览器 python # # author: 测试-老姜 交流…...

POSIX API与网络协议栈
本文介绍linux中与tcp网络通信相关的POSIX API,在每次调用的时候,网络协议栈会进行的操作与记录。 POSIX API Posix API,提供了统一的接口,使程序能得以在不同的系统上运行。简单来说不同的操作系统进行同一个活动,比…...

互联网加竞赛 基于卷积神经网络的乳腺癌分类 深度学习 医学图像
文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度,召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…...

腾讯云 IPv6 解决方案
产品矩阵全覆盖 腾讯云全线产品 All in IPv6;云服务器、私有网络、负载均衡、内容分发、域名解析、DDoS 高防等都已支持 IPv6。 全球 IPv6 基础设施 腾讯云在全球开放25个地理区域,运营53个可用区;目前已有多个地域提供 IPv6 接入能力。 …...

Appium 自动化测试
1.Appium介绍 1,appium是开源的移动端自动化测试框架; 2,appium可以测试原生的、混合的、以及移动端的web项目; 3,appium可以测试ios,android应用(当然了,还有firefoxos)…...

深入浅出Android dmabuf_dump工具
目录 dmabuf是什么? dmabuf_dump工具介绍(基于Android 14) Android.bp dmabuf_dump.cpp 整体架构结构如下 dmabuf_dump主要包含以下功能 前置背景知识 fdinfo 思考 bufinfo Dump整个手机系统的dmabuf Dump某个进程的dmabuf 以Table[buff…...

Guava RateLimiter预热模型
本文已收录至我的个人网站:程序员波特,主要记录Java相关技术系列教程,共享电子书、Java学习路线、视频教程、简历模板和面试题等学习资源,让想要学习的你,不再迷茫。 什么是流量预热 我们都知道在做运动之前先得来几组…...

【搭建个人知识库-3】
搭建个人知识库-3 1 大模型开发范式1.1 RAG原理1.2 LangChain框架1.3 构建向量数据库1.4 构建知识库助手1.5 Web Demo部署 2 动手实践2.1 环境配置2.2 知识库搭建2.2.1 数据收集2.2.2 加载数据2.2.3 构建向量数据库 2.3 InternLM接入LangChain2.4 构建检索问答链1 加载向量数据…...

如何看待 Linux 内核邮件列表重启将内核中的 C 代码转换为 C++
如何看待 Linux 内核邮件列表重启将内核中的 C 代码转换为 C 的讨论? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「Linux的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿…...
springboot网关添加swagger
添加依赖 <dependency><groupId>com.spring4all</groupId><artifactId>swagger-spring-boot-starter</artifactId><version>2.0.2</version></dependency>添加配置类,与服务启动类同一个层级 地址:http…...

代码随想录 Leetcode383. 赎金信
题目: 代码(首刷自解 2024年1月15日): class Solution { public:bool canConstruct(string ransomNote, string magazine) {vector<int> v(26);for(auto letter : magazine) {v[letter - a];}for(auto letter : ransomNote…...

上下左右视频转场模板PR项目工程文件 Vol. 05
pr转场模板,视频画面上下左右转场后带有一点点回弹效果的PR项目工程模板 Vol. 05 项目特点: 回弹效果视频转场; Premiere Pro 2020及以上; 适用于照片和视频转场; 适用于任何FPS和分辨率; 视频教程。 PR转场…...
【正点原子STM32连载】第三十三章 单通道ADC采集实验 摘自【正点原子】APM32E103最小系统板使用指南
1)实验平台:正点原子APM32E103最小系统板 2)平台购买地址:https://detail.tmall.com/item.htm?id609294757420 3)全套实验源码手册视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban 第三…...

Linux系统使用docker部署Geoserver(简单粗暴,复制即用)
1、拉取镜像 docker pull kartoza/geoserver:2.20.32、创建数据挂载目录 # 统一管理Docker容器的数据文件,geoserver mkdir -p /mydata/geoserver# 创建geoserver的挂载数据目录 mkdir -p /mydata/geoserver/data_dir# 创建geoserver的挂载数据目录,存放shp数据 m…...
libcurl使用默认编译的winssl进行https的双向认证
双向认证: 1.服务器回验证客户端上报的证书 2.客户端回验证服务器的证书 而证书一般分为:1.受信任的根证书,2不受信任的根证书。 但是由于各种限制不想在libcurl中增加openssl,那么使用默认的winssl也可以完成以上两种证书的双…...
MySQL运维实战(3.3) 管理数据库(database)
作者:俊达 引言 数据库的创建和管理是构建可靠数据的关键,关系到所存储数据的安全与稳定。在 MySQL 这个强大的关系型数据库系统中,数据库的创建与管理需要精准的步骤和妥善的配置。下面,将深入探讨如何使用MySQL 来管理数据库&…...

Web3去中心化存储:重新定义云服务
随着Web3技术的崭露头角,去中心化存储正在成为数字时代云服务的全新范式。传统的云服务依赖于中心化的数据存储架构,而Web3的去中心化存储则为用户带来了更安全、更隐私、更可靠的数据管理方式,重新定义了云服务的未来。 1.摒弃中心化的弊端 …...
纸尿裤行业调研:预计到2024年提高至68.1%
母婴大消费是指围绕孕产妇和0-14岁婴幼童人群,贯穿孕产妇孕产及产后护理周期、婴幼童成长周期的满足其衣、食、住、行、用、玩、教等需求的消费品的总和。 不同产品消费频次各异,纸尿裤是母婴大消费中的最为高频且刚需的易耗品。当前,消费升…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...

WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
RLHF vs RLVR:对齐学习中的两种强化方式详解
在语言模型对齐(alignment)中,强化学习(RL)是一种重要的策略。而其中两种典型形式——RLHF(Reinforcement Learning with Human Feedback) 与 RLVR(Reinforcement Learning with Ver…...