Wagtail 教程系列 记录了基于 Wagtail 搭建博客站点的整个过程,博客站点 所呈现的即是搭建过程的最新效果。

更多 Wagtail 内容:https://slowread.cn/wagtail-tutorials

博客列表和文章正文

  • 执行 python manage.py startapp blog 创建 blog app.
  • 编辑 slowread/settings/base.py 在 INSTALLED_APPS 中添加 blog app.

博客列表实现

编辑 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")]

Copy

执行 python manage.py makemigrations && python manage.py migrate

因为模型名字为BlogIndexPage,因此模板文件的名字就成了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 %}

Copy

博客正文实现

编辑 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"),]

Copy

执行 python manage.py makemigrations && python 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 %}

Copy

查看效果

进入 Wagtail 管理后台:

  1. 选择 页面,Home,添加子页面,Blog index page,编辑博客列表标题,发布;
  2. 选择 页面,Home,点击上一步创建的 Blog index page 最右侧右箭头,添加子页面,选择 Blog page,编辑博客文章内容,发布;重复几次发布几篇不同文章;

打开 http://127.0.0.1:8000/blog ,查看效果。

一点改进

  1. 博客文章列表根据创建时间倒叙排列。
  2. 只显示发布的文章。

编辑 blog/models.py ,修改以下相应内容:

class BlogIndexPage(Page):intro = RichTextField(blank=True)def get_context(self, request):# Update context to include only published posts, ordered by reverse-chroncontext = super().get_context(request)blogpages = self.get_children().live().order_by('-first_published_at')context['blogpages'] = blogpagesreturn context

Copy

编辑 blog/templates/blog/blog_index_page.html,修改 {% for post in page.get_children %} 为 {% for post in blogpages %}。

现在,可以在管理后台撤销发布一篇文章,查看效果。

图像

编辑 blog/models.py 添加 BlogPageGalleryImage model,内容如下:

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'),]

Copy

执行 python manage.py makemigrations && python 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 %}

Copy

现在,可以在管理后台,编辑一篇文章,增加图片内容,然后发布,查看效果。

再次改进博客列表显示效果,编辑 blog/models.py 修改 BlogPage model 为下面内容:

class BlogPage(Page):date = models.DateField("Post date")intro = models.CharField(max_length=250)body = RichTextField(blank=True)def main_image(self):gallery_item = self.gallery_images.first()if gallery_item:return gallery_item.imageelse:return Nonesearch_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"),]

Copy

编辑博客文章页面模板文件 blog/templates/blog/blog_index_page.html ,内容如下:

{% extends "base.html" %}{% load wagtailcore_tags wagtailimages_tags %}{% block body_class %}template-blogindexpage{% endblock %}{% block content %}<h1>{{ page.title }}</h1><div class="intro">{{ page.intro|richtext }}</div>{% for post in blogpages %}{% with post=post.specific %}<h2><a href="{% pageurl post %}">{{ post.title }}</a></h2>{% with post.main_image as main_image %}{% if main_image %}{% image main_image fill-160x100 %}{% endif %}{% endwith %}<p>{{ post.intro }}</p>{{ post.body|richtext }}{% endwith %}{% endfor %}{% endblock %}

Copy

查看效果,包含图像的文章在博客列表页面增加了缩略图显示。

标签

再次修改 blog/models.py , 增加/修改以下相应内容:

from django.db import models# New imports added for ClusterTaggableManager, TaggedItemBase, MultiFieldPanelfrom modelcluster.fields import ParentalKey
from modelcluster.contrib.taggit import ClusterTaggableManager
from taggit.models import TaggedItemBasefrom wagtail.core.models import Page, Orderable
from wagtail.core.fields import RichTextField
from wagtail.admin.edit_handlers import FieldPanel, InlinePanel, MultiFieldPanel
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.search import index# ... (Keep the definition of BlogIndexPage)class BlogPageTag(TaggedItemBase):content_object = ParentalKey('BlogPage',related_name='tagged_items',on_delete=models.CASCADE)class BlogPage(Page):date = models.DateField("Post date")intro = models.CharField(max_length=250)body = RichTextField(blank=True)tags = ClusterTaggableManager(through=BlogPageTag, blank=True)# ... (Keep the main_image method and search_fields definition)content_panels = Page.content_panels + [MultiFieldPanel([FieldPanel('date'),FieldPanel('tags'),], heading="Blog information"),FieldPanel('intro'),FieldPanel('body'),InlinePanel('gallery_images', label="Gallery images"),]

Copy

执行 python manage.py makemigrations && python manage.py migrate.

进入管理后台,编辑部分博客文章,增加自定义标签。

编辑博客文章页面模板文件 blog/templates/blog/blog_page.html ,在文件最后增加如下内容:

{% if page.tags.all.count %}<div class="tags"><h3>标签</h3>{% for tag in page.tags.all %}<a href="{% slugurl 'tags' %}?tag={{ tag }}"><button type="button">{{ tag }}</button></a>{% endfor %}</div>
{% endif %}

Copy

修改 blog/models.py , 增加 BlogTagIndexPage model,内容如下:

class BlogTagIndexPage(Page):def get_context(self, request):# Filter by tagtag = request.GET.get('tag')blogpages = BlogPage.objects.filter(tags__name=tag)# Update template contextcontext = super().get_context(request)context['blogpages'] = blogpagesreturn context

Copy

执行 python manage.py makemigrations && python manage.py migrate.

进入管理后台,在 Home 页面下,增加 Blog tag index page 类型的子页面,名字为 标签,推荐中缩略名为 tags。

新建对应标签页的页面模板文件 blog/blog_tag_index_page.html,内容如下:

{% extends "base.html" %}
{% load wagtailcore_tags %}{% block content %}{% if request.GET.tag|length %}<h4>Showing pages tagged "{{ request.GET.tag }}"</h4>{% endif %}{% for blogpage in blogpages %}<p><strong><a href="{% pageurl blogpage %}">{{ blogpage.title }}</a></strong><br /><small>Revised: {{ blogpage.latest_revision_created_at }}</small><br />{% if blogpage.author %}<p>By {{ blogpage.author.profile }}</p>{% endif %}</p>{% empty %}No pages found with that tag.{% endfor %}{% endblock %}

Copy

打开 http://127.0.0.1:8000/blog/ ,查看效果。

Wagtail 教程 2:简单博客实现相关推荐

  1. Python Flask框架-开发简单博客-认证蓝图

    作者:Eason_LYC 悲观者预言失败,十言九中. 乐观者创造奇迹,一次即可. 一个人的价值,在于他所拥有的.可以不学无术,但不能一无所有! 技术领域:WEB安全.网络攻防 关注WEB安全.网络攻防 ...

  2. 响应式pbootcms教程资讯新闻博客类网站模板

    模板介绍: PbootCMS内核开发的模板,该模板属于教程资讯.建站教程.新闻博客类企业使用! 页面简洁简单,容易管理,附带测试数据! 手机预览请扫描二维码: 此模板为免费模板 下载地址:建站教程pb ...

  3. Windows Azure微软免费云空间成功申请和使用教程:安装WP博客

    Windows Azure也是Windows Azure Platform,是一个由微软推出的云计算平台,Windows Azure Platform一开始提供的是平台即服务(PaaS),在2012 ...

  4. Django实现简单博客系统

    Django实现简单博客系统 第一节 - 基础 1. 简单的导览图,学会不迷路 2. 基本操作介绍 3. 命令简单介绍 4. mysite:所建项目的管理功能目录 5. blog:我们创建的项目之一 ...

  5. php开发博客系统源码,php简单博客系统

    [实例简介] php简单博客系统,是基于php+mysql组合的简单系统,下来看看吧 [实例截图] [核心代码] webstar ├── web_star │   ├── code.php │   ├ ...

  6. 【Rust日报】2022-09-14 使用 Rust 构建简单博客 华为实习生招募

    使用 Rust 构建简单博客 作者以写 Go 为主,他认为学习任何语言都可以从一个 web 程序入手,那么事情就会变得明朗,本文展示的是作者在学习了一段时间 Rust 后开始搭建简单博客系统的过程,很 ...

  7. 如何在 CSDN 中增加博客访问量 史上最简单的博客教程 学会之后博客访问量直线上升。

    蹭热度 如何蹭是问题.下面分几点 你发布的有关技术是什么 你发布的是否是别人发布过的东西 你发布的东西在别人是怎样搜索的. 其实重点在流量,也就是点击.点击到位了,无论你文章来自哪里,或者说抄自哪里, ...

  8. Python Flask框架-开发简单博客-项目布局、应用设置

    作者:Eason_LYC 悲观者预言失败,十言九中. 乐观者创造奇迹,一次即可. 一个人的价值,只在于他所拥有的.所以可以不学无术,但不能一无所有! 技术领域:WEB安全.网络攻防 关注WEB安全.网 ...

  9. nodejs 菜鸟教程,nodejs个人博客

    有了git和nodejs怎么搭建自己的博客 (1)假装你已经安装了,再假装你已经安装过git,再假装你注册了github账号.然后创建一个repositories.记住名字要和github用户名一致. ...

  10. uliweb新教程--多人博客系统开发

    2019独角兽企业重金招聘Python工程师标准>>> 开始写一个uliweb的新教程,主要围绕着一个多人博客系统的开发来写.下面是我想实现的功能: blog功能 blog首页展示 ...

最新文章

  1. 【rnnoise源码分析】biquad滤波器
  2. kakfa怎么看消息是否堆积_纯种哈士奇多少钱一只,怎么看是否是纯种哈士奇
  3. Code4Fun: 通过XML模板系统实现对象的灵活序列化
  4. java中的问题_java中一些常见问题
  5. poj Washing Clothes挺好的一道01背包
  6. xamarin.android listview绑定数据及点击事件
  7. Overlay 网络 VXLAN 技术解析
  8. tcp 抓包出现spurious retransmission
  9. 稳压二极管的原理,它有什么作用?
  10. springboot中如何graceful关闭服务器
  11. 每日必读DZone News—什么是敏捷真实的含义?
  12. linux的命令名必须是小写英文字母,Linux常用命令及操作
  13. 系列推荐 |《最强的 VLC 多媒体开发教程》
  14. 4.1.1 网络层的功能(路由选择与分组转发、异构网络互连、拥塞控制)
  15. Word文档 替换功能
  16. 【区块链与密码学】第9-1讲:白话群签名
  17. 【力扣每日一题】804. 唯一摩尔斯密码词
  18. google play网页改版后查看英文评论的方法
  19. mysql 1168_解决fatal error LNK1168的终极方法
  20. 计算机一级70分是什么等级,公务员笔试行测70分是个什么水平?

热门文章

  1. python scipy 密度函数 分位数 累计函数计算p值 卡方检验 t检验 F检验 假设检验 AB实验 显著性检验
  2. 下行法求最小割集案例_最小割集求法 -
  3. 腾讯视频qlv格式怎么转换成mp4在手机上播放
  4. Speedoffice(Excel)行高列宽自动调整的方法
  5. msp432快速入门第三节之让LED闪起来
  6. xlsx表格怎么筛选重复数据_excel表格怎么筛选重复数据
  7. access如何设置定期报表汇总_创建分组报表或汇总报表
  8. 绿城离职员工万言书全文
  9. 零基础学 Python(17):if 条件语句
  10. 数据表对应关系(一对一、一对多、多对多)