wagtail的使用

文章目录

  • 安装虚拟环境
    • 新建项目时指定虚拟环境
    • 打开已有项目添加虚拟环境
  • 安装wagtail
    • 查看安装后的包
  • 创建wagtail项目
    • 安装依赖
    • 迁移
    • 创建超级用户
    • 运行项目
  • 管理工作台
  • 内容
  • 扩展首页的数据模型
    • 更新数据库
    • 修改模板页
    • 创建一个页面的过程
  • models中的基本字段
    • templates
    • 字符型
    • 文本字段
    • 富文本字段
    • 图片字段
    • 图片添加cta
    • 文件字段
    • 引入bootstrap
    • 优化模板文档
  • 模板
    • 加载静态文件
    • 引用models元素
  • 常用web组件的实现
    • 带banner的首页
    • 页面主题
    • 轮播图
  • StreamField 字段
    • 使用StreamField
    • 模板呈现
    • 组合块
    • StructBlock
    • 子类化结构块
    • Block icons
    • ListBlock
    • StreamBlock
    • Per-block templates
  • card
  • StreamField实例
  • 一个blog应用
    • 一个简单的起始页
      • 配置修改
      • 管理页面操作
    • blog页
      • 配置修改
      • 父与子
    • 加入图片
      • 添加BlogPageGalleryImage 模型到 models.py
      • 管理页面添加图片
      • 展示
    • 缩略图样式
  • snippets
    • Snippet Models
    • Binding Pages to Snippets
  • 定制管理平台
    • Customising admin templates
  • 把wagtail集成到django项目
    • 安装插件
    • Settings配置
    • URL配置
  • 错误
  • wagtail的api
    • 基本配置
      • 使能app
      • 配置endpoints
      • 注册url
    • 访问api
    • 使字段能够访问
    • 按类型获取
    • 限制获取的字段
    • 限制获取数量
    • 偏移量
    • 排序
    • 获得子页面
    • 获取orderable数据
      • 只查询orderable的数据
    • 获取StreamField 中的image的url
    • 表单
  • Django数据模型的纳管
    • 配置
    • 使用
    • 更为复杂些的例子
  • 增加Django数据模型的用户档案
  • 通过接口添加用户档案
  • 通过接口认证获得token方法
    • 流程
    • 使用方法
    • 配置完成后的数据库迁移
    • 在根urls增加

安装虚拟环境

新建项目时指定虚拟环境

在这里插入图片描述

打开已有项目添加虚拟环境

添加虚拟环境
在这里插入图片描述

安装wagtail

(wagenv) C:\djproject\wagprj>pip list
Package    Version
---------- -------
pip        21.0.1
setuptools 54.2.0
wheel      0.36.2(wagenv) C:\djproject\wagprj>pip install wagtail
Collecting wagtailDownloading wagtail-2.12.3-py3-none-any.whl (11.2 MB)|████████████████████████████████| 11.2 MB 84 kB/s
Collecting l18n>=2018.5Downloading l18n-2020.6.1.tar.gz (50 kB)|████████████████████████████████| 50 kB 93 kB/s
Collecting django-modelcluster<6.0,>=5.1Downloading django_modelcluster-5.1-py2.py3-none-any.whl (26 kB)
Collecting Willow<1.5,>=1.4Downloading Willow-1.4-py2.py3-none-any.whl (106 kB)|████████████████████████████████| 106 kB 111 kB/s
Collecting djangorestframework<4.0,>=3.11.1Using cached djangorestframework-3.12.4-py3-none-any.whl (957 kB)
Collecting django-taggit<2.0,>=1.0Downloading django_taggit-1.3.0-py3-none-any.whl (45 kB)|████████████████████████████████| 45 kB 126 kB/s
Collecting xlsxwriter<2.0,>=1.2.8Downloading XlsxWriter-1.3.9-py2.py3-none-any.whl (145 kB)|████████████████████████████████| 145 kB 92 kB/s
Collecting anyascii>=0.1.5Downloading anyascii-0.2.0-py3-none-any.whl (283 kB)|████████████████████████████████| 283 kB 152 kB/s
Collecting beautifulsoup4<4.9,>=4.8Downloading beautifulsoup4-4.8.2-py3-none-any.whl (106 kB)|████████████████████████████████| 106 kB 139 kB/s
Collecting draftjs-exporter<3.0,>=2.1.5Downloading draftjs_exporter-2.1.7-py3-none-any.whl (43 kB)|████████████████████████████████| 43 kB 131 kB/s
Collecting html5lib<2,>=0.999Using cached html5lib-1.1-py2.py3-none-any.whl (112 kB)
Collecting requests<3.0,>=2.11.1Using cached requests-2.25.1-py2.py3-none-any.whl (61 kB)
Collecting Django<3.2,>=2.2Using cached Django-3.1.8-py3-none-any.whl (7.8 MB)
Collecting tablib[xls,xlsx]>=0.14.0Downloading tablib-3.0.0-py3-none-any.whl (47 kB)|████████████████████████████████| 47 kB 156 kB/s
Collecting Pillow<9.0.0,>=4.0.0Using cached Pillow-8.2.0-cp38-cp38-win_amd64.whl (2.2 MB)
Collecting django-filter<3.0,>=2.2Downloading django_filter-2.4.0-py3-none-any.whl (73 kB)|████████████████████████████████| 73 kB 130 kB/s
Collecting django-treebeard!=4.5,<5.0,>=4.2.0Using cached django_treebeard-4.5.1-py3-none-any.whl (103 kB)
Collecting soupsieve>=1.2Downloading soupsieve-2.2.1-py3-none-any.whl (33 kB)
Collecting pytzUsing cached pytz-2021.1-py2.py3-none-any.whl (510 kB)
Collecting asgiref<4,>=3.2.10Using cached asgiref-3.3.4-py3-none-any.whl (22 kB)
Collecting sqlparse>=0.2.2Using cached sqlparse-0.4.1-py3-none-any.whl (42 kB)
Collecting six>=1.9Using cached six-1.15.0-py2.py3-none-any.whl (10 kB)
Collecting webencodingsUsing cached webencodings-0.5.1-py2.py3-none-any.whl (11 kB)
Collecting urllib3<1.27,>=1.21.1Using cached urllib3-1.26.4-py2.py3-none-any.whl (153 kB)
Collecting idna<3,>=2.5Downloading idna-2.10-py2.py3-none-any.whl (58 kB)|████████████████████████████████| 58 kB 155 kB/s
Collecting certifi>=2017.4.17Downloading certifi-2020.12.5-py2.py3-none-any.whl (147 kB)|████████████████████████████████| 147 kB 148 kB/s
Collecting chardet<5,>=3.0.2Downloading chardet-4.0.0-py2.py3-none-any.whl (178 kB)|████████████████████████████████| 178 kB 198 kB/s
Collecting openpyxl>=2.6.0Downloading openpyxl-3.0.7-py2.py3-none-any.whl (243 kB)|████████████████████████████████| 243 kB 242 kB/s
Collecting xlrdDownloading xlrd-2.0.1-py2.py3-none-any.whl (96 kB)|████████████████████████████████| 96 kB 293 kB/s
Collecting xlwtDownloading xlwt-1.3.0-py2.py3-none-any.whl (99 kB)|████████████████████████████████| 99 kB 293 kB/s
Collecting et-xmlfileDownloading et_xmlfile-1.0.1.tar.gz (8.4 kB)
Building wheels for collected packages: l18n, et-xmlfileBuilding wheel for l18n (setup.py) ... doneCreated wheel for l18n: filename=l18n-2020.6.1-py3-none-any.whl size=51577 sha256=4672c5c34b8cdb840a4b10982cc7e669169e4741e0624878a24e92e89380f421Stored in directory: c:\users\administrator\appdata\local\pip\cache\wheels\ea\5f\6f\2e7864d49b0f7badda5c1402b11254b62a3eadb949e3fc2ab9Building wheel for et-xmlfile (setup.py) ... doneCreated wheel for et-xmlfile: filename=et_xmlfile-1.0.1-py3-none-any.whl size=8913 sha256=65ee864758d0c127daa8ea81099d063653500e1d576fe59126c6aff5f260a29bStored in directory: c:\users\administrator\appdata\local\pip\cache\wheels\6e\df\38\abda47b884e3e25f9f9b6430e5ce44c47670758a50c0c51759
Successfully built l18n et-xmlfile
Installing collected packages: sqlparse, pytz, et-xmlfile, asgiref, xlwt, xlrd, webencodings, urllib3, tablib, soupsieve, six, openpyxl, idna, Django, chardet, certifi, xlsxwriter, Willow, requests, Pillow, l18n, html5lib, draftjs-exporter, djangorestframework, django-treebeard, django-taggit, django-modelcluster, django-filter, beautifulsoup4, anyascii, wagtail
Successfully installed Django-3.1.8 Pillow-8.2.0 Willow-1.4 anyascii-0.2.0 asgiref-3.3.4 beautifulsoup4-4.8.2 certifi-2020.12.5 chardet-4.0.0 django-filter-2.4.0 django-modelcluster-5.1 django-taggit-1.3.0 django-treebeard-4.5.1 djangorestframework-3.12.4 draftjs-exporter-2.1.7 et-xmlfile-1.0.1 html5lib-1.1 idna-2.10 l18n-2020.6.1 openpyxl-3.0.7 pytz-2021.1 requests-2.25.1 six-1.15.0 soupsieve-2.2.1 sqlparse-0.4.1 tablib-3.0.0 urllib3-1.26.4 wagtail-2.12.3 webencodings-0.5.1 xlrd-2.0.1 xlsxwriter-1.3.9 xlwt-1.3.0

查看安装后的包


(wagenv) C:\djproject\wagprj>pip list
Package             Version
------------------- ---------
anyascii            0.2.0
asgiref             3.3.4
beautifulsoup4      4.8.2
certifi             2020.12.5
chardet             4.0.0
Django              3.1.8
django-filter       2.4.0
django-modelcluster 5.1
django-taggit       1.3.0
django-treebeard    4.5.1
djangorestframework 3.12.4
draftjs-exporter    2.1.7
et-xmlfile          1.0.1
html5lib            1.1
idna                2.10
l18n                2020.6.1
openpyxl            3.0.7
Pillow              8.2.0
pip                 21.0.1
pytz                2021.1
requests            2.25.1
setuptools          54.2.0
six                 1.15.0
soupsieve           2.2.1
sqlparse            0.4.1
tablib              3.0.0
urllib3             1.26.4
wagtail             2.12.3
webencodings        0.5.1
wheel               0.36.2
Willow              1.4
xlrd                2.0.1
XlsxWriter          1.3.9
xlwt                1.3.0

创建wagtail项目

wagtail start mysite

安装依赖

pip install -r requirements.txt

迁移

(wagenv) C:\djproject\wagprj\mysite>python manage.py migrate
Operations to perform:Apply all migrations: admin, auth, contenttypes, home, sessions, taggit, wagtailadmin, wagtailcore, wagtaildocs, wagtailembeds, wagtailforms, wagtailimages, wagtailredirects, wagtailsearch, wagtailusers
Running migrations:Applying contenttypes.0001_initial... OKApplying auth.0001_initial... OKApplying admin.0001_initial... OKApplying admin.0002_logentry_remove_auto_add... OKApplying admin.0003_logentry_add_action_flag_choices... OKApplying contenttypes.0002_remove_content_type_name... OKApplying auth.0002_alter_permission_name_max_length... OKApplying auth.0003_alter_user_email_max_length... OKApplying auth.0004_alter_user_username_opts... OKApplying auth.0005_alter_user_last_login_null... OKApplying auth.0006_require_contenttypes_0002... OKApplying auth.0007_alter_validators_add_error_messages... OKApplying auth.0008_alter_user_username_max_length... OKApplying auth.0009_alter_user_last_name_max_length... OKApplying auth.0010_alter_group_name_max_length... OKApplying auth.0011_update_proxy_permissions... OKApplying auth.0012_alter_user_first_name_max_length... OKApplying wagtailcore.0001_squashed_0016_change_page_url_path_to_text_field... OKApplying wagtailcore.0017_change_edit_page_permission_description... OKApplying wagtailcore.0018_pagerevision_submitted_for_moderation_index... OKApplying wagtailcore.0019_verbose_names_cleanup... OKApplying wagtailcore.0020_add_index_on_page_first_published_at... OKApplying wagtailcore.0021_capitalizeverbose... OKApplying wagtailcore.0022_add_site_name... OKApplying wagtailcore.0023_alter_page_revision_on_delete_behaviour... OKApplying wagtailcore.0024_collection... OKApplying wagtailcore.0025_collection_initial_data... OKApplying wagtailcore.0026_group_collection_permission... OKApplying wagtailcore.0027_fix_collection_path_collation... OKApplying wagtailcore.0024_alter_page_content_type_on_delete_behaviour... OKApplying wagtailcore.0028_merge... OKApplying wagtailcore.0029_unicode_slugfield_dj19... OKApplying wagtailcore.0030_index_on_pagerevision_created_at... OKApplying wagtailcore.0031_add_page_view_restriction_types... OKApplying wagtailcore.0032_add_bulk_delete_page_permission... OKApplying wagtailcore.0033_remove_golive_expiry_help_text... OKApplying wagtailcore.0034_page_live_revision... OKApplying wagtailcore.0035_page_last_published_at... OKApplying wagtailcore.0036_populate_page_last_published_at... OKApplying wagtailcore.0037_set_page_owner_editable... OKApplying wagtailcore.0038_make_first_published_at_editable... OKApplying wagtailcore.0039_collectionviewrestriction... OKApplying wagtailcore.0040_page_draft_title... OKApplying home.0001_initial... OKApplying home.0002_create_homepage... OKApplying sessions.0001_initial... OKApplying taggit.0001_initial... OKApplying taggit.0002_auto_20150616_2121... OKApplying taggit.0003_taggeditem_add_unique_index... OKApplying wagtailadmin.0001_create_admin_access_permissions... OKApplying wagtailadmin.0002_admin... OKApplying wagtailadmin.0003_admin_managed... OKApplying wagtailcore.0041_group_collection_permissions_verbose_name_plural... OKApplying wagtailcore.0042_index_on_pagerevision_approved_go_live_at... OKApplying wagtailcore.0043_lock_fields... OKApplying wagtailcore.0044_add_unlock_grouppagepermission... OKApplying wagtailcore.0045_assign_unlock_grouppagepermission... OKApplying wagtailcore.0046_site_name_remove_null... OKApplying wagtailcore.0047_add_workflow_models... OKApplying wagtailcore.0048_add_default_workflows... OKApplying wagtailcore.0049_taskstate_finished_by... OKApplying wagtailcore.0050_workflow_rejected_to_needs_changes... OKApplying wagtailcore.0051_taskstate_comment... OKApplying wagtailcore.0052_pagelogentry... OKApplying wagtailcore.0053_locale_model... OKApplying wagtailcore.0054_initial_locale... OKApplying wagtailcore.0055_page_locale_fields... OKApplying wagtailcore.0056_page_locale_fields_populate... OKApplying wagtailcore.0057_page_locale_fields_notnull... OKApplying wagtailcore.0058_page_alias_of... OKApplying wagtailcore.0059_apply_collection_ordering... OKApplying wagtailcore.0060_fix_workflow_unique_constraint... OKApplying wagtaildocs.0001_initial... OKApplying wagtaildocs.0002_initial_data... OKApplying wagtaildocs.0003_add_verbose_names... OKApplying wagtaildocs.0004_capitalizeverbose... OKApplying wagtaildocs.0005_document_collection... OKApplying wagtaildocs.0006_copy_document_permissions_to_collections... OKApplying wagtaildocs.0005_alter_uploaded_by_user_on_delete_action... OKApplying wagtaildocs.0007_merge... OKApplying wagtaildocs.0008_document_file_size... OKApplying wagtaildocs.0009_document_verbose_name_plural... OKApplying wagtaildocs.0010_document_file_hash... OKApplying wagtaildocs.0011_add_choose_permissions... OKApplying wagtaildocs.0012_uploadeddocument... OKApplying wagtailembeds.0001_initial... OKApplying wagtailembeds.0002_add_verbose_names... OKApplying wagtailembeds.0003_capitalizeverbose... OKApplying wagtailembeds.0004_embed_verbose_name_plural... OKApplying wagtailembeds.0005_specify_thumbnail_url_max_length... OKApplying wagtailembeds.0006_add_embed_hash... OKApplying wagtailembeds.0007_populate_hash... OKApplying wagtailembeds.0008_allow_long_urls... OKApplying wagtailforms.0001_initial... OKApplying wagtailforms.0002_add_verbose_names... OKApplying wagtailforms.0003_capitalizeverbose... OKApplying wagtailforms.0004_add_verbose_name_plural... OKApplying wagtailimages.0001_squashed_0021... OKApplying wagtailimages.0022_uploadedimage... OKApplying wagtailimages.0023_add_choose_permissions... OKApplying wagtailredirects.0001_initial... OKApplying wagtailredirects.0002_add_verbose_names... OKApplying wagtailredirects.0003_make_site_field_editable... OKApplying wagtailredirects.0004_set_unique_on_path_and_site... OKApplying wagtailredirects.0005_capitalizeverbose... OKApplying wagtailredirects.0006_redirect_increase_max_length... OKApplying wagtailsearch.0001_initial... OKApplying wagtailsearch.0002_add_verbose_names... OKApplying wagtailsearch.0003_remove_editors_pick... OKApplying wagtailsearch.0004_querydailyhits_verbose_name_plural... OKApplying wagtailusers.0001_initial... OKApplying wagtailusers.0002_add_verbose_name_on_userprofile... OKApplying wagtailusers.0003_add_verbose_names... OKApplying wagtailusers.0004_capitalizeverbose... OKApplying wagtailusers.0005_make_related_name_wagtail_specific... OKApplying wagtailusers.0006_userprofile_prefered_language... OKApplying wagtailusers.0007_userprofile_current_time_zone... OKApplying wagtailusers.0008_userprofile_avatar... OKApplying wagtailusers.0009_userprofile_verbose_name_plural... OK

创建超级用户

(wagenv) C:\djproject\wagprj\mysite>python manage.py createsuperuser
Username (leave blank to use 'administrator'): admin
Email address: admin@sina.com
Password:123
Password (again):
Superuser created successfully.

运行项目

python manage.py runserver

在这里插入图片描述

管理工作台

内容

扩展首页的数据模型

编辑 home/models.py 添加一个 body 字段到数据模型:

from django.db import modelsfrom wagtail.core.models import Page
from wagtail.core.fields import RichTextField
from wagtail.admin.edit_handlers import FieldPanelclass HomePage(Page):body = RichTextField(blank=True)content_panels = Page.content_panels + [FieldPanel('body', classname="full"),]

更新数据库

每次修改完models都要运行以下命令更新数据库。

python manage.py makemigrations
python manage.py migrate 

pages-》home-》编辑,多了一个body

在这里插入图片描述

修改模板页

home/templates/home/home_page.html
{% extends "base.html" %}{% load wagtailcore_tags %}{% block body_class %}template-homepage{% endblock %}{% block content %}{{ page.body|richtext }}
{% endblock %}

运行项目,首页展示为

在这里插入图片描述

创建一个页面的过程

要访问models中HomePage类,需要在home/templates/home/中创建一个home_page.html的对应模板来渲染这个类。这个命名是wagtail规定。
其中的

{% extends "base.html" %}

表示扩展基础模板

{% include 'home/welcome_page.html' %}

包含欢迎页面
删除此页面后,首页就空白了。

在models中添加另外一个类Article,表示另外一个页面。
在这里插入图片描述
做下数据库迁移
选择页面根
在这里插入图片描述
添加子页面
在这里插入图片描述
出现Article类代表的页面类型。可以以这种类型来创建页面。
在这里插入图片描述
Each Wagtail page type is a Django model, represented in the database as a separate table.
说明每个Wagtail的页面类型就是Django的数据模型,在数据库中代表一个表。

以这个类型创建一个article1的页
在这里插入图片描述
发布一下
在这里插入图片描述
创建一个站点

在这里插入图片描述
在这里插入图片描述
但是还不能浏览,没有模板文件。
在这里插入图片描述
创建一个模板文件,位置一定在models对应的文件夹中的templates/home/下,名字必须和类名相同,小写。
在这里插入图片描述
重新浏览
在这里插入图片描述

models中的基本字段

templates

template = 'home/home_page.html'

指定模板文件的位置,如果不指定,则模板文件位于本app的models同级templates文件夹下的app文件名下的与class同名的html中
在这里插入图片描述

字符型

页面中展示的内容都是models中类的一个字段,在homepage添加一个subtile字段
在这里插入图片描述
并把它展示在页面中,如下,使用content_panels 和 FieldPanel关键字
在这里插入图片描述

迁移下数据
打开首页编辑
在这里插入图片描述

目前首页是没有内容的,因为对应的渲染模板页面还没有处理。
在模板中,所有的变量被封存到了page对象中。
在这里插入图片描述
{{ }}用来显示变量。

在这里插入图片描述

文本字段

在models中增加一个问本字段
在这里插入图片描述
数据迁移下
刷新管理页面
多了一个content1字段
在这里插入图片描述
添加内容
在这里插入图片描述
模板页
在这里插入图片描述

在这里插入图片描述

富文本字段

添加一个富文本字段
在这里插入图片描述
迁移数据

在这里插入图片描述
发布出去
在这里插入图片描述
模板增加标签加载和富文本的过滤器
在这里插入图片描述
刷新页面

在这里插入图片描述

图片字段

图片的处理
在这里插入图片描述
迁移数据,刷新管理页面
在这里插入图片描述

渲染模板增加标签加载和指定图片加载尺寸
在这里插入图片描述
在这里插入图片描述

图片添加cta

文件字段

文件处理
在这里插入图片描述

迁移数据刷新管理页面
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

引入bootstrap

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

优化模板文档

公共部分都移入到base.html中
mysite\templates\base.html

{% load static wagtailuserbar %}<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><!-- CSS --><link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css" rel="stylesheet"><!-- jQuery and JavaScript Bundle with Popper --><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.slim.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.min.js"></script>
</head>
<body><nav class="navbar navbar-expand-lg navbar-light bg-light"><a class="navbar-brand" href="#">Navbar</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarSupportedContent"><ul class="navbar-nav mr-auto"><li class="nav-item active"><a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a></li><li class="nav-item"><a class="nav-link" href="#">Link</a></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"aria-haspopup="true" aria-expanded="false">Dropdown</a><div class="dropdown-menu" aria-labelledby="navbarDropdown"><a class="dropdown-item" href="#">Action</a><a class="dropdown-item" href="#">Another action</a><div class="dropdown-divider"></div><a class="dropdown-item" href="#">Something else here</a></div></li><li class="nav-item"><a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a></li></ul><form class="form-inline my-2 my-lg-0"><input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"><button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button></form></div>
</nav>{% block content %}
{% endblock %}
</body>
</html>

定义一个内容块

{% block content %}
{% endblock %}

其他页面非共同内容包含其中,通过上面的定义的块,代入base.html中,如下所示。

home\templates\home\home_page.html

{% extends "base.html" %}{% block content %}{% load wagtailcore_tags %}{% load wagtailimages_tags %}<div><div class="alert alert-primary" role="alert">{{ page.subtitle }}</div><p>{{ page.content1 }}</p><p>{{ page.content2 | richtext }}</p>{% image page.image fill-600x200 %}<a href="{{ page.file.url }}">{{ page.file }}</a></div>
{% endblock %}

模板

加载静态文件

图片
在这里插入图片描述
css
在这里插入图片描述

引用models元素

cta引用需要加上url,才能完整引用路径,否则引用较深目录层次会找不到
在这里插入图片描述

常用web组件的实现

带banner的首页

在这里插入图片描述
在base.html中引入公共部分的导航条,

{% load static wagtailuserbar %}<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><!-- CSS --><link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css" rel="stylesheet"><!-- jQuery and JavaScript Bundle with Popper --><script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.slim.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.min.js"></script>
</head>
<body><nav class="navbar navbar-expand-lg navbar-light bg-light"><a class="navbar-brand" href="#">Navbar</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarSupportedContent"><ul class="navbar-nav mr-auto"><li class="nav-item active"><a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a></li><li class="nav-item"><a class="nav-link" href="#">Link</a></li><li class="nav-item dropdown"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown"aria-haspopup="true" aria-expanded="false">Dropdown</a><div class="dropdown-menu" aria-labelledby="navbarDropdown"><a class="dropdown-item" href="#">Action</a><a class="dropdown-item" href="#">Another action</a><div class="dropdown-divider"></div><a class="dropdown-item" href="#">Something else here</a></div></li><li class="nav-item"><a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a></li></ul><form class="form-inline my-2 my-lg-0"><input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"><button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button></form></div>
</nav>{% block content %}
{% endblock %}
</body>
</html>

在home的模板页引入banner图片和图片跳转cta

{# templates/home/home_page.html #}
{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}{% block content %}{% image self.banner_image fill-900x300 as img %}<div class="jumbotron" style="background-image: url('{{ img.url }}'); background-size: cover "><h1 class="display-4" style="color: #e6e6e6">{{ self.banner_title }}</h1><div class="lead" style="color: #e6e6e6">{{ page.banner_subtitle|richtext }}</div><a class="btn btn-primary btn-lg" href="{{ self.banner_cta }}" role="button">详情</a></div>
{% endblock %}

在home的models中定义数据模型

# home/models.py
from django.db import modelsfrom wagtail.core.models import Page, Orderable
from wagtail.core.fields import RichTextField
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, PageChooserPanel
from wagtail.images.edit_handlers import ImageChooserPanelclass HomePage(Page):'''HomePage models '''template = 'home/home_page.html'banner_title = models.CharField(max_length=100, blank=True, null=True)# max_count = 1banner_subtitle = RichTextField(features=['bold', 'italic'], blank=True, null=True)banner_image = models.ForeignKey('wagtailimages.Image',blank=True,null=True,on_delete=models.DO_NOTHING,related_name="+")banner_cta = models.ForeignKey('wagtailcore.Page',blank=True,null=True,on_delete=models.DO_NOTHING,related_name="+")content_panels = Page.content_panels + [FieldPanel('banner_title'),FieldPanel('banner_subtitle'),ImageChooserPanel('banner_image'),PageChooserPanel('banner_cta'),]class Meta:verbose_name = '首页这里'verbose_name_plural = '首页plural'

页面主题

https://bootswatch.com/

轮播图

https://v4.bootcss.com/docs/getting-started/introduction/

StreamField 字段

StreamField字段可实现多媒体的展示
StreamField提供了一种内容编辑模型,适用于不遵循固定结构的页面(如博客文章或新闻故事),其中文本可能会穿插副标题、图像、引述和视频。它也适用于更专业的内容类型,如地图和图表(或者,对于编程博客,代码片段)。在这个模型中,这些不同的内容类型被表示为一系列的“块”,这些块可以以任何顺序重复和排列。
StreamField还提供了一个丰富的API来定义您自己的块类型,范围从简单的子块集合(例如由名字、姓氏和照片组成的“person”块)到完全自定义的具有自己编辑界面的组件。在数据库中,StreamField内容存储为JSON,确保字段的完整信息内容得到保留,而不仅仅是它的HTML表示。
下面展示如何使用StremField

使用StreamField

StreamField是一个模型字段,可以像任何其他字段一样在页面模型中定义:

from django.db import modelsfrom wagtail.core.models import Page
from wagtail.core.fields import StreamField
from wagtail.core import blocks
from wagtail.admin.edit_handlers import FieldPanel, StreamFieldPanel
from wagtail.images.blocks import ImageChooserBlockclass BlogPage(Page):author = models.CharField(max_length=255)date = models.DateField("Post date")body = StreamField([                              ('heading', blocks.CharBlock(form_classname="full title")),    //标题('paragraph', blocks.RichTextBlock()),     //段落('image', ImageChooserBlock()),             //图像])content_panels = Page.content_panels + [FieldPanel('author'),FieldPanel('date'),StreamFieldPanel('body'),]

在本例中,BlogPage的body字段被定义为StreamField,在StreamField中,作者可以使用三种不同的块类型组成内容:标题、段落和图像,这些块可以按任何顺序使用和重复。可供作者使用的块类型定义为(name, block_type)元组列表:“name”用于标识模板中的块类型,并且应遵循变量名称的标准Python约定:小写和下划线,无空格。

您可以在StreamField块参照中找到可用块类型的完整列表。

模板呈现

StreamField像展示单个块一样,把stream 的内容作为整一个整体展示为HTML。要将此HTML包含到你的页面中,请使用{% include_block %}标记:

{% load wagtailcore_tags %}...{% include_block page.body %}

实际中使用
mysite\templates\flex\flex_page.html

{% extends "base.html" %}
{% load wagtailcore_tags wagtailimages_tags %}{% block content %}<div>{{ self.subtitle }}</div>{% for block in page.content %}{% include_block block %}{% endfor %}{% endblock %}

content来自这里
flex\models.py

from django.db import models
from django.db import models
from modelcluster.fields import ParentalKey
from wagtail.core import blocks
from streams import myblocksfrom wagtail.core.models import Page, Orderable
from wagtail.core.fields import RichTextField, StreamField
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, PageChooserPanel, StreamFieldPanel
from wagtail.images.edit_handlers import ImageChooserPanelclass FlexPage(Page):template = 'flex/flex_page.html'subtitle = models.CharField(max_length=100, blank=True, null=True)content = StreamField([('title_and_text', myblocks.TitleAndTextBlock()),],blank=True,null=True,)content_panels = Page.content_panels + [FieldPanel('subtitle'),StreamFieldPanel('content'),]class Meta:verbose_name = 'Flex Page'verbose_name_plural = 'Flex Pages'

为了更好地控制特定块类型的渲染,每个块对象都提供块类型和值特性:

{% load wagtailcore_tags %}...<article>{% for block in page.body %}{% if block.block_type == 'heading' %}<h1>{{ block.value }}</h1>{% else %}<section class="block-{{ block.block_type }}">{% include_block block %}</section>{% endif %}{% endfor %}
</article>

组合块

除了直接在StreamField中使用内置块类型外,还可以通过各种方式组合子块来构造新的块类型。这方面的例子包括:

  • 由图像选择器和文本字段组成的“带标题的图像”块
  • 一个“相关链接”部分,作者可以提供任何数量的链接到其他网页
  • 一种幻灯片放映块,其中每张幻灯片可以是图像、文本或视频,按任何顺序排列

一旦以这种方式构建了新的块类型,就可以在任何使用内置块类型的地方使用它—包括将它用作另一个块类型的组件。例如,您可以定义一个图像库块,其中每个项目都是一个“带标题的图像”块。

StructBlock

StructBlock允许您将多个“子”块组合在一起,以显示为单个块。子块作为(名称,块类型)元组列表传递给StructBlock:

 body = StreamField([('person', blocks.StructBlock([('first_name', blocks.CharBlock()),('surname', blocks.CharBlock()),('photo', ImageChooserBlock(required=False)),('biography', blocks.RichTextBlock()),])),('heading', blocks.CharBlock(form_classname="full title")),('paragraph', blocks.RichTextBlock()),('image', ImageChooserBlock()),])

其中person对应了一个StructBlock

在读回StreamField的内容时(例如在呈现模板时),StructBlock的值是一个类似dict的对象,其键与定义中给出的块名相对应:

<article>{% for block in page.body %}{% if block.block_type == 'person' %}<div class="person">{% image block.value.photo width-400 %}<h2>{{ block.value.first_name }} {{ block.value.surname }}</h2>{{ block.value.biography }}</div>{% else %}(rendering for other block types){% endif %}{% endfor %}
</article>

子类化结构块

在StreamField定义中放置StructBlock的子块列表通常很难读懂,并且使得同一块很难在多个位置重用。因此,StructBlock可以子类化,子块定义为子类上的属性。上例中的“person”块可以重写为:

class PersonBlock(blocks.StructBlock):first_name = blocks.CharBlock()surname = blocks.CharBlock()photo = ImageChooserBlock(required=False)biography = blocks.RichTextBlock()

PersonBlock可以在StreamField定义中使用,使用方式与内置块类型相同:

body = StreamField([('person', PersonBlock()),('heading', blocks.CharBlock(form_classname="full title")),('paragraph', blocks.RichTextBlock()),('image', ImageChooserBlock()),
])

Block icons

在内容作者用于向StreamField添加新块的菜单中,每个块类型都有一个关联的图标。对于StructBlock和其他结构块类型,将使用占位符图标,因为这些块的用途特定于您的项目。要设置自定义图标,请将选项图标作为关键字参数传递给StructBlock,或作为元类的属性传递:

 body = StreamField([('person', blocks.StructBlock([('first_name', blocks.CharBlock()),('surname', blocks.CharBlock()),('photo', ImageChooserBlock(required=False)),('biography', blocks.RichTextBlock()),], icon='user')),('heading', blocks.CharBlock(form_classname="full title")),('paragraph', blocks.RichTextBlock()),('image', ImageChooserBlock()),])

其中的icon=‘user’

 class PersonBlock(blocks.StructBlock):first_name = blocks.CharBlock()surname = blocks.CharBlock()photo = ImageChooserBlock(required=False)biography = blocks.RichTextBlock()class Meta:icon = 'user'

ListBlock

ListBlock定义了一个重复块,允许内容作者插入任意多个特定块类型的实例。例如,由多个图像组成的“多媒体资料”块可以定义如下:

 body = StreamField([('gallery', blocks.ListBlock(ImageChooserBlock())),('heading', blocks.CharBlock(form_classname="full title")),('paragraph', blocks.RichTextBlock()),('image', ImageChooserBlock()),])

在读回StreamField的内容时(例如在呈现模板时),ListBlock的值是子值的列表:

<article>{% for block in page.body %}{% if block.block_type == 'gallery' %}<ul class="gallery">{% for img in block.value %}<li>{% image img width-400 %}</li>{% endfor %}</ul>{% else %}(rendering for other block types){% endif %}{% endfor %}
</article>

StreamBlock

StreamBlock定义了一组子块类型,这些子块类型可以通过与StreamField本身相同的机制以任何顺序混合和重复。例如,支持图像和视频幻灯片的轮播图可以定义如下:

 body = StreamField([('carousel', blocks.StreamBlock(['image': ImageChooserBlock(),'video': EmbedBlock(),])),('heading', blocks.CharBlock(form_classname="full title")),('paragraph', blocks.RichTextBlock()),('image', ImageChooserBlock()),])

StreamBlock也可以与StructBlock相同的方式子类化,子块被指定为类上的属性:

class PersonBlock(blocks.StreamBlock):image = ImageChooserBlock()video = EmbedBlock()class Meta:icon = 'image'

以这种方式定义的StreamBlock子类也可以传递给StreamField定义,而不是传递块类型列表。这允许设置一组公共块类型,以便在多个页面类型上使用:

class CommonContentBlock(blocks.StreamBlock):heading = blocks.CharBlock(form_classname="full title")paragraph = blocks.RichTextBlock()image = ImageChooserBlock()class BlogPage(Page):body = StreamField(CommonContentBlock())

当读回StreamField的内容时,StreamBlock的值是具有block类型和值属性的块对象序列,就像StreamField本身的顶级值一样。

<article>{% for block in page.body %}{% if block.block_type == 'carousel' %}<ul class="carousel">{% for slide in block.value %}{% if slide.block_type == 'image' %}<li class="image">{% image slide.value width-200 %}</li>{% else %}<li> class="video">{% include_block slide %}</li>{% endif %}{% endfor %}</ul>{% else %}(rendering for other block types){% endif %}{% endfor %}
</article>

Per-block templates

默认情况下,每个块都使用简单、最小的HTML标记呈现,或者根本不使用任何标记。例如,CharBlock值呈现为纯文本,而ListBlock在

  • 包装器中输出其子块。要使用自己的自定义HTML呈现覆盖此选项,可以将模板参数传递给块,给出要呈现的模板文件的文件名。这对于从StructBlock派生的自定义块类型特别有用:

('person', blocks.StructBlock([('first_name', blocks.CharBlock()),('surname', blocks.CharBlock()),('photo', ImageChooserBlock(required=False)),('biography', blocks.RichTextBlock()),],template='myapp/blocks/person.html',icon='user'
))

Or, when defined as a subclass of StructBlock:
或者,当定义为结构块的子类时

class PersonBlock(blocks.StructBlock):first_name = blocks.CharBlock()surname = blocks.CharBlock()photo = ImageChooserBlock(required=False)biography = blocks.RichTextBlock()class Meta:template = 'myapp/blocks/person.html'icon = 'user'

在模板中,可以将块值作为变量值进行访问:

{% load wagtailimages_tags %}<div class="person">{% image value.photo width-400 %}<h2>{{ value.first_name }} {{ value.surname }}</h2>{{ value.biography }}
</div>

{% load wagtailcore_tags wagtailimages_tags %}<div class="person">{% image value.photo width-400 %}<h2>{% include_block value.first_name %} {% include_block value.surname %}</h2>{% include_block value.biography %}
</div>

Like Django’s {% include %} tag, {% include_block %} also allows passing additional variables to the included template, through the syntax {% include_block my_block with foo=“bar” %}:
As well as passing variables from the parent template, block subclasses can pass additional template variables of their own by overriding the get_context method:

card

有时,您需要一个可以有多个重复内容区域的StreamField。一个很好的例子是被称为卡片的设计组件。在这里,我们将探讨一个ListBlock,使我们能够使用自定义数据、ImageChooserBlock、PageChooserBlock以及如何在Wagtail CMS模板中循环使用ListBlock创建无限的卡片。
myblocks.py增加以下内容

class Cardblock(blocks.StructBlock):title = blocks.CharBlock(required=True,help_text='add your title here')# text = blocks.TextBlock(required=True,help_text='add your text here')cards = blocks.ListBlock(blocks.StructBlock([('image',ImageChooserBlock(required=True)),('title',blocks.CharBlock(required=True, max_length=40)),('text',blocks.TextBlock(required=True,max_length=200)),('button_page',blocks.PageChooserBlock(required=False)),('button_url',blocks.URLBlock(required=False)),]))

flex/models.py增加以下内容

class FlexPage(Page):template = 'flex/flex_page.html'subtitle = models.CharField(max_length=100, blank=True, null=True)content = StreamField([('title_and_text', myblocks.TitleAndTextBlock()),('full_richtext', myblocks.RichTextBlock()),('cards',myblocks.Cardblock()),    ## add is here],blank=True,null=True,)content_panels = Page.content_panels + [FieldPanel('subtitle'),StreamFieldPanel('content'),]class Meta:verbose_name = 'Flex Page'verbose_name_plural = 'Flex Pages'

Streams/myblocks.py

class CardBlock(blocks.StructBlock):"""Cards with image and text and button(s)."""title = blocks.CharBlock(required=True, help_text="Add your title")cards = blocks.ListBlock(blocks.StructBlock([("image", ImageChooserBlock(required=True)),("title", blocks.CharBlock(required=True, max_length=40)),("text", blocks.TextBlock(required=True, max_length=200)),("button_page", blocks.PageChooserBlock(required=False)),("button_url",blocks.URLBlock(required=False,help_text="If the button page above is selected, that will be used first.",  # noqa),),]))class Meta:  # noqatemplate = "streams/cards_block.html"icon = "placeholder"label = "Staff Cards"

刷新管理页面已增加card
在这里插入图片描述

StreamField实例

首先创建一个新的app

(env) C:\djproject\wagprj\mysite>django-admin startapp article

注册到配置文件base.py
在这里插入图片描述
article\models.py

from wagtail.core.models import Page, Orderable
from django.db import models
from wagtail.images.blocks import ImageChooserBlock
from wagtail.core import blocksfrom wagtail.core.models import Page
from wagtail.core.fields import RichTextField, StreamField
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, StreamFieldPanelclass Article(Page):intro = models.TextField(blank=True, null=True)content = StreamField([('subtitle', blocks.TextBlock()),('paragraph', blocks.TextBlock()),('image', ImageChooserBlock()),])content_panels = Page.content_panels + [FieldPanel('intro'),StreamFieldPanel('content'),]

做下数据迁移
管理页面在首页下增加一个子页面,类型选article
在这里插入图片描述

在这里插入图片描述
还不能访问,需要增加对应的模板

在这里插入图片描述
创建模板文件
在这里插入图片描述
article\templates\article\article.html
内容替换如下

{% extends 'base.html' %}{% block content %}{{ page.title }}{{ page.intro }}{% for item in page.content %}<div>{{ item }}</div>{% endfor %}{% endblock %}

在这里插入图片描述
完善一下,增加单独处理标签的能力

{% extends 'base.html' %}{% block content %}<div><h2>{{ page.title }}</h2></div>{% for item in page.content %}{% if item.block_type == 'subtitle' %}<div><h4>{{ item }}</h4></div>{% endif %}{% if item.block_type == 'paragraph' %}<div><p style="color: #308282">{{ item }}</p></div>{% endif %}{% if item.block_type == 'image' %}<div>{{ item }}</div>{% endif %}{% endfor %}{% endblock %}

一个blog应用

(env) C:\djproject\wagprj\mysite>python manage.py startapp blog

Add the new blog app to INSTALLED_APPS in mysite/settings/base.py.

一个简单的起始页

配置修改

blog/models.py

from wagtail.core.models import Page
from wagtail.core.fields import RichTextField
from wagtail.admin.edit_handlers import FieldPanelclass BlogIndexPage(Page):intro = RichTextField(blank=True)content_panels = Page.content_panels + [FieldPanel('intro', classname="full")]

迁移数据
展示模板,新建文件
blog/templates/blog/blog_index_page.html

{% extends "base.html" %}{% load wagtailcore_tags %}{% block body_class %}template-blogindexpage{% endblock %}{% block content %}<h1>{{ page.title }}</h1><div class="intro">{{ page.intro|richtext }}</div>{% for post in page.get_children %}<h2><a href="{% pageurl post %}">{{ post.title }}</a></h2>{{ post.specific.intro }}{{ post.specific.body|richtext }}{% endfor %}{% endblock %}

管理页面操作

在Wagtail的admin界面, 创建一个BlogIndexPage作为Homepage的子叶,确保slug “blog” 在Promote页, 发布. 现在可以访问 url /blog 在你的站点上。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

blog页

配置修改

blog/models.py

from django.db import modelsfrom wagtail.core.models import Page
from wagtail.core.fields import RichTextField
from wagtail.admin.edit_handlers import FieldPanel
from wagtail.search import index# Keep the definition of BlogIndexPage, and add:class BlogPage(Page):date = models.DateField("Post date")intro = models.CharField(max_length=250)body = RichTextField(blank=True)search_fields = Page.search_fields + [index.SearchField('intro'),index.SearchField('body'),]content_panels = Page.content_panels + [FieldPanel('date'),FieldPanel('intro'),FieldPanel('body', classname="full"),]

迁移数据

 python manage.py makemigrationspython manage.py migrate

blog/templates/blog/blog_page.html

{% extends "base.html" %}{% load wagtailcore_tags %}{% block body_class %}template-blogpage{% endblock %}{% block content %}<h1>{{ page.title }}</h1><p class="meta">{{ page.date }}</p><div class="intro">{{ page.intro }}</div>{{ page.body|richtext }}<p><a href="{{ page.get_parent.url }}">Return to blog</a></p>     {% endblock %}

现在创建一些BlogIndexPage的子页
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

发布它
在这里插入图片描述

父与子

在wagtail所作的工作,大部分围绕树的概念,其包含节点和叶子;在这个例子中 BlogIndexPage 是 “node” 单独一个 BlogPage 是“leaves”.

加入图片

添加BlogPageGalleryImage 模型到 models.py

blog\models.py

from django.db import models# New imports added for ParentalKey, Orderable, InlinePanel, ImageChooserPanelfrom modelcluster.fields import ParentalKeyfrom wagtail.core.models import Page, Orderable
from wagtail.core.fields import RichTextField
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.search import index# ... (Keep the definition of BlogIndexPage, and update BlogPage:)class BlogPage(Page):date = models.DateField("Post date")intro = models.CharField(max_length=250)body = RichTextField(blank=True)search_fields = Page.search_fields + [index.SearchField('intro'),index.SearchField('body'),]content_panels = Page.content_panels + [FieldPanel('date'),FieldPanel('intro'),FieldPanel('body', classname="full"),InlinePanel('gallery_images', label="Gallery images"),]class BlogPageGalleryImage(Orderable):page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='gallery_images')image = models.ForeignKey('wagtailimages.Image', on_delete=models.CASCADE, related_name='+')caption = models.CharField(blank=True, max_length=250)panels = [ImageChooserPanel('image'),FieldPanel('caption'),]

迁移数据

 python manage.py makemigrationspython manage.py migrate

blog\templates\blog\blog_page.html


{% extends "base.html" %}{% load wagtailcore_tags wagtailimages_tags %}{% block body_class %}template-blogpage{% endblock %}{% block content %}<h1>{{ page.title }}</h1><p class="meta">{{ page.date }}</p><div class="intro">{{ page.intro }}</div>{{ page.body|richtext }}{% for item in page.gallery_images.all %}<div style="float: left; margin: 10px">{% image item.image fill-320x240 %}<p>{{ item.caption }}</p></div>{% endfor %}<p><a href="{{ page.get_parent.url }}">Return to blog</a></p>{% endblock %}

管理页面添加图片

在这里插入图片描述

展示

在这里插入图片描述

缩略图样式

既然 gallery images 独立的存在云数据库中, 我们可以独立低使用它,定义一个方法main_image 让它返回查询gallery images的第一个值。
在这里插入图片描述
在模板中使用。
在这里插入图片描述

给第二和第三帖子各增加gallery images

在这里插入图片描述

snippets

Snippet Models

snippets是一小段内容,而不是一个完整的web页面。一般被用来作为第二种内容展示,如,文章头部,注脚,侧部栏目,在管理后台可以进行编辑。snippets是一个Django 数据模型,没有继承Page类,因此没有组织到wagtail的目录树中。但是,他们仍然可以被编辑,通过访问后台面板并且在代码中以register_snippet 作为装饰。
snippets 缺乏很多pages的特性,比如,wagtail管理后台可排序,有一个确定的url,使用时候需要根据你的内容来权衡是否使用。
在这里插入图片描述
这个定义好之后,通过数据迁移,即可在wagtail管理后台看到对应的菜单
在这里插入图片描述
官方的帮助文档是按下面方式处理的

from django.db import modelsfrom wagtail.admin.edit_handlers import FieldPanel
from wagtail.snippets.models import register_snippet...@register_snippet
class Advert(models.Model):url = models.URLField(null=True, blank=True)text = models.CharField(max_length=255)panels = [FieldPanel('url'),FieldPanel('text'),]def __str__(self):return self.text

Advert model uses the basic Django model class and defines two properties: text and URL. The editing interface is very close to that provided for Page-derived models, with fields assigned in the panels property. Snippets do not use multiple tabs of fields, nor do they provide the “save as draft” or “submit for moderation” features.

@register_snippet tells Wagtail to treat the model as a snippet. The panels list defines the fields to show on the snippet editing page. It’s also important to provide a string representation of the class through def str(self): so that the snippet objects make sense when listed in the Wagtail admin.

Binding Pages to Snippets

即在页面中引用这个片段。
在这里插入图片描述

In the above example, the list of adverts is a fixed list that is displayed via the custom template tag independent of any other content on the page. This might be what you want for a common panel in a sidebar, but, in another scenario, you might wish to display just one specific instance of a snippet on a particular page. This can be accomplished by defining a foreign key to the snippet model within your page model and adding a SnippetChooserPanel to the page’s content_panels list. For example, if you wanted to display a specific advert on a BookPage instance:

from wagtail.snippets.edit_handlers import SnippetChooserPanel
# ...
class BookPage(Page):advert = models.ForeignKey('demo.Advert',null=True,blank=True,on_delete=models.SET_NULL,related_name='+')content_panels = Page.content_panels + [SnippetChooserPanel('advert'),# ...]

The snippet could then be accessed within your template as page.advert.

To attach multiple adverts to a page, the SnippetChooserPanel can be placed on an inline child object of BookPage rather than on BookPage itself. Here, this child model is named BookPageAdvertPlacement (so called because there is one such object for each time that an advert is placed on a BookPage):

from django.db import modelsfrom wagtail.core.models import Page, Orderable
from wagtail.snippets.edit_handlers import SnippetChooserPanelfrom modelcluster.fields import ParentalKey...class BookPageAdvertPlacement(Orderable, models.Model):page = ParentalKey('demo.BookPage', on_delete=models.CASCADE, related_name='advert_placements')advert = models.ForeignKey('demo.Advert', on_delete=models.CASCADE, related_name='+')class Meta(Orderable.Meta):verbose_name = "advert placement"verbose_name_plural = "advert placements"panels = [SnippetChooserPanel('advert'),]def __str__(self):return self.page.title + " -> " + self.advert.textclass BookPage(Page):...content_panels = Page.content_panels + [InlinePanel('advert_placements', label="Adverts"),# ...]

These child objects are now accessible through the page’s advert_placements property, and from there we can access the linked Advert snippet as advert. In the template for BookPage, we could include the following:

{% for advert_placement in page.advert_placements.all %}<p><a href="{{ advert_placement.advert.url }}">{{ advert_placement.advert.text }}</a></p>
{% endfor %}

定制管理平台

Customising admin templates

In your projects with Wagtail, you may wish to replace elements such as the Wagtail logo within the admin interface with your own branding. This can be done through Django’s template inheritance mechanism.

You need to create a templates/wagtailadmin/ folder within one of your apps - this may be an existing one, or a new one created for this purpose, for example, dashboard. This app must be registered in INSTALLED_APPS before wagtail.admin:

INSTALLED_APPS = (# ...'dashboard','wagtail.core','wagtail.admin',# ...
)

把wagtail集成到django项目

安装插件

$ pip install wagtail

安装后的内容


(venv) C:\djangoprj\eshop>pip list
Package             Version
------------------- ---------
anyascii            0.2.0
asgiref             3.3.4
beautifulsoup4      4.9.3
certifi             2020.12.5
chardet             4.0.0
Django              3.2.3
django-cors-headers 3.7.0
django-filter       2.4.0
django-modelcluster 5.1
django-taggit       1.4.0
django-tinymce      3.3.0
django-treebeard    4.5.1
djangorestframework 3.12.4
draftjs-exporter    2.1.7
et-xmlfile          1.1.0
html5lib            1.1
idna                2.10
l18n                2020.6.1
openpyxl            3.0.7
Pillow              8.2.0
pip                 21.1.2
PyMySQL             1.0.2
pytz                2021.1
requests            2.25.1
setuptools          57.0.0
six                 1.16.0
soupsieve           2.2.1
sqlparse            0.4.1
tablib              3.0.0
telepath            0.1.1
urllib3             1.26.5
wagtail             2.13
webencodings        0.5.1
Willow              1.4
xlrd                2.0.1
XlsxWriter          1.4.3
xlwt                1.3.0

Settings配置

INSTALLED_APPS:

'wagtail.contrib.forms',
'wagtail.contrib.redirects',
'wagtail.embeds',
'wagtail.sites',
'wagtail.users',
'wagtail.snippets',
'wagtail.documents',
'wagtail.images',
'wagtail.search',
'wagtail.admin',
'wagtail.core','modelcluster',
'taggit',

MIDDLEWARE:

'wagtail.contrib.redirects.middleware.RedirectMiddleware',

Add a STATIC_ROOT setting, if your project does not have one already:

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

Add MEDIA_ROOT and MEDIA_URL settings, if your project does not have these already:

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

Add a WAGTAIL_SITE_NAME - this will be displayed on the main dashboard of the Wagtail admin backend:

WAGTAIL_SITE_NAME = 'My Example Site'

Various other settings are available to configure Wagtail’s behaviour - see Settings.

URL配置

from django.urls import path, re_path, includefrom wagtail.admin import urls as wagtailadmin_urls
from wagtail.core import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urlsurlpatterns = [...path('cms/', include(wagtailadmin_urls)),path('documents/', include(wagtaildocs_urls)),path('pages/', include(wagtail_urls)),...
]

wagtailadmin_urls provides the admin interface for Wagtail. This is separate from the Django admin interface (django.contrib.admin); Wagtail-only projects typically host the Wagtail admin at /admin/, but if this would clash with your project’s existing admin backend then an alternative path can be used, such as /cms/ here.

wagtaildocs_urls is the location from where document files will be served. This can be omitted if you do not intend to use Wagtail’s document management features.

wagtail_urls is the base location from where the pages of your Wagtail site will be served. In the above example, Wagtail will handle URLs under /pages/, leaving the root URL and other paths to be handled as normal by your Django project. If you want Wagtail to handle the entire URL space including the root URL, this can be replaced with:

错误

报错如下,可能是Pillow的版本不对,降低下版本即可。

wagtailusers.UserProfile.avatar: (fields.E210) Cannot use ImageField because Pillow is not installed.HINT: Get Pillow at https://pypi.org/project/Pillow/ or run command "python -m pip install Pillow".
(venv) C:\djangoprj\hotlinewag>pip uninstall Pillow
Found existing installation: Pillow 8.3.0
Uninstalling Pillow-8.3.0:Would remove:c:\djangoprj\hotlinewag\venv\lib\site-packages\pil\*c:\djangoprj\hotlinewag\venv\lib\site-packages\pillow-8.3.0.dist-info\*
Proceed (y/n)? ySuccessfully uninstalled Pillow-8.3.0(venv) C:\djangoprj\hotlinewag>pip install Pillow==8.2.0
Collecting Pillow==8.2.0Using cached Pillow-8.2.0-cp38-cp38-win_amd64.whl (2.2 MB)
Installing collected packages: Pillow
Successfully installed Pillow-8.2.0

wagtail的api

基本配置

使能app

在配置文件中加入api应用

# settings.pyINSTALLED_APPS = [...'wagtail.api.v2',...
]

可选的,通过添加rest_frameworkINSTALLED_APPS. 可以通过浏览器来查看api,如果是基本的json格式输出是不必须的。

配置endpoints

下面配置那些内容暴露到API。每种内容类型有对应的endpoint。endpoint结合路由,通过url配置连接项目的其他部分。
三种endpoint

Pages wagtail.api.v2.views.PagesAPIViewSet
Images wagtail.images.api.v2.views.ImagesAPIViewSet
Documents wagtail.documents.api.v2.views.DocumentsAPIViewSet

可以继承他们定制自己的类。也可以从基础类派生

 wagtail.api.v2.views.BaseAPIViewSet

在项目目录新建一个文件api.py
在这里插入图片描述

# api.pyfrom wagtail.api.v2.views import PagesAPIViewSet
from wagtail.api.v2.router import WagtailAPIRouter
from wagtail.images.api.v2.views import ImagesAPIViewSet
from wagtail.documents.api.v2.views import DocumentsAPIViewSet# Create the router. "wagtailapi" is the URL namespace
api_router = WagtailAPIRouter('wagtailapi')# Add the three endpoints using the "register_endpoint" method.
# The first parameter is the name of the endpoint (eg. pages, images). This
# is used in the URL of the endpoint
# The second parameter is the endpoint class that handles the requests
api_router.register_endpoint('pages', PagesAPIViewSet)
api_router.register_endpoint('images', ImagesAPIViewSet)
api_router.register_endpoint('documents', DocumentsAPIViewSet)

注册url

注册url,使Django能够路由请求道API。

# urls.pyfrom .api import api_routerurlpatterns = [...path('api/v2/', api_router.urls),...# 确保api_route.urls 必须在wagtail_urls之前。re_path(r'^', include(wagtail_urls)),
]

访问api

通过以上配置,可以访问pages通过 /api/v2/pages/, images 通过 /api/v2/images/ 和 documents 通过 /api/v2/documents/
所有页面
在这里插入图片描述
单个一面
在这里插入图片描述

图像、文档同样
在这里插入图片描述

使字段能够访问

从上面看到,不是所有的页面的定制字段都能够通过API访问到,实现这一点,可以通过添加字段列表到api_fields属性来实现。

# models.pyfrom wagtail.api import APIFieldclass BlogPageAuthor(Orderable):page = models.ForeignKey('blog.BlogPage', on_delete=models.CASCADE, related_name='authors')name = models.CharField(max_length=255)api_fields = [APIField('name'),]class BlogPage(Page):published_date = models.DateTimeField()body = RichTextField()feed_image = models.ForeignKey('wagtailimages.Image', on_delete=models.SET_NULL, null=True, ...)private_field = models.CharField(max_length=255)# Export fields over the APIapi_fields = [APIField('published_date'),APIField('body'),APIField('feed_image'),APIField('authors'),  # This will nest the relevant BlogPageAuthor objects in the API response]

在models增加导入,

from wagtail.api import APIField

在APIField中加入需要暴露的字段,各种类型字段都可以。

在这里插入图片描述

在这里插入图片描述
图片的详细链接
在这里插入图片描述

按类型获取

在这里插入图片描述

限制获取的字段

可以获取指定的字段,包含在嵌套中的字段。
在这里插入图片描述

限制获取数量

分页使用,每页显示数量。
在这里插入图片描述

偏移量

分页显示,每页开始位置。
在这里插入图片描述

排序

字母顺序
在这里插入图片描述

order=-title将获得反向排序。

获得子页面

在这里插入图片描述

获取orderable数据

把需要暴露的orderable添加到APIfield
在这里插入图片描述
在orderable中添加需要暴露的字段到APIfiled
在这里插入图片描述

只查询orderable的数据

http://192.168.2.21/api/v2/pages/3/?fields=_,mycarousel

在这里插入图片描述

获取StreamField 中的image的url

通常的方法只能获得StreamField 中图片的id,不能满足需要,做一下改动
page中引用的StreamField 如下

from streams.blocks import BaseStreamBlock
。。。body = StreamField(BaseStreamBlock(), verbose_name="Page body", blank=True
。。。

blocks中的BaseStreamBlock

# 原有的导入
# from wagtail.images.blocks import ImageChooserBlock
# 增加的导入
from wagtail.images.blocks import ImageChooserBlock as DefaultImageChooserBlock# 增加的定义
class ImageChooserBlock(DefaultImageChooserBlock):def get_api_representation(self, value, context=None):if value:return {'id': value.id,'title': value.title,'large': value.get_rendition('width-1000').attrs_dict,'mobile': value.get_rendition('width-320').attrs_dict,'thumbnail': value.get_rendition('fill-120x120').attrs_dict,}# 原有的结构
class ImageBlock(StructBlock):"""Custom `StructBlock` for utilizing images with associated caption andattribution data"""image = ImageChooserBlock(required=True)caption = CharBlock(required=False)attribution = CharBlock(required=False)class Meta:icon = 'image'template = "blocks/image_block.html"

相当于重写了get_api_representation,可以灵活定义图片的大小。
返回结果
在这里插入图片描述

表单

https://stackoverflow.com/questions/61289214/wagtail-form-file-uploadhttps://github.com/spapas/wagtail-multi-upload

Django数据模型的纳管

Wagtail 的数据模型管理类和Django的是不同的,虽然有相同的名字和实现相同的功能,但还是有些不同。添加和编辑表单仍然通过panels和edit_handlers来实现。
在Wagtail中控制那些字段显示或可编辑在数据模型中,以及如何分组和排序,不管你的数据模型是页类型或片段或是标准的django模型。 Wagtail’s ModelAdmin 类更多的关心列表配置。例如,列表显示,列表过滤,搜索字段类似与Django,同时字段,字段设置,排除等其他属性是wagtail不支持的。

配置

添加 wagtail.contrib.modeladmin to your INSTALLED_APPS:

INSTALLED_APPS = [...'wagtail.contrib.modeladmin',
]

使用

可以定义普通的Django 模型,然后用ModelAdmin创建一个菜单来查看和编辑这个模型。

models.py looks like this:

from django.db import models
from wagtail.admin.edit_handlers import FieldPanel
from wagtail.images.edit_handlers import ImageChooserPanelclass Book(models.Model):title = models.CharField(max_length=255)author = models.CharField(max_length=255)cover_photo = models.ForeignKey('wagtailimages.Image',null=True, blank=True,on_delete=models.SET_NULL,related_name='+')panels = [FieldPanel('title'),FieldPanel('author'),ImageChooserPanel('cover_photo')]

You can specify FieldPanels like ImageChooserPanel, PageChooserPanel, and DocumentChooserPanel within the panels attribute of the model. This lets you use Wagtail-specific features in an otherwise traditional Django model.

创建wagtail_hooks.py in your app directory would look something like this:
也可以利用admin.py文件。在其中录入以下内容。

from wagtail.contrib.modeladmin.options import (ModelAdmin, modeladmin_register)
from .models import Bookclass BookAdmin(ModelAdmin):model = Bookmenu_label = 'Book'  # ditch this to use verbose_name_plural from modelmenu_icon = 'pilcrow'  # change as requiredmenu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)add_to_settings_menu = False  # or True to add your model to the Settings sub-menuexclude_from_explorer = False # or True to exclude pages of this type from Wagtail's explorer viewlist_display = ('title', 'author')list_filter = ('author',)search_fields = ('title', 'author')# Now you just need to register your customised ModelAdmin class with Wagtail
modeladmin_register(BookAdmin)

实际的例子:
models.py

from django.db import models# 图片上传模型
class Image(models.Model):eventID = models.CharField(max_length=200, verbose_name='事件id')images = models.ImageField(upload_to='images/uploads/%Y/%m/%d/', blank=True)# 投诉类数据模型
class ComplainFirstCategory(models.Model):"""投诉一级类别"""name = models.CharField(max_length=200, verbose_name='名称')class Meta:verbose_name = '投诉一级类别'verbose_name_plural = verbose_namedef __str__(self):return self.name  # 被引用时返回的值class ComplainSecondCategory(models.Model):"""投诉二级类别"""name = models.CharField(max_length=200, verbose_name='名称')ComplainFirstCategory = models.ForeignKey(ComplainFirstCategory, related_name='CompSecondCate',on_delete=models.CASCADE, verbose_name='类别')class Meta:verbose_name = '投诉二级类别'verbose_name_plural = verbose_namedef __str__(self):return self.name  # 被引用时返回的值class Complain(models.Model):"""投诉"""eventID = models.CharField(max_length=200, verbose_name='Id', blank=True, null=True)title = models.CharField(max_length=200, verbose_name='标题', blank=True, null=True)telnum = models.CharField(max_length=200, verbose_name='联系人电话', blank=True, null=True)address = models.CharField(max_length=200, verbose_name='事件地点', blank=True, null=True)contents = models.TextField(verbose_name='投诉内容')ComplainFirstCategory = models.ForeignKey(ComplainFirstCategory, related_name='CompFirstCate',on_delete=models.CASCADE, verbose_name='类别', blank=True, null=True)ComplainSecondCategory = models.ForeignKey(ComplainSecondCategory, related_name='CompSecondCate',on_delete=models.CASCADE, verbose_name='类别', blank=True, null=True)created = models.DateTimeField(auto_now_add=True)class Meta:verbose_name = '投诉'verbose_name_plural = verbose_namedef __str__(self):return self.title

admin.py

# Register your models here.
from wagtail.contrib.modeladmin.options import (ModelAdmin, modeladmin_register)
# import imageuploadapps
from .models import Imageclass ImageAdmin(ModelAdmin):model = Imagemenu_label = 'Image'  # ditch this to use verbose_name_plural from modelmenu_icon = 'placeholder'  # change as requiredmenu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)add_to_settings_menu = False  # or True to add your model to the Settings sub-menuexclude_from_explorer = False # or True to exclude pages of this type from Wagtail's explorer viewlist_display = ('eventID', 'images')list_filter = ('eventID',)search_fields = ('title', 'images')# Now you just need to register your customised ModelAdmin class with Wagtail
modeladmin_register(ImageAdmin)

管理平台显示这样:
在这里插入图片描述

更为复杂些的例子

假设你定义了Book, Author, and Genre 模型在models.py.
你的app目录的admins.py 像这样:

from wagtail.contrib.modeladmin.options import (ModelAdmin, ModelAdminGroup, modeladmin_register)
from .models import (Book, Author, Genre)class BookAdmin(ModelAdmin):model = Bookmenu_label = 'Book'  # ditch this to use verbose_name_plural from modelmenu_icon = 'pilcrow'  # change as requiredlist_display = ('title', 'author')list_filter = ('genre', 'author')search_fields = ('title', 'author')class AuthorAdmin(ModelAdmin):model = Authormenu_label = 'Author'  # ditch this to use verbose_name_plural from modelmenu_icon = 'user'  # change as requiredlist_display = ('first_name', 'last_name')list_filter = ('first_name', 'last_name')search_fields = ('first_name', 'last_name')class GenreAdmin(ModelAdmin):model = Genremenu_label = 'Genre'  # ditch this to use verbose_name_plural from modelmenu_icon = 'group'  # change as requiredlist_display = ('name',)       # 单个字段需要后面加逗号。list_filter = ('name',)search_fields = ('name',)class LibraryGroup(ModelAdminGroup):       #制作一个菜单组,三个数据模型放在一起menu_label = 'Library'menu_icon = 'folder-open-inverse'  # change as requiredmenu_order = 200  # will put in 3rd place (000 being 1st, 100 2nd)items = (BookAdmin, AuthorAdmin, GenreAdmin)# When using a ModelAdminGroup class to group several ModelAdmin classes together,
# you only need to register the ModelAdminGroup class with Wagtail:
modeladmin_register(LibraryGroup)

在这里插入图片描述

增加Django数据模型的用户档案

新建一个通用的应用common

python manage.py startapp common

models.py

from django.conf import settings
from django.db import models# Create your models here.
# 用户信息
# @python_2_unicode_compatible
class UserProfile(models.Model):"""用户档案"""user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='userprofile', )mobile_phone = models.CharField(blank=True, null=True, max_length=200, verbose_name='电话号码')nickname = models.CharField(blank=True, null=True, max_length=200)address = models.CharField(blank=True, null=True, max_length=400)created = models.DateTimeField(auto_now_add=True)updated = models.DateTimeField(auto_now=True)

admin.py

# Register your models here.
from wagtail.contrib.modeladmin.options import (ModelAdmin, ModelAdminGroup, modeladmin_register)
from .models import (UserProfile, )class UserProfileAdmin(ModelAdmin):model = UserProfilemenu_label = '用户档案'  # ditch this to use verbose_name_plural from modelmenu_icon = 'placeholder'  # change as requiredlist_display = ('user', 'mobile_phone','nickname','address')list_filter = ('user',)search_fields = ('user', 'mobile_phone')# Now you just need to register your customised ModelAdmin class with Wagtail
# modeladmin_register(ImageAdmin)modeladmin_register(UserProfileAdmin)

在这里插入图片描述

通过接口添加用户档案

https://blog.csdn.net/qq_37975685/article/details/81867334

https://blog.csdn.net/weixin_42134789/article/details/80207322?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control

https://www.cnblogs.com/lvye001/p/9967421.html

通过接口认证获得token方法

流程

前端通过用户名密码访问token获取接口,获取token,存储在本地,以后再访问需要认证的资源,可以带着这个token访问接口,后端即认为是此用户名密码用户访问。
目前常用的为客户端webstorage,服务端token;cookie和session方法不再常用

使用方法

要使用 TokenAuthentication 方案 ,需要在setting包含rest_framework.authtoken应用项;并且配置认证类包含TokenAuthentication。

INSTALLED_APPS = [...'rest_framework.authtoken'
]

增加认证类

在这里插入图片描述

当使用 TokenAuthentication, 你可能需要通过提供用户名和密码而获得token这样一个机制。REST framework提供了一个内置的 view 来实现这个功能。只需要添加 obtain_auth_token view 到你的 URLconf就可以使用它。

from rest_framework.authtoken import views
urlpatterns += [path('api-token-auth/', views.obtain_auth_token)
]

用户前端访问这个接口,只需要这一行代码即完成token的生成并返回。
Note that the URL part of the pattern can be whatever you want to use.

The obtain_auth_token view will return a JSON response when valid username and password fields are POSTed to the view using form data or JSON:

{ 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }

配置完成后的数据库迁移

manage.py makemigrations 
manage.py migrate


rest_framework.authtoken
应用提供了数据库迁移。

C:\djproject\eshop>python manage.py makemigrations
Migrations for 'computerapp':computerapp\migrations\0002_auto_20210404_1048.py- Change Meta options on category- Change Meta options on product- Alter field name on category- Alter field category on product- Alter field model on product- Alter field price on product
C:\djproject\eshop>python manage.py migrate
Operations to perform:Apply all migrations: admin, auth, authtoken, computerapp, contenttypes, sessions
Running migrations:Applying computerapp.0002_auto_20210404_1048... OK

在根urls增加

在这里插入图片描述

第一行为引入views
第二行为增加认证功能
第三行为获得token功能,利用了rest自带功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/131997.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汽车标定技术(四)--问题分析:多周期测量时上位机显示异常

目录 1.问题现象 2.数据流分析 ​​​​3.代码分析 3.1 AllocDAQ 3.2 AllocOdt 3.3 AllocOdtEntry 4.根因分析及解决方法 4.1 根因分析 4.2 解决方案 1.问题现象 在手撸XCP代码时&#xff0c; DAQ的实现是一大头痛的事情。最初单周期实现还好一点&#xff0c;特别是…

MATLAB - Gazebo 联合仿真 —— 使用 UR10 机械臂检测和采摘水果

系列文章目录 文章目录 系列文章目录前言一、设置 Gazebo 仿真环境二、在 Gazebo 中模拟和控制机器人2.1 概述2.2 任务调度器2.3 感知和目标生成系统2.4 运动规划2.5 机械臂和关节控制系统 三、分配用于控制机器人的参数3.1 定义机器人模型和运动规划参数&#xff0c;3.2 定义机…

学习c++的第十一天

目录 继承和派生 基类 & 派生类 访问控制和继承 派生类的构造函数 派生类的析构函数 继承类型 多继承 重载运算符和重载函数 函数重载 运算符重载 可重载运算符/不可重载运算符 运算符重载实例 继承和派生 先来说继承&#xff0c;这与现实生活中的继承意思差不…

[直播自学]-[汇川easy320]搞起来(1)给PLC供电

从没正儿八经的用一用PLC&#xff0c;所以双11在淘宝入手一个EASY320&#xff0c;大概1000出头。 到货后&#xff0c;汇川官网搜了一下资料&#xff0c;搜到这几个&#xff1a; 首先是给PLC供电吧&#xff0c;看了下PLC前面是24V&#xff0c;不知道供电范围多宽&#xff0c;于…

YoloV8目标检测与实例分割——目标检测onnx模型推理

一、模型转换 1.onnxruntime ONNX Runtime&#xff08;ONNX Runtime或ORT&#xff09;是一个开源的高性能推理引擎&#xff0c;用于部署和运行机器学习模型。它的设计目标是优化执行使用Open Neural Network Exchange&#xff08;ONNX&#xff09;格式定义的模型&#xff0c;…

https原理

首先说一下几个概念&#xff1a;对称加密、非对称加密 对称加密&#xff1a; 客户端和服务端使用同一个秘钥&#xff0c;分两种情况&#xff1a; 1、所有的客户端和服务端使用同一个秘钥&#xff0c;这个秘钥被泄漏后数据不再安全 2、每个客户端生成一个秘钥&…

[云原生案例2.1 ] Kubernetes的部署安装 【单master集群架构 ---- (二进制安装部署)】节点部分

文章目录 1. 常见的K8S安装部署方式1.1 Minikube1.2 Kubeadm1.3 二进制安装部署 2. Kubernetes单master集群架构 ---- &#xff08;二进制安装部署&#xff09;2.1 前置准备2.2 操作系统初始化2.3 部署 docker引擎 ---- &#xff08;所有 node 节点&#xff09;2.4 部署 etcd 集…

HTML_案例1_注册页面

用纯html页面&#xff0c;不用css画一个注册页面。 最终效果如下&#xff1a; html页面代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>注册页面</title> </head>…

ffmpeg命令帮助文档

一&#xff1a;帮助文档的命令格式 ffmpeg -h帮助的基本信息ffmpeg -h long帮助的高级信息ffmpeg -h full帮助的全部信息 ffmpeg的命令使用方式&#xff1a;ffmpeg [options] [[infile options] -i infile] [[outfile options] outfile] 二&#xff1a;将帮助文档输出到文件 …

部署ELK

一、elasticsearch #拉取镜像 docker pull elasticsearch:7.12.1 #创建ELK docker网络 docker network create elk #启动ELK docker run -d --name es --net elk -P -e "discovery.typesingle-node" elasticsearch:7.12.1 #拷贝配置文件 docker cp es:/usr/share/el…

【2023年MathorCup高校数学建模挑战赛-大数据竞赛】赛道A:基于计算机视觉的坑洼道路检测和识别 python 代码解析

【2023年MathorCup高校数学建模挑战赛-大数据竞赛】赛道A&#xff1a;基于计算机视觉的坑洼道路检测和识别 python 代码解析 1 题目 坑洼道路检测和识别是一种计算机视觉任务&#xff0c;旨在通过数字图像&#xff08;通常是地表坑洼图像&#xff09;识别出存在坑洼的道路。这…

Pycharm 对容器中的 Python 程序断点远程调试

pycharm如何连接远程服务器的docker容器有两种方法&#xff1a; 第一种&#xff1a;pycharm通过ssh连接已在运行中的docker容器 第二种&#xff1a;pycharm连接docker镜像&#xff0c;pycharm运行代码再自动创建容器 本文是第一种方法的教程&#xff0c;第二种请点击以上的链接…

个人服务器到期,项目下线,新的开始

告别旧服务器 2023.11.06服务器到期&#xff0c;所有项目正式下线 时间真的过的很快&#xff0c;从开始踏入编程的大门&#xff0c;到现在不知不觉已经陆续经手了两台服务器了&#xff0c;目前这台服务器是一年前的阿里云活动白嫖的嘿嘿嘿&#xff0c;该服务器上目前运行的项…

项目实战:service业务逻辑组件引入

1、第一层DAO层 1.1、FruitDao接口 package com.csdn.fruit.dao; import com.csdn.fruit.pojo.Fruit; import java.util.List; //dao &#xff1a;Data Access Object 数据访问对象 //接口设计 public interface FruitDao {void addFruit(Fruit fruit);void delFruit(String fn…

计网【链路带宽100Mbps代表什么,“翻译”成人话是?】

这里写目录标题 带宽的概念本来的意思【通信领域】计网中的意思 结论【100Mbps代表什么】 带宽的概念 本来的意思【通信领域】 带宽这个概念本来是通信领域的&#xff0c;表示通信线路允许通过的信号频带范围&#xff0c;单位是赫兹Hz 感觉最简单的意思&#xff0c;例如如果…

ActiveMq学习⑧__ActiveMQ的消息持久化机制

ActiveMQ的消息存储和持久化 MQ的高可用 事务持久签收可持久化 &#xff08;类似于与mq消息的同步机制&#xff09; 为了避免意外宕机以后丢失信息&#xff0c;需要做到重启后可以恢复消息队列&#xff0c;消息系统一半都会采用持久化机制。 ActiveMQ的消息持久化机制 Act…

SurfaceFlinger的硬件Vsync深入分析-千里马android framework车机手机系统开发

背景&#xff1a; 学过或者你看过surfaceflinger相关文章同学都知道&#xff0c;vsync其实都是由surfaceflinger软件层面进行模拟的&#xff0c;但是软件模拟有可能会有误差或偏差&#xff0c;这个时候就需要有个硬件vsync帮忙校准。 故才会在surfaceflinger的systrace出现如下…

C语言从入门到精通之【第一个程序hello world】

编程步骤 通常&#xff0c;我们按照以下步骤进行 确立目标设计程序编写代码编译程序运行程序测试&调试修改维护 输出hello world 每个学编程的人都会从最经典的【输出hello world】开始。 https://lightly.teamcode.com/ 我们可以使用这个在线IDE学习C语言。 代码很简…

Go语言与Python语言的性能比较

目录 一、背景与意义 二、执行速度 三、内存消耗 四、并发性能 五、编译速度与开发效率 六、综合考虑 七、应用场景 八、未来发展趋势 总结 一、背景与意义 在编程世界中&#xff0c;Go语言和Python语言都占有一席之地。Go语言是由Google开发的&#xff0c;其设计初衷…

【JavaEE】JVM 剖析

JVM 1. JVM 的内存划分2. JVM 类加载机制2.1 类加载的大致流程2.2 双亲委派模型2.3 类加载的时机 3. 垃圾回收机制3.1 为什么会存在垃圾回收机制?3.2 垃圾回收, 到底实在做什么?3.3 垃圾回收的两步骤第一步: 判断对象是否是"垃圾"第二步: 如何回收垃圾 1. JVM 的内…