Flask is a small and lightweight Python web framework that provides useful tools and features that make creating web applications in Python easier. It gives developers flexibility and is a more accessible framework for new developers since you can build a web application quickly using only a single Python file. Flask is also extensible and doesn’t force a particular directory structure or require complicated boilerplate code before getting started.
Flask是一个小型轻量级的Python Web框架,提供有用的工具和功能,这些工具和功能使使用Python创建Web应用程序更加容易。 它为开发人员提供了灵活性,并且是新开发人员更易于访问的框架,因为您可以仅使用单个Python文件快速构建Web应用程序。 Flask也是可扩展的,在开始之前不需要强制特定的目录结构或需要复杂的样板代码。
As part of this tutorial, you’ll use the Bootstrap toolkit to style your application so it is more visually appealing. Bootstrap will help you incorporate responsive web pages in your web application so that it also works well on mobile browsers without writing your own HTML, CSS, and JavaScript code to achieve these goals. The toolkit will allow you to focus on learning how Flask works.
作为本教程的一部分,您将使用Bootstrap工具箱来设置应用程序的样式,从而在外观上更具吸引力。 Bootstrap将帮助您将响应性网页合并到Web应用程序中,从而使其在移动浏览器中也能很好地工作,而无需编写自己HTML,CSS和JavaScript代码来实现这些目标。 该工具包将使您可以专注于学习Flask的工作方式。
Flask uses the Jinja template engine to dynamically build HTML pages using familiar Python concepts such as variables, loops, lists, and so on. You’ll use these templates as part of this project.
Flask使用Jinja模板引擎使用熟悉的Python概念(例如变量,循环,列表等)动态构建HTML页面。 您将使用这些模板作为该项目的一部分。
In this tutorial, you’ll build a small web blog using Flask and SQLite in Python 3. Users of the application can view all the posts in your database and click on the title of a post to view its contents with the ability to add a new post to the database and edit or delete an existing post.
在本教程中,您将使用Python 3中的Flask和SQLite构建一个小型的Web博客。该应用程序的用户可以查看数据库中的所有帖子,并单击帖子标题以查看其内容并可以添加内容。将新帖子添加到数据库,然后编辑或删除现有帖子。
Before you start following this guide, you will need:
在开始遵循本指南之前,您需要:
A local Python 3 programming environment, follow the tutorial for your distribution in How To Install and Set Up a Local Programming Environment for Python 3 series for your local machine. In this tutorial we’ll call our project directory flask_blog
.
在本地Python 3编程环境中,请按照如何为本地计算机上的Python 3系列安装和设置本地编程环境系列中的教程进行操作。 在本教程中,我们将项目目录flask_blog
。
An understanding of Python 3 concepts, such as data types, conditional statements, for loops, functions, and other such concepts. If you are not familiar with Python, check out our How To Code in Python 3 series.
对Python 3概念的理解,例如数据类型 , 条件语句 , 循环 , 函数和其他此类概念。 如果您不熟悉Python,请查看我们的《 如何使用Python 3编码》系列。
In this step, you’ll activate your Python environment and install Flask using the pip
package installer.
在此步骤中,您将激活Python环境并使用pip
软件包安装程序安装Flask。
If you haven’t already activated your programming environment, make sure you’re in your project directory (flask_blog
) and use the following command to activate the environment:
如果尚未激活编程环境,请确保您位于项目目录( flask_blog
)中,并使用以下命令激活环境:
source env/bin/activate
源ENV /斌/激活
Once your programming environment is activated, your prompt will now have an env
prefix that may look as follows:
激活编程环境后,您的提示现在将带有一个env
前缀,看起来可能如下:
This prefix is an indication that the environment env
is currently active, which might have another name depending on how you named it during creation.
此前缀表示环境env
当前处于活动状态,根据您在创建过程中的命名方式,环境env
可能具有另一个名称。
Note: You can use Git, a version control system, to effectively manage and track the development process for your project. To learn how to use Git, you might want to check out our Introduction to Git Installation Usage and Branches article.
注意:您可以使用版本控制系统Git来有效管理和跟踪项目的开发过程。 要了解如何使用Git,您可能需要查看我们的《 Git安装用法和分支简介》文章。
If you are using Git, it is a good idea to ignore the newly created env
directory in your .gitignore
file to avoid tracking files not related to the project.
如果您使用的是Git,最好忽略.gitignore
文件中新创建的env
目录,以避免跟踪与项目无关的文件。
Now you’ll install Python packages and isolate your project code away from the main Python system installation. You’ll do this using pip
and python
.
现在,您将安装Python软件包,并将您的项目代码与主要的Python系统安装隔离开。 您将使用pip
和python
进行此操作。
To install Flask, run the following command:
要安装Flask,请运行以下命令:
Once the installation is complete, run the following command to confirm the installation:
安装完成后,运行以下命令以确认安装:
You use the python
command line interface with the option -c
to execute Python code. Next you import the flask
package with import flask;
then print the Flask version, which is provided via the flask.__version__
variable.
您可以将python
命令行界面与-c
选项一起使用来执行Python代码。 接下来,使用import flask;
导入flask
包import flask;
然后打印Flask版本,该版本通过flask.__version__
变量提供。
The output will be a version number similar to the following:
输出将是类似于以下内容的版本号:
Output
1.1.2
You’ve created the project folder, a virtual environment, and installed Flask. You’re now ready to move on to setting up your base application.
您已经创建了项目文件夹,虚拟环境并安装了Flask。 现在您可以继续设置基本应用程序了。
Now that you have your programming environment set up, you’ll start using Flask. In this step, you’ll make a small web application inside a Python file and run it to start the server, which will display some information on the browser.
现在您已经设置了编程环境,您将开始使用Flask。 在此步骤中,您将在Python文件中创建一个小型Web应用程序,然后运行该应用程序以启动服务器,该服务器将在浏览器上显示一些信息。
In your flask_blog
directory, open a file named hello.py
for editing, use nano
or your favorite text editor:
在flask_blog
目录中,打开一个名为hello.py
的文件进行编辑,使用nano
或您喜欢的文本编辑器:
This hello.py
file will serve as a minimal example of how to handle HTTP requests. Inside it, you’ll import the Flask
object, and create a function that returns an HTTP response. Write the following code inside hello.py
:
此hello.py
文件将作为如何处理HTTP请求的最小示例。 在其中,您将导入Flask
对象 ,并创建一个返回HTTP响应的函数。 在hello.py
编写以下代码:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
In the preceding code block, you first import the Flask
object from the flask
package. You then use it to create your Flask application instance with the name app
. You pass the special variable __name__
that holds the name of the current Python module. It’s used to tell the instance where it’s located—you need this because Flask sets up some paths behind the scenes.
在前面的代码块中,您首先从flask
包中导入Flask
对象。 然后,您可以使用它来创建名为app
Flask应用程序实例。 您传递包含当前Python模块名称的特殊变量__name__
。 它用来告诉实例它的位置,您需要它,因为Flask在后台设置了一些路径。
Once you create the app
instance, you use it to handle incoming web requests and send responses to the user. @app.route
is a decorator that turns a regular Python function into a Flask view function, which converts the function’s return value into an HTTP response to be displayed by an HTTP client, such as a web browser. You pass the value '/'
to @app.route()
to signify that this function will respond to web requests for the URL /
, which is the main URL.
创建app
实例后,就可以使用它来处理传入的Web请求并将响应发送给用户。 @app.route
是一个修饰器 ,它将常规的Python函数转换为Flask 视图函数 ,该函数将函数的返回值转换为HTTP响应,以由HTTP客户端(例如网络浏览器)显示。 您将值'/'
传递给@app.route()
表示此函数将响应Web对URL /
请求,URL是主URL。
The hello()
view function returns the string 'Hello, World!'
as a response.
hello()
视图函数返回字符串'Hello, World!'
作为回应。
Save and close the file.
保存并关闭文件。
To run your web application, you’ll first tell Flask where to find the application (the hello.py
file in your case) with the FLASK_APP
environment variable:
要运行您的Web应用程序,您首先要使用FLASK_APP
环境变量告诉Flask在哪里找到该应用程序(在您的情况下为hello.py
文件):
Then run it in development mode with the FLASK_ENV
environment variable:
然后使用FLASK_ENV
环境变量在开发模式下运行它:
Lastly, run the application using the flask run
command:
最后,使用flask run
命令运行该应用程序:
Once the application is running the output will be something like this:
一旦应用程序运行,输出将如下所示:
Output
* Serving Flask app "hello" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 813-894-335
The preceding output has several pieces of information, such as:
前面的输出包含一些信息,例如:
Debug mode: on
signifies that the Flask debugger is running. This is useful when developing because it gives us detailed error messages when things go wrong, which makes troubleshooting easier.
Debug mode: on
亮起表示Flask调试器正在运行。 这在开发时很有用,因为当出现问题时它会向我们提供详细的错误消息,这使故障排除更加容易。
The application is running locally on the URL http://127.0.0.1:5000/
, 127.0.0.1
is the IP that represents your machine’s localhost
and :5000
is the port number.
该应用程序在URL http://127.0.0.1:5000/
上本地运行, 127.0.0.1
是代表您计算机的localhost
的IP,而:5000
是端口号。
Open a browser and type in the URL http://127.0.0.1:5000/
, you will receive the string Hello, World!
as a response, this confirms that your application is successfully running.
打开浏览器,输入URL http://127.0.0.1:5000/
,您将收到字符串Hello, World!
作为响应,这确认您的应用程序已成功运行。
Warning Flask uses a simple web server to serve our application in a development environment, which also means that the Flask debugger is running to make catching errors easier. This development server should not be used in a production deployment. See the Deployment Options page on the Flask documentation for more information, you can also check out this Flask deployment tutorial.
警告 Flask使用简单的Web服务器在开发环境中为我们的应用程序提供服务,这也意味着Flask调试器正在运行,以使捕获错误变得更加容易。 此开发服务器不应在生产部署中使用。 有关更多信息,请参见Flask文档上的Deployment Options页面。您还可以查看此Flask部署教程 。
You can now leave the development server running in the terminal and open another terminal window. Move into the project folder where hello.py
is located, activate the virtual environment, set the environment variables FLASK_ENV
and FLASK_APP
, and continue to the next steps. (These commands are listed earlier in this step.)
现在,您可以使开发服务器在终端中运行,并打开另一个终端窗口。 移入hello.py
所在的项目文件夹,激活虚拟环境,设置环境变量FLASK_ENV
和FLASK_APP
,然后继续下一步。 (这些命令在本步骤的前面列出。)
Note: When opening a new terminal, it is important to remember activating the virtual environment and setting the environment variables FLASK_ENV
and FLASK_APP
.
注意 :打开新终端时,切记要激活虚拟环境并设置环境变量FLASK_ENV
和FLASK_APP
,这一点很重要。
While a Flask application’s development server is already running, it is not possible to run another Flask application with the same flask run
command. This is because flask run
uses the port number 5000
by default, and once it is taken, it becomes unavailable to run another application on so you would receive an error similar to the following:
当Flask应用程序的开发服务器已经在运行时,无法使用相同的flask run
命令运行另一个Flask应用程序。 这是因为默认情况下, flask run
使用端口号5000
,一旦被占用,它将无法在其上运行另一个应用程序,因此您将收到类似于以下内容的错误:
Output
OSError: [Errno 98] Address already in use
To solve this problem, either stop the server that’s currently running via CTRL+C
, then run flask run
again, or if you want to run both at the same time, you can pass a different port number to the -p
argument, for example, to run another application on port 5001
use the following command:
要解决此问题,请停止通过CTRL+C
停止当前正在运行的服务器,然后再次运行flask run
,或者如果要同时运行两者,则可以将不同的端口号传递给-p
参数,例如,要在端口5001
上运行另一个应用程序,请使用以下命令:
You now have a small Flask web application. You’ve run your application and displayed information on the web browser. Next, you’ll use HTML files in your application.
您现在有了一个小的Flask Web应用程序。 您已经运行了应用程序,并在Web浏览器上显示了信息。 接下来,您将在应用程序中使用HTML文件。
Currently your application only displays a simple message without any HTML. Web applications mainly use HTML to display information for the visitor, so you’ll now work on incorporating HTML files in your app, which can be displayed on the web browser.
当前,您的应用程序仅显示一条简单的消息,没有任何HTML。 Web应用程序主要使用HTML来显示访问者的信息,因此您现在要在应用程序中合并HTML文件,该文件可以在Web浏览器上显示。
Flask provides a render_template()
helper function that allows use of the Jinja template engine. This will make managing HTML much easier by writing your HTML code in .html
files as well as using logic in your HTML code. You’ll use these HTML files, (templates) to build all of your application pages, such as the main page where you’ll display the current blog posts, the page of the blog post, the page where the user can add a new post, and so on.
Flask提供了render_template()
帮助函数,该函数允许使用Jinja模板引擎 。 通过在.html
文件中编写HTML代码以及在HTML代码中使用逻辑,这将使管理HTML更加容易。 您将使用这些HTML文件( 模板 )来构建所有应用程序页面,例如用于显示当前博客文章的主页,博客文章的页面,用户可以在其中添加新页面的页面。发布等等。
In this step, you’ll create your main Flask application in a new file.
在这一步中,您将在一个新文件中创建您的主Flask应用程序。
First, in your flask_blog
directory, use nano
or your favorite editor to create and edit your app.py
file. This will hold all the code you’ll use to create the blogging application:
首先,在flask_blog
目录中,使用nano
或您喜欢的编辑器来创建和编辑app.py
文件。 这将包含您用于创建博客应用程序的所有代码:
In this new file, you’ll import the Flask
object to create a Flask application instance as you previously did. You’ll also import the render_template()
helper function that lets you render HTML template files that exist in the templates
folder you’re about to create. The file will have a single view function that will be responsible for handling requests to the main /
route. Add the following content:
在这个新文件中,您将像以前一样导入Flask
对象以创建Flask应用程序实例。 您还将导入render_template()
帮助函数,该函数使您可以呈现要创建的templates
文件夹中存在HTML模板文件。 该文件将具有单个视图功能,该功能将负责处理对主/
路由的请求。 添加以下内容:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
The index()
view function returns the result of calling render_template()
with index.html
as an argument, this tells render_template()
to look for a file called index.html
in the templates folder. Both the folder and the file do not yet exist, you will get an error if you were to run the application at this point. You’ll run it nonetheless so you’re familiar with this commonly encountered exception. You’ll then fix it by creating the needed folder and file.
index()
视图函数返回以index.html
作为参数调用render_template()
的结果,这告诉render_template()
在模板文件夹中查找名为index.html
的文件 。 文件夹和文件都不存在,如果此时要运行该应用程序,则会出现错误。 尽管如此,您仍将运行它,因此您熟悉此常见遇到的异常。 然后,您将通过创建所需的文件夹和文件来修复它。
Save and exit the file.
保存并退出文件。
Stop the development server in your other terminal that runs the hello
application with CTRL+C
.
在另一个使用CTRL+C
运行hello
应用程序的终端中停止开发服务器。
Before you run the application, make sure you correctly specify the value for the FLASK_APP
environment variable, since you’re no longer using the application hello
:
在运行应用程序之前,请确保正确指定FLASK_APP
环境变量的值,因为您将不再使用应用程序hello
:
Opening the URL http://127.0.0.1:5000/
in your browser will result in the debugger page informing you that the index.html
template was not found. The main line in the code that was responsible for this error will be highlighted. In this case, it is the line return render_template('index.html')
.
在浏览器中打开URL http://127.0.0.1:5000/
将导致调试器页面通知您未找到index.html
模板。 代码中负责此错误的主行将突出显示。 在这种情况下,它是return render_template('index.html')
。
If you click this line, the debugger will reveal more code so that you have more context to help you solve the problem.
如果单击此行,调试器将显示更多代码,以便您有更多上下文来帮助您解决问题。
To fix this error, create a directory called templates
inside your flask_blog
directory. Then inside it, open a file called index.html
for editing:
要解决此错误,请在flask_blog
目录中创建一个名为templates
的目录。 然后在其中打开一个名为index.html
的文件进行编辑:
Next, add the following HTML code inside index.html
:
接下来,在index.html
添加以下HTML代码:
FlaskBlog
Welcome to FlaskBlog
Save the file and use your browser to navigate to http://127.0.0.1:5000/
again, or refresh the page. This time the browser should display the text Welcome to FlaskBlog
in an tag.
保存文件,然后使用浏览器再次导航到http://127.0.0.1:5000/
或刷新页面。 这次,浏览器应在标记中显示文本
Welcome to FlaskBlog
。
In addition to the templates
folder, Flask web applications also typically have a static
folder for hosting static files, such as CSS files, JavaScript files, and images the application uses.
除了templates
文件夹外,Flask Web应用程序通常还具有一个static
文件夹,用于承载静态文件,例如CSS文件,JavaScript文件和应用程序使用的图像。
You can create a style.css
style sheet file to add CSS to your application. First, create a directory called static
inside your main flask_blog
directory:
您可以创建一个style.css
样式表文件,以将CSS添加到您的应用程序中。 首先,在主flask_blog
目录中创建一个名为static
目录:
Then create another directory called css
inside the static
directory to host .css
files. This is typically done to organize static files in dedicated folders, as such, JavaScript files typically live inside a directory called js
, images are put in a directory called images
(or img
), and so on. The following command will create the css
directory inside the static
directory:
然后在static
目录中创建另一个名为css
的目录,以承载.css
文件。 通常这样做是为了将静态文件组织在专用文件夹中,因此,JavaScript文件通常位于一个名为js
的目录中,图像放在一个名为images
(或img
)的目录中,依此类推。 以下命令将在static
目录内创建css
目录:
Then open a style.css
file inside the css
directory for editing:
然后在css
目录中打开一个style.css
文件进行编辑:
Add the following CSS rule to your style.css
file:
将以下CSS规则添加到您的style.css
文件中:
h1 {
border: 2px #eee solid;
color: brown;
text-align: center;
padding: 10px;
}
The CSS code will add a border, change the color to brown, center the text, and add a little padding to tags.
CSS代码将添加边框,将颜色更改为棕色,将文本居中,并在标签上添加一些填充。
Save and close the file.
保存并关闭文件。
Next, open the index.html
template file for editing:
接下来,打开index.html
模板文件进行编辑:
You’ll add a link to the style.css
file inside the section of the
index.html
template file:
您将在index.html
模板文件的部分内添加到
style.css
文件的链接:
. . .
FlaskBlog
. . .
Here you use the url_for()
helper function to generate the appropriate location of the file. The first argument specifies that you’re linking to a static file and the second argument is the path of the file inside the static directory.
在这里,您可以使用url_for()
帮助函数来生成文件的适当位置。 第一个参数指定您要链接到静态文件,第二个参数是文件在静态目录中的路径。
Save and close the file.
保存并关闭文件。
Upon refreshing the index page of your application, you will notice that the text Welcome to FlaskBlog
is now in brown, centered, and enclosed inside a border.
刷新应用程序的索引页面后,您会注意到, Welcome to FlaskBlog
文本现在为棕色,居中并包含在边框内。
You can use the CSS language to style the application and make it more appealing using your own design. However, if you’re not a web designer, or if you aren’t familiar with CSS, then you can use the Bootstrap toolkit, which provides easy-to-use components for styling your application. In this project, we’ll use Bootstrap.
您可以使用CSS语言来设计应用程序样式,并使用自己的设计使其更具吸引力。 但是,如果您不是Web设计人员,或者您不熟悉CSS,那么可以使用Bootstrap工具箱 ,该工具箱提供了易于使用的组件来设置应用程序的样式。 在这个项目中,我们将使用Bootstrap。
You might have guessed that making another HTML template would mean repeating most of the HTML code you already wrote in the index.html
template. You can avoid unnecessary code repetition with the help of a base template file, which all of your HTML files will inherit from. See Template Inheritance in Jinja for more information.
您可能已经猜到制作另一个HTML模板将意味着重复您已经在index.html
模板中编写的大多数HTML代码。 您可以借助基本模板文件避免不必要的代码重复,该模板文件将继承所有HTML文件。 有关更多信息,请参见Jinja中的模板继承 。
To make a base template, first create a file called base.html
inside your templates
directory:
要制作基本模板,请首先在templates
目录内创建一个名为base.html
的文件:
Type the following code in your base.html
template:
在base.html
模板中输入以下代码:
{% block title %} {% endblock %}
{% block content %} {% endblock %}
Save and close the file once you’re done editing it.
完成编辑后,保存并关闭文件。
Most of the code in the preceding block is standard HTML and code required for Bootstrap. The tags provide information for the web browser, the
tag links the Bootstrap CSS files, and the
tags are links to JavaScript code that allows some additional Bootstrap features, check out the Bootstrap documentation for more.
前面块中的大多数代码是标准HTML和Bootstrap所需的代码。 标记为Web浏览器提供信息,
标记链接Bootstrap CSS文件,而
标记是指向JavaScript代码的链接,该JavaScript代码允许一些其他Bootstrap功能,请查看Bootstrap文档以获取更多信息。
However, the following highlighted parts are specific to the Jinja template engine:
但是,以下突出显示的部分特定于Jinja模板引擎:
{% block title %} {% endblock %}
: A block that serves as a placeholder for a title, you’ll later use it in other templates to give a custom title for each page in your application without rewriting the entire section each time.
{% block title %} {% endblock %}
:用作标题占位符的块 ,稍后您将在其他模板中使用该块为应用程序中的每个页面提供自定义标题,而无需重写整个每次。
{ { url_for('index')}}
: A function call that will return the URL for the index()
view function. This is different from the past url_for()
call you used to link a static CSS file, because it only takes one argument, which is the view function’s name, and links to the route associated with the function instead of a static file.
{ { url_for('index')}}
:一个函数调用,它将返回index()
视图函数的URL。 这与过去用于链接静态CSS文件的url_for()
调用不同,因为它仅采用一个参数(即视图函数的名称),并链接到与该函数关联的路由,而不是静态文件。
{% block content %} {% endblock %}
: Another block that will be replaced by content depending on the child template (templates that inherit from base.html
) that will override it.
{% block content %} {% endblock %}
:另一个块将由内容替换,具体取决于将覆盖它的子模板 (从base.html
继承的base.html
)。
Now that you have a base template, you can take advantage of it using inheritance. Open the index.html
file:
有了基本模板后,您就可以通过继承来利用它了。 打开index.html
文件:
Then replace its contents with the following:
然后将其内容替换为以下内容:
{% extends 'base.html' %}
{% block content %}
{% block title %} Welcome to FlaskBlog {% endblock %}
{% endblock %}
In this new version of the index.html
template, you use the {% extends %}
tag to inherit from the base.html
template. You then extend it via replacing the content
block in the base template with what is inside the content
block in the preceding code block.
在index.html
模板的此新版本中,您使用{% extends %}
标记从base.html
模板继承。 然后,您可以通过将基本模板中的content
块替换为前面代码块中content
块内部的content
扩展它。
This content
block contains an tag with the text
Welcome to FlaskBlog
inside a title
block, which in turn replaces the original title
block in the base.html
template with the text Welcome to FlaskBlog
. This way, you can avoid repeating the same text twice, as it works both as a title for the page and a heading that appears below the navigation bar inherited from the base template.
此content
块包含与文本标签
Welcome to FlaskBlog
一个内部title
块,这反过来又替代原始title
的块base.html
与文本模板Welcome to FlaskBlog
。 这样,您可以避免重复两次相同的文本,因为它既可以作为页面的标题,也可以作为从基本模板继承的导航栏下方显示的标题。
Template inheritance also gives you the ability to reuse the HTML code you have in other templates (base.html
in this case) without having to repeat it each time it is needed.
模板继承还使您能够重复使用其他模板中HTML代码(在本例中为base.html
),而不必在每次需要时都重复该代码。
Save and close the file and refresh the index page on your browser. You’ll see your page with a navigation bar and styled title.
保存并关闭文件,然后在浏览器上刷新索引页面。 您将看到带有导航栏和样式标题的页面。
You’ve used HTML templates and static files in Flask. You also used Bootstrap to start refining the look of your page and a base template to avoid code repetition. In the next step, you’ll set up a database that will store your application data.
您已经在Flask中使用了HTML模板和静态文件。 您还使用了Bootstrap开始完善页面的外观和基本模板,以避免代码重复。 在下一步中,您将建立一个数据库来存储您的应用程序数据。
In this step, you’ll set up a database to store data, that is, the blog posts for your application. You’ll also populate the database with a few example entries.
在此步骤中,您将建立一个数据库来存储数据,即应用程序的博客文章。 您还将用一些示例条目填充数据库。
You’ll use a SQLite database file to store your data because the sqlite3
module, which we will use to interact with the database, is readily available in the standard Python library. For more information about SQLite, check out this tutorial.
您将使用SQLite数据库文件存储数据,因为标准Python库中已经提供了sqlite3
模块(我们将使用该模块与数据库进行交互)。 有关SQLite的更多信息,请查看本教程 。
First, because data in SQLite is stored in tables and columns, and since your data mainly consists of blog posts, you first need to create a table called posts
with the necessary columns. You’ll create a .sql
file that contains SQL commands to create the posts
table with a few columns. You’ll then use this file to create the database.
首先,由于SQLite中的数据存储在表和列中,并且由于数据主要由博客帖子组成,因此您首先需要创建一个具有必要列的表,称为posts
。 您将创建一个包含SQL命令的.sql
文件,以创建带有几列的posts
表。 然后,您将使用此文件来创建数据库。
Open a file called schema.sql
inside your flask_blog
directory:
打开一个名为schema.sql
的内部flask_blog
目录:
Type the following SQL commands inside this file:
在此文件中键入以下SQL命令:
DROP TABLE IF EXISTS posts;
CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
title TEXT NOT NULL,
content TEXT NOT NULL
);
Save and close the file.
保存并关闭文件。
The first SQL command is DROP TABLE IF EXISTS posts;
, this deletes any already existing tables named posts
so you don’t get confusing behavior. Note that this will delete all of the content you have in the database whenever you use these SQL commands, so ensure you don’t write any important content in the web application until you finish this tutorial and experiment with the final result. Next, CREATE TABLE posts
is used to create the posts
table with the following columns:
第一个SQL命令是DROP TABLE IF EXISTS posts;
,这将删除任何已存在的名为posts
表,因此您不会感到困惑。 请注意,无论何时使用这些SQL命令,这都会删除数据库中所有的内容,因此请确保在完成本教程并尝试最终结果之前,不要在Web应用程序中编写任何重要的内容。 接下来,使用CREATE TABLE posts
创建具有以下列的posts
表:
id
: An integer that represents a primary key, this will get assigned a unique value by the database for each entry (that is a blog post).
id
:代表主键的整数,数据库将为每个条目(即博客文章)分配一个唯一值。
created
: The time the blog post was created at. NOT NULL
signifies that this column should not be empty and the DEFAULT
value is the CURRENT_TIMESTAMP
value, which is the time at which the post was added to the database. Just like id
, you don’t need to specify a value for this column, as it will be automatically filled in.
created
: created
博客文章的时间。 NOT NULL
表示此列不应为空,并且DEFAULT
值是CURRENT_TIMESTAMP
值,这是将帖子添加到数据库的时间。 就像id
一样,您无需为此列指定值,因为它将自动填充。
title
: The post title.
title
:帖子标题。
content
: The post content.
content
:帖子内容。
Now that you have a SQL schema in the schema.sql
file, you’ll use it to create the database using a Python file that will generate an SQLite .db
database file. Open a file named init_db.py
inside the flask_blog
directory using your preferred editor:
现在,您在schema.sql
文件中有了一个SQL模式,您将使用它通过一个Python文件创建数据库,该文件将生成一个SQLite .db
数据库文件。 使用您喜欢的编辑器在flask_blog
目录中打开一个名为init_db.py
的文件:
And then add the following code.
然后添加以下代码。
import sqlite3
connection = sqlite3.connect('database.db')
with open('schema.sql') as f:
connection.executescript(f.read())
cur = connection.cursor()
cur.execute("INSERT INTO posts (title, content) VALUES (?, ?)",
('First Post', 'Content for the first post')
)
cur.execute("INSERT INTO posts (title, content) VALUES (?, ?)",
('Second Post', 'Content for the second post')
)
connection.commit()
connection.close()
You first import the sqlite3
module and then open a connection to a database file named database.db
, which will be created once you run the Python file. Then you use the open()
function to open the schema.sql
file. Next you execute its contents using the executescript()
method that executes multiple SQL statements at once, which will create the posts
table. You create a Cursor object that allows you to use its execute()
method to execute two INSERT
SQL statements to add two blog posts to your posts
table. Finally, you commit the changes and close the connection.
首先导入sqlite3
模块,然后打开与名为database.db
的数据库文件的连接,该文件将在运行Python文件后创建。 然后,您使用open()
函数打开schema.sql
文件。 接下来,使用executescript()
方法执行其内容,该方法一次执行多个SQL语句,这将创建posts
表。 您创建一个Cursor对象 ,该对象允许您使用其execute()
方法执行两个INSERT
SQL语句,以将两个博客文章添加到您的posts
表中。 最后,提交更改并关闭连接。
Save and close the file and then run it in the terminal using the python
command:
保存并关闭文件,然后使用python
命令在终端中运行该文件:
Once the file finishes execution, a new file called database.db
will appear in your flask_blog
directory. This means you’ve successfully set up your database.
文件执行完毕后,一个名为database.db
的新文件将出现在flask_blog
目录中。 这意味着您已经成功设置了数据库。
In the next step, you’ll retrieve the posts you inserted into your database and display them in your application’s homepage.
在下一步中,您将检索插入数据库中的帖子,并将其显示在应用程序的主页中。
Now that you’ve set up your database, you can now modify the index()
view function to display all the posts you have in your database.
现在,您已经建立了数据库,现在可以修改index()
视图函数以显示数据库中所有的帖子。
Open the app.py
file to make the following modifications:
打开app.py
文件进行以下修改:
For your first modification, you’ll import the sqlite3
module at the top of the file:
对于第一次修改,您将在文件顶部导入sqlite3
模块:
import sqlite3
from flask import Flask, render_template
. . .
Next, you’ll create a function that creates a database connection and return it. Add it directly after the imports:
接下来,您将创建一个函数,该函数创建数据库连接并返回它。 导入后直接添加:
. . .
from flask import Flask, render_template
def get_db_connection():
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row
return conn
. . .
This get_db_connection()
function opens a connection to the database.db
database file, and then sets the row_factory
attribute to sqlite3.Row
so you can have name-based access to columns. This means that the database connection will return rows that behave like regular Python dictionaries. Lastly, the function returns the conn
connection object you’ll be using to access the database.
此get_db_connection()
函数打开与database.db
数据库文件的连接,然后将row_factory
属性设置为sqlite3.Row
以便您可以对列进行基于名称的访问。 这意味着数据库连接将返回行为类似于常规Python字典的行。 最后,该函数返回将用于访问数据库的conn
连接对象。
After defining the get_db_connection()
function, modify the index()
function to look like the following:
定义get_db_connection()
函数后,将index()
函数修改为如下所示:
. . .@app.route('/')
def index():
conn = get_db_connection()
posts = conn.execute('SELECT * FROM posts').fetchall()
conn.close()
return render_template('index.html', posts=posts)
In this new version of the index()
function, you first open a database connection using the get_db_connection()
function you defined earlier. Then you execute an SQL query to select all entries from the posts
table. You implement the fetchall()
method to fetch all the rows of the query result, this will return a list of the posts you inserted into the database in the previous step.
在这个新版本的index()
函数中,您首先使用先前定义的get_db_connection()
函数打开数据库连接。 然后,执行SQL查询以从posts
表中选择所有条目。 您实现fetchall()
方法来获取查询结果的所有行,这将返回上一步中插入数据库的帖子列表。
You close the database connection using the close()
method and return the result of rendering the index.html
template. You also pass the posts
object as an argument, which contains the results you got from the database, this will allow you to access the blog posts in the index.html
template.
您使用close()
方法关闭数据库连接,并返回呈现index.html
模板的结果。 您还可以将posts
对象作为参数传递,其中包含您从数据库获得的结果,这将使您可以访问index.html
模板中的博客文章。
With these modifications in place, save and close the app.py
file.
完成这些修改后,保存并关闭app.py
文件。
Now that you’ve passed the posts you fetched from the database to the index.html
template, you can use a for
loop to display each post on your index page.
现在,您已经将从数据库中获取的帖子传递到了index.html
模板,您可以使用for
循环在索引页面上显示每个帖子。
Open the index.html
file:
打开index.html
文件:
Then, modify it to look as follows:
然后,对其进行修改,如下所示:
{% extends 'base.html' %}
{% block content %}
{% block title %} Welcome to FlaskBlog {% endblock %}
{% for post in posts %}
{
{ post['title'] }}
{
{ post['created'] }}
{% endfor %}
{% endblock %}
Here, the syntax {% for post in posts %}
is a Jinja for
loop, which is similar to a Python for
loop except that it has to be later closed with the {% endfor %}
syntax. You use this syntax to loop over each item in the posts
list that was passed by the index()
function in the line return render_template('index.html', posts=posts)
. Inside this for
loop, you display the post title in an heading inside an
tag (you’ll later use this tag to link to each post individually).
在这里,语法{% for post in posts %}
是Jinja for
循环,与Python for
loop相似,不同之处在于以后必须使用{% endfor %}
语法将其关闭。 您可以使用此语法在return render_template('index.html', posts=posts)
行中由index()
函数传递的posts
列表中的每个项目上进行循环。 在此for
循环中,您可以在标记内的
标题中显示帖子标题(您稍后将使用此标记单独链接到每个帖子)。
You display the title using a literal variable delimiter ({ { ... }}
). Remember that post
will be a dictionary-like object, so you can access the post title with post['title']
. You also display the post creation date using the same method.
您可以使用文字变量定界符( { { ... }}
)显示标题。 请记住, post
将是一个类似于字典的对象,因此您可以使用post['title']
访问帖子标题。 您还可以使用相同的方法显示创建后的日期。
Once you are done editing the file, save and close it. Then navigate to the index page in your browser. You’ll see the two posts you added to the database on your page.
编辑完文件后,保存并关闭它。 然后在浏览器中导航到索引页面。 您会在页面上看到添加到数据库中的两个帖子。
Now that you’ve modified the index()
view function to display all the posts you have in the database on your application’s homepage, you’ll move on to display each post in a single page and allow users to link to each individual post.
现在,您已经修改了index()
视图函数以在应用程序的主页上显示数据库中所有的帖子,接下来将继续在单个页面中显示每个帖子,并允许用户链接到每个单独的帖子。
In this step, you’ll create a new Flask route with a view function and a new HTML template to display an individual blog post by its ID.
在此步骤中,您将创建一个具有查看功能的新Flask路线和一个新HTML模板,以按ID显示单个博客文章。
By the end of this step, the URL http://127.0.0.1:5000/1
will be a page that displays the first post (because it has the ID 1
). The http://127.0.0.1:5000/ID
URL will display the post with the associated ID
number if it exists.
在此步骤结束时,URL http://127.0.0.1:5000/1
将是显示第一篇文章的页面(因为它的ID为1
)。 如果存在,则http://127.0.0.1:5000/ ID
URL将显示带有相关ID
号的帖子。
Open app.py
for editing:
打开app.py
进行编辑:
Since you’ll need to get a blog post by its ID from the database in multiple locations later in this project, you’ll create a standalone function called get_post()
. You can call it by passing it an ID and receive back the blog post associated with the provided ID, or make Flask respond with a 404 Not Found
message if the blog post does not exist.
由于在此项目后面的多个位置需要从数据库中获取博客文章的ID,因此您将创建一个独立的函数get_post()
。 您可以通过传递一个ID来调用它,并返回与提供的ID相关联的博客帖子,或者如果该博客帖子不存在,请让Flask响应并返回404 Not Found
消息。
To respond with a 404
page, you need to import the abort()
function from the Werkzeug
library, which was installed along with Flask, at the top of the file:
要响应404
页面,您需要从Werkzeug
库(与Flask一起安装abort()
导入abort()
函数,该库位于文件顶部:
import sqlite3
from flask import Flask, render_template
from werkzeug.exceptions import abort
. . .
Then, add the get_post()
function right after the get_db_connection()
function you created in the previous step:
然后,在上一步中创建的get_db_connection()
函数之后get_db_connection()
添加get_post()
函数:
. . .
def get_db_connection():
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row
return conn
def get_post(post_id):
conn = get_db_connection()
post = conn.execute('SELECT * FROM posts WHERE id = ?',
(post_id,)).fetchone()
conn.close()
if post is None:
abort(404)
return post
. . .
This new function has a post_id
argument that determines what blog post to return.
这个新函数具有一个post_id
参数,该参数确定要返回的博客文章。
Inside the function, you use the get_db_connection()
function to open a database connection and execute a SQL query to get the blog post associated with the given post_id
value. You add the fetchone()
method to get the result and store it in the post
variable then close the connection. If the post
variable has the value None
, meaning no result was found in the database, you use the abort()
function you imported earlier to respond with a 404
error code and the function will finish execution. If however, a post was found, you return the value of the post
variable.
在该函数内部,使用get_db_connection()
函数打开数据库连接并执行SQL查询以获取与给定post_id
值关联的博客帖子。 您添加fetchone()
方法以获取结果并将其存储在post
变量中,然后关闭连接。 如果post
变量的值为None
,这意味着在数据库中找不到结果,则可以使用之前导入的abort()
函数以404
错误代码进行响应,并且该函数将完成执行。 但是,如果找到帖子,则返回post
变量的值。
Next, add the following view function at the end of the app.py
file:
接下来,在app.py
文件的末尾添加以下视图函数:
. . .
@app.route('/')
def post(post_id):
post = get_post(post_id)
return render_template('post.html', post=post)
In this new view function, you add a variable rule
to specify that the part after the slash (/
) is a positive integer (marked with the int
converter) that you need to access in your view function. Flask recognizes this and passes its value to the post_id
keyword argument of your post()
view function. You then use the get_post()
function to get the blog post associated with the specified ID and store the result in the post
variable, which you pass to a post.html
template that you’ll soon create.
在这个新的视图函数中,您添加了一个可变规则
以指定斜杠( /
)后的部分是需要在视图函数中访问的正整数(标记为int
转换器)。 Flask会识别出该错误,并将其值传递给post()
视图函数的post_id
关键字参数。 然后,您可以使用get_post()
函数获取与指定ID关联的博客帖子,并将结果存储在post
变量中,该变量将传递到您将很快创建的post.html
模板中。
Save the app.py
file and open a new post.html
template file for editing:
保存app.py
文件并打开一个新的post.html
模板文件以进行编辑:
Type the following code in this new post.html
file. This will be similar to the index.html
file, except that it will only display a single post, in addition to also displaying the contents of the post:
在这个新的post.html
文件中键入以下代码。 这将与index.html
文件类似,除了它仅显示单个帖子之外,还显示帖子的内容:
{% extends 'base.html' %}
{% block content %}
{% block title %} {
{ post['title'] }} {% endblock %}
{
{ post['created'] }}
{
{ post['content'] }}
{% endblock %}
You add the title
block that you defined in the base.html
template to make the title of the page reflect the post title that is displayed in an heading at the same time.
您添加title
,你在定义块base.html
模板,使页面的标题反映了被显示在文章标题在同一时间前往。
Save and close the file.
保存并关闭文件。
You can now navigate to the following URLs to see the two posts you have in your database, along with a page that tells the user that the requested blog post was not found (since there is no post with an ID number of 3
so far):
现在,您可以导航到以下URL,以查看数据库中已有的两个帖子,以及一个页面,该页面告诉用户未找到所请求的博客帖子(因为到目前为止没有ID号为3
帖子) :
http://127.0.0.1:5000/1
http://127.0.0.1:5000/2
http://127.0.0.1:5000/3
Going back to the index page, you’ll make each post title link to its respective page. You’ll do this using the url_for()
function. First, open the index.html
template for editing:
返回索引页面,您将使每个帖子标题链接到其各自的页面。 您将使用url_for()
函数进行此操作。 首先,打开index.html
模板进行编辑:
Then change the value of the href
attribute from #
to { { url_for('post', post_id=post['id']) }}
so that the for
loop will look exactly as follows:
然后将href
属性的值从#
更改为{ { url_for('post', post_id=post['id']) }}
以便for
循环如下所示:
{% for post in posts %}
{
{ post['title'] }}
{
{ post['created'] }}
{% endfor %}
Here, you pass 'post'
to the url_for()
function as a first argument. This is the name of the post()
view function and since it accepts a post_id
argument, you give it the value post['id']
. The url_for()
function will return the proper URL for each post based on its ID.
在这里,您将'post'
作为第一个参数传递给url_for()
函数。 这是post()
视图函数的名称,由于它接受post_id
参数,因此您可以给它赋值post['id']
。 url_for()
函数将根据其ID返回每个帖子的正确URL。
Save and close the file.
保存并关闭文件。
The links on the index page will now function as expected. With this, you’ve now finished building the part of the application responsible for displaying the blog posts in your database. Next, you’ll add the ability to create, edit, and delete blog posts to your application.
现在,索引页面上的链接将按预期运行。 至此,您现在已经完成了应用程序部分的构建,该部分负责在数据库中显示博客文章。 接下来,您将添加在应用程序中创建,编辑和删除博客文章的功能。
Now that you’ve finished displaying the blog posts that are present in the database on the web application, you need to allow the users of your application to write new blog posts and add them to the database, edit the existing ones, and delete unnecessary blog posts.
现在,您已经完成了显示Web应用程序数据库中存在的博客文章的工作,您需要允许应用程序的用户编写新的博客文章并将其添加到数据库中,编辑现有的博客文章,并删除不必要的博客文章博客文章。
Up to this point, you have an application that displays the posts in your database but provides no way of adding a new post unless you directly connect to the SQLite database and add one manually. In this section, you’ll create a page on which you will be able to create a post by providing its title and content.
到目前为止,您已经有了一个应用程序,该应用程序显示数据库中的帖子,但是除非您直接连接到SQLite数据库并手动添加一个帖子,否则无法添加新帖子。 在本部分中,您将创建一个页面,通过提供标题和内容可以在其上创建帖子。
Open the app.py
file for editing:
打开app.py
文件进行编辑:
First, you’ll import the following from the Flask framework:
首先,您将从Flask框架导入以下内容:
The global request
object to access incoming request data that will be submitted via an HTML form.
全局request
对象,用于访问将通过HTML表单提交的传入请求数据。
The url_for()
function to generate URLs.
url_for()
函数生成URL。
The flash()
function to flash a message when a request is processed.
flash()
函数用于在处理请求时刷新消息。
The redirect()
function to redirect the client to a different location.
redirect()
函数可将客户端重定向到其他位置。
Add the imports to your file like the following:
将导入内容添加到文件中,如下所示:
import sqlite3
from flask import Flask, render_template, request, url_for, flash, redirect
from werkzeug.exceptions import abort
. . .
The flash()
function stores flashed messages in the client’s browser session, which requires setting a secret key. This secret key is used to secure sessions, which allow Flask to remember information from one request to another, such as moving from the new post page to the index page. The user can access the information stored in the session, but cannot modify it unless they have the secret key, so you must never allow anyone to access your secret key. See the Flask documentation for sessions for more information.
flash()
函数将flash()
消息存储在客户端的浏览器会话中,这需要设置密钥 。 此密钥用于保护会话,从而使Flask能够记住从一个请求到另一个请求的信息,例如从新的帖子页移到索引页。 用户可以访问存储在会话中的信息,但除非拥有密钥,否则无法对其进行修改,因此您绝不能允许任何人访问您的密钥。 有关更多信息,请参见Flask文档以获取会话 。
To set a secret key, you’ll add a SECRET_KEY
configuration to your application via the app.config
object. Add it directly following the app
definition before defining the index()
view function:
要设置密钥 ,您将通过app.config
对象向您的应用程序添加SECRET_KEY
配置。 在定义index()
视图函数之前,将其直接添加到app
定义之后:
. . .
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your secret key'
@app.route('/')
def index():
conn = get_db_connection()
posts = conn.execute('SELECT * FROM posts').fetchall()
conn.close()
return render_template('index.html', posts=posts)
. . .
Remember that the secret key should be a long random string.
请记住,密钥应该是一个长随机字符串。
After setting a secret key, you’ll create a view function that will render a template that displays a form you can fill in to create a new blog post. Add this new function at the bottom of the file:
设置密钥后,您将创建一个视图函数,该函数将呈现一个模板,该模板显示可填写的表单以创建新的博客文章。 在文件底部添加此新功能:
. . .
@app.route('/create', methods=('GET', 'POST'))
def create():
return render_template('create.html')
This creates a /create
route that accepts both GET and POST requests. GET requests are accepted by default. To also accept POST requests, which are sent by the browser when submitting forms, you’ll pass a tuple with the accepted types of requests to the methods
argument of the @app.route()
decorator.
这将创建一个同时接受GET和POST请求的/create
路由。 默认情况下接受GET请求。 为了也接受浏览器在提交表单时发送的POST请求,您将一个带有接受的请求类型的元组传递给@app.route()
装饰器的methods
参数。
Save and close the file.
保存并关闭文件。
To create the template, open a file called create.html
inside your templates
folder:
要创建模板, create.html
在templates
文件夹中打开一个名为create.html
的文件:
Add the following code inside this new file:
在此新文件中添加以下代码:
{% extends 'base.html' %}
{% block content %}
{% block title %} Create a New Post {% endblock %}
{% endblock %}
Most of this code is standard HTML. It will display an input box for the post title, a text area for the post content, and a button to submit the form.
这些代码大部分是标准HTML。 它将显示帖子标题的输入框,帖子内容的文本区域以及提交表单的按钮。
The value of the post title input is { { request.form['title'] }}
and the text area has the value { { request.form['content'] }}
, this is done so that the data you enter does not get lost if something goes wrong. For example, if you write a long post and you forget to give it a title, a message will be displayed informing you that the title is required. This will happen without losing the post you wrote since it will be stored in the request
global object that you have access to in your templates.
帖子标题输入的值为{ { request.form['title'] }}
,文本区域的值为{ { request.form['content'] }}
,这样做是为了使您输入的数据如果出现问题,不会迷路。 例如,如果您写了一篇长文章而忘记给它命名,则会显示一条消息,通知您标题是必需的。 这将不会丢失您写的帖子,因为它将被存储在您可以在模板中访问的request
全局对象中。
Now, with the development server running, use your browser to navigate to the /create
route:
现在,在运行开发服务器的情况下,使用浏览器导航到/create
路由:
http://127.0.0.1:5000/create
You will see a Create a New Post page with a box for a title and content.
您将看到“ 创建新帖子”页面,其中包含标题和内容的框。
This form submits a POST request to your create()
view function. However, there is no code to handle a POST request in the function yet, so nothing happens after filling in the form and submitting it.
该表单向您的create()
视图函数提交POST请求。 但是,该函数中尚无代码可处理POST请求,因此在填写表格并提交后没有任何React。
You’ll handle the incoming POST request when a form is submitted. You’ll do this inside the create()
view function. You can separately handle the POST request by checking the value of request.method
. When its value is set to 'POST'
it means the request is a POST request, you’ll then proceed to extract submitted data, validate it, and insert it into your database.
提交表单后,您将处理传入的POST请求。 您将在create()
视图函数中执行此操作。 您可以通过检查request.method
的值来单独处理POST请求。 当其值设置为'POST'
,表示该请求是POST请求,然后您将继续提取提交的数据,对其进行验证,然后将其插入数据库中。
Open the app.py
file for editing:
打开app.py
文件进行编辑:
Modify the create()
view function to look exactly as follows:
修改create()
视图函数,使其外观如下所示:
. . .@app.route('/create', methods=('GET', 'POST'))
def create():
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
if not title:
flash('Title is required!')
else:
conn = get_db_connection()
conn.execute('INSERT INTO posts (title, content) VALUES (?, ?)',
(title, content))
conn.commit()
conn.close()
return redirect(url_for('index'))
return render_template('create.html')
In the if
statement you ensure that the code following it is only executed when the request is a POST request via the comparison request.method == 'POST'
.
在if
语句中,确保仅通过比较请求将请求后的代码作为POST请求执行request.method == 'POST'
。
You then extract the submitted title and content from the request.form
object that gives you access to the form data in the request. If the title is not provided, the condition if not title
would be fulfilled, displaying a message to the user informing them that the title is required. If, on the other hand, the title is provided, you open a connection with the get_db_connection()
function and insert the title and the content you received into the posts
table.
然后,您从request.form
对象提取提交的标题和内容,该对象使您可以访问请求中的表单数据。 如果未提供if not title
则将满足if not title
的条件,并向用户显示一条消息,通知他们要求标题。 另一方面,如果提供了标题,则可以使用get_db_connection()
函数打开一个连接,然后将标题和收到的内容插入posts
表中。
You then commit the changes to the database and close the connection. After adding the blog post to the database, you redirect the client to the index page using the redirect()
function passing it the URL generated by the url_for()
function with the value 'index'
as an argument.
然后,将更改提交到数据库并关闭连接。 将博客文章添加到数据库后,您可以使用redirect()
函数将客户端重定向到索引页面,并向其传递url_for()
函数生成的URL,并将值'index'
作为参数。
Save and close the file.
保存并关闭文件。
Now, navigate to the /create
route using your web browser:
现在,使用您的网络浏览器导航到/create
路由:
http://127.0.0.1:5000/create
Fill in the form with a title of your choice and some content. Once you submit the form, you will see the new post listed on the index page.
在表格中填写您选择的标题和一些内容。 Once you submit the form, you will see the new post listed on the index page.
Lastly, you’ll display flashed messages and add a link to the navigation bar in the base.html
template to have easy access to this new page. Open the template file:
Lastly, you'll display flashed messages and add a link to the navigation bar in the base.html
template to have easy access to this new page. Open the template file:
Edit the file by adding a new tag following the
About
link inside the tag. Then add a new
for
loop directly above the content
block to display the flashed messages below the navigation bar. These messages are available in the special get_flashed_messages()
function Flask provides:
Edit the file by adding a new tag following the
About
link inside the tag. Then add a new
for
loop directly above the content
block to display the flashed messages below the navigation bar. These messages are available in the special get_flashed_messages()
function Flask provides:
{% for message in get_flashed_messages() %}
{
{ message }}
{% endfor %}
{% block content %} {% endblock %}
Save and close the file. The navigation bar will now have a New Post
item that links to the /create
route.
保存并关闭文件。 The navigation bar will now have a New Post
item that links to the /create
route.
For a blog to be up to date, you’ll need to be able to edit your existing posts. This section will guide you through creating a new page in your application to simplify the process of editing a post.
For a blog to be up to date, you'll need to be able to edit your existing posts. This section will guide you through creating a new page in your application to simplify the process of editing a post.
First, you’ll add a new route to the app.py
file. Its view function will receive the ID of the post that needs to be edited, the URL will be in the format /post_id/edit
with the post_id
variable being the ID of the post. Open the app.py
file for editing:
First, you'll add a new route to the app.py
file. Its view function will receive the ID of the post that needs to be edited, the URL will be in the format / post_id /edit
with the post_id
variable being the ID of the post. Open the app.py
file for editing:
Next, add the following edit()
view function at the end of the file. Editing an existing post is similar to creating a new one, so this view function will be similar to the create()
view function:
Next, add the following edit()
view function at the end of the file. Editing an existing post is similar to creating a new one, so this view function will be similar to the create()
view function:
. . .
@app.route('//edit', methods=('GET', 'POST'))
def edit(id):
post = get_post(id)
if request.method == 'POST':
title = request.form['title']
content = request.form['content']
if not title:
flash('Title is required!')
else:
conn = get_db_connection()
conn.execute('UPDATE posts SET title = ?, content = ?'
' WHERE id = ?',
(title, content, id))
conn.commit()
conn.close()
return redirect(url_for('index'))
return render_template('edit.html', post=post)
The post you edit is determined by the URL and Flask will pass the ID number to the edit()
function via the id
argument. You add this value to the get_post()
function to fetch the post associated with the provided ID from the database. The new data will come in a POST request, which is handled inside the if request.method == 'POST'
condition.
The post you edit is determined by the URL and Flask will pass the ID number to the edit()
function via the id
argument. You add this value to the get_post()
function to fetch the post associated with the provided ID from the database. The new data will come in a POST request, which is handled inside the if request.method == 'POST'
condition.
Just like when you create a new post, you first extract the data from the request.form
object then flash a message if the title has an empty value, otherwise, you open a database connection. Then you update the posts
table by setting a new title and new content where the ID of the post in the database is equal to the ID that was in the URL.
Just like when you create a new post, you first extract the data from the request.form
object then flash a message if the title has an empty value, otherwise, you open a database connection. Then you update the posts
table by setting a new title and new content where the ID of the post in the database is equal to the ID that was in the URL.
In the case of a GET request, you render an edit.html
template passing in the post
variable that holds the returned value of the get_post()
function. You’ll use this to display the existing title and content on the edit page.
In the case of a GET request, you render an edit.html
template passing in the post
variable that holds the returned value of the get_post()
function. You'll use this to display the existing title and content on the edit page.
Save and close the file, then create a new edit.html
template:
Save and close the file, then create a new edit.html
template:
Write the following code inside this new file:
Write the following code inside this new file:
{% extends 'base.html' %}
{% block content %}
{% block title %} Edit "{
{ post['title'] }}" {% endblock %}
{% endblock %}
Save and close the file.
保存并关闭文件。
This code follows the same pattern except for the { { request.form['title'] or post['title'] }}
and { { request.form['content'] or post['content'] }}
syntax. This displays the data stored in the request if it exists, otherwise it displays the data from the post
variable that was passed to the template containing current database data.
This code follows the same pattern except for the { { request.form['title'] or post['title'] }}
and { { request.form['content'] or post['content'] }}
syntax. This displays the data stored in the request if it exists, otherwise it displays the data from the post
variable that was passed to the template containing current database data.
Now, navigate to the following URL to edit the first post:
Now, navigate to the following URL to edit the first post:
http://127.0.0.1:5000/1/edit
You will see an Edit “First Post” page.
You will see an Edit “First Post” page.
Edit the post and submit the form, then make sure the post was updated.
Edit the post and submit the form, then make sure the post was updated.
You now need to add a link that points to the edit page for each post on the index page. Open the index.html
template file:
You now need to add a link that points to the edit page for each post on the index page. Open the index.html
template file:
Edit the file to look exactly like the following:
Edit the file to look exactly like the following:
{% extends 'base.html' %}
{% block content %}
{% block title %} Welcome to FlaskBlog {% endblock %}
{% for post in posts %}
{
{ post['title'] }}
{
{ post['created'] }}
Edit
{% endfor %}
{% endblock %}
Save and close the file.
保存并关闭文件。
Here you add an tag to link to the
edit()
view function, passing in the post['id']
value to link to the edit page of each post with the Edit
link.
Here you add an tag to link to the
edit()
view function, passing in the post['id']
value to link to the edit page of each post with the Edit
link.
Sometimes a post no longer needs to be publicly available, which is why the functionality of deleting a post is crucial. In this step you will add the delete functionality to your application.
Sometimes a post no longer needs to be publicly available, which is why the functionality of deleting a post is crucial. In this step you will add the delete functionality to your application.
First, you’ll add a new /ID/delete
route that accepts POST requests, similar to the edit()
view function. Your new delete()
view function will receive the ID of the post to be deleted from the URL. Open the app.py
file:
First, you'll add a new / ID /delete
route that accepts POST requests, similar to the edit()
view function. Your new delete()
view function will receive the ID of the post to be deleted from the URL. Open the app.py
file:
Add the following view function at the bottom of the file:
Add the following view function at the bottom of the file:
# ....
@app.route('//delete', methods=('POST',))
def delete(id):
post = get_post(id)
conn = get_db_connection()
conn.execute('DELETE FROM posts WHERE id = ?', (id,))
conn.commit()
conn.close()
flash('"{}" was successfully deleted!'.format(post['title']))
return redirect(url_for('index'))
This view function only accepts POST requests. This means that navigating to the /ID/delete
route on your browser will return an error because web browsers default to GET requests.
This view function only accepts POST requests. This means that navigating to the / ID /delete
route on your browser will return an error because web browsers default to GET requests.
However you can access this route via a form that sends a POST request passing in the ID of the post you want to delete. The function will receive the ID value and use it to get the post from the database with the get_post()
function.
However you can access this route via a form that sends a POST request passing in the ID of the post you want to delete. The function will receive the ID value and use it to get the post from the database with the get_post()
function.
Then you open a database connection and execute a DELETE FROM
SQL command to delete the post. You commit the change to the database and close the connection while flashing a message to inform the user that the post was successfully deleted and redirect them to the index page.
Then you open a database connection and execute a DELETE FROM
SQL command to delete the post. You commit the change to the database and close the connection while flashing a message to inform the user that the post was successfully deleted and redirect them to the index page.
Note that you don’t render a template file, this is because you’ll just add a Delete
button to the edit page.
Note that you don't render a template file, this is because you'll just add a Delete
button to the edit page.
Open the edit.html
template file:
Open the edit.html
template file:
Then add the following tag after the
tag and directly before the {% endblock %}
line:
Then add the following tag after the
tag and directly before the {% endblock %}
line:
{% endblock %}
You use the confirm()
method to display a confirmation message before submitting the request.
You use the confirm()
method to display a confirmation message before submitting the request.
Now navigate again to the edit page of a blog post and try deleting it:
Now navigate again to the edit page of a blog post and try deleting it:
http://127.0.0.1:5000/1/edit
At the end of this step, the source code of your project will look like the code on this page.
At the end of this step, the source code of your project will look like the code on this page .
With this, the users of your application can now write new blog posts and add them to the database, edit, and delete existing posts.
With this, the users of your application can now write new blog posts and add them to the database, edit, and delete existing posts.
This tutorial introduced essential concepts of the Flask Python framework. You learned how to make a small web application, run it in a development server, and allow the user to provide custom data via URL parameters and web forms. You also used the Jinja template engine to reuse HTML files and use logic in them. At the end of this tutorial, you now have a fully functioning web blog that interacts with an SQLite database to create, display, edit, and delete blog posts using the Python language and SQL queries.
This tutorial introduced essential concepts of the Flask Python framework. You learned how to make a small web application, run it in a development server, and allow the user to provide custom data via URL parameters and web forms. You also used the Jinja template engine to reuse HTML files and use logic in them. At the end of this tutorial, you now have a fully functioning web blog that interacts with an SQLite database to create, display, edit, and delete blog posts using the Python language and SQL queries.
You can further develop this application by adding user authentication so that only registered users can create and modify blog posts, you may also add comments and tags for each blog post, and add file uploads to give users the ability to include images in the post. See the Flask documentation for more information.
You can further develop this application by adding user authentication so that only registered users can create and modify blog posts, you may also add comments and tags for each blog post, and add file uploads to give users the ability to include images in the post. See the Flask documentation for more information.
Flask has many community-made Flask extensions. The following is a list of extensions you might consider using to make your development process easier:
Flask has many community-made Flask extensions . The following is a list of extensions you might consider using to make your development process easier:
Flask-Login: manages the user session and handles logging in and logging out and remembering logged-in users.
Flask-Login : manages the user session and handles logging in and logging out and remembering logged-in users.
Flask-SQLAlchemy: simplifies using Flask with SQLAlchemy, a Python SQL toolkit and Object Relational Mapper for interacting with SQL databases.
Flask-SQLAlchemy : simplifies using Flask with SQLAlchemy , a Python SQL toolkit and Object Relational Mapper for interacting with SQL databases.
Flask-Mail: helps with the task of sending email messages in your Flask application.
Flask-Mail : helps with the task of sending email messages in your Flask application.
翻译自: https://www.digitalocean.com/community/tutorials/how-to-make-a-web-application-using-flask-in-python-3