用Python实现一个简单的博客-Day 1

开发环境

  • Python 3.6.4
  • Flask 0.12 pip install Flask
  • UIkit 3.0.0
  • Vue.js 2.x

配置环境

Linux

在官网下载Python3的源码包,解压并进入目录

1
2
3
4
./configure && make
sudo make install
python3 -V #如成功输出版本号等信息则表示安装成功
sudo pip install Flask

Windows

在官网下载Python3的安装包,双击安装,记住勾选配置环境变量安装pip
打开命令行,输入pip install Flask

通用

将UIkit(其依赖于jQuery)和Vue.js相关文件下载,按类别放在站点根目录的static目录下,最终结构图如下:

.
├── app.py
├── blogman.py
├── README.md
├── static
│ ├── css
│ ├── fonts
│ └── js
└── templates
├── base.html
└── list.html

创建数据类

BlogMan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class BlogMan:
def __init__(self):
self.blogs = []

def new(self, title, content):
index = len(self.blogs)
self.blogs.append({
'title': title,
'content': content,
'link': '/blogs/' + str(index)
})

def list(self):
return self.blogs

博客文章存放在BlogMan实例的blogs列表中,这里暂时不会用到数据库和文件IO,缺点就是程序结束后,数据会丢失,这个我们后面再接入数据库。

调用new方法并传入文章标题和内容会构造一个dict对象存储文章数据并添加至blogs列表中。

list方法则返回实例内部的blogs列表。

构建路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
app = Flask(__name__)
blogMan = BlogMan()

@app.route('/')
def index():
blogs = blogMan.list()
return render_template('list.html', blogs=blogs)

@app.route('/blogs/new', methods=['GET', 'POST'])
def new_blog():
if request.method == 'POST':
blogMan.new(request.form['title'], request.form['content'])
return redirect(url_for('index'))
return '''
<form method="post">
<p><label>请输入文章标题 <input type=text name=title></label></p>
<p><label>请输入文章内容 <input type=text name=content></label></p>
<p><input type=submit value="提交">
</form>
'''

装饰器route会将特定URL与当前函数绑定,这样访问该URL的请求就会“转发”到这个函数

index函数和/挂钩了,直接访问网站时会调用,也就是首页的处理。这里的render_template的两个参数分别指定了Jinja模板文件和绑定的变量,这样就可以动态生成首页的内容了。

new_blog函数则在GET时输出一个表格来接收文章数据,然后POST。接收到POST的表单数据后,会调用BlogMan的new方法添加新文章。

模板

考虑到博客整站基调基本一致,我们来写一个base.html作为所有模板的基本模板,将需要的静态资源引入,并将站点分为几大版块,这样后面的模板只需要修改自己需要的版块内容即可。

接下啦我们将base.html分解成几个重要的点来讲一下

引入静态资源

1
2
3
<head>
<script src="{{ url_for('static', filename='js/awesome.js') }}></script>
</head>

这里的两对大括号表示其中的内容将会被模板引擎处理,而url_for则是一个函数,其会根据参数去加载指定文件,而不需要写上静态资源的具体路径,这样更加灵活。

内容分块

1
2
{% block content %}
{% endblock %}

这样则是声明了一个名为content的块,继承自base的模板可以覆写指定块的内容,这样就使得复用率更高了。

条件表达式

1
2
3
4
5
{% if xxx %}
xx
{% else %}
yy
{% endif %}

这样的表达式则会动态地根据xxx的值选择显示xx或者yy处的内容。

循环表达式

这个在list.html会用到

1
2
3
4
5
{% for blog in blogs %}
<h1><a href={{ blog.link }}>{{ blog.title }}</a></h1>
<p>{{ blog.content }}</p>
<hr>
{% endfor %}

这个模板会遍历blogs列表,并为每一篇博文生成一段HTML,内容包括指向文章的链接,文章标题和文章内容。

写在最后

按照上面的步骤,我们再给BlogMan加上几个方法。find方法对传入的index进行检查,并在返回文章之前检查文章的逻辑删除标志,如果其已经被标记为逻辑删除,则返回Falseupdate方法则根据文章id更新文章的标题和内容。同时对应添加处理相关URL的函数。

完整代码 Day-1

示例图: