Hướng dẫn flask mysql - bình mysql
Trong phần này, chúng ta sẽ cùng tìm hiểu về cách sử dụng cơ sở dữ liệu với ứng dụng Flask. Show
Để giúp cho bạn dễ theo dõi, sau đây là danh sách các bài viết trong loạt bài hướng dẫn này:
Bạn có thể truy cập mã nguồn cho phần này tại GitHub. Đây là một phần rất quan trọng vì hầu hết các ứng dụng đều cần đọc và lưu trữ dữ liệu một cách hiệu quả. Vì thế, chúng ta cần phải dùng đến cơ sở dữ liệu cho mục đích này. Nếu bạn có tìm hiểu qua, bạn sẽ biết rằng Flask không hỗ trợ sẵn cơ sở dữ liệu. Tuy nhiên đây không phải là do sơ sót mà Flask được thiết kế như vậy để cho phép bạn chọn cơ sở dữ liệu nào thích hợp nhất cho ứng dụng của bạn thay vì bắt buộc bạn phải dùng một hệ cơ sở dữ liệu nào đó. Các thư viện mở rộng trong Flask hỗ trợ cho việc sử dụng nhiều cơ sở dữ liệu khác nhau. Các hệ cơ sở dữ liệu có thể được chia thành hai nhóm chính: nhóm cơ sở dữ liệu theo mô hình quan hệ (relational) và nhóm còn lại không sử dụng mô hình này. Nhóm sau cũng được biết với tên gọi NoSQL bởi vì các hệ cơ sở dữ liệu trong nhóm này không sử dụng ngôn ngữ hỏi đáp SQL nối tiếng. Mặc dù cả hai nhóm đều có các đại diện xuất sắc, các hệ cơ sở dữ liệu trong nhóm đầu thích hợp hơn với các dữ liệu có cấu trúc như là danh sách người sử dụng, các bài viết … trong khi NoSQL thích hợp cho dữ liệu không có cấu trúc chặt chẽ. Ứng dụng của chúng ta có thể sử dụng các hệ cơ sở dữ liệu trong cả hai nhóm, nhưng chúng ta sẽ chọn cơ sở dữ liệu quan hệ theo như lý do đã nói ở trên. Trong Phần 3, chúng ta đã sử dụng thư viện mở rộng đầu tiên trong Flask (còn nhớ Flask-WTF không?). Trong phần này, chúng ta sẽ sử dụng thêm hai thư viện mở rộng nữa. Thư viện đầu tiên là Flask-SQLAlchemy. Đây là một thư viện cho phép chúng ta sử dụng một gói rất phổ biến là SQLAlchemy. Đây là một phần mềm trong nhóm sản phẩm gọi là Object Relational Mapping hay ORM. Các phần mềm trong nhóm này giúp chúng ta giao tiếp với cơ sở dữ liệu thông qua các thực thể như lớp, đối tượng và phương thức thay vi dùng các bảng và ngôn ngữ SQL (Các đại diện tiêu biểu cho nhóm sản phẩm này gồm có Hibernate cho Java, NHibernate hoặc EntityFramework cho .NET framework, …). Công việc chính của các phần mềm ORM là dịch các tác vụ bậc cao thành các lệnh dùng trong cơ sở dữ liệu. Một đặc điểm rất hay của SQLAlchemy là nó hỗ trợ cho rất nhiều cơ sở dữ liệu quan hệ khác nhau như MySQL, PostgreSQL và SQLite. Điều này rất hữu ích vì nó có nghĩa là bạn có thể phát triển ứng dụng với một hệ cơ sở dữ liệu đơn giản như SQLite – vốn không đòi hỏi việc cài đặt phức tạp, nhưng khi triển khai ứng dụng, bạn có thể chuyển sang một hệ cơ sở dữ liệu khác tốt hơn như là MySQL hay PostgreSQL mà không cần phải thay đổi mã trong ứng dụng của bạn. Để cài đặt Flask-SQLAlchemy trong môi trường ảo của bạn, hãy kích hoạt nó và chạy lệnh sau:
Chuyển đổi dữ liệuPhần lớn các bài hướng dẫn về cơ sở dữ liệu chỉ dạy cách tạo và sử dụng chúng nhưng lại không đề cập đến vấn đề làm sao để cập nhật cấu trúc của cơ sở dữ liệu sẵn có khi ứng dụng thay đổi. Điều này khó thực hiện bởi vì các thiết kế cơ sở dữ liệu quan hệ có liên quan chặt chẽ đến cấu trúc của dữ liệu. Khi cấu trúc của dữ liệu thay đổi, cơ sở dữ liệu cũng phải được chuyển đổi để thích ứng với cấu trúc mới. Thư viện mở rộng thứ hai mà chúng ta sẽ sử dụng là Flask-Migrate. Thư viện này là một giao diện của Flask với Alembic – một framework chuyên cho viện chuyển đổi dữ liệu với SQLAlchemy. Việc chuyển đổi cơ sở dữ liệu sẽ làm cho chúng ta mất công hơn một chút khi khởi tạo cơ sở dữ liệu, nhưng đáng giá vì nó sẽ giảm nhiều gánh nặng cho chúng ta trong việc thay đổi cơ sở dữ liệu trong tượng lai. Quá trình cài đặt thư viện Flask-Migrate hoàn toàn tương tự như các thư viện khác:
Thiết lập cấu hình cho Flask-SQLAlchemyChúng ta sẽ sử dụng cơ sở dữ liệu SQLite cho ứng dụng của chúng ta. SQLite là một hệ cơ sở dữ liệu được sử dụng rộng rãi trong quá trình phát triển các ứng dụng nhỏ hoặc thậm chí một vài ứng dụng lớn. Với SQLite, mỗi cơ sở dữ liệu sẽ được lưu trữ trong một file duy nhất và không đòi hỏi phải cài đặt thêm các phần mềm khác trên máy chủ như trong trường hợp của MySQL và PostgreSQL. Chúng ta sẽ phải thêm vào một số cấu hình mới trong file config.py: config.py: Cấu hình cho Flask-SQLAlchemy Cấu hình cho Flask-SQLAlchemy
Thư viện Flask-SQLAlchemy sẽ sử dụng cơ sở dữ liệu tại URL được chỉ định bởi tham số cấu hình Tham số Trong ứng dụng của chúng ta, cơ sở dữ liệu sẽ được đại diện bởi một đối tượng gọi là thực thể cơ sở dữ liệu (database instance). Thành phần đảm nhiệm việc chuyển đổi cơ sở dữ liệu cũng sẽ được đại diện bởi một đối tượng khác. Các đối tượng này cần được khởi tạo trong ứng dụng, cụ thể hơn là trong file app/__init__.py: app/__init__.py: Khởi tạo các đối tượng Flask-SQLAlchemy và Flask-Migrate Khởi tạo các đối tượng Flask-SQLAlchemy và Flask-Migrate
Chúng ta thay đổi ba chỗ trong mã ở trên. Đầu tiên, chúng ta thêm một đối tượng tên là Mô hình dữ liệuDữ liệu trong các hệ thống cơ sở dữ liệu sẽ được đại diện bởi một tập hợp các lớp, thường được gọi là mô hình dữ liệu (database model). Lớp ORM bên trong của SQLAlchemy sẽ thực hiện các công việc chuyển đổi cần thiết để ánh xạ các đối tượng từ mô hình dữ liệu vào các hàng và bảng trong cơ sở dữ liệu. Để bắt đầu, chúng ta hãy thử tạo một mô hình cho người sử dụng theo như sơ đồ sau: Trường Các trường Bây giờ, chúng ta có thể chuyển đổi mô hình dữ liệu người dùng ở trên thành mã chương trình trong file app/models như sau: app/models.py: Mô hình dữ liệu về người sử dụng Mô hình dữ liệu về người sử dụng
Lớp Phương thức
Tạo ra kho lưu trữ cho quá trình chuyển đổi dữ liệu (migration repository)Mô hình dữ liệu mà chúng ta tạo ra ở trên định nghĩa cấu trúc ban đầu của dữ liệu (schema) mà chúng ta sẽ dùng trong ứng dụng. Nhưng khi chúng ta tiếp tục phát triển ứng dụng về sau, sẽ có những lúc chúng ta sẽ cần thay đổi hay cập nhật cấu trúc này. Để giúp cho quá trình này, Alembic (framework cho việc chuyển đổi dữ liệu được sử dụng trong thư viện Flask-Migrate) sẽ đảm nhiệm việc thay đổi cấu trúc dữ liệu trong cơ sở dữ liệu mà không cần phải tạo lại cơ sở dữ liệu từ đầu. Để thực thi công việc có vẻ khó khăn này, Alembic có một kho lưu trữ cho quá trình chuyển đổi dữ liệu (migration repository). Đây thực ra là một thư mục có chứa các đoạn mã kịch bản (script) cho việc chuyển đổi dữ liệu. Mỗi khi chúng ta cập nhật cấu trúc dữ liệu, một đoạn mã mới có chứa các thay đổi cần thiết sẽ được thêm vào trong kho lưu trữ này. Để thực hiện việc chuyển đổi cho cơ sở dữ liệu, các đoạn mã này sẽ được thực hiện theo đúng thứ tự mà chúng đã được tạo ra. Thư viện Flask-Migrate có các lệnh riêng được gọi thông qua lệnh
Lưu ý rằng lệnh flask cần có biến môi trường FLASK_APP để biết vị trí của ứng dụng Flask. Vì vậy, xin nhắc lại để chạy ứng dụng, chúng ta cần thiết lập biến môi trường Sau khi chạy lệnh này, bạn sẽ thấy thư mục mới tên là migrations có chứa một số file và một thư mục con của thư mục này tên là versions. Tất cả những file này là một phần trong mã nguồn của bạn và cần được thêm vào hệ thống quản lý mã nguồn của bạn. Chuyển đổi dữ liệu lần đầuKhi đã có kho lưu trữ cho chuyển đổi dữ liệu, chúng ta có thể tiến hành thực hiện việc chuyển đổi dữ liệu lần thứ nhất. Quá trình này sẽ tạo ra bảng user trong hệ thống cơ sở dữ liệu tương ứng với mô hình dữ liệu
Các dòng trạng thái của lệnh này cho chúng ta biết đại thể Alembic làm việc như thế nào trong quá trình này. Hai dòng đầu tiên chỉ mang tính tham khảo và có thể bỏ qua. Sau đó, Alembic cho biết đã tìm được một bảng user với hai chỉ mục. Tiếp theo, chúng ta cũng thấy được vị trí của mã kịch bản chuyển đổi. Chuỗi fcf566b5be7f là một chuỗi được sinh ra tự động và có giá trị duy nhất (nó sẽ có giá trị khác trên máy của bạn) cho quá trình chuyển đổi. Tham số Mã kịch bản cho chuyển đổi dữ liệu sinh ra sau lệnh này sẽ là một phần trong dự án của bạn và cần được thêm vào hệ thống quản lý mã nguồn mà bạn đang sử dụng. Nếu bạn muốn, bạn có thể xem thử các đoạn mã này. Bạn sẽ thấy rằng nó có hai hàm gọi là Lệnh
INFO [alembic.autogenerate.compare]Detected added index'ix_user_email'on'['email']' INFO [alembic.autogenerate.compare]Detected added index'ix_user_username'on'['username']' Các dòng trạng thái của lệnh này cho chúng ta biết đại thể Alembic làm việc như thế nào trong quá trình này. Hai dòng đầu tiên chỉ mang tính tham khảo và có thể bỏ qua. Sau đó, Alembic cho biết đã tìm được một bảng user với hai chỉ mục. Tiếp theo, chúng ta cũng thấy được vị trí của mã kịch bản chuyển đổi. Chuỗi fcf566b5be7f là một chuỗi được sinh ra tự động và có giá trị duy nhất (nó sẽ có giá trị khác trên máy của bạn) cho quá trình chuyển đổi. Tham số DATABASE_URL2 và chuỗi “Tạo bảng users” theo sau là tùy chọn (optional), nó chỉ có tác dụng thêm một dòng mô tả vào mã chuyển đổi.Mã kịch bản cho chuyển đổi dữ liệu sinh ra sau lệnh này sẽ là một phần trong dự án của bạn và cần được thêm vào hệ thống quản lý mã nguồn mà bạn đang sử dụng. Nếu bạn muốn, bạn có thể xem thử các đoạn mã này. Bạn sẽ thấy rằng nó có hai hàm gọi là Lệnh (myenv)$flask db upgrade INFO [alembic.runtime.migration]Running upgrade ->fcf566b5be7f,Tao bang users Như chúng ta đã thấy, Flask-Migration cũng bao gồm lệnh Sơ lược về quan hệ trong cơ sở dữ liệuCác hệ thống cơ sở dữ liệu quan hệ đảm nhiệm rất tốt việc lưu trữ và thiết lập các mối quan hệ giữa các bản ghi (record). Ví dụ như trong trường hợp một người sử dụng viết một bài trên blog, người sử dụng sẽ được đại diện bởi một bản ghi trong bản (table) Sau khi mối quan hệ giữa người sử dụng và bài viết được thiết lập, hệ thống cơ sở dữ liệu sẽ có thể tìm ra kết quả cho các truy vấn (query) về mối liên hệ này. Một ví dụ dễ thấy là bạn có một bài viết và muốn tìm ra ai đã viết bài này. Ngược lại, nếu bạn muốn tìm ra các bài viết được thực hiện bởi một tác giả, bạn sẽ phải dùng một truy vấn phức tạp hơn. Flask-SQLAlchemy sẽ hỗ trợ cho chúng ta trong cả hai trường hợp. Bây giờ hãy mở rộng cơ sở dữ liệu của chúng ta để lưu trữ cả các bài viết để hiểu rõ hơn về các quan hệ. Sau đây là cấu trúc của bảng Bảng Chúng ta sẽ cập nhật file app/models.py để tạo mô hình dữ liệu cho các bài viết như sau: app/models.py: Bảng Posts và liên hệ với bảng User Bảng Posts và liên hệ với bảng User
Lớp Trường Lớp Vì chúng ta vừa thay đổi mô hình dữ liệu, chúng ta cần tạo ra mã chuyển đổi mới:
Và tiếp theo, chúng ta cần tiến hành quá trình chuyển đổi bằng cách chạy các mã vừa sinh ra ở trên:
INFO [alembic.autogenerate.compare]Detected added index'ix_post_timestamp'on'['timestamp']' Và tiếp theo, chúng ta cần tiến hành quá trình chuyển đổi bằng cách chạy các mã vừa sinh ra ở trên:(myenv)$flask db upgrade INFO [alembic.runtime.migration]Running upgrade fcf566b5be7f->f0db34c99253,Tao bang posts
Suốt từ đầu đến giờ, chúng ta hầu như chỉ nói về việc định nghĩa dữ liệu, thật là chán phải không? Bây giờ chúng ta hãy thực tập một chút để làm quen với cách hoạt động của cơ sở dữ liệu và Python. Bạn hãy gọi trình biên dịch Python bằng lệnh
Tại dấu nhắc lệnh của trình biên dịch Python, hãy tham chiếu (import) đến các thư viện và đối tượng trong mô hình dữ liệu của chúng ta: Tiếp theo, chúng ta hãy thêm một người sử dụng nữa:
Đến đây, cơ sở dữ liệu của chúng ta có thể trả lời cho truy vấn tìm kiếm tất cả người sử dụng trong hệ thống:
Tât cả các đối tượng mô hình dữ liệu đều có thuộc tính Sau đây chúng ta sẽ thử tìm thông tin về người sử dụng qua Id của họ:
Vậy nếu chúng ta muốn thêm một bài viết thì sao?
Chúng ta không gán giá trị cho trường Để kết thúc mục này, chúng ta sẽ xem qua vài ví dụ truy vấn dữ liệu nữa:
Nếu bạn muốn tìm hiểu thêm về các ùy chọn khi truy vấn dữ liệu, bạn có thể tham khảo các tài liệu trực tuyến của Flask-SQLAlchemy. Vậy nếu chúng ta muốn thêm một bài viết thì sao?
Tât cả các đối tượng mô hình dữ liệu đều có thuộc tính (myenv) $ pip3 install flask-migrate03 để thực hiện truy vấn. Truy vấn cơ bản nhất là tìm tất cả những đối tượng thuộc cùng một lớp với hàm (myenv) $ pip3 install flask-migrate04. Lưu ý là trường (myenv) $ pip3 install flask-migrate1 sẽ được tự động gán cá giá trị số nguyên theo thứ tự tăng dần (ở đây là 1 và 2) khi chúng ta thêm các dữ liệu mới vào.Sau đây chúng ta sẽ thử tìm thông tin về người sử dụng qua Id của họ:
>>>p=Post(body='my first post!',author=u)
>>># Tìm tất cả bài được viết bởi một user []
... print(p.id,p.author.username,p.body) Sau khi đã tạo hàm xử lý ngữ cảnh lệnh như trên, bạn có thể làm sử dụng trực tiếp các đối tượng và hàm từ cơ sở dữ liệu mà không cần phải tham chiếu đến chúng:
Nếu bạn gặp lỗi Chúng ta sẽ kết thúc phần này ở đây. Hẹn gặp bạn trong phần tiếp theo. |