Cách tạo ứng dụng web bằng Flask trong Python 3
Flask là một khung công tác web Python nhỏ và nhẹ, cung cấp các công cụ và tính năng hữu ích giúp tạo các ứng dụng web bằng Python dễ dàng hơn. Nó cung cấp cho các nhà phát triển sự linh hoạt và là một khuôn khổ dễ tiếp cận hơn cho các nhà phát triển mới vì bạn có thể xây dựng một ứng dụng web một cách nhanh chóng chỉ bằng một file Python duy nhất. Flask cũng có thể mở rộng và không bắt buộc cấu trúc folder cụ thể hoặc yêu cầu mã soạn sẵn phức tạp trước khi bắt đầu.Là một phần của hướng dẫn này, bạn sẽ sử dụng bộ công cụ Bootstrap để tạo kiểu cho ứng dụng của bạn sao cho nó hấp dẫn hơn về mặt hình ảnh. Bootstrap sẽ giúp bạn kết hợp các trang web đáp ứng trong ứng dụng web của bạn để nó cũng hoạt động tốt trên các trình duyệt di động mà không cần viết mã HTML, CSS và JavaScript của bạn để đạt được những mục tiêu này. Bộ công cụ sẽ cho phép bạn tập trung vào việc tìm hiểu cách hoạt động của Flask.
Flask sử dụng công cụ mẫu Jinja để tạo động các trang HTML bằng cách sử dụng các khái niệm Python quen thuộc như biến, vòng lặp, danh sách, v.v. Bạn sẽ sử dụng các mẫu này như một phần của dự án này.
Trong hướng dẫn này, bạn sẽ xây dựng một blog web nhỏ bằng Flask và SQLite bằng Python 3. User ứng dụng có thể xem tất cả các bài đăng trong database của bạn và nhấp vào tiêu đề của bài đăng để xem nội dung của nó với khả năng thêm bài đăng mới vào database và chỉnh sửa hoặc xóa bài đăng hiện có.
Yêu cầu
Trước khi bắt đầu làm theo hướng dẫn này, bạn cần :
- Môi trường lập trình Python 3 local , hãy làm theo hướng dẫn dành cho bản phân phối của bạn trong Cách cài đặt và cài đặt môi trường lập trình cục bộ cho loạt Python 3 cho máy local của bạn. Trong hướng dẫn này, ta sẽ gọi folder dự án của ta là
flask_blog
. - Hiểu biết về các khái niệm Python 3, chẳng hạn như kiểu dữ liệu , câu lệnh điều kiện , vòng lặp for , hàm và các khái niệm tương tự khác. Nếu bạn không quen thuộc với Python, hãy xem loạt bài Cách viết mã trong Python 3 của ta .
Bước 1 - Cài đặt Bình
Trong bước này, bạn sẽ kích hoạt môi trường Python của bạn và cài đặt Flask bằng trình cài đặt gói pip
.
Nếu bạn chưa kích hoạt môi trường lập trình của bạn , hãy đảm bảo bạn đang ở trong folder dự án ( flask_blog
) và sử dụng lệnh sau để kích hoạt môi trường:
- source env/bin/activate
Khi môi trường lập trình của bạn được kích hoạt, dấu nhắc của bạn bây giờ sẽ có tiền tố env
có thể trông như sau:
-
Tiền tố này là một dấu hiệu cho thấy môi trường env
hiện đang hoạt động, có thể có tên khác tùy thuộc vào cách bạn đặt tên cho nó trong quá trình tạo.
Lưu ý: Bạn có thể sử dụng Git , một hệ thống kiểm soát version , để quản lý và theo dõi hiệu quả quá trình phát triển cho dự án của bạn . Để tìm hiểu cách sử dụng Git, bạn có thể cần xem bài viết Giới thiệu về Chi nhánh và Cách sử dụng Cài đặt Git của ta .
Nếu bạn đang sử dụng Git, bạn nên bỏ qua folder env
mới được tạo trong file .gitignore
của bạn để tránh theo dõi các file không liên quan đến dự án.
Đến đây bạn sẽ cài đặt các gói Python và cô lập mã dự án của bạn khỏi cài đặt hệ thống Python chính. Bạn sẽ làm điều này bằng cách sử dụng pip
và python
.
Để cài đặt Flask, hãy chạy lệnh sau:
- pip install flask
Sau khi cài đặt xong, hãy chạy lệnh sau để xác nhận cài đặt:
- python -c "import flask; print(flask.__version__)"
Bạn sử dụng giao diện dòng lệnh python
với tùy chọn -c
để thực thi mã Python. Tiếp theo, bạn nhập gói flask
với import flask;
sau đó in version Flask, được cung cấp qua biến flask.__version__
.
Đầu ra sẽ là số version tương tự như sau:
Output1.1.2
Bạn đã tạo folder dự án, môi trường ảo và cài đặt Flask. Đến đây bạn đã sẵn sàng để chuyển sang cài đặt ứng dụng cơ sở của bạn .
Bước 2 - Tạo ứng dụng cơ sở
Đến đây bạn đã cài đặt xong môi trường lập trình, bạn sẽ bắt đầu sử dụng Flask. Trong bước này, bạn sẽ tạo một ứng dụng web nhỏ bên trong file Python và chạy nó để khởi động server , server sẽ hiển thị một số thông tin trên trình duyệt.
Trong folder flask_blog
của bạn, hãy mở file có tên hello.py
để chỉnh sửa, sử dụng nano
hoặc editor yêu thích của bạn:
- nano hello.py
Tệp hello.py
này sẽ đóng role là một ví dụ tối thiểu về cách xử lý các yêu cầu HTTP. Bên trong nó, bạn sẽ nhập đối tượng Flask
và tạo một hàm trả về phản hồi HTTP. Viết mã sau bên trong hello.py
:
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): return 'Hello, World!'
Trong khối mã trước đó, trước tiên bạn nhập đối tượng Flask
từ gói flask
. Sau đó, bạn sử dụng nó để tạo version ứng dụng Flask của bạn với app
tên. Bạn chuyển biến đặc biệt __name__
chứa tên của module Python hiện tại. Nó được sử dụng để cho cá thể biết vị trí của nó — bạn cần điều này vì Flask cài đặt một số đường dẫn phía sau mức thấp .
Khi bạn tạo version app
, bạn sử dụng nó để xử lý các yêu cầu web đến và gửi phản hồi cho user . @app.route
là một trình trang trí biến một hàm Python thông thường thành một hàm Flask view , chuyển đổi giá trị trả về của hàm thành một phản hồi HTTP để hiển thị bởi một ứng dụng HTTP, chẳng hạn như trình duyệt web. Bạn chuyển giá trị '/'
cho @app.route()
để biểu thị rằng chức năng này sẽ phản hồi các yêu cầu web đối với URL /
, là URL chính.
Hàm view hello()
trả về chuỗi 'Hello, World!'
như một phản ứng.
Lưu và đóng file .
Để chạy ứng dụng web của bạn, trước tiên bạn sẽ cho Flask biết nơi tìm ứng dụng (tệp hello.py
trong trường hợp của bạn) với biến môi trường FLASK_APP
:
- export FLASK_APP=hello
Sau đó, chạy nó ở chế độ phát triển với biến môi trường FLASK_ENV
:
- export FLASK_ENV=development
Cuối cùng, chạy ứng dụng bằng lệnh flask run
:
- flask run
Khi ứng dụng đang chạy, kết quả sẽ giống như sau:
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
Đầu ra trước có một số thông tin, chẳng hạn như:
- Tên của ứng dụng bạn đang chạy.
- Môi trường mà ứng dụng đang được chạy.
-
Debug mode: on
nghĩa là trình gỡ lỗi Flask đang chạy. Điều này rất hữu ích khi phát triển vì nó cung cấp cho ta các thông báo lỗi chi tiết khi có sự cố, giúp khắc phục sự cố dễ dàng hơn. - Ứng dụng đang chạy local trên URL
http://127.0.0.1:5000/
,127.0.0.1
là IP đại diện cho serverlocalhost
của máy bạn và:5000
là số cổng.
Mở trình duyệt và nhập URL http://127.0.0.1:5000/
, bạn sẽ nhận được chuỗi Hello, World!
như một phản hồi, điều này xác nhận ứng dụng của bạn đang chạy thành công.
Cảnh báo Flask sử dụng một web server đơn giản để phục vụ ứng dụng của ta trong môi trường phát triển, điều này cũng nghĩa là trình gỡ lỗi Flask đang chạy để giúp bắt lỗi dễ dàng hơn. Server phát triển này không nên được sử dụng trong triển khai production . Xem trang Tùy chọn triển khai trên tài liệu Flask để biết thêm thông tin, bạn cũng có thể xem hướng dẫn triển khai Flask này.
Đến đây bạn có thể để server phát triển đang chạy trong terminal và mở một cửa sổ terminal khác. Di chuyển vào folder dự án nơi chứa hello.py
, kích hoạt môi trường ảo, đặt các biến môi trường FLASK_ENV
và FLASK_APP
, và tiếp tục các bước tiếp theo. (Các lệnh này được liệt kê trước đó trong bước này.)
Lưu ý : Khi mở một terminal mới, điều quan trọng cần nhớ là kích hoạt môi trường ảo và cài đặt các biến môi trường FLASK_ENV
và FLASK_APP
.
Trong khi server phát triển của ứng dụng Flask đã chạy, không thể chạy một ứng dụng Flask khác với cùng lệnh flask run
. Điều này là do flask run
sử dụng số cổng 5000
theo mặc định và khi nó được sử dụng, nó sẽ không khả dụng để chạy ứng dụng khác, vì vậy bạn sẽ nhận được lỗi tương tự như sau:
OutputOSError: [Errno 98] Address already in use
Để giải quyết vấn đề này, hãy dừng server hiện đang chạy qua CTRL+C
, sau đó chạy flask run
lại hoặc nếu bạn muốn chạy cả hai cùng một lúc, bạn có thể chuyển một số cổng khác cho đối số -p
, ví dụ: , để chạy một ứng dụng khác trên cổng 5001
sử dụng lệnh sau:
- flask run -p 5001
Đến đây bạn có một ứng dụng web Flask nhỏ. Bạn đã chạy ứng dụng của bạn và hiển thị thông tin trên trình duyệt web. Tiếp theo, bạn sẽ sử dụng các file HTML trong ứng dụng của bạn .
Bước 3 - Sử dụng các mẫu HTML
Hiện tại ứng dụng của bạn chỉ hiển thị một thông báo đơn giản mà không có bất kỳ HTML nào. Các ứng dụng web chủ yếu sử dụng HTML để hiển thị thông tin cho khách truy cập, vì vậy bây giờ bạn sẽ làm việc để kết hợp các file HTML vào ứng dụng của bạn , file này có thể được hiển thị trên trình duyệt web.
Flask cung cấp hàm trợ giúp render_template()
cho phép sử dụng công cụ mẫu Jinja . Điều này sẽ giúp quản lý HTML dễ dàng hơn nhiều bằng cách viết mã HTML của bạn trong các file .html
cũng như sử dụng logic trong mã HTML của bạn. Bạn sẽ sử dụng các file HTML này, ( mẫu ) để tạo tất cả các trang ứng dụng của bạn , chẳng hạn như trang chính nơi bạn sẽ hiển thị các bài đăng blog hiện tại, trang của bài đăng blog, trang nơi user có thể thêm đăng, và như vậy.
Trong bước này, bạn sẽ tạo ứng dụng Flask chính của bạn trong một file mới.
Đầu tiên, trong folder flask_blog
của bạn, sử dụng nano
hoặc editor bạn quen dùng để tạo và chỉnh sửa file app.py
của bạn. Điều này sẽ giữ tất cả mã bạn sẽ sử dụng để tạo ứng dụng blog:
- nano app.py
Trong file mới này, bạn sẽ nhập đối tượng Flask
để tạo một version ứng dụng Flask như bạn đã làm trước đây. Bạn cũng sẽ nhập hàm trợ giúp render_template()
cho phép bạn hiển thị các file mẫu HTML tồn tại trong folder templates
mà bạn sắp tạo. Tệp sẽ có một chức năng xem duy nhất sẽ chịu trách nhiệm xử lý các yêu cầu đến main /
route. Thêm nội dung sau:
from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html')
Hàm view index()
trả về kết quả của việc gọi render_template()
với index.html
làm đối số, hàm này yêu cầu render_template()
tìm kiếm một file có tên là index.html
trong thư mục mẫu . Cả folder và file đều chưa tồn tại, bạn sẽ gặp lỗi nếu chạy ứng dụng tại thời điểm này. Tuy nhiên, bạn sẽ chạy nó để bạn quen thuộc với ngoại lệ thường gặp này. Sau đó, bạn sẽ sửa nó bằng cách tạo folder và file cần thiết.
Lưu và thoát khỏi file .
Dừng server phát triển trong terminal khác của bạn đang chạy ứng dụng hello
bằng CTRL+C
Trước khi bạn chạy ứng dụng, hãy đảm bảo bạn chỉ định chính xác giá trị cho biến môi trường FLASK_APP
, vì bạn không còn sử dụng ứng dụng hello
:
- export FLASK_APP=app
- flask run
Mở URL http://127.0.0.1:5000/
trong trình duyệt của bạn sẽ dẫn đến trang trình gỡ lỗi thông báo cho bạn rằng không tìm thấy mẫu index.html
. Dòng chính trong mã gây ra lỗi này sẽ được đánh dấu. Trong trường hợp này, nó là dòng return render_template('index.html')
.
Nếu bạn nhấp vào dòng này, trình gỡ lỗi sẽ tiết lộ nhiều mã hơn để bạn có thêm ngữ cảnh để giúp bạn giải quyết vấn đề.
Để khắc phục lỗi này, hãy tạo một folder có tên là các templates
bên trong folder flask_blog
của bạn. Sau đó, bên trong nó, mở một file có tên là index.html
để chỉnh sửa:
- mkdir templates
- nano templates/index.html
Tiếp theo, thêm mã HTML sau vào trong index.html
:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>FlaskBlog</title> </head> <body> <h1>Welcome to FlaskBlog</h1> </body> </html>
Lưu file và sử dụng trình duyệt của bạn để chuyển lại đến http://127.0.0.1:5000/
hoặc làm mới trang. Lần này trình duyệt sẽ hiển thị dòng chữ Welcome to FlaskBlog
trong <h1>
.
Ngoài folder templates
, các ứng dụng web Flask thường có một folder static
để lưu trữ các file tĩnh, chẳng hạn như file CSS, file JavaScript và hình ảnh mà ứng dụng sử dụng.
Bạn có thể tạo style.css
kiểu style.css
để thêm CSS vào ứng dụng của bạn . Đầu tiên, tạo một folder có tên static
bên trong folder flask_blog
chính của bạn:
- mkdir static
Sau đó, tạo một folder khác có tên là css
bên trong folder static
để lưu trữ các file .css
. Điều này thường được thực hiện để tổ chức các file tĩnh trong các folder chuyên dụng, như vậy, các file JavaScript thường nằm trong một folder có tên là js
, hình ảnh được đặt trong một folder có tên là images
(hoặc img
), v.v. Lệnh sau sẽ tạo folder css
bên trong folder static
:
- mkdir static/css
Sau đó, mở style.css
bên trong folder css
để chỉnh sửa:
- nano static/css/style.css
Thêm luật CSS sau vào style.css
của bạn:
h1 { border: 2px #eee solid; color: brown; text-align: center; padding: 10px; }
Mã CSS sẽ thêm đường viền, thay đổi màu thành nâu, căn giữa văn bản và thêm một chút đệm vào <h1>
.
Lưu và đóng file .
Tiếp theo, mở index.html
mẫu index.html
để chỉnh sửa:
- nano templates/index.html
Bạn sẽ thêm một liên kết đến style.css
bên trong phần <head>
của index.html
mẫu index.html
:
. . . <head> <meta charset="UTF-8"> <link rel="stylesheet" href="{{ url_for('static', filename= 'css/style.css') }}"> <title>FlaskBlog</title> </head> . . .
Ở đây bạn sử dụng hàm trợ giúp url_for()
để tạo vị trí thích hợp của file . Đối số đầu tiên chỉ định rằng bạn đang liên kết đến một file tĩnh và đối số thứ hai là đường dẫn của file bên trong folder tĩnh.
Lưu và đóng file .
Khi làm mới trang index của ứng dụng của bạn, bạn sẽ nhận thấy rằng văn bản Welcome to FlaskBlog
hiện có màu nâu, căn giữa và được bao bên trong một đường viền.
Bạn có thể sử dụng ngôn ngữ CSS để tạo kiểu cho ứng dụng và làm cho nó hấp dẫn hơn bằng cách sử dụng thiết kế của bạn . Tuy nhiên, nếu bạn không phải là nhà thiết kế web hoặc nếu bạn không quen với CSS, thì bạn có thể sử dụng bộ công cụ Bootstrap , cung cấp các thành phần dễ sử dụng để tạo kiểu cho ứng dụng của bạn. Trong dự án này, ta sẽ sử dụng Bootstrap.
Bạn có thể đoán rằng việc tạo một mẫu HTML khác nghĩa là lặp lại hầu hết mã HTML mà bạn đã viết trong mẫu index.html
. Bạn có thể tránh lặp lại mã không cần thiết với sự trợ giúp của file mẫu cơ sở , file mà tất cả các file HTML của bạn sẽ kế thừa từ đó. Xem Kế thừa Mẫu trong Jinja để biết thêm thông tin.
Để tạo một mẫu cơ sở, trước tiên hãy tạo một file có tên base.html
bên trong folder templates
của bạn:
- nano templates/base.html
base.html
mã sau vào mẫu base.html
của bạn:
<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <title>{% block title %} {% endblock %}</title> </head> <body> <nav class="navbar navbar-expand-md navbar-light bg-light"> <a class="navbar-brand" href="{{ url_for('index')}}">FlaskBlog</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="#">About</a> </li> </ul> </div> </nav> <div class="container"> {% block content %} {% endblock %} </div> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> </body> </html>
Lưu file sau khi bạn chỉnh sửa xong.
Hầu hết mã trong khối trước là HTML tiêu chuẩn và mã bắt buộc cho Bootstrap. Các <meta>
cung cấp thông tin cho trình duyệt web, <link>
liên kết các file Bootstrap CSS và các <script>
là các liên kết đến mã JavaScript cho phép một số tính năng Bootstrap bổ sung, hãy xem tài liệu Bootstrap để biết thêm.
Tuy nhiên, các phần được đánh dấu sau đây là dành riêng cho công cụ mẫu Jinja:
-
{% block title %} {% endblock %}
: Một khối đóng role giữ chỗ cho tiêu đề, sau này bạn sẽ sử dụng nó trong các mẫu khác để đặt tiêu đề tùy chỉnh cho mỗi trang trong ứng dụng của bạn mà không cần viết lại toàn bộ<head>
mỗi lần. -
{{ url_for('index')}}
: Một lệnh gọi hàm sẽ trả về URL cho hàm xemindex()
. Điều này khác với lệnh gọiurl_for()
trước đây mà bạn đã sử dụng để liên kết file CSS tĩnh, vì nó chỉ nhận một đối số, đó là tên của hàm dạng xem và liên kết đến tuyến được liên kết với hàm thay vì file tĩnh. -
{% block content %} {% endblock %}
: Một khối khác sẽ được thay thế bằng nội dung tùy thuộc vào mẫu con (các mẫu kế thừa từbase.html
) sẽ overrides nó.
Đến đây bạn đã có một mẫu cơ sở, bạn có thể tận dụng nó bằng cách sử dụng tính năng kế thừa. Mở index.html
:
- nano templates/index.html
Sau đó thay thế nội dung của nó bằng những thứ sau:
{% extends 'base.html' %} {% block content %} <h1>{% block title %} Welcome to FlaskBlog {% endblock %}</h1> {% endblock %}
Trong version mới này của mẫu index.html
, bạn sử dụng thẻ {% extends %}
để kế thừa từ mẫu base.html
. Sau đó, bạn mở rộng nó bằng cách thay thế khối content
trong mẫu cơ sở bằng những gì bên trong khối content
trong khối mã trước đó.
Khối content
này chứa <h1>
với văn bản Welcome to FlaskBlog
bên trong khối title
, khối này sẽ thay thế khối title
ban đầu trong mẫu base.html
bằng text Welcome to FlaskBlog
. Bằng cách này, bạn có thể tránh lặp lại cùng một văn bản hai lần, vì nó vừa hoạt động như một tiêu đề cho trang và một tiêu đề xuất hiện bên dưới thanh chuyển được kế thừa từ mẫu cơ sở.
Kế thừa mẫu cũng cung cấp cho bạn khả năng sử dụng lại mã HTML mà bạn có trong các mẫu khác (trong trường hợp này là base.html
) mà không cần phải lặp lại mỗi khi cần.
Lưu file cũng như làm mới trang index trên trình duyệt của bạn. Bạn sẽ thấy trang của bạn với thanh chuyển và tiêu đề được tạo kiểu.
Bạn đã sử dụng các mẫu HTML và file tĩnh trong Flask. Bạn cũng đã sử dụng Bootstrap để bắt đầu tinh chỉnh giao diện trang của bạn và một mẫu cơ sở để tránh lặp lại mã. Trong bước tiếp theo, bạn sẽ cài đặt một database sẽ lưu trữ dữ liệu ứng dụng của bạn.
Bước 4 - Cài đặt database
Trong bước này, bạn sẽ cài đặt database để lưu trữ dữ liệu, tức là các bài đăng trên blog cho ứng dụng của bạn. Bạn cũng sẽ điền vào database với một vài mục nhập ví dụ.
Bạn sẽ sử dụng file cơ sở dữ liệu SQLite để lưu trữ dữ liệu của bạn vì module sqlite3
, mà ta sẽ sử dụng để tương tác với database , có sẵn trong thư viện Python chuẩn. Để biết thêm thông tin về SQLite, hãy xem hướng dẫn này .
Đầu tiên, vì dữ liệu trong SQLite được lưu trữ trong các bảng và cột, và vì dữ liệu chủ yếu bao gồm các bài đăng trên blog, nên trước tiên bạn cần tạo một bảng gọi là posts
với các cột cần thiết. Bạn sẽ tạo một file .sql
chứa các lệnh SQL để tạo bảng posts
với một vài cột. Sau đó, bạn sẽ sử dụng file này để tạo database .
Mở một file có tên schema.sql
bên trong folder flask_blog
của bạn:
- nano schema.sql
Nhập các lệnh SQL sau bên trong file này:
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 );
Lưu và đóng file .
Lệnh SQL đầu tiên là DROP TABLE IF EXISTS posts;
, điều này sẽ xóa bất kỳ bảng nào hiện có có tên các posts
để bạn không gặp phải hành vi khó hiểu. Lưu ý thao tác này sẽ xóa tất cả nội dung bạn có trong database khi nào bạn sử dụng các lệnh SQL này, vì vậy hãy đảm bảo bạn không viết bất kỳ nội dung quan trọng nào trong ứng dụng web cho đến khi hoàn thành hướng dẫn này và thử nghiệm với kết quả cuối cùng. Tiếp theo, CREATE TABLE posts
được sử dụng để tạo bảng posts
với các cột sau:
-
id
: Một số nguyên đại diện cho một khóa chính , điều này sẽ được database gán một giá trị duy nhất cho mỗi mục nhập (đó là một bài đăng trên blog). -
created
: Thời gian bài đăng trên blog được tạo lúc.NOT NULL
biểu thị rằng cột này không được để trống và giá trịDEFAULT
là giá trịCURRENT_TIMESTAMP
, là thời điểm mà bài đăng được thêm vào database . Cũng giống nhưid
, bạn không cần chỉ định giá trị cho cột này, vì nó sẽ tự động được điền vào. -
title
:title
bài đăng. -
content
:content
bài đăng.
Đến đây bạn có một schemas SQL trong file schema.sql
, bạn sẽ sử dụng nó để tạo database bằng cách sử dụng file Python sẽ tạo file database SQLite .db
. Mở file có tên init_db.py
bên trong folder flask_blog
bằng editor bạn muốn :
- nano init_db.py
Và sau đó thêm mã sau.
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()
Trước tiên, bạn nhập module sqlite3
và sau đó mở kết nối đến file database.db
có tên database.db
, file này sẽ được tạo sau khi bạn chạy file Python. Sau đó, bạn sử dụng hàm open()
để mở file schema.sql
. Tiếp theo, bạn thực thi nội dung của nó bằng cách sử dụng phương thức executescript()
thực thi nhiều câu lệnh SQL cùng một lúc, điều này sẽ tạo ra bảng posts
. Bạn tạo một đối tượng Con trỏ cho phép bạn sử dụng phương thức execute()
của nó để thực thi hai INSERT
SQL để thêm hai bài đăng trên blog vào bảng posts
của bạn. Cuối cùng, bạn commit các thay đổi và đóng kết nối.
Lưu file , sau đó chạy nó trong terminal bằng lệnh python
:
- python init_db.py
Sau khi file hoàn tất thực thi, một file mới có tên là database.db
sẽ xuất hiện trong folder flask_blog
của bạn. Điều này nghĩa là bạn đã cài đặt thành công database của bạn .
Trong bước tiếp theo, bạn sẽ truy xuất các bài đăng bạn đã chèn vào database của bạn và hiển thị chúng trong trang chủ ứng dụng của bạn.
Bước 5 - Hiển thị tất cả các bài đăng
Đến đây bạn đã cài đặt database của bạn , bây giờ bạn có thể sửa đổi chức năng xem index()
để hiển thị tất cả các bài đăng bạn có trong database của bạn .
Mở file app.py
để thực hiện các sửa đổi sau:
- nano app.py
Đối với sửa đổi đầu tiên của bạn, bạn sẽ nhập module sqlite3
ở đầu file :
import sqlite3 from flask import Flask, render_template . . .
Tiếp theo, bạn sẽ tạo một hàm tạo kết nối database và trả về. Thêm nó trực tiếp sau khi nhập:
. . . from flask import Flask, render_template def get_db_connection(): conn = sqlite3.connect('database.db') conn.row_factory = sqlite3.Row return conn . . .
Đây get_db_connection()
chức năng mở một kết nối đến database.db
file database , và sau đó đặt row_factory
thuộc tính để sqlite3.Row
vì vậy bạn có thể có tên dựa trên quyền truy cập vào các cột. Điều này nghĩa là kết nối database sẽ trả về các hàng hoạt động giống như các từ điển Python thông thường. Cuối cùng, hàm trả về đối tượng kết nối conn
mà bạn sẽ sử dụng để truy cập database .
Sau khi xác định hàm get_db_connection()
, hãy sửa đổi hàm index()
để trông giống như sau:
. . . @app.route('/') def index(): conn = get_db_connection() posts = conn.execute('SELECT * FROM posts').fetchall() conn.close() return render_template('index.html', posts=posts)
Trong version mới này của hàm index()
, trước tiên bạn mở một kết nối database bằng cách sử dụng hàm get_db_connection()
mà bạn đã xác định trước đó. Sau đó, bạn thực hiện một truy vấn SQL để chọn tất cả các mục từ bảng posts
. Bạn triển khai phương thức fetchall()
để tìm nạp tất cả các hàng của kết quả truy vấn, điều này sẽ trả về danh sách các bài đăng bạn đã chèn vào database ở bước trước.
Bạn đóng kết nối database bằng phương thức close()
và trả về kết quả hiển thị mẫu index.html
. Bạn cũng chuyển đối tượng posts
dưới dạng đối số, chứa kết quả bạn nhận được từ database , điều này sẽ cho phép bạn truy cập các bài đăng trên blog trong mẫu index.html
.
Với các sửa đổi này, hãy lưu file app.py
Đến đây bạn đã chuyển các bài đăng mà bạn đã tìm nạp từ database sang mẫu index.html
, bạn có thể sử dụng vòng lặp for
để hiển thị từng bài đăng trên trang index của bạn .
Mở index.html
:
- nano templates/index.html
Sau đó, sửa đổi nó để trông như sau:
{% extends 'base.html' %} {% block content %} <h1>{% block title %} Welcome to FlaskBlog {% endblock %}</h1> {% for post in posts %} <a href="#"> <h2>{{ post['title'] }}</h2> </a> <span class="badge badge-primary">{{ post['created'] }}</span> <hr> {% endfor %} {% endblock %}
Ở đây, cú pháp {% for post in posts %}
là vòng lặp Jinja for
, tương tự như vòng lặp for
Python ngoại trừ việc nó phải được đóng lại sau đó bằng cú pháp {% endfor %}
. Bạn sử dụng cú pháp này để lặp lại từng mục trong danh sách posts
đã được chuyển bởi hàm index()
trong dòng return render_template('index.html', posts=posts)
. Bên trong vòng lặp for
này, bạn hiển thị tiêu đề bài đăng trong tiêu đề <h2>
bên trong thẻ <a>
(sau này bạn sẽ sử dụng thẻ này để liên kết đến từng bài đăng riêng lẻ).
Bạn hiển thị tiêu đề bằng dấu phân cách biến theo nghĩa đen ( {{ ... }}
). Lưu ý post
sẽ là một đối tượng giống như từ điển, vì vậy bạn có thể truy cập tiêu đề post['title']
bằng post['title']
. Bạn cũng hiển thị ngày tạo bài đăng bằng phương pháp tương tự.
Khi bạn đã hoàn tất việc chỉnh sửa file , hãy lưu file đó. Sau đó chuyển đến trang index trong trình duyệt của bạn. Bạn sẽ thấy hai bài đăng bạn đã thêm vào database trên trang của bạn .
Đến đây bạn đã sửa đổi chức năng xem index()
để hiển thị tất cả các bài đăng bạn có trong database trên trang chủ ứng dụng của bạn , bạn sẽ chuyển sang hiển thị từng bài đăng trong một trang duy nhất và cho phép user liên kết đến từng bài đăng riêng lẻ.
Bước 6 - Hiển thị một bài đăng
Trong bước này, bạn sẽ tạo một tuyến Flask mới với chức năng xem và mẫu HTML mới để hiển thị một bài đăng blog riêng lẻ theo ID của nó.
Đến cuối bước này, URL http://127.0.0.1:5000/1
sẽ là trang hiển thị bài viết đầu tiên (vì nó có ID 1
). URL http://127.0.0.1:5000/ ID
sẽ hiển thị bài đăng có số ID
liên kết nếu nó tồn tại.
Mở app.py
để chỉnh sửa:
- nano app.py
Vì bạn cần lấy một bài đăng blog theo ID của nó từ database ở nhiều vị trí sau này trong dự án này, bạn sẽ tạo một hàm độc lập có tên get_post()
. Bạn có thể gọi nó bằng cách chuyển cho nó một ID và nhận lại bài đăng blog được liên kết với ID được cung cấp hoặc yêu cầu Flask phản hồi bằng thông báo 404 Not Found
nếu bài đăng trên blog không tồn tại.
Để trả lời trang 404
, bạn cần nhập hàm abort()
từ thư viện Werkzeug
, được cài đặt cùng với Flask, ở đầu file :
import sqlite3 from flask import Flask, render_template from werkzeug.exceptions import abort . . .
Sau đó, thêm hàm get_post()
ngay sau hàm get_db_connection()
mà bạn đã tạo ở bước trước:
. . . 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 . . .
Hàm mới này có đối số post_id
xác định bài đăng trên blog nào sẽ trả về.
Bên trong hàm, bạn sử dụng hàm get_db_connection()
để mở kết nối database và thực hiện truy vấn SQL để lấy bài đăng blog được liên kết với giá trị post_id
cho. Bạn thêm phương thức fetchone()
để lấy kết quả và lưu trữ nó trong biến post
sau đó đóng kết nối. Nếu biến post
có giá trị None
, nghĩa là không tìm thấy kết quả nào trong database , bạn sử dụng hàm abort()
mà bạn đã nhập trước đó để phản hồi với mã lỗi 404
và hàm sẽ kết thúc quá trình thực thi. Tuy nhiên, nếu một bài đăng được tìm thấy, bạn trả về giá trị của biến post
.
Tiếp theo, thêm chức năng xem sau vào cuối file app.py
:
. . . @app.route('/<int:post_id>') def post(post_id): post = get_post(post_id) return render_template('post.html', post=post)
Trong hàm xem mới này, bạn thêm một luật biến <int:post_id>
để chỉ định rằng phần sau dấu gạch chéo ( /
) là một số nguyên dương (được đánh dấu bằng trình chuyển đổi int
) mà bạn cần truy cập trong hàm xem của bạn . Flask nhận ra điều này và chuyển giá trị của nó cho đối số từ khóa post_id
của hàm view post()
của bạn. Sau đó, bạn sử dụng hàm get_post()
để nhận bài đăng trên blog được liên kết với ID được chỉ định và lưu trữ kết quả trong biến post
, biến này bạn chuyển vào mẫu post.html
mà bạn sẽ sớm tạo.
Lưu file app.py
và mở file mẫu post.html
mới để chỉnh sửa:
- nano templates/post.html
post.html
mã sau vào file post.html
mới này. Điều này sẽ tương tự với index.html
, ngoại trừ việc nó sẽ chỉ hiển thị một bài đăng duy nhất, ngoài việc hiển thị nội dung của bài đăng:
{% extends 'base.html' %} {% block content %} <h2>{% block title %} {{ post['title'] }} {% endblock %}</h2> <span class="badge badge-primary">{{ post['created'] }}</span> <p>{{ post['content'] }}</p> {% endblock %}
Bạn thêm khối title
mà bạn đã xác định trong mẫu base.html
để làm cho tiêu đề của trang phản ánh tiêu đề bài đăng được hiển thị trong tiêu đề <h2>
cùng một lúc.
Lưu và đóng file .
Bây giờ, bạn có thể chuyển đến các URL sau để xem hai bài đăng bạn có trong database của bạn , cùng với một trang cho user biết rằng bài đăng blog được yêu cầu không được tìm thấy (vì không có bài đăng nào có số ID là 3
cho đến nay) :
http://127.0.0.1:5000/1 http://127.0.0.1:5000/2 http://127.0.0.1:5000/3
Quay lại trang index , bạn sẽ tạo liên kết mỗi tiêu đề bài đăng đến trang tương ứng của nó. Bạn sẽ thực hiện việc này bằng cách sử dụng hàm url_for()
. Đầu tiên, hãy mở mẫu index.html
để chỉnh sửa:
- nano templates/index.html
Sau đó, thay đổi giá trị của thuộc tính href
từ #
thành {{ url_for('post', post_id=post['id']) }}
để vòng lặp for
trông chính xác như sau:
{% for post in posts %} <a href="{{ url_for('post', post_id=post['id']) }}"> <h2>{{ post['title'] }}</h2> </a> <span class="badge badge-primary">{{ post['created'] }}</span> <hr> {% endfor %}
Tại đây, bạn chuyển 'post'
vào hàm url_for()
như một đối số đầu tiên. Đây là tên của hàm view post()
và vì nó chấp nhận một đối số post_id
, nên bạn đặt cho nó giá trị post['id']
. Hàm url_for()
sẽ trả về URL thích hợp cho mỗi bài đăng dựa trên ID của nó.
Lưu và đóng file .
Các liên kết trên trang index bây giờ sẽ hoạt động như mong đợi. Với điều này, bây giờ bạn đã hoàn thành việc xây dựng phần của ứng dụng chịu trách nhiệm hiển thị các bài đăng trên blog trong database của bạn. Tiếp theo, bạn sẽ thêm khả năng tạo, chỉnh sửa và xóa các bài đăng trên blog vào ứng dụng của bạn .
Bước 7 - Sửa đổi bài đăng
Đến đây bạn đã hoàn thành việc hiển thị các bài đăng trên blog có trong database trên ứng dụng web, bạn cần cho phép user ứng dụng của bạn viết các bài đăng blog mới và thêm chúng vào database , chỉnh sửa những bài hiện có và xóa những bài không cần thiết bài đăng trên blog.
Tạo bài đăng mới
Cho đến thời điểm này, bạn có một ứng dụng hiển thị các bài đăng trong database của bạn nhưng không cung cấp cách nào để thêm bài đăng mới trừ khi bạn kết nối trực tiếp với database SQLite và thêm một bài theo cách thủ công. Trong phần này, bạn sẽ tạo một trang mà trên đó bạn có thể tạo một bài đăng bằng cách cung cấp tiêu đề và nội dung của nó.
Mở file app.py
để chỉnh sửa:
- nano app.py
import sqlite3 from flask import Flask, render_template, request, url_for, flash, redirect from werkzeug.exceptions import abort . . .
Hàm flash()
lưu trữ các tin nhắn đã nhấp nháy trong phiên trình duyệt của khách hàng, hàm này yêu cầu cài đặt khóa bí mật . Khóa bí mật này được sử dụng để bảo mật các phiên, cho phép Flask ghi nhớ thông tin từ yêu cầu này sang yêu cầu khác, chẳng hạn như chuyển từ trang bài đăng mới sang trang index . User có thể truy cập thông tin được lưu trữ trong phiên, nhưng không thể sửa đổi nó trừ khi họ có khóa bí mật, vì vậy bạn không bao giờ được cho phép bất kỳ ai truy cập vào khóa bí mật của bạn . Xem tài liệu về Flask cho các phiên để biết thêm thông tin.
Để đặt khóa bí mật , bạn sẽ thêm cấu hình SECRET_KEY
vào ứng dụng của bạn thông qua đối tượng app.config
. Thêm nó trực tiếp theo định nghĩa app
trước khi xác định hàm xem index()
:
. . . 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) . . .
Lưu ý khóa bí mật phải là một chuỗi dài ngẫu nhiên.
Sau khi đặt khóa bí mật, bạn sẽ tạo một chức năng xem sẽ hiển thị một mẫu hiển thị biểu mẫu mà bạn có thể điền vào để tạo một bài đăng blog mới. Thêm chức năng mới này ở cuối file :
. . . @app.route('/create', methods=('GET', 'POST')) def create(): return render_template('create.html')
Điều này tạo ra một tuyến đường /create
chấp nhận cả yêu cầu GET và POST. Yêu cầu GET được chấp nhận theo mặc định. Để cũng chấp nhận các yêu cầu POST, được gửi bởi trình duyệt khi gửi biểu mẫu, bạn sẽ chuyển một bộ dữ liệu với các loại yêu cầu được chấp nhận đến đối số methods
của trình trang trí @app.route()
.
Lưu và đóng file .
Để tạo mẫu, hãy mở file có tên create.html
bên trong folder templates
của bạn:
- nano templates/create.html
Thêm mã sau vào trong file mới này:
{% extends 'base.html' %} {% block content %} <h1>{% block title %} Create a New Post {% endblock %}</h1> <form method="post"> <div class="form-group"> <label for="title">Title</label> <input type="text" name="title" placeholder="Post title" class="form-control" value="{{ request.form['title'] }}"></input> </div> <div class="form-group"> <label for="content">Content</label> <textarea name="content" placeholder="Post content" class="form-control">{{ request.form['content'] }}</textarea> </div> <div class="form-group"> <button type="submit" class="btn btn-primary">Submit</button> </div> </form> {% endblock %}
Hầu hết mã này là HTML tiêu chuẩn. Nó sẽ hiển thị một hộp nhập cho tiêu đề bài đăng, một vùng văn bản cho nội dung bài đăng và một nút để gửi biểu mẫu.
Giá trị của đầu vào tiêu đề bài đăng là {{ request.form['title'] }}
và vùng văn bản có giá trị {{ request.form['content'] }}
, điều này được thực hiện để dữ liệu bạn nhập vào không bị lạc nếu có sự cố. Ví dụ, nếu bạn viết một bài dài và bạn quên đặt tiêu đề cho nó, một thông báo sẽ hiển thị cho bạn biết rằng tiêu đề đó là bắt buộc. Điều này sẽ xảy ra mà không làm mất bài đăng bạn đã viết vì nó sẽ được lưu trữ trong đối tượng toàn request
cầu mà bạn có quyền truy cập trong các mẫu của bạn .
Bây giờ, với server phát triển đang chạy, hãy sử dụng trình duyệt của bạn để chuyển đến /create
tuyến:
http://127.0.0.1:5000/create
Bạn sẽ thấy trang Tạo bài đăng mới có hộp cho tiêu đề và nội dung.
Biểu mẫu này gửi yêu cầu ĐĂNG đến chức năng xem create()
của bạn. Tuy nhiên, chưa có mã nào để xử lý yêu cầu POST trong hàm, vì vậy không có gì xảy ra sau khi điền vào biểu mẫu và gửi nó.
Bạn sẽ xử lý yêu cầu ĐĂNG đến khi biểu mẫu được gửi. Bạn sẽ thực hiện việc này bên trong hàm view create()
. Bạn có thể xử lý riêng yêu cầu ĐĂNG bằng cách kiểm tra giá trị của request.method
. Khi giá trị của nó được đặt thành 'POST'
điều đó nghĩa là yêu cầu là một yêu cầu ĐĂNG, sau đó bạn sẽ tiến hành extract dữ liệu đã gửi, xác thực và chèn nó vào database của bạn .
Mở file app.py
để chỉnh sửa:
- nano app.py
Sửa đổi hàm view create()
để trông chính xác như sau:
. . . @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')
Trong if
tuyên bố bạn đảm bảo đoạn mã sau nó chỉ được thực hiện khi yêu cầu là một yêu cầu POST qua việc so sánh request.method == 'POST'
.
Sau đó, bạn extract tiêu đề và nội dung đã gửi từ đối tượng request.form
để cung cấp cho bạn quyền truy cập vào dữ liệu biểu mẫu trong yêu cầu. Nếu tiêu đề không được cung cấp, điều kiện if not title
sẽ được đáp ứng, hiển thị thông báo cho user thông báo rằng họ cần có tiêu đề. Mặt khác, nếu tiêu đề được cung cấp, bạn mở một kết nối với hàm get_db_connection()
và chèn tiêu đề và nội dung bạn nhận được vào bảng posts
.
Sau đó, bạn commit các thay đổi đối với database và đóng kết nối. Sau khi thêm bài đăng trên blog vào database , bạn chuyển hướng khách hàng đến trang index bằng cách sử dụng hàm redirect()
chuyển cho nó URL được tạo bởi hàm url_for()
với giá trị 'index'
làm đối số.
Lưu và đóng file .
Bây giờ, chuyển đến /create
tuyến đường bằng trình duyệt web :
http://127.0.0.1:5000/create
Điền vào biểu mẫu với tiêu đề bạn chọn và một số nội dung. Khi bạn gửi biểu mẫu, bạn sẽ thấy bài đăng mới được liệt kê trên trang index .
Cuối cùng, bạn sẽ hiển thị các thông báo nhấp nháy và thêm một liên kết vào thanh chuyển trong mẫu base.html
để dễ dàng truy cập vào trang mới này. Mở file mẫu:
- nano templates/base.html
Chỉnh sửa file bằng cách thêm <li>
theo liên kết About
bên trong <nav>
. Sau đó, thêm vòng lặp for
mới ngay phía trên khối content
để hiển thị các thông báo nhấp nháy bên dưới thanh chuyển . Những thông báo này có sẵn trong hàm get_flashed_messages()
đặc biệt get_flashed_messages()
Flask cung cấp:
<nav class="navbar navbar-expand-md navbar-light bg-light"> <a class="navbar-brand" href="{{ url_for('index')}}">FlaskBlog</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item"> <a class="nav-link" href="#">About</a> </li> <li class="nav-item"> <a class="nav-link" href="{{url_for('create')}}">New Post</a> </li> </ul> </div> </nav> <div class="container"> {% for message in get_flashed_messages() %} <div class="alert alert-danger">{{ message }}</div> {% endfor %} {% block content %} {% endblock %} </div>
Lưu và đóng file . Thanh chuyển lúc này sẽ có mục New Post
liên kết đến /create
tuyến đường.
Chỉnh sửa bài đăng
Để blog được cập nhật, bạn cần có thể chỉnh sửa các bài đăng hiện có của bạn . Phần này sẽ hướng dẫn bạn tạo một trang mới trong ứng dụng của bạn để đơn giản hóa quá editor bài đăng.
Đầu tiên, bạn sẽ thêm một tuyến đường mới vào file app.py
Chức năng view của nó sẽ nhận ID của bài viết cần chỉnh sửa, URL sẽ có dạng / post_id /edit
với biến post_id
là ID của bài viết. Mở file app.py
để chỉnh sửa:
- nano app.py
Tiếp theo, thêm chức năng xem edit()
vào cuối file . Chỉnh sửa một bài viết hiện có tương tự như tạo một bài mới, vì vậy hàm xem này sẽ giống với hàm xem create()
:
. . . @app.route('/<int:id>/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)
Bài đăng bạn chỉnh sửa được xác định bởi URL và Flask sẽ chuyển số ID vào hàm edit()
thông qua đối số id
. Bạn thêm giá trị này vào hàm get_post()
để tìm nạp bài đăng được liên kết với ID được cung cấp từ database . Dữ liệu mới sẽ đến trong một yêu cầu POST, được xử lý bên trong điều kiện if request.method == 'POST'
.
Giống như khi bạn tạo một bài đăng mới, trước tiên bạn extract dữ liệu từ đối tượng request.form
sau đó nhấp vào thông báo nếu tiêu đề có giá trị trống, nếu không, bạn mở một kết nối database . Sau đó, bạn cập nhật bảng posts
bằng cách đặt tiêu đề mới và nội dung mới trong đó ID của bài đăng trong database bằng với ID có trong URL.
Trong trường hợp yêu cầu GET, bạn kết xuất một mẫu edit.html
chuyển vào biến post
chứa giá trị trả về của hàm get_post()
. Bạn sẽ sử dụng nó để hiển thị tiêu đề và nội dung hiện có trên trang chỉnh sửa.
Lưu file , sau đó tạo một mẫu edit.html
mới:
- nano templates/edit.html
Viết mã sau bên trong file mới này:
{% extends 'base.html' %} {% block content %} <h1>{% block title %} Edit "{{ post['title'] }}" {% endblock %}</h1> <form method="post"> <div class="form-group"> <label for="title">Title</label> <input type="text" name="title" placeholder="Post title" class="form-control" value="{{ request.form['title'] or post['title'] }}"> </input> </div> <div class="form-group"> <label for="content">Content</label> <textarea name="content" placeholder="Post content" class="form-control">{{ request.form['content'] or post['content'] }}</textarea> </div> <div class="form-group"> <button type="submit" class="btn btn-primary">Submit</button> </div> </form> <hr> {% endblock %}
Lưu và đóng file .
Mã này tuân theo cùng một mẫu ngoại trừ cú pháp {{ request.form['title'] or post['title'] }}
và {{ request.form['content'] or post['content'] }}
. Điều này sẽ hiển thị dữ liệu được lưu trữ trong yêu cầu nếu tồn tại, nếu không, nó sẽ hiển thị dữ liệu từ biến post
đã được chuyển đến mẫu chứa dữ liệu database hiện tại.
Bây giờ, hãy chuyển đến URL sau để chỉnh sửa bài đăng đầu tiên:
http://127.0.0.1:5000/1/edit
Bạn sẽ thấy trang Chỉnh sửa “Bài đăng đầu tiên” .
Chỉnh sửa bài đăng và gửi biểu mẫu, sau đó đảm bảo bài đăng đã được cập nhật.
Đến đây bạn cần thêm một liên kết trỏ đến trang chỉnh sửa cho mỗi bài đăng trên trang index . Mở index.html
mẫu index.html
:
- nano templates/index.html
Chỉnh sửa file để trông giống hệt như sau:
{% extends 'base.html' %} {% block content %} <h1>{% block title %} Welcome to FlaskBlog {% endblock %}</h1> {% for post in posts %} <a href="{{ url_for('post', post_id=post['id']) }}"> <h2>{{ post['title'] }}</h2> </a> <span class="badge badge-primary">{{ post['created'] }}</span> <a href="{{ url_for('edit', id=post['id']) }}"> <span class="badge badge-warning">Edit</span> </a> <hr> {% endfor %} {% endblock %}
Lưu và đóng file .
Tại đây, bạn thêm thẻ <a>
để liên kết đến chức năng edit()
xem, chuyển giá trị post['id']
của bài đăng để liên kết đến trang chỉnh sửa của mỗi bài đăng với liên kết Edit
.
Xóa bài đăng
Đôi khi một bài đăng không còn cần phải được công bố công khai nữa, đó là lý do tại sao chức năng xóa bài đăng là rất quan trọng. Trong bước này, bạn sẽ thêm chức năng xóa vào ứng dụng của bạn .
Đầu tiên, bạn sẽ thêm một tuyến / ID /delete
mới chấp nhận các yêu cầu POST, tương tự như chức năng xem edit()
. Chức năng xem delete()
mới của bạn sẽ nhận được ID của bài viết cần xóa khỏi URL. Mở file app.py
:
- nano app.py
Thêm chức năng xem sau vào cuối file :
# .... @app.route('/<int:id>/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'))
Chức năng xem này chỉ chấp nhận các yêu cầu POST. Điều này nghĩa là việc chuyển đến tuyến đường / ID /delete
trên trình duyệt của bạn sẽ trả về lỗi vì trình duyệt web mặc định yêu cầu GET.
Tuy nhiên, bạn có thể truy cập vào tuyến đường này thông qua một biểu mẫu gửi yêu cầu POST chuyển đến ID của bài đăng bạn muốn xóa. Hàm sẽ nhận giá trị ID và sử dụng nó để lấy bài đăng từ database với hàm get_post()
.
Sau đó, bạn mở kết nối database và thực hiện DELETE FROM
SQL để xóa bài đăng. Bạn thực hiện thay đổi đối với database và đóng kết nối trong khi nhấp nháy thông báo để thông báo cho user rằng bài đăng đã được xóa thành công và chuyển hướng họ đến trang index .
Lưu ý bạn không hiển thị file mẫu, điều này là do bạn sẽ chỉ thêm nút Delete
vào trang chỉnh sửa.
Mở file mẫu edit.html
:
- nano templates/edit.html
Sau đó, thêm <form>
sau thẻ <hr>
và ngay trước dòng {% endblock %}
:
<hr> <form action="{{ url_for('delete', id=post['id']) }}" method="POST"> <input type="submit" value="Delete Post" class="btn btn-danger btn-sm" onclick="return confirm('Are you sure you want to delete this post?')"> </form> {% endblock %}
Bạn sử dụng phương thức confirm()
để hiển thị thông báo xác nhận trước khi gửi yêu cầu.
Bây giờ chuyển lại đến trang chỉnh sửa của một bài đăng trên blog và thử xóa nó:
http://127.0.0.1:5000/1/edit
Vào cuối bước này, mã nguồn của dự án của bạn sẽ giống như mã trên trang này .
Với điều này, user ứng dụng của bạn giờ đây có thể viết các bài đăng blog mới và thêm chúng vào database , chỉnh sửa và xóa các bài đăng hiện có.
Kết luận
Hướng dẫn này đã giới thiệu các khái niệm cơ bản về khuôn khổ Flask Python. Bạn đã học cách tạo một ứng dụng web nhỏ, chạy nó trong server phát triển và cho phép user cung cấp dữ liệu tùy chỉnh thông qua các tham số URL và biểu mẫu web. Bạn cũng đã sử dụng công cụ mẫu Jinja để sử dụng lại các file HTML và sử dụng logic trong chúng. Vào cuối hướng dẫn này, giờ đây bạn đã có một blog web hoạt động đầy đủ tương tác với cơ sở dữ liệu SQLite để tạo, hiển thị, chỉnh sửa và xóa các bài đăng trên blog bằng ngôn ngữ Python và truy vấn SQL.
Bạn có thể phát triển thêm ứng dụng này bằng cách thêm xác thực user để chỉ những user đã đăng ký mới có thể tạo và sửa đổi các bài đăng trên blog, bạn cũng có thể thêm comment và thẻ cho mỗi bài đăng trên blog và thêm tải lên file để cung cấp cho user khả năng đưa hình ảnh vào bài đăng. Xem tài liệu về Bình để biết thêm thông tin.
Flask có nhiều tiện ích mở rộng Flask do cộng đồng tạo ra. Sau đây là danh sách các tiện ích mở rộng bạn có thể cân nhắc sử dụng để giúp quá trình phát triển của bạn dễ dàng hơn:
- Flask-Login : quản lý phiên user và xử lý việc đăng nhập, đăng xuất và ghi nhớ những user đã đăng nhập.
- Flask-SQLAlchemy : đơn giản hóa việc sử dụng Flask với SQLAlchemy , một bộ công cụ Python SQL và Object Relational Mapper để tương tác với database SQL.
- Flask-Mail : giúp thực hiện nhiệm vụ gửi email trong ứng dụng Flask của bạn.
Các tin liên quan
Cách tạo web server trong Node.js bằng module HTTP2020-04-10
Mã thông báo web JSON (JWT) trong Express.js
2020-02-19
Phát triển bản địa với API thông báo web
2020-02-12
Cách tạo ứng dụng chuyển văn bản thành giọng nói với API giọng nói trên web
2019-12-12
Cách tạo băng chuyền image danh mục đầu tư với các thanh trượt được đồng bộ hóa trên trang web
2019-12-12
Cách tạo thông báo trên web bằng kênh Laravel và Pusher
2019-12-12
Khả năng truy cập web cho người mới bắt đầu
2019-12-12
Cách cài đặt web server OpenLiteSpeed trên Ubuntu 18.04
2019-12-02
Sử dụng Phông chữ Google trong các Trang web của bạn
2019-08-22
Cách triển khai ứng dụng web Go bằng Nginx trên Ubuntu 18.04
2019-07-24