本文简介
如果你学了我前面写的 Django 文章,现在已经有能力去试试自己搭建博客网站了。
虽然用的不是现在流行的前后端分离的方式(前后端分离的方式会在之后的文章讲解)。
但在搭建网站之前我们还要做一些额外的功能让你的博客内容更丰富。
比如在写博客时会给文章内容配图,会给重点内容的文本加粗或者进行高亮处理。
这就需要用到富文本编辑器了。
本文把 Django 入门阶段的最后一块拼图补全。
本文的代码比之前的 Django 文章要多,需要有点耐心,最好跟着敲一遍。
前面的文章已经介绍了怎么读写数据库,怎么将设置路由,怎么让页面动态加载内容。
我们先把这些知识点串起来,先实现一个简单的页面。将 article 这个表的数据加载到网页中展示出来。
前面我们已经将 Django 自带的后台配置起来了,现在使用这个后台添加多几篇文章。
由于前面我们将 article 表的 id 设置为不可修改,所以在模型文件中需要将这个 id 设置为自增( models.AutoField )才行,不然无法增加文章。
# blog/models.py
# 省略部分代码
class Article(models.Model):
id = models.AutoField(primary_key=True)然后再重新执行数据库迁移命令。
python manage.py makemigrations
python manage.py migrate接着就在后台开心创建文章吧。

在调整完模型并创建好文章后,接下来就要将后台编写好的这些文章放到前台展示了。
所谓的前台就是我们前面讲应用和路由时提到的内容。比如在 http://127.0.0.1:8000/blog/ 这个地址访问博客列表,在 http://127.0.0.1:8000/blog/article/<str:id>/ 这个地址后面拼上博客 id 去访问对应文章的详情。
先看看效果。

本专栏重点讲 Django ,偏后端的内容,所以页面样式我没写得很复杂(我懒)。
要实现这个功能需要走以下流程。

路由、视图、模型之间的关系大概如上图所示。
第一步先配好路由,打开项目的 urls.py ,在路由部分写上以下代码。
# demo/urls.py
from django.contrib import admin
from django.urls import path, include
from blog.views import blogIndex, article
urlpatterns = [
path("admin/", admin.site.urls),
path("blog/", blogIndex),
path("blog/article/<str:id>/", article)
]admin/ 匹配的是自带后台,blog/ 是博客列表页,blog/article/<str:id>/ 是博客详情页,<str:id> 匹配的是博客 id 。
然后在 blog 应用中创建2个视图。
# blog/views.py
from django.http import HttpResponse
from django.shortcuts import render
from blog.models import Article
# 博客列表
def blogIndex(request):
articles = Article.objects.all() # 向数据库查询所有博客
return render(request, 'blog.html', {
"articles": articles
})
# 博客详情
def article(request, id):
article = Article.objects.get(id=id) # 根据博客id,向数据库查询具体博客内容
return render(request, 'article.html', {
"article": article
})blog.html 我们在之前的文章中已经创建好了,它在 blog/templates 里。现在需要修改一下它的内容,以便呈现博客列表。
<!-- blog/templates/blog.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客</title>
<style>
.main {
width: 980px;
margin: 0 auto;
}
.main h1 {
margin: 0;
box-sizing: border-box;
padding: 10px 6px;
text-align: center;
border-bottom: 1px solid cadetblue;
}
.blog_x {
box-sizing: border-box;
padding: 6px;
}
.blog_li {
display: block;
box-sizing: border-box;
padding: 10px;
background-color: aliceblue;
margin-bottom: 10px;
text-decoration: none;
}
.blog_li:hover {
background-color: rgb(216, 239, 255);
}
.blog_li .title {
color: #333;
font-size: 20px;
font-weight: 600;
margin-bottom: 10px;
}
.blog_li .user,
.blog_li .publish_date {
color: #999;
}
</style>
</head>
<body>
<div class="main">
<h1>博客</h1>
<div class="blog_x">
{% for article in articles %}
<!-- 这个链接跳转到 blog/article/<str:id>/ 页面 -->
<a href="article/{{ article.id }}" class="blog_li">
<div class="title">{{ article.title }}</div>
<div class="user">作者:{{ article.user }}</div>
<div class="publish_date">发布时间:{{ article.publish_date }}</div>
</a>
{% endfor %}
</div>
</div>
</body>
</html>然后再创建 article.html 页面。
<!-- blog/templates/article.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ article.title }}</title>
<style>
.main {
display: flex;
justify-content: center;
margin-left: -40px;
}
.main .return_btn {
margin-right: 20px;
padding-top: 10px;
align-self: flex-start;
text-decoration: none;
color: cornflowerblue;
}
.main .article_x {
width: 980px;
}
.main .article_x .title {
text-align: center;
}
.main .article_x .user,
.main .article_x .publish_date {
text-align: center;
color: #999;
}
</style>
</head>
<body>
<div class="main" style="display: flex; align-items: center;">
<a href="javascript:history.back(-1)" class="return_btn">返回</a>
<div class="article_x">
<h1 class="title">{{ article.title }}</h1>
<p class="user">作者:{{ article.user }}</p>
<p class="publish_date">发布时间:{{ article.publish_date }}</p>
<p>{{ article.content }}</p>
</div>
</div>
</body>
</html>搞掂,做完上述几步就已经把路由、视图、模型的关系串起来了,此时在浏览器访问 http://127.0.0.1:8000/blog/ 就能查看到博客列表页。自己试试吧~
有些博客平台是有封面图的。如果我们也想给自己的博客配置封面图需要怎么做呢?

要实现封面图的功能需要5步。
Pillow**先操作第1步,安装 Pillow。**这一步非常简单,只需执行下面这条命令。
pip install Pillow**第2步,在 blog 应用中,给模型配置一个 cover_image ,**该字段就是用来存储封面图的。
# blog/models.py
# 省略部分代码
class Article(models.Model):
cover_image = models.ImageField("封面图", upload_to="cover", default="", help_text="最佳尺寸:256 x 256")models.ImageField 表示这个字段是存图片的。upload_to="cover" 意思是图片要上传到 cover 目录下。
需要注意,因为我们前面已经创建了 Article 这个模型,并且已经填充了数据进这个表了。此时增加一个字段的话,原本已经存在的数据会丢失个字段的信息的。所以在新增 cover_image 时需要配置默认值 default=""。
第3步,配置图片存储位置。
我们在项目的根目录下创建一个 media 文件夹,你可以起其他名字。在这个例子中要保存多媒体文件(图片也是一种多媒体),所以我起了一个 media 名字。
然后在项目的 settings.py 文件中加上这两句代码。
MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")意思是多媒体的路径在 /media/ 。
**第4步,生成模型迁移文件,并执行迁移操作。**这步很简单,就是用之前讲过的那2条命令。
python manage.py makemigrations
python manage.py migrate第5步,在页面中加载图片。
想在浏览器通过指定路径访问到图片资源,还需要给图片资源配置一个路由入口。
在项目的 urls.py 中写上以下代码。
# urls.py
# 省略部分代码
from django.conf import settings
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)接着就是要处理展示部分的内容了。
打开 blog/templates/blog.html 文件,在文章列表的每一项前面加上一个图片标签,读取 cover_image 这个字段的内容。
<img class="cover_image" src="/media/{{ article.cover_image }}" alt="">
要注意,图片的 src="/media/{{ article.cover_image }}" 这个值,media 前面是有一个斜杠的。
blog/templates/blog.html 的完整代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>博客</title>
<style>
.main {
width: 980px;
margin: 0 auto;
}
.main h1 {
margin: 0;
box-sizing: border-box;
padding: 10px 6px;
text-align: center;
border-bottom: 1px solid cadetblue;
}
.blog_x {
box-sizing: border-box;
padding: 6px;
}
.blog_li {
display: block;
box-sizing: border-box;
padding: 10px;
background-color: aliceblue;
margin-bottom: 10px;
text-decoration: none;
display: flex;
}
.blog_li:hover {
background-color: rgb(216, 239, 255);
}
.blog_li .title {
color: #333;
font-size: 20px;
font-weight: 600;
margin-bottom: 10px;
}
.blog_li .cover_image {
width: 80px;
height: 80px;
margin-right: 20px;
}
.blog_li .user,
.blog_li .publish_date {
color: #999;
}
</style>
</head>
<body>
<div class="main">
<h1>博客</h1>
<div class="blog_x">
{% for article in articles %}
<a href="article/{{ article.id }}" class="blog_li">
<img class="cover_image" src="/media/{{ article.cover_image }}" alt="">
<div class="article_text">
<div class="title">{{ article.title }}</div>
<div class="user">作者:{{ article.user }}</div>
<div class="publish_date">发布时间:{{ article.publish_date }}</div>
</div>
</a>
{% endfor %}
</div>
</div>
</body>
</html>最后在后台 http://127.0.0.1:8000/admin/ 手动配置好博客文章的封面图即可。

终于到本文最后一节了,富文本。
什么是富文本呢?简单来说,富文本就是一个内容丰富的文本。
相应的,要展示富文本之前,首先需要录入一段富文本内容。所以就有富文本编辑器。
Django 的生态非常丰富,我们可以用 django-ckeditor 这个富文本编辑器实现我们的需求。
先看看这个富文本编辑器长什么样子。

安装 django-ckeditor 很简单。
pip install django-ckeditor安装成功后,就要开始一系列的配置了。
首先打开项目的 settings.py 文件,加上这几行代码。
# settings.py
INSTALLED_APPS = [
# 省略部分代码
'ckeditor',
'ckeditor_uploader'
]django-ckeditor 这个富文本编辑器也是一个应用,所以需要在项目的 settings.py 里注册这个应用。
ckeditor是富文本编辑器,ckeditor_uploader是富文本上传图片的应用。
安装完 django-ckeditor 后就已经包含 ckeditor 和 ckeditor_uploade。
然后需要配置富文本上传图片的路径,也是在 settings.py里配置。
在这个文件最下方配置以下内容:
# settings.py
# 配置ckeditor
# 配置上传的路径
CKEDITOR_UPLOAD_PATH = 'upload/'
# 配置上传图片时使用的后台
CKEDITOR_IMAGE_BACKEND = 'pillow'配置完了,接下来就是使用富文本。
我们会在博客中用到富文本,所以在 blog 应用中配置一下模型。
# blog/models.py
# 省略部分代码
from ckeditor.fields import RichTextField # 导入富文本编辑器
from ckeditor_uploader.fields import RichTextUploadingField # 上传图片
class Article(models.Model):
content = RichTextUploadingField()我们将之前的 content = models.TextField() 改成 content = RichTextUploadingField(),意思是使用 django-ckeditor 并且会用到它的上传图片功能。
因为要上传图片,所以还要在项目的 urls.py 里配置一下路由。
# urls.py
# 省略部分代码
urlpatterns = [
# 省略了其他路由...
path("ckeditor", include("ckeditor_uploader.urls"))
]path("ckeditor", include("ckeditor_uploader.urls")) 这句是固定写法,因为这个 ckeditor 是我们安装的一个模块,在 Django 中它相当于一个应用,所以这些东西就和 admin 一样,它已经被我们设置好了。
因为修改了 models.py 文件,所以需要重新执行一下迁移动作。
python manage.py makemigrations
python manage.py migrate之后打开后台的博客编辑模块,编辑博客时就能看到富文本编辑器了。
但是,在保存完富文本内容后,在前台页面显示出来的内容变得有点奇怪了。

这是因为 Django 有一个自带的安全机制,如果要显示富文本内容,需要在模版中添加一个参数。
打开 blog/templates/blog.html 文件,有一段代码是 <p>{{ article.content }}</p>,意思是展示文章内容。我们需要将这段代码改为 <p>{{ article.content | safe }}</p>,然后重新刷新页面就能正常展示内容了。

safe 是 Django 自带的一个过滤器。我在 《『Django』模板使用指南》 中介绍过过滤器的用法。只不过当时没讲 safe 这个过滤器,因为当时没讲到富文本的内容。
以上就是本文的全部内容了,同时也是 《 Django 专栏》的入门篇的全部内容。
学到这里,相信你已经会做一个博客网站出来了。如果你想做一个企业官网,用以上提到的知识也是完全能实现的。
《 Django 专栏》 这个专栏还会继续写下去,接下来会讲前后端分离、部署到云服务器等内容。