Trong phần này, chúng ta sẽ thiết lập cơ sở dữ liệu Postgres để lưu trữ kết quả đếm từ của chúng ta cũng như SQLAlchemy, Object Relational Mapper và Alembic để xử lý việc di chuyển cơ sở dữ liệu.
Phần thưởng miễn phí: Nhấp vào đây để có quyền truy cập vào video hướng dẫn Flask + Python miễn phí hướng dẫn bạn cách xây dựng ứng dụng web Flask theo từng bước.
Cập nhật:
- 02/09/2020:Được nâng cấp lên phiên bản Python 3.8.1 cũng như các phiên bản mới nhất của Psycopg2, Flask-SQLAlchemy và Flask-Migrate. Xem chi tiết bên dưới. Cài đặt và sử dụng Flask-Script một cách rõ ràng do sự thay đổi của giao diện bên trong Flask-Migrate.
- 22/03/2016:Được nâng cấp lên phiên bản Python 3.5.1 cũng như các phiên bản mới nhất của Psycopg2, Flask-SQLAlchemy và Flask-Migrate. Xem chi tiết bên dưới.
- 22/02/2015:Đã thêm hỗ trợ Python 3.
Hãy nhớ:Đây là những gì chúng tôi đang xây dựng - Một ứng dụng Flask tính toán các cặp tần suất từ dựa trên văn bản từ một URL nhất định.
- Phần một:Thiết lập môi trường phát triển cục bộ, sau đó triển khai cả môi trường dàn dựng và sản xuất trên Heroku.
- Phần Hai:Thiết lập cơ sở dữ liệu PostgreSQL cùng với SQLAlchemy và Alembic để xử lý việc di chuyển. ( hiện tại )
- Phần thứ ba:Thêm logic back-end để quét và sau đó xử lý số lượng từ từ một trang web bằng cách sử dụng các thư viện yêu cầu, BeautifulSoup và Bộ công cụ ngôn ngữ tự nhiên (NLTK).
- Phần thứ tư:Triển khai hàng đợi tác vụ Redis để xử lý việc xử lý văn bản.
- Phần năm:Thiết lập Angular trên front-end để liên tục thăm dò ý kiến của back-end để xem liệu yêu cầu đã được xử lý xong chưa.
- Phần thứ sáu:Đẩy tới máy chủ dàn trên Heroku - thiết lập Redis và nêu chi tiết cách chạy hai quy trình (web và công nhân) trên một Dyno.
- Phần thứ bảy:Cập nhật giao diện người dùng để làm cho giao diện người dùng thân thiện hơn.
- Phần 8:Tạo Chỉ thị góc tùy chỉnh để hiển thị biểu đồ phân phối tần suất bằng JavaScript và D3.
Cần mã? Lấy nó từ repo.
Yêu cầu cài đặt
Các công cụ được sử dụng trong phần này:
- PostgreSQL (11.6)
- Psycopg2 (2.8.4) - một bộ điều hợp Python cho Postgres
- Flask-SQLAlchemy (2.4.1) - Tiện ích mở rộng Flask cung cấp hỗ trợ SQLAlchemy
- Flask-Migrate (2.5.2) - tiện ích mở rộng hỗ trợ di chuyển cơ sở dữ liệu SQLAlchemy qua Alembic
Để bắt đầu, hãy cài đặt Postgres trên máy tính cục bộ của bạn, nếu bạn chưa có. Vì Heroku sử dụng Postgres, sẽ rất tốt cho chúng tôi khi phát triển cục bộ trên cùng một cơ sở dữ liệu. Nếu bạn chưa cài đặt Postgres, thì Postgres.app là một cách dễ dàng để thiết lập và chạy cho người dùng Mac OS X. Tham khảo trang tải xuống để biết thêm thông tin.
Khi bạn đã cài đặt và chạy Postgres, hãy tạo cơ sở dữ liệu có tên wordcount_dev
để sử dụng làm cơ sở dữ liệu phát triển cục bộ của chúng tôi:
$ psql
# create database wordcount_dev;
CREATE DATABASE
# \q
Để sử dụng cơ sở dữ liệu mới được tạo của chúng tôi trong ứng dụng Flask, chúng tôi cần cài đặt một số thứ:
$ cd flask-by-example
cd
khi nhập vào thư mục sẽ kích hoạt môi trường ảo và đặt các biến môi trường được tìm thấy trong.env
tệp qua autoenv, mà chúng tôi đã thiết lập trong phần 1.
$ python -m pip install psycopg2==2.8.4 Flask-SQLAlchemy===2.4.1 Flask-Migrate==2.5.2
$ python -m pip freeze > requirements.txt
Nếu bạn đang sử dụng OS X và gặp sự cố khi cài đặt psycopg2, hãy xem bài viết Stack Overflow này.
Bạn có thể cần cài đặt
psycopg2-binary
thay vìpsycopg2
nếu cài đặt của bạn không thành công.
Cập nhật cấu hình
Thêm SQLALCHEMY_DATABASE_URI
trường Config()
trong config.py của bạn tệp để đặt ứng dụng của bạn sử dụng cơ sở dữ liệu mới được tạo trong quá trình phát triển (cục bộ), dàn dựng và sản xuất:
import os
class Config(object):
...
SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']
config.py của bạn tệp bây giờ sẽ giống như sau:
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
DEBUG = False
TESTING = False
CSRF_ENABLED = True
SECRET_KEY = 'this-really-needs-to-be-changed'
SQLALCHEMY_DATABASE_URI = os.environ['DATABASE_URL']
class ProductionConfig(Config):
DEBUG = False
class StagingConfig(Config):
DEVELOPMENT = True
DEBUG = True
class DevelopmentConfig(Config):
DEVELOPMENT = True
DEBUG = True
class TestingConfig(Config):
TESTING = True
Bây giờ khi cấu hình của chúng tôi được tải vào ứng dụng của chúng tôi, cơ sở dữ liệu thích hợp cũng sẽ được kết nối với nó.
Tương tự như cách chúng tôi đã thêm một biến môi trường trong bài đăng trước, chúng tôi sẽ thêm một DATABASE_URL
Biến đổi. Chạy điều này trong thiết bị đầu cuối:
$ export DATABASE_URL="postgresql:///wordcount_dev"
Và sau đó thêm dòng đó vào .env của bạn tệp.
Trong app.py của bạn nhập tệp SQLAlchemy và kết nối với cơ sở dữ liệu:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os
app = Flask(__name__)
app.config.from_object(os.environ['APP_SETTINGS'])
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
from models import Result
@app.route('/')
def hello():
return "Hello World!"
@app.route('/<name>')
def hello_name(name):
return "Hello {}!".format(name)
if __name__ == '__main__':
app.run()
Mô hình dữ liệu
Thiết lập mô hình cơ bản bằng cách thêm models.py tệp:
from app import db
from sqlalchemy.dialects.postgresql import JSON
class Result(db.Model):
__tablename__ = 'results'
id = db.Column(db.Integer, primary_key=True)
url = db.Column(db.String())
result_all = db.Column(JSON)
result_no_stop_words = db.Column(JSON)
def __init__(self, url, result_all, result_no_stop_words):
self.url = url
self.result_all = result_all
self.result_no_stop_words = result_no_stop_words
def __repr__(self):
return '<id {}>'.format(self.id)
Ở đây, chúng tôi đã tạo một bảng để lưu trữ kết quả của số lượng từ.
Đầu tiên, chúng tôi nhập kết nối cơ sở dữ liệu mà chúng tôi đã tạo trong app.py cũng như JSON từ phương ngữ PostgreSQL của SQLAlchemy. Các cột JSON khá mới đối với Postgres và không có sẵn trong mọi cơ sở dữ liệu được SQLAlchemy hỗ trợ, vì vậy chúng tôi cần nhập nó một cách cụ thể.
Tiếp theo, chúng tôi tạo một Result()
và gán cho nó một tên bảng gồm results
. Sau đó, chúng tôi đặt các thuộc tính mà chúng tôi muốn lưu trữ cho một kết quả-
-
id
kết quả mà chúng tôi đã lưu trữ -
url
mà chúng tôi đã đếm các từ từ - danh sách đầy đủ các từ mà chúng tôi đã đếm
- danh sách các từ mà chúng tôi đã đếm trừ các từ dừng (sẽ nói thêm về điều này sau)
Sau đó, chúng tôi đã tạo một __init__()
phương thức sẽ chạy lần đầu tiên chúng ta tạo một kết quả mới và cuối cùng là __repr__()
để đại diện cho đối tượng khi chúng tôi truy vấn nó.
Di chuyển cục bộ
Chúng tôi sẽ sử dụng Alembic, một phần của Flask-Migrate, để quản lý việc di chuyển cơ sở dữ liệu nhằm cập nhật giản đồ của cơ sở dữ liệu.
Lưu ý: Flask-Migrate sử dụng công cụ CLI mới của Flasks. Tuy nhiên, bài viết này sử dụng giao diện được cung cấp bởi Flask-Script, giao diện được sử dụng bởi Flask-Migrate trước đây. Để sử dụng nó, bạn cần cài đặt nó qua:
$ python -m pip install Flask-Script==2.0.6 $ python -m pip freeze > requirements.txt
Tạo một tệp mới có tên là management.py :
import os
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import app, db
app.config.from_object(os.environ['APP_SETTINGS'])
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
Để sử dụng Flask-Migrate, chúng tôi đã nhập Manager
cũng như Migrate
và MigrateCommand
tới management.py của chúng tôi tập tin. Chúng tôi cũng đã nhập ứng dụng app
và db
vì vậy chúng tôi có quyền truy cập vào chúng từ bên trong tập lệnh.
Đầu tiên, chúng tôi đặt cấu hình của mình để có được môi trường của chúng tôi - dựa trên biến môi trường - đã tạo một phiên bản di chuyển, với ứng dụng app
và db
làm đối số và thiết lập manager
lệnh để khởi tạo Manager
ví dụ cho ứng dụng của chúng tôi. Cuối cùng, chúng tôi đã thêm db
lệnh cho manager
để chúng tôi có thể chạy quá trình di chuyển từ dòng lệnh.
Để chạy quá trình di chuyển, hãy khởi chạy Alembic:
$ python manage.py db init
Creating directory /flask-by-example/migrations ... done
Creating directory /flask-by-example/migrations/versions ... done
Generating /flask-by-example/migrations/alembic.ini ... done
Generating /flask-by-example/migrations/env.py ... done
Generating /flask-by-example/migrations/README ... done
Generating /flask-by-example/migrations/script.py.mako ... done
Please edit configuration/connection/logging settings in
'/flask-by-example/migrations/alembic.ini' before proceeding.
Sau khi chạy khởi tạo cơ sở dữ liệu, bạn sẽ thấy một thư mục mới có tên là “di chuyển” trong dự án. Điều này giữ thiết lập cần thiết để Alembic thực hiện các cuộc di cư chống lại dự án. Bên trong "di chuyển", bạn sẽ thấy rằng nó có một thư mục được gọi là "phiên bản", sẽ chứa các tập lệnh di chuyển khi chúng được tạo.
Hãy tạo lần di chuyển đầu tiên của chúng ta bằng cách chạy migrate
lệnh.
$ python manage.py db migrate
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'results'
Generating /flask-by-example/migrations/versions/63dba2060f71_.py
... done
Bây giờ, bạn sẽ nhận thấy trong thư mục “phiên bản” của mình có một tệp di chuyển. Tệp này được Alembic tạo tự động dựa trên mô hình. Bạn có thể tự tạo (hoặc chỉnh sửa) tệp này; tuy nhiên, đối với hầu hết các trường hợp, tệp được tạo tự động sẽ làm được.
Bây giờ chúng tôi sẽ áp dụng các nâng cấp cho cơ sở dữ liệu bằng cách sử dụng db upgrade
lệnh:
$ python manage.py db upgrade
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 63dba2060f71, empty message
Cơ sở dữ liệu hiện đã sẵn sàng để chúng tôi sử dụng trong ứng dụng của mình:
$ psql
# \c wordcount_dev
You are now connected to database "wordcount_dev" as user "michaelherman".
# \dt
List of relations
Schema | Name | Type | Owner
--------+-----------------+-------+---------------
public | alembic_version | table | michaelherman
public | results | table | michaelherman
(2 rows)
# \d results
Table "public.results"
Column | Type | Modifiers
----------------------+-------------------+------------------------------------------------------
id | integer | not null default nextval('results_id_seq'::regclass)
url | character varying |
result_all | json |
result_no_stop_words | json |
Indexes:
"results_pkey" PRIMARY KEY, btree (id)
Di chuyển từ xa
Cuối cùng, hãy áp dụng các di chuyển cho cơ sở dữ liệu trên Heroku. Tuy nhiên, trước tiên, chúng tôi cần thêm các chi tiết của cơ sở dữ liệu sản xuất và dàn dựng vào config.py tệp.
Để kiểm tra xem chúng tôi có cơ sở dữ liệu được thiết lập trên máy chủ chạy dàn dựng hay không:
$ heroku config --app wordcount-stage
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig
Đảm bảo thay thế
wordcount-stage
với tên của ứng dụng dàn dựng của bạn.
Vì chúng tôi không thấy biến môi trường cơ sở dữ liệu, chúng tôi cần thêm addon Postgres vào máy chủ dàn. Để làm như vậy, hãy chạy lệnh sau:
$ heroku addons:create heroku-postgresql:hobby-dev --app wordcount-stage
Creating postgresql-cubic-86416... done, (free)
Adding postgresql-cubic-86416 to wordcount-stage... done
Setting DATABASE_URL and restarting wordcount-stage... done, v8
Database has been created and is available
! This database is empty. If upgrading, you can transfer
! data from another database with pg:copy
Use `heroku addons:docs heroku-postgresql` to view documentation.
hobby-dev
là cấp miễn phí của addon Heroku Postgres.
Bây giờ khi chúng ta chạy heroku config --app wordcount-stage
một lần nữa, chúng ta sẽ thấy cài đặt kết nối cho cơ sở dữ liệu:
=== wordcount-stage Config Vars
APP_SETTINGS: config.StagingConfig
DATABASE_URL: postgres://azrqiefezenfrg:Zti5fjSyeyFgoc-U-yXnPrXHQv@ec2-54-225-151-64.compute-1.amazonaws.com:5432/d2kio2ubc804p7
Tiếp theo, chúng tôi cần cam kết những thay đổi mà bạn đã thực hiện đối với git và đẩy lên máy chủ dàn của bạn:
$ git push stage master
Chạy quá trình di chuyển mà chúng tôi đã tạo để di chuyển cơ sở dữ liệu dàn của chúng tôi bằng cách sử dụng heroku run
lệnh:
$ heroku run python manage.py db upgrade --app wordcount-stage
Running python manage.py db upgrade on wordcount-stage... up, run.5677
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade -> 63dba2060f71, empty message
Lưu ý cách chúng tôi chỉ chạy
upgrade
, không phảiinit
hoặcmigrate
các lệnh như trước đây. Chúng tôi đã thiết lập tệp di chuyển của mình và sẵn sàng hoạt động; chúng ta chỉ cần áp dụng nó với cơ sở dữ liệu Heroku.
Bây giờ chúng ta hãy làm điều tương tự cho quá trình sản xuất.
- Thiết lập cơ sở dữ liệu cho ứng dụng sản xuất của bạn trên Heroku, giống như bạn đã làm để dàn dựng:
heroku addons:create heroku-postgresql:hobby-dev --app wordcount-pro
- Đẩy các thay đổi của bạn vào trang web sản xuất của bạn:
git push pro master
Lưu ý rằng bạn không phải thực hiện bất kỳ thay đổi nào đối với tệp cấu hình - nó đang thiết lập cơ sở dữ liệu dựa trênDATABASE_URL
mới được tạo biến môi trường. - Áp dụng di chuyển:
heroku run python manage.py db upgrade --app wordcount-pro
Giờ đây, cả trang web dàn dựng và sản xuất của chúng tôi đều đã thiết lập cơ sở dữ liệu và đã được di chuyển - và sẵn sàng hoạt động!
Khi bạn áp dụng một chuyển đổi mới cho cơ sở dữ liệu sản xuất, có thể có thời gian ngừng hoạt động. Nếu đây là sự cố, bạn có thể thiết lập sao chép cơ sở dữ liệu bằng cách thêm cơ sở dữ liệu “người theo dõi” (thường được gọi là nô lệ). Để biết thêm về điều này, hãy xem tài liệu chính thức của Heroku.
Kết luận
Vậy là xong phần 2. Nếu bạn muốn tìm hiểu sâu hơn về Flask, hãy xem loạt video đi kèm của chúng tôi:
Phần thưởng miễn phí: Nhấp vào đây để có quyền truy cập vào video hướng dẫn Flask + Python miễn phí hướng dẫn bạn cách xây dựng ứng dụng web Flask theo từng bước.
Trong Phần 3, chúng ta sẽ xây dựng chức năng đếm từ và đưa nó đến hàng đợi tác vụ để xử lý quá trình đếm từ đang chạy lâu hơn.
Hẹn gặp lại các bạn trong những lần sau. Chúc mừng!
Đây là tác phẩm hợp tác giữa Cam Linke, đồng sáng lập Startup Edmonton và những người tại Real Python.