BLOG
Enjoy when you can, and endure when you must.
APR 07, 2016/Django
用 Django 构建简易博客(二):开启博客系统之旅

在我建立这个网站之初,我就发了一个系列的博客《Django 博客系统开发》,当时的想法是将自己所学和所实践的一些东西整理一下、记录下来。时至今日,三年的时光已在眨眼间过去,我发现这几篇文章在我网站的访问量排行中依然居高不下。说明这几年大家对 Python 和 Django 的关注度确实比较高并且有很多新的开发者加入其中,这当然要数是一个非常好的趋势。但技术是不断发展的,特别 Python 和 Django 都一直处于快速发展期,当年的文章中提到的方法很多已不再适用。因此萌发了做一个更新的想法,让更多的朋友关注最新的技术,而不是面对一个旧版冥思苦想。

用 Django 来快速搭建一个简易的博客,我一直认为是一个自我实践的好方法。就像我自己的网站一样,我在多个版本迭代中出现了一个从简到繁、又从繁到简的过程,这是我不断的在尝试和优化。只要愿意关注细节、乐意去思考,即使是一个很小的东西,也能从中收获不少。

当然,这里我用到了一个名词:实践。是的,要想做出一样东西,即使再简单,也需要基础来支撑。因此在开始实践前,务必要首先学习 Python 语言本身并对 Django 开发框架有一定的了解。
这也明确了本文所面向的读者:具备 Python 基础,对 Django 开发框架有一定了解,想要利用他来做一些基础实践的开发者。如果你还处于零基础阶段,建议阅读一下 Mark Lutz 的《Learning Python》以及 《The Django Book》两本书籍,他们能够引领你进入这个奇妙的世界。

另外,文章中会包含一些我个人的编码风格、见解与主张。因此并不一定要遵循。如果对其有一些独到的看法和改进意见,我们都可以随时沟通、共同改进。

 

第二篇:开启博客系统之旅

 

美好的构想

一个好的产品要从一个好的构思开始,也就是说我们要真正明白想实现什么、要达到怎样的效果。当然,这里的例子并不能称得上是一个“美好的构想”。仅仅包含以下基本的构思:

  • 博客拥有标题、作者、正文及发布的时间等基本的元素。同时,一个博客还会隶属于一个分类,并可能包含一个或多个标签。博客也可以有一个或多个评论,评论中要记录评论者的称呼、邮箱以及评论内容;
  • 需要有一个“博客列表”页来呈现发布的博客。博客要按发布时间的倒叙来排列,每个博客都要包含标题、作者、分类、发布时间的显示(年-月-日 时:分)及节选的正文内容(前 100 个字)。点击单独的博客可以进入其详情页;
  • 需要有一个“详情”页来呈现完整的博客,包括标题、作者、分类、发布的时间、标签和完整的正文内容,并附加评论显示和发布功能。

为了最简化,我不打算用上样式布局。有时候从简开始也许会让思路更为清晰。也正因为这只是一个示例,所以这一节会有一种空荡荡的感觉。而在真正的产品开发中,诸如产品需求分析、原型设计等环节都是相当重要而繁杂的工作。

 

新增一个 APP

博客算是一个功能集,因此我们应将其体现为一个模块。这表现在 Django 应用里则是为其创建一个 APP Package。现在让 manage.py 中的 startapp 闪亮登场:

$ python manage.py startapp blog

这样,工程根目录下会增加一个 blog package 并包含如下文件/目录:

其中:

  • migrations 下包含对模型定义与修改的迁移记录;
  • admin.py 是对 Django 站点管理的定制;
  • apps.py 包含对 App 的配置;
  • models.py 应包含定义的模型;
  • tests.py 包含单元测试;
  • views.py 应包含各种视图。

注意释义中的“应”这个字,这是代表不一定要完全这么做,他们只是 Django 建议的结构。事实上“怎么玩”完全可以取决于自己,进而打造一种属于自己的代码结构。然后还需要做一件事,就是注册这个新的 APP,这样在运行工程的时候 Django 才会去识别它。打开 myblog/settings.py,在 INSTALLED_APPS 添加 blog:

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'blog',
]

 

铸造基石 —— 模型的建立

从分析“要实现什么”中,我们应该对这个要实现的系统有一个整体的认识与把控。接下来首先要做的就是通过需求来建立模型,即 M 层,它决定了数据的存取。之前的需求中存在这样的一句话:

博客拥有标题、作者、正文及发布的时间等基本的元素。同时,一个博客还会隶属于一个分类,并可能包含一个或多个标签。博客也可以有一个或多个评论,评论中要记录评论者的称呼、邮箱以及评论内容;

从中可以看出:

  1. 直接与博客相关的模型应包含三个:博客、分类以及标签。博客包含标题、作者、正文、发布时间等基础字段。分类和标签则应有名称;
  2. 一个博客仅隶属于一个分类,反过来一个分类则可以包含多个博客,这是明显的一对多的关系,因此博客中应有一个外键关联至分类;
  3. 一个博客可能包含一个或多个标签,反过来一个标签页会包含多个博客,因此是多对多的关系;
  4. 还有一个评论模型来存储用户评论,并主动关联到博客上去。一个博客可以有一个或多个评论,但反过来评论只针对一篇博客,因此也是一对多的关系。

接下来我们可以以此建立对应的模型,最基础的代码如下:

from django.db import models


class Category(models.Model):
    """
    分类
    """

    name = models.CharField('名称', max_length=16)


class Tag(models.Model):
    """
    标签
    """

    name = models.CharField('名称', max_length=16)


class Blog(models.Model):
    """
    博客
    """

    title = models.CharField('标题', max_length=32)
    author = models.CharField('作者', max_length=16)
    content = models.TextField('正文')
    created = models.DateTimeField('发布时间', auto_now_add=True)

    category = models.ForeignKey(Category, verbose_name='分类')
    tags = models.ManyToManyField(Tag, verbose_name='标签')


class Comment(models.Model):
    """
    评论
    """

    blog = models.ForeignKey(Blog, verbose_name='博客')

    name = models.CharField('称呼', max_length=16)
    email = models.EmailField('邮箱')
    content = models.CharField('内容', max_length=140)

    created = models.DateTimeField('发布时间', auto_now_add=True)

模型只是利用 Django 提供的 ORM 完成对实际表结构的映射,因此在完成模型定义后,我们需要将其真正同步到实际的数据库中去。新版本的 Django 中,该操作需要分成两步,第一步是生成 migrations:

$ python manage.py makemigrations blog

会生成如下所示的文件:

然后执行 migrate 命令来进行数据库的同步操作:

$ python35 manage.py migrate
Operations to perform:
  Apply all migrations: admin, contenttypes, auth, blog, sessions
Running migrations:
  Rendering model states... DONE
  Applying blog.0001_initial... OK

注意最后一行,说明新的表已经成功同步至数据库。

 

添加内容

既然存储博客的地方已经有了,现在是时候尝试往里面插入一些数据了,这也方便之后在实现功能之后进行测试。传统的方式可以选择手动连接到数据库,写原生的 SQL 来完成该步骤。当然还有一个更“酷”的方法就是利用 Django 内置的站点管理工具。(在前一章中我在最后的“发现更多”中提到了站点管理并建议你做一些简单的尝试,如果忽略了这一步的话,在做接下来的操作之前,你可能需要先运行 manage.py createsuperuser 命令创建一个超级管理员账户)。

我们已经注意到在 app 目录下的 admin.py 文件,要想让定义的模型在站点管理中展示,就需要在此将所需的模型显示的添加进去。打开 blog/admin.py 文件并添加如下内容:

from django.contrib import admin

from .models import Category, Tag, Blog


admin.site.register([Category, Tag, Blog])

重新运行 runserver 开发服务器并通过 /admin/ 访问后台,应该能看到我们所期望的内容:

怎么样?是不是很神奇!赶紧添加一条数据试试吧!

 

发现更多

 

这个站点管理不好用!

 

这一章的最后,我推荐使用一下 Django 的站点管理。不过你可能会在初次试用之后反驳我说“这一点也不好用!”。说得很对。类似于 “Blog Object” 这样的东西有点压根不是给人看的感觉。这是因为你还没有发现到很多可定制化的元素。因此,值得探索的东西还有很多,我只是帮你挖了个坑。

 

让编辑博客更舒心

 

在编辑博客的页面,你也许已经注意到正文的输入框不过是一个简陋的文本域。这对于要想像 Word 那样编辑一个华丽的文章是肯定不可能的事了。而反观众多成熟的博客网站后台、论坛发帖功能会发现他们就有一个类似的编辑工具。这就是所谓的富文本。其实我们自己也可以有,可以做一个大胆的尝试让自己的博客编辑也更舒心。

 

继续阅读下一篇《用 Django 构建简易博客(三):专注功能的实现之博客列表​

COMMENTS
24/08From 小王

你很帅气

22/02From 美腻的五花肉

想问一下问什么我runserver出来的网页没有排版呢TOT 好丑的页面

03/11From james

已解决

03/11From james

管理员的用户名密码是什么?执行添加超管的时候没记得输入啊?

30/10From zifeng

实时评论功能

25/07From li

刚开始学不久,怎么出来的是登录界面?

22/07From qiuhan

我来试试评论的功能

LEAVE COMMNT