Mẫu kho lưu trữ python sqlalchemy

Đây là phần thứ tư của sê-ri Flask Mega-Tutorial, trong đó tôi sẽ cho bạn biết cách làm việc với cơ sở dữ liệu

Để bạn tham khảo, dưới đây là danh sách các bài viết trong loạt bài này

  • Chương 1. Chào thế giới
  • chương 2. mẫu
  • Chương 3. biểu mẫu web
  • Chương 4. Cơ sở dữ liệu [bài viết này]
  • Chương 5. Đăng nhập người dùng
  • Chương 6. Trang hồ sơ và hình đại diện
  • Chương 7. Xử lý lỗi
  • Chương 8. Người theo dõi
  • Chương 9. phân trang
  • Chương 10. Hỗ trợ email
  • chương 11. căng da mặt
  • Chương 12. Ngày và Giờ
  • Chương 13. I18n và L10n
  • Chương 14. Ajax
  • Chương 15. Cấu trúc ứng dụng tốt hơn
  • Chương 16. Tìm kiếm toàn văn
  • Chương 17. Triển khai trên Linux
  • Chương 18. Triển khai trên Heroku
  • Chương 19. Triển khai trên Docker Container
  • Chương 20. Một số ma thuật JavaScript
  • Chương 21. Thông báo người dùng
  • Chương 22. công việc nền
  • Chương 23. Giao diện lập trình ứng dụng [API]

Chủ đề của chương này cực kỳ quan trọng. Đối với hầu hết các ứng dụng, sẽ cần phải duy trì dữ liệu liên tục có thể được truy xuất hiệu quả và đây chính xác là mục đích của cơ sở dữ liệu.

Các liên kết GitHub cho chương này là. Duyệt, Zip, Khác biệt

Cơ sở dữ liệu trong Flask

Như tôi chắc rằng bạn đã nghe rồi, Flask không hỗ trợ cơ sở dữ liệu nguyên bản. Đây là một trong nhiều lĩnh vực mà Flask cố ý không cố ý, điều này thật tuyệt, vì bạn có quyền tự do lựa chọn cơ sở dữ liệu phù hợp nhất với ứng dụng của mình thay vì bị buộc phải thích ứng với một cơ sở dữ liệu.

Có nhiều lựa chọn tuyệt vời cho cơ sở dữ liệu bằng Python, nhiều trong số chúng có phần mở rộng Flask giúp tích hợp tốt hơn với ứng dụng. Các cơ sở dữ liệu có thể được tách thành hai nhóm lớn, những nhóm tuân theo mô hình quan hệ và những nhóm không theo mô hình quan hệ. Nhóm thứ hai thường được gọi là NoSQL, chỉ ra rằng họ không triển khai ngôn ngữ truy vấn quan hệ phổ biến SQL. Mặc dù có những sản phẩm cơ sở dữ liệu tuyệt vời trong cả hai nhóm, nhưng ý kiến ​​của tôi là cơ sở dữ liệu quan hệ phù hợp hơn cho các ứng dụng có dữ liệu có cấu trúc như danh sách người dùng, bài đăng trên blog, v.v. , trong khi cơ sở dữ liệu NoSQL có xu hướng tốt hơn cho dữ liệu có cấu trúc ít xác định hơn. Ứng dụng này, giống như hầu hết các ứng dụng khác, có thể được triển khai bằng một trong hai loại cơ sở dữ liệu, nhưng vì những lý do đã nêu ở trên, tôi sẽ sử dụng cơ sở dữ liệu quan hệ

Trong Chương 3, tôi đã giới thiệu cho bạn tiện ích mở rộng Flask đầu tiên. Trong chương này tôi sẽ sử dụng thêm hai. Đầu tiên là Flask-SQLAlchemy, một tiện ích mở rộng cung cấp trình bao bọc thân thiện với Flask cho gói SQLAlchemy phổ biến, là Trình ánh xạ quan hệ đối tượng hoặc ORM. ORM cho phép các ứng dụng quản lý cơ sở dữ liệu bằng cách sử dụng các thực thể cấp cao như lớp, đối tượng và phương thức thay vì bảng và SQL. Công việc của ORM là dịch các hoạt động cấp cao thành các lệnh cơ sở dữ liệu

Điều thú vị về SQLAlchemy là nó không phải là một ORM cho một mà cho nhiều cơ sở dữ liệu quan hệ. SQLAlchemy hỗ trợ một danh sách dài các công cụ cơ sở dữ liệu, bao gồm MySQL, PostgreSQL và SQLite phổ biến. Điều này cực kỳ mạnh mẽ, bởi vì bạn có thể thực hiện quá trình phát triển của mình bằng cách sử dụng cơ sở dữ liệu SQLite đơn giản không yêu cầu máy chủ và sau đó khi đến lúc triển khai ứng dụng trên máy chủ sản xuất, bạn có thể chọn máy chủ MySQL hoặc PostgreSQL mạnh mẽ hơn mà không cần có

Để cài đặt Flask-SQLAlchemy trong môi trường ảo của bạn, hãy đảm bảo rằng bạn đã kích hoạt nó trước rồi chạy

[venv] $ pip install flask-sqlalchemy

Di chuyển cơ sở dữ liệu

Hầu hết các hướng dẫn về cơ sở dữ liệu mà tôi đã xem bao gồm việc tạo và sử dụng cơ sở dữ liệu, nhưng không giải quyết thỏa đáng vấn đề cập nhật cơ sở dữ liệu hiện có khi ứng dụng cần thay đổi hoặc phát triển. Điều này khó vì cơ sở dữ liệu quan hệ tập trung vào dữ liệu có cấu trúc, vì vậy khi cấu trúc thay đổi, dữ liệu đã có trong cơ sở dữ liệu cần được di chuyển sang cấu trúc đã sửa đổi

Tiện ích mở rộng thứ hai mà tôi sẽ trình bày trong chương này là Flask-Migrate, đây thực sự là một tiện ích do chính bạn tạo ra. Tiện ích mở rộng này là trình bao bọc Flask cho Alembic, khung di chuyển cơ sở dữ liệu cho SQLAlchemy. Làm việc với di chuyển cơ sở dữ liệu sẽ thêm một chút công việc để bắt đầu cơ sở dữ liệu, nhưng đó là một cái giá nhỏ phải trả cho một cách mạnh mẽ để thực hiện các thay đổi đối với cơ sở dữ liệu của bạn trong tương lai

Quá trình cài đặt Flask-Migrate cũng tương tự như các tiện ích mở rộng khác mà bạn đã thấy

[venv] $ pip install flask-migrate

Cấu hình Flask-SQLAlchemy

Trong quá trình phát triển, tôi sẽ sử dụng cơ sở dữ liệu SQLite. Cơ sở dữ liệu SQLite là lựa chọn thuận tiện nhất để phát triển các ứng dụng nhỏ, đôi khi thậm chí không quá nhỏ, vì mỗi cơ sở dữ liệu được lưu trữ trong một tệp duy nhất trên đĩa và không cần chạy máy chủ cơ sở dữ liệu như MySQL và PostgreSQL

Chúng tôi có hai mục cấu hình mới để thêm vào tệp cấu hình

cấu hình. py. Cấu hình Flask-SQLAlchemy

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False

Tiện ích mở rộng Flask-SQLAlchemy lấy vị trí cơ sở dữ liệu của ứng dụng từ biến cấu hình

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

0. Như bạn nhớ lại từ Chương 3, nói chung, nên đặt cấu hình từ các biến môi trường và cung cấp giá trị dự phòng khi môi trường không xác định biến. Trong trường hợp này, tôi đang lấy URL cơ sở dữ liệu từ biến môi trường
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

1 và nếu điều đó không được xác định, thì tôi đang định cấu hình cơ sở dữ liệu có tên ứng dụng. db nằm trong thư mục chính của ứng dụng, được lưu trữ trong biến
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

2

Tùy chọn cấu hình

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

3 được đặt thành
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

4 để tắt một tính năng của Flask-SQLAlchemy mà tôi không cần, đó là gửi tín hiệu đến ứng dụng mỗi khi sắp có thay đổi trong cơ sở dữ liệu

Cơ sở dữ liệu sẽ được đại diện trong ứng dụng bởi cá thể cơ sở dữ liệu. Công cụ di chuyển cơ sở dữ liệu cũng sẽ có một phiên bản. Đây là những đối tượng cần được tạo sau ứng dụng, trong app/__init__. tập tin py

ứng dụng/__init__. py. Khởi tạo Flask-SQLAlchemy và Flask-Migrate

________số 8

Tôi đã thực hiện ba thay đổi đối với tập lệnh init. Đầu tiên, tôi đã thêm một đối tượng

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

5 đại diện cho cơ sở dữ liệu. Sau đó, tôi đã thêm một đối tượng khác đại diện cho công cụ di chuyển. Hy vọng rằng bạn thấy một mẫu về cách làm việc với các phần mở rộng Flask. Hầu hết các phần mở rộng được khởi tạo như hai. Cuối cùng, tôi đang nhập một mô-đun mới có tên là
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

6 ở phía dưới. Mô-đun này sẽ xác định cấu trúc của cơ sở dữ liệu

Mô hình cơ sở dữ liệu

Dữ liệu sẽ được lưu trữ trong cơ sở dữ liệu sẽ được biểu diễn bằng một tập hợp các lớp, thường được gọi là mô hình cơ sở dữ liệu. Lớp ORM trong SQLAlchemy sẽ thực hiện các bản dịch cần thiết để ánh xạ các đối tượng được tạo từ các lớp này thành các hàng trong các bảng cơ sở dữ liệu thích hợp

Hãy bắt đầu bằng cách tạo một mô hình đại diện cho người dùng. Sử dụng công cụ WWW SQL Designer, tôi đã tạo sơ đồ sau để biểu diễn dữ liệu mà chúng tôi muốn sử dụng trong bảng người dùng

Trường

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7 thường có trong tất cả các mô hình và được dùng làm khóa chính. Mỗi người dùng trong cơ sở dữ liệu sẽ được gán một giá trị id duy nhất, được lưu trữ trong trường này. Trong hầu hết các trường hợp, khóa chính được cơ sở dữ liệu tự động gán, vì vậy tôi chỉ cần cung cấp trường
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7 được đánh dấu là khóa chính

Các trường

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

9,
[venv] $ pip install flask-migrate
40 và
[venv] $ pip install flask-migrate
41 được định nghĩa là các chuỗi [hoặc
[venv] $ pip install flask-migrate
42 trong thuật ngữ cơ sở dữ liệu] và độ dài tối đa của chúng được chỉ định để cơ sở dữ liệu có thể tối ưu hóa việc sử dụng không gian. Mặc dù các trường
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

9 và
[venv] $ pip install flask-migrate
40 dễ hiểu, nhưng các trường
[venv] $ pip install flask-migrate
41 đáng được chú ý. Tôi muốn đảm bảo ứng dụng mà tôi đang xây dựng áp dụng các biện pháp bảo mật tốt nhất và vì lý do đó, tôi sẽ không lưu trữ mật khẩu người dùng trong cơ sở dữ liệu. Vấn đề với việc lưu trữ mật khẩu là nếu cơ sở dữ liệu bị xâm phạm, những kẻ tấn công sẽ có quyền truy cập vào mật khẩu và điều đó có thể gây thiệt hại cho người dùng. Thay vì viết mật khẩu trực tiếp, tôi sẽ viết mật khẩu băm, giúp cải thiện đáng kể tính bảo mật. Đây sẽ là chủ đề của một chương khác, vì vậy đừng lo lắng về nó quá nhiều vào lúc này

Vì vậy, bây giờ tôi biết những gì tôi muốn cho bảng người dùng của mình, tôi có thể dịch nó thành mã trong ứng dụng/mô hình mới. mô-đun py

ứng dụng/mô hình. py. Mô hình cơ sở dữ liệu người dùng

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
0

Lớp

[venv] $ pip install flask-migrate
46 được tạo ở trên kế thừa từ
[venv] $ pip install flask-migrate
47, một lớp cơ sở cho tất cả các mô hình từ Flask-SQLAlchemy. Lớp này định nghĩa một số trường dưới dạng biến lớp. Các trường được tạo dưới dạng các thể hiện của lớp
[venv] $ pip install flask-migrate
48, lấy loại trường làm đối số, cộng với các đối số tùy chọn khác, chẳng hạn như cho phép tôi chỉ ra trường nào là duy nhất và được lập chỉ mục, điều này rất quan trọng để tìm kiếm cơ sở dữ liệu hiệu quả

Phương thức

[venv] $ pip install flask-migrate
49 cho Python biết cách in các đối tượng của lớp này, điều này sẽ hữu ích cho việc gỡ lỗi. Bạn có thể thấy phương thức
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
50 đang hoạt động trong phiên phiên dịch Python bên dưới

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

Tạo kho lưu trữ di chuyển

Lớp mô hình được tạo trong phần trước xác định cấu trúc cơ sở dữ liệu ban đầu [hoặc lược đồ] cho ứng dụng này. Nhưng khi ứng dụng tiếp tục phát triển, có khả năng tôi sẽ cần thực hiện các thay đổi đối với cấu trúc đó, chẳng hạn như thêm những thứ mới và đôi khi sửa đổi hoặc xóa các mục. Alembic [khung di chuyển được sử dụng bởi Flask-Migrate] sẽ thực hiện các thay đổi lược đồ này theo cách không yêu cầu cơ sở dữ liệu phải được tạo lại từ đầu mỗi khi cần thực hiện thay đổi

Để hoàn thành nhiệm vụ có vẻ khó khăn này, Alembic duy trì một kho lưu trữ di chuyển, đây là một thư mục lưu trữ các tập lệnh di chuyển của nó. Mỗi khi có thay đổi đối với lược đồ cơ sở dữ liệu, tập lệnh di chuyển sẽ được thêm vào kho lưu trữ với các chi tiết về thay đổi. Để áp dụng di chuyển vào cơ sở dữ liệu, các tập lệnh di chuyển này được thực thi theo trình tự chúng được tạo

Flask-Migrate hiển thị các lệnh của nó thông qua lệnh

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
51. Bạn đã thấy
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
52, một lệnh phụ có nguồn gốc từ Flask. Lệnh phụ
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
53 được Flask-Migrate thêm vào để quản lý mọi thứ liên quan đến di chuyển cơ sở dữ liệu. Vì vậy, hãy tạo kho lưu trữ di chuyển cho tiểu blog bằng cách chạy
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
54

[venv] $ pip install flask-migrate
4

Hãy nhớ rằng lệnh

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
51 dựa vào biến môi trường
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
56 để biết vị trí của ứng dụng Flask. Đối với ứng dụng này, bạn muốn đặt
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
56 thành giá trị
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
58, như đã thảo luận trong Chương 1

Sau khi bạn chạy lệnh này, bạn sẽ tìm thấy một thư mục di chuyển mới, với một vài tệp và thư mục con phiên bản bên trong. Tất cả các tệp này sẽ được coi là một phần của dự án của bạn kể từ bây giờ và đặc biệt, nên được thêm vào kiểm soát nguồn cùng với mã ứng dụng của bạn

Di chuyển cơ sở dữ liệu đầu tiên

Với kho lưu trữ di chuyển đã sẵn sàng, đã đến lúc tạo di chuyển cơ sở dữ liệu đầu tiên, bao gồm bảng người dùng ánh xạ tới mô hình cơ sở dữ liệu

[venv] $ pip install flask-migrate
46. Có hai cách để tạo di chuyển cơ sở dữ liệu. thủ công hoặc tự động. Để tự động tạo di chuyển, Alembic so sánh lược đồ cơ sở dữ liệu như được xác định bởi các mô hình cơ sở dữ liệu, với lược đồ cơ sở dữ liệu thực tế hiện được sử dụng trong cơ sở dữ liệu. Sau đó, nó điền vào tập lệnh di chuyển những thay đổi cần thiết để làm cho lược đồ cơ sở dữ liệu khớp với các mô hình ứng dụng. Trong trường hợp này, vì không có cơ sở dữ liệu trước đó, quá trình di chuyển tự động sẽ thêm toàn bộ mô hình
[venv] $ pip install flask-migrate
46 vào tập lệnh di chuyển. Lệnh phụ
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

81 tạo các lần di chuyển tự động này

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
5

Đầu ra của lệnh cung cấp cho bạn ý tưởng về những gì Alembic bao gồm trong quá trình di chuyển. Hai dòng đầu tiên là thông tin và thường có thể bỏ qua. Sau đó, nó nói rằng nó đã tìm thấy một bảng người dùng và hai chỉ mục. Sau đó, nó sẽ cho bạn biết nó đã viết tập lệnh di chuyển ở đâu. Mã

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

82 là mã duy nhất được tạo tự động cho quá trình di chuyển [mã này sẽ khác đối với bạn]. Nhận xét được đưa ra với tùy chọn
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

83 là tùy chọn, nó thêm một đoạn văn bản mô tả ngắn vào quá trình di chuyển

Tập lệnh di chuyển được tạo hiện là một phần của dự án của bạn và cần được kết hợp với kiểm soát nguồn. Bạn có thể kiểm tra tập lệnh nếu bạn tò mò muốn xem nó trông như thế nào. Bạn sẽ thấy rằng nó có hai chức năng gọi là

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

84 và
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

85. Hàm
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

84 áp dụng di chuyển và hàm
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

85 loại bỏ nó. Điều này cho phép Alembic di chuyển cơ sở dữ liệu đến bất kỳ điểm nào trong lịch sử, thậm chí đến các phiên bản cũ hơn, bằng cách sử dụng đường dẫn hạ cấp

Lệnh

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

81 không thực hiện bất kỳ thay đổi nào đối với cơ sở dữ liệu, nó chỉ tạo tập lệnh di chuyển. Để áp dụng các thay đổi cho cơ sở dữ liệu, phải sử dụng lệnh
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

89

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

8

Bởi vì ứng dụng này sử dụng SQLite, lệnh

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

90 sẽ phát hiện ra rằng cơ sở dữ liệu không tồn tại và sẽ tạo nó [bạn sẽ thấy một tệp có tên app. db được thêm vào sau khi lệnh này kết thúc, đó là cơ sở dữ liệu SQLite]. Khi làm việc với máy chủ cơ sở dữ liệu như MySQL và PostgreSQL, bạn phải tạo cơ sở dữ liệu trong máy chủ cơ sở dữ liệu trước khi chạy
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

90

Lưu ý rằng Flask-SQLAlchemy sử dụng quy ước đặt tên "trường hợp rắn" cho các bảng cơ sở dữ liệu theo mặc định. Đối với mô hình

[venv] $ pip install flask-migrate
46 ở trên, bảng tương ứng trong cơ sở dữ liệu sẽ có tên là
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

93. Đối với một lớp mô hình
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

94, bảng sẽ được đặt tên là
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

95. Nếu bạn muốn chọn tên bảng của riêng mình, bạn có thể thêm thuộc tính có tên
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

96 vào lớp mô hình, đặt thành tên mong muốn dưới dạng chuỗi

Quy trình nâng cấp và hạ cấp cơ sở dữ liệu

Ứng dụng này đang ở giai đoạn sơ khai vào thời điểm này, nhưng sẽ không hại gì khi thảo luận về chiến lược di chuyển cơ sở dữ liệu trong tương lai. Hãy tưởng tượng rằng bạn có ứng dụng của mình trên máy phát triển và cũng có một bản sao được triển khai tới máy chủ sản xuất trực tuyến và đang được sử dụng

Giả sử rằng đối với bản phát hành tiếp theo của ứng dụng, bạn phải đưa ra một thay đổi đối với các mô hình của mình, ví dụ: cần thêm một bảng mới. Nếu không có sự di chuyển, bạn sẽ cần phải tìm ra cách thay đổi lược đồ cơ sở dữ liệu của mình, cả trong máy phát triển và sau đó một lần nữa trong máy chủ của bạn và điều này có thể tốn rất nhiều công sức

Nhưng với hỗ trợ di chuyển cơ sở dữ liệu, sau khi bạn sửa đổi các mô hình trong ứng dụng của mình, bạn sẽ tạo một tập lệnh di chuyển mới [

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

81], bạn có thể xem lại tập lệnh đó để đảm bảo rằng quá trình tạo tự động đã thực hiện đúng, sau đó áp dụng các thay đổi cho cơ sở dữ liệu phát triển của bạn [
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

89 . Bạn sẽ thêm tập lệnh di chuyển vào kiểm soát nguồn và cam kết nó

Khi bạn đã sẵn sàng phát hành phiên bản mới của ứng dụng cho máy chủ sản xuất của mình, tất cả những gì bạn cần làm là lấy phiên bản cập nhật của ứng dụng, phiên bản này sẽ bao gồm tập lệnh di chuyển mới và chạy

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

89. Alembic sẽ phát hiện ra rằng cơ sở dữ liệu sản xuất không được cập nhật lên bản sửa đổi mới nhất của lược đồ và chạy tất cả các tập lệnh di chuyển mới được tạo sau bản phát hành trước đó

Như tôi đã đề cập trước đó, bạn cũng có lệnh

[venv] $ pip install flask-migrate
00, lệnh này hoàn tác lần di chuyển cuối cùng. Mặc dù bạn sẽ không cần tùy chọn này trên hệ thống sản xuất, nhưng bạn có thể thấy nó rất hữu ích trong quá trình phát triển. Bạn có thể đã tạo một tập lệnh di chuyển và áp dụng nó, chỉ để thấy rằng những thay đổi mà bạn đã thực hiện không chính xác như những gì bạn cần. Trong trường hợp này, bạn có thể hạ cấp cơ sở dữ liệu, xóa tập lệnh di chuyển rồi tạo tập lệnh mới để thay thế

Mối quan hệ cơ sở dữ liệu

Cơ sở dữ liệu quan hệ rất tốt trong việc lưu trữ quan hệ giữa các mục dữ liệu. Xem xét trường hợp người dùng viết một bài đăng trên blog. Người dùng sẽ có một bản ghi trong bảng

[venv] $ pip install flask-migrate
01 và bài đăng sẽ có một bản ghi trong bảng
[venv] $ pip install flask-migrate
02. Cách hiệu quả nhất để ghi lại ai đã viết một bài đăng nhất định là liên kết hai bản ghi liên quan

Khi liên kết giữa người dùng và bài đăng được thiết lập, cơ sở dữ liệu có thể trả lời các truy vấn về liên kết này. Điều tầm thường nhất là khi bạn có một bài đăng trên blog và cần biết người dùng đã viết gì. Truy vấn phức tạp hơn thì ngược lại với truy vấn này. Nếu bạn có người dùng, bạn có thể muốn biết tất cả các bài đăng mà người dùng này đã viết. Flask-SQLAlchemy sẽ trợ giúp với cả hai loại truy vấn

Hãy mở rộng cơ sở dữ liệu để lưu trữ các bài đăng trên blog để xem các mối quan hệ đang hoạt động. Đây là lược đồ cho một bảng

[venv] $ pip install flask-migrate
02 mới

Bảng

[venv] $ pip install flask-migrate
02 sẽ có
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7 bắt buộc,
[venv] $ pip install flask-migrate
06 của bài đăng và một
[venv] $ pip install flask-migrate
07. Nhưng ngoài những trường dự kiến ​​này, tôi đang thêm một trường
[venv] $ pip install flask-migrate
08, trường này liên kết bài đăng với tác giả của nó. Bạn đã thấy rằng tất cả người dùng đều có khóa chính
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7, khóa này là duy nhất. Cách để liên kết một bài đăng trên blog với người dùng đã tạo ra nó là thêm một tham chiếu đến
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7 của người dùng và đó chính xác là trường
[venv] $ pip install flask-migrate
08. Trường
[venv] $ pip install flask-migrate
08 này được gọi là khóa ngoại. Sơ đồ cơ sở dữ liệu ở trên hiển thị các khóa ngoại dưới dạng liên kết giữa trường và trường
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7 của bảng mà nó đề cập đến. Loại mối quan hệ này được gọi là một-nhiều, bởi vì "một" người dùng viết "nhiều" bài đăng

Ứng dụng/mô hình đã sửa đổi. py được hiển thị bên dưới

ứng dụng/mô hình. py. Bài viết bảng cơ sở dữ liệu và mối quan hệ

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

9

Lớp

[venv] $ pip install flask-migrate
14 mới sẽ đại diện cho các bài đăng trên blog được viết bởi người dùng. Trường
[venv] $ pip install flask-migrate
07 sẽ được lập chỉ mục, rất hữu ích nếu bạn muốn truy xuất các bài đăng theo trình tự thời gian. Tôi cũng đã thêm đối số
[venv] $ pip install flask-migrate
16 và chuyển hàm
[venv] $ pip install flask-migrate
17. Khi bạn chuyển một hàm làm mặc định, SQLAlchemy sẽ đặt trường thành giá trị gọi hàm đó [lưu ý rằng tôi không bao gồm
[venv] $ pip install flask-migrate
18 sau
[venv] $ pip install flask-migrate
19, vì vậy tôi đang chuyển chính hàm đó chứ không phải kết quả của việc gọi nó]. Nói chung, bạn sẽ muốn làm việc với ngày và giờ UTC trong ứng dụng máy chủ. Điều này đảm bảo rằng bạn đang sử dụng dấu thời gian thống nhất bất kể vị trí của người dùng. Các dấu thời gian này sẽ được chuyển đổi thành giờ địa phương của người dùng khi chúng được hiển thị

Trường

[venv] $ pip install flask-migrate
08 được khởi tạo làm khóa ngoại cho
[venv] $ pip install flask-migrate
21, có nghĩa là trường này tham chiếu giá trị
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7 từ bảng người dùng. Trong tài liệu tham khảo này, phần
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

93 là tên của bảng cơ sở dữ liệu cho mô hình. Có một sự mâu thuẫn đáng tiếc là trong một số trường hợp, chẳng hạn như trong lệnh gọi
[venv] $ pip install flask-migrate
24, mô hình được tham chiếu bởi lớp mô hình, thường bắt đầu bằng một ký tự viết hoa, trong khi trong các trường hợp khác, chẳng hạn như khai báo
[venv] $ pip install flask-migrate
25 này, một mô hình được cung cấp bởi cơ sở dữ liệu của nó

Lớp

[venv] $ pip install flask-migrate
46 có trường
[venv] $ pip install flask-migrate
02 mới, được khởi tạo với
[venv] $ pip install flask-migrate
28. Đây không phải là trường cơ sở dữ liệu thực tế mà là chế độ xem cấp cao về mối quan hệ giữa người dùng và bài đăng và vì lý do đó, trường này không có trong sơ đồ cơ sở dữ liệu. Đối với mối quan hệ một-nhiều, trường
[venv] $ pip install flask-migrate
28 thường được xác định ở phía "một" và được sử dụng như một cách thuận tiện để truy cập vào "nhiều". Vì vậy, ví dụ: nếu tôi có một người dùng được lưu trữ trong
[venv] $ pip install flask-migrate
30, biểu thức
[venv] $ pip install flask-migrate
31 sẽ chạy một truy vấn cơ sở dữ liệu trả về tất cả các bài đăng được viết bởi người dùng đó. Đối số đầu tiên của
[venv] $ pip install flask-migrate
28 là lớp mô hình đại diện cho phía "nhiều" của mối quan hệ. Đối số này có thể được cung cấp dưới dạng một chuỗi có tên lớp nếu mô hình được xác định sau trong mô-đun. Đối số
[venv] $ pip install flask-migrate
33 xác định tên của một trường sẽ được thêm vào các đối tượng của lớp "nhiều" trỏ lại đối tượng "một". Điều này sẽ thêm một biểu thức
[venv] $ pip install flask-migrate
34 sẽ trả lại cho người dùng một bài đăng. Đối số
[venv] $ pip install flask-migrate
35 xác định cách truy vấn cơ sở dữ liệu cho mối quan hệ sẽ được đưa ra, đây là điều mà tôi sẽ thảo luận sau. Đừng lo lắng nếu những chi tiết này vẫn chưa có nhiều ý nghĩa, tôi sẽ chỉ cho bạn các ví dụ về điều này ở cuối bài viết này

Vì tôi có các bản cập nhật cho các mô hình ứng dụng nên cần phải tạo một quá trình di chuyển cơ sở dữ liệu mới

[venv] $ pip install flask-migrate
0

Và việc di chuyển cần được áp dụng cho cơ sở dữ liệu

[venv] $ pip install flask-migrate
1

Nếu bạn đang lưu trữ dự án của mình trong kiểm soát nguồn, hãy nhớ thêm tập lệnh di chuyển mới vào đó

Chơi với cơ sở dữ liệu

Tôi đã khiến bạn phải trải qua một quá trình dài để xác định cơ sở dữ liệu, nhưng tôi vẫn chưa chỉ cho bạn cách mọi thứ hoạt động. Vì ứng dụng chưa có bất kỳ logic cơ sở dữ liệu nào, hãy chơi với cơ sở dữ liệu trong trình thông dịch Python để làm quen với nó. Kích hoạt Python bằng cách chạy

[venv] $ pip install flask-migrate
36 trên thiết bị đầu cuối của bạn. Đảm bảo rằng môi trường ảo của bạn được kích hoạt trước khi bạn khởi động trình thông dịch

Khi ở trong dấu nhắc Python, hãy nhập ứng dụng, phiên bản cơ sở dữ liệu và các mô hình

[venv] $ pip install flask-migrate
2

Bước tiếp theo hơi lạ. Để Flask và các tiện ích mở rộng của nó có quyền truy cập vào ứng dụng Flask mà không cần phải chuyển

[venv] $ pip install flask-migrate
37 làm đối số vào mọi chức năng, ngữ cảnh ứng dụng phải được tạo và đẩy. Bối cảnh ứng dụng sẽ được đề cập chi tiết hơn ở phần sau của hướng dẫn, vì vậy, hiện tại, hãy nhập mã sau vào phiên trình bao Python của bạn

[venv] $ pip install flask-migrate
3

Tiếp theo, tạo một người dùng mới

[venv] $ pip install flask-migrate
4

Các thay đổi đối với cơ sở dữ liệu được thực hiện trong ngữ cảnh của phiên cơ sở dữ liệu, có thể được truy cập dưới dạng

[venv] $ pip install flask-migrate
38. Nhiều thay đổi có thể được tích lũy trong một phiên và sau khi tất cả các thay đổi đã được đăng ký, bạn có thể phát hành một
[venv] $ pip install flask-migrate
39 duy nhất, viết tất cả các thay đổi một cách nguyên tử. Nếu bất cứ lúc nào trong khi làm việc trên một phiên có lỗi, một cuộc gọi tới
[venv] $ pip install flask-migrate
40 sẽ hủy phiên và xóa mọi thay đổi được lưu trữ trong đó. Điều quan trọng cần nhớ là các thay đổi chỉ được ghi vào cơ sở dữ liệu khi một cam kết được ban hành với
[venv] $ pip install flask-migrate
39. Các phiên đảm bảo rằng cơ sở dữ liệu sẽ không bao giờ ở trạng thái không nhất quán

Bạn có tự hỏi làm thế nào để tất cả các hoạt động cơ sở dữ liệu này biết cơ sở dữ liệu nào sẽ sử dụng không? . Tiện ích mở rộng tìm trong từ điển

[venv] $ pip install flask-migrate
43 cho mục nhập
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

0, chứa URL cơ sở dữ liệu

Hãy thêm một người dùng khác

[venv] $ pip install flask-migrate
5

Cơ sở dữ liệu có thể trả lời một truy vấn trả về tất cả người dùng

[venv] $ pip install flask-migrate
6

Tất cả các mô hình đều có thuộc tính

[venv] $ pip install flask-migrate
45 là điểm vào để chạy các truy vấn cơ sở dữ liệu. Truy vấn cơ bản nhất là truy vấn trả về tất cả các phần tử của lớp đó, được đặt tên thích hợp là
[venv] $ pip install flask-migrate
46. Lưu ý rằng các trường
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7 được tự động đặt thành 1 và 2 khi những người dùng đó được thêm vào

Đây là một cách khác để thực hiện truy vấn. Nếu bạn biết

>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

7 của người dùng, bạn có thể truy xuất người dùng đó như sau

[venv] $ pip install flask-migrate
7

Bây giờ hãy thêm một bài đăng trên blog

[venv] $ pip install flask-migrate
8

Tôi không cần đặt giá trị cho trường

[venv] $ pip install flask-migrate
07 vì trường đó có giá trị mặc định, bạn có thể thấy giá trị này trong định nghĩa mô hình. Còn trường
[venv] $ pip install flask-migrate
08 thì sao? . Tôi chỉ định tác giả cho bài đăng bằng cách sử dụng trường ảo
[venv] $ pip install flask-migrate
54 thay vì phải xử lý ID người dùng. SQLAlchemy rất tuyệt vời ở khía cạnh đó, vì nó cung cấp mức độ trừu tượng cao đối với các mối quan hệ và khóa ngoại

Để hoàn thành phần này, hãy xem xét thêm một vài truy vấn cơ sở dữ liệu

[venv] $ pip install flask-migrate
9

Tài liệu Flask-SQLAlchemy là nơi tốt nhất để tìm hiểu về nhiều tùy chọn có sẵn để truy vấn cơ sở dữ liệu

Để hoàn thành phần này, hãy xóa những người dùng thử nghiệm và bài đăng đã tạo ở trên, để cơ sở dữ liệu sạch sẽ và sẵn sàng cho chương tiếp theo

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
0

bối cảnh vỏ

Hãy nhớ những gì bạn đã làm khi bắt đầu phần trước, ngay sau khi khởi động trình thông dịch Python?

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
1

Trong khi bạn làm việc trên ứng dụng của mình, bạn sẽ cần phải kiểm tra mọi thứ trong trình bao Python rất thường xuyên, vì vậy việc phải lặp lại các câu lệnh trên mỗi lần sẽ trở nên tẻ nhạt, vì vậy đây là thời điểm tốt để giải quyết vấn đề này

Lệnh

[venv] $ pip install flask-migrate
56 là một công cụ rất hữu ích khác trong bộ lệnh
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
51. Lệnh
[venv] $ pip install flask-migrate
58 là lệnh "cốt lõi" thứ hai được triển khai bởi Flask, sau
[venv] $ pip install flask-migrate
59. Mục đích của lệnh này là khởi động trình thông dịch Python trong ngữ cảnh của ứng dụng. Điều đó nghĩa là gì?

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
2

Với phiên thông dịch thông thường, ký hiệu

[venv] $ pip install flask-migrate
37 không được biết trừ khi nó được nhập rõ ràng, nhưng khi sử dụng
[venv] $ pip install flask-migrate
56, lệnh sẽ nhập trước phiên bản ứng dụng. Điều thú vị về
[venv] $ pip install flask-migrate
56 không chỉ là nó nhập trước
[venv] $ pip install flask-migrate
37 mà còn có thể định cấu hình "bối cảnh trình bao", là danh sách các ký hiệu khác để nhập trước

Chức năng sau trong microblog. py tạo một ngữ cảnh trình bao để thêm phiên bản cơ sở dữ liệu và các mô hình vào phiên trình bao

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
3

Trình trang trí

[venv] $ pip install flask-migrate
64 đăng ký hàm dưới dạng hàm ngữ cảnh trình bao. Khi lệnh
[venv] $ pip install flask-migrate
56 chạy, nó sẽ gọi hàm này và đăng ký các mục mà nó trả về trong phiên trình bao. Lý do hàm trả về từ điển chứ không phải danh sách là vì đối với mỗi mục, bạn cũng phải cung cấp tên mà nó sẽ được tham chiếu trong trình bao, tên này được cung cấp bởi các khóa từ điển

Sau khi thêm chức năng trình xử lý ngữ cảnh hệ vỏ, bạn có thể làm việc với các thực thể cơ sở dữ liệu mà không cần phải nhập chúng

import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
4

Nếu bạn thử cách trên và nhận được ngoại lệ

[venv] $ pip install flask-migrate
66 khi bạn cố truy cập vào
>>> from app.models import User
>>> u = User[username='susan', email='susan@example.com']
>>> u

5,
[venv] $ pip install flask-migrate
46 và
[venv] $ pip install flask-migrate
14, thì hàm
[venv] $ pip install flask-migrate
70 không được đăng ký với Flask. Nguyên nhân rất có thể của việc này là do bạn chưa đặt
[venv] $ pip install flask-migrate
71 trong môi trường. Trong trường hợp đó, hãy quay lại Chương 1 và xem lại cách đặt biến môi trường
import os
basedir = os.path.abspath[os.path.dirname[__file__]]

class Config[object]:
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get['DATABASE_URL'] or \
        'sqlite:///' + os.path.join[basedir, 'app.db']
    SQLALCHEMY_TRACK_MODIFICATIONS = False
56. Nếu bạn thường quên đặt biến này khi mở các cửa sổ đầu cuối mới, bạn có thể cân nhắc thêm một. flaskenv vào dự án của bạn, như được mô tả ở cuối chương đó

Xin chào và cảm ơn bạn đã ghé thăm blog của tôi. Nếu bạn thích bài viết này, vui lòng xem xét hỗ trợ công việc của tôi trên blog này trên Patreon

Chủ Đề