30天学习Python👨💻第二十五天——Web开发基础2
从Flask应用的基本结构开始,今天我实现了一些基础的功能来完善我们极简的博客应用。首先使用flask模板继承模式,我复用了通用模板的代码,并且添加了两篇虚拟的帖子来动态渲染它们。最后,生成了一个requirements.txt文件将所有的包依赖存储在一个文件中,这样就可以使用只使用一条命令下载所需要的所有包。
模板继承
现在,index.html和about.html模板包含了重复的HTML代码。因为Flask使用了Jinja作为模板引擎,我们可以使用模板继承的强大能力,创建一个包含所有通用HTML代码的基础模板,比如HTML骨架、导航栏、通用底部样式等。其他模板可以继承这个基础模板,这样可以使我们代码的重用性更高。如下我创建了一个基础的模板文件layout.html来包含通用的模板结构。
layout.html
{% extends "layout.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>About</h1>
<p class="important">
Hi. I am Arindam. I love building User Interfaces. I am currently learning
Python and created this simple blog using the Flask web development
framework.
{% endblock %}
创建可重复使用的模板块,该块的代码需要放在{% block block_name %}``{% endblock %}中。{% block %}通知模板引擎子模板可以覆盖模板的这些部分。
其他文件可以像这样继承这个基础模板
about.html
{% extends "layout.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>About</h1>
<p class="important">
Hi. I am Arindam. I love building User Interfaces. I am currently learning
Python and created this simple blog using the Flask web development
framework.
{% endblock %}
这里super()用于呈现父模板中定义的块的内容。
更多Flask模板的使用可以看这里flask.palletsprojects.com/en/1.1.x/pa…
创建404页面
在Flask中我们可以处理各种各样的异常,当路由找不到时,加载从服务器获取的资源时会显示一个自定义的404页面,当服务器内部500错误时会显示一个自定义的页面等等。我创建了一个简单的not_found.html文件当路由找不到的时候会把这个文件渲染出来。
not_found.html
{% extends 'layout.html' %}
{% block title %}Page Not Found{% endblock %}
{% block content %}
<h1>Page Not Found</h1>
<p class="important">
Sorry, this page does not exist!
{% endblock %}
server.py
@app.errorhandler(404)
def page_not_found(error):
return render_template('not_found.html'), 404
更多关于Flaks错误处理的内容请看这里ttps://flask.palletsprojects.com/en/1.1.x/patterns/errorpages/
添加帖子
类似的,我在模板目录内部创建了一个帖子文件夹,并且创建了两个假的帖子文件first-post.html和second-post.html。然后我创建类一个posts.py文件来读取所有的帖子文件,并且将文件名称存储在一个列表中,在主页面可以把它渲染出来。
post.py
import os
def get_all_post_names():
try:
post_files = os.listdir('templates/posts')
post_names = list(map(lambda x: x.split('.')[0], post_files))
return post_names
except:
print('An error occurred while fetching posts')
return []
{% extends "layout.html" %}
{% block title %}Index{% endblock %}
{% block head%}
{{ super() }}
{% endblock %}
{% block content %}
<h1 class="title">
Welcome to the Python Blog.
</h1>
<h2>Recent Posts</h2>
<ul class="post-list">
{% for post in post_names %}
<li><a href="posts/{{post}}.html">{{post}}</a></li>
{% endfor %}
</ul>
{% endblock %}
按照Jinja的模板语法,所有的Python语句都应该被写在{% %}块中。动态值写入{{ }}中。现在我们应该在主页面能够看到两篇文章。现在当我们点击一篇文章时,它应该打开相应的文章页面。我们必须创建一个动态处理文章页面的路由。
@app.route('/posts/<string:post_name>')
def show_post(post_name):
return render_template(f'posts/{post_name}.html')
这个路由将会处理页面名称,并且动态的渲染出来各自的文章页面。
生成一个requirement.txt文件
在Python项目中,我们会使用很多第三方的包。如果我们想把这个项目分享给其他人,我们需要分享整个项目文件,以及运行这个项目所需要的所有包的正确版本。这并不是很实用。
在项目中使用的下载的依赖都会列入一个单独的requirement.txt文件中(按照惯例),并使用下面的命令可以列出它们的版本
$ pip freeze > requirements.txt
这将为项目生成requirement.txt文件。这个文件可以上传到任意的GIT仓库。当有人下载这个项目时,它们只需要运行pip install -r requirement.txt文件,所有的项目依赖都会以正确的版本自动的下载。
这个项目的完整代码可以在 这里找到
参考链接
上面的项目是使用Python创建web应用的一个非常小的示例。我在下面列出了一些进一步探索的链接
- A great Python web development course from edX
- Building REST APIs using Flask
- REST api using Django
- programminghistorian.org/en/lessons/…
- Using Flask with Angular
- Using Flask with React
- Django and Angular app
这就是今天的全部了。这个系列剩下的部分,我会探索一些高级主题,比如机器学习和数据科学基础。