



















Preview text:
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn Câu :1 (5 điểm) g
CHÉP MÃ NGUỒN VÀ MÀN HÌNH KẾT QUẢ
Chép màn hình thể trực quan TRƯỜNG id là khóa chính (Primary key) from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate import os app = Flask(__name__)
# Cấu hình cơ sở dữ liệu PostgreSQL
app.config['SQLALCHEMY_DATABASE_URI'] =
'postgresql://postgres:123@localhost:5432/flask_db' 1
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) migrate = Migrate(app, db) class Role(db.Model): __tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True) def __repr__(self): return '' % self.name class User(db.Model): __tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, index=True)
password = db.Column(db.String(128)) # Thêm cột password
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
role = db.relationship('Role', backref=db.backref('users', lazy=True)) def __repr__(self): return '' % self.username
@app.route('/') # Đảm bảo route này đã được định nghĩa def home(): return 'Hello, Flask!' if __name__ == '__main__': with app.app_context():
db.create_all() # Tạo tất cả các bảng đã định nghĩa 2
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn app.run(debug=True) Màn hình kết quả : 3
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn 4
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn Câu 2: (5 điểm)
CHÉP MÃ NGUỒN VÀ MÀN HÌNH KẾT QUẢ
Phần hướng dẫn thực hành sau
Tham khảo https://deneb.click/migration-from-tkinter-to-flask/
Di chuyển từ Tkinter sang Flask
Thư viện phổ biến nhất để tạo GUI trong Python là Tkinter, đây là một phần của cài đặt
Python chuẩn. Tkinter là một công cụ trưởng thành và ổn định, được chuyển rộng rãi và
tương đối dễ học. Tuy nhiên, nó cũng khá cũ với nhiều nhược điểm, trong số đó, nó có một
bộ tiện ích hạn chế. Mặc dù mô hình đơn giản dễ học, Tkinter cũng trở nên cồng kềnh với
các giao diện phức tạp hơn. Trên hết, nó không hỗ trợ phát triển ứ
ng dụng di động và web. Cửa sổ Tkinter
Giao diện người dùng Flask Giao diện web
Có một ứng dụng máy tính để bàn truyền thống được phát triển trong Tkinter, chúng tôi
muốn điều chỉnh nó theo các tiêu chuẩn hiện đại bằng cách triển khai GUI web. Tuy nhiên,
việc di chuyển có thể là một nhiệm vụ tốn thời gian. Một trong những cách tiếp cận là biến
nó thành một quá trình tiến hóa, tức là chúng tôi cho phép các tình huống mà chúng tôi sẽ
có cả máy tính để bàn và ứng dụng web cùng một lúc. Nó cho phép các nhà phát triển dần
dần thay thế các cửa sổ máy tính để bàn bằng các điều khiển web, điều này cho phép họ
tránh làm việc với hai phiên bản của một ứng dụng (Tkinter và Flask). Trong trường hợp 5
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
như vậy, cả hai mô-đun GUI sẽ hợp tác và giao tiếp với nhau. Sau khi phiên bản Flask cuối
cùng đã sẵn sàng, chúng tôi có thể xóa mã Tkinter không cần thiết.
Dưới đây, tôi trình bày bản nháp của một cách tiếp cận như vậy. Cả hai GUI, được biểu
diễn bởi các hàm tk_main và flask_main, phải nằm trong các luồng riêng biệt. Để giảm số
luồng, chúng ta có thể sử dụng lại luồng chính và gán cho nó GUI Tkinter. Đối với GUI
Flask, chúng ta tạo một luồng mới (xem ví dụ tại đây để biết thông tin về các luồng
Python). Trong phần Tkinter, được biểu diễn bởi lớp TkApp , chúng ta định nghĩa một nút
mở trình duyệt web có trang web Flask. Đồng thời, chúng ta truyền một đối số cho Flask
thông qua một biến toàn cục, hơi cồng kềnh, nhưng tôi cố gắng đơn giản hóa trong ví dụ
này. Sau khi chạy ví dụ, chúng ta có thể sử dụng đồng thời cả hai GUI – một tính năng hữu
ích khi di chuyển ứ
ng dụng của mình. Trong trường hợp có sự cố xảy ra với cửa sổ Flask mới của bạn –
bạn vẫn có bản sao lưu Tkinter giúp ứng dụng luôn có thể sử dụng được. 1 ĐIỂM
Giải thích mã nguồn LỆNH THỰC HIỆN
Dùng để chạy Flask import threading trong một luồng (thread) riêng biệt
Tạo giao diện người
from tkinter import Tk, Button, END, mainloop dùng với một nút
nhấn trong cửa sổ Tkinter.
Khởi tạo ứng dụng
from flask import Flask
Flask để làm việc với HTTP requests. Mở một URL trong import webbrowser trình duyệt mặc
định của hệ thống. 6
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
Khởi tạo một ứng
flask_app = Flask(__name__)
dụng Flask với tên flask_app. Lớp TkApp class TkApp: __init__ khởi tạo
def __init__(self, master): giao diện Tkinter
với một nút nhấn.
self.button = Button(master, text="Show in webbrowser",
command=self.btn_callback) self.button.pack() btn_callback: Hàm
def btn_callback(self): này chạy khi nhấn
nút, thiết lập biến
var với thông điệp "Greetings from Tkinter" và mở URL http://localhost:5001 trên trình duyệt. global var
var = 'Greetings from Tkinter' 7
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
webbrowser.open("http://localhost:5001") Khởi tạo route /
@flask_app.route('/', methods=['POST', 'GET']) trong Flask: def flask_index(): Khi truy cập, Flask return var
trả về giá trị của
biến var (thông điệp từ Tkinter).
Hàm này khởi động def flask_main(): Flask trên localhost cổng 5001.
flask_app.run(debug=False, host="localhost", port=5001) Hàm tk_main khởi def tk_main(): tạo giao diện
Tkinter với cửa sổ chính root và vào
vòng lặp sự kiện (event loop) của Tkinter. root = Tk() TkApp(root) root.mainloop() 8
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
if __name__ == "__main__": Khởi động Flask
flask_thread = threading.Thread(target=flask_main) trong một luồng (flask_thread) với daemon=True để Flask đóng khi chương trình chính kết thúc.
flask_thread.daemon = True
Bắt đầu giao diện flask_thread.start() Tkinter (tk_main). tk_main()
view rawintro.py hosted with by GitHub
Màn hình kết quả : 9
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn 10
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
Di chuyển tiện ích
Trong bước tiếp theo, chúng ta sẽ di chuyển một tiện ích Tkinter mẫu — listbox. Hãy bắt
đầu với một đoạn mã lộn xộn kết hợp giữa tính toán và trình bày dữ liệu. 1 ĐIỂM
Giải thích mã nguồn LỆNH THỰC HIỆN
Tạo giao diện đồ họa
from tkinter import Tk, Listbox, END, mainloop
đơn giản với danh sách (Listbox).
Tạo và làm việc với cơ import sqlite3 sở dữ l ệ i u SQLite trong bộ nhớ.
Tạo cửa sổ chính của master = Tk()
ứng dụng Tkinter và gán nó vào biến master.
Tạo một Listbox (danh
listbox = Listbox(master) sách) để h ể i n thị dữ
liệu, đặt nó trong cửa
sổ master, và sử dụng
pack() để hiển thị
Listbox trên giao diện. listbox.pack() 11
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
Tạo một cơ sở dữ liệu
connection = sqlite3.connect(':memory:')
SQLite trong bộ nhớ
(không lưu vào file).
Tạo con trỏ (cursor) để
cursor = connection.cursor()
thực thi các lệnh SQL.
Tạo bảng foo với hai
cursor.execute('''CREATE TABLE foo cột
id: Kiểu số nguyên
(id INTEGER PRIMARY KEY
(INTEGER), tự động AUTOINCREMENT, tăng (AUTOINCREMENT), làm khóa chính. Bar : Kiểu chuỗi bar TEXT)''')
(TEXT), dùng để lưu trữ giá trị.
Chuẩn bị lệnh SQL cho sql = 'INSERT INTO foo (bar) values (?)'
thao tác thêm dữ liệu
vào bảng foo với cột bar.
Thực hiện vòng lặp để for i in range(5): thêm dữ l ệ i u vào bảng .
Chạy từ i = 0 đến i = 4,
mỗi lần thêm một bản
ghi với bar chứa giá trị
từ 1 đến 5 (i + 1). 12
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn cursor.execute(sql,
cursor.execute(sql, (i+1,))
(i+1,)): Thực hiện lệnh
SQL, với giá trị của
bar được truyền vào qua (i+1,).
Lấy tất cả các bản ghi
cursor.execute('SELECT * from foo') từ bảng foo.
Trả về danh sách chứa
for row in cursor.fetchall():
tất cả các bản ghi lấy được.
Với mỗi dòng (row)
listbox.insert(END, row[0])
trong kết quả, lấy cột
id (row[0]) và chèn vào cuối Listbox. Run mainloop()
view rawstep_1.py hosted with by GitHub
Màn hình kết quả : 13
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
Mã này đang hoạt động nhưng được viết trái với các nguyên tắc của kỹ thuật phần mềm.
Để sẵn sàng di chuyển tức là thay thế Tkinter bằng HTML GUI, chúng ta phải trích xuất
mã chịu trách nhiệm hiển thị dữ liệu. Chức năng GUI chỉ nên xử lý việc trình bày dữ liệu
và tránh xa việc xử lý dữ liệu. 1 ĐIỂM 14
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
Giải thích mã nguồn LỆNH THỰC HIỆN
Tạo giao diện đồ họa
from tkinter import Tk, Listbox, Button, END, mainloop
đơn giản với một Listbox.
Tạo và làm việc với cơ import sqlite3 sở dữ l ệ i u SQLite trong bộ nhớ.
Tạo cửa sổ chính master = Tk() master của ứ ng dụng Tkinter. def prepare_data():
Tạo cơ sở dữ liệu
connection = sqlite3.connect(':memory:')
SQLite trong bộ nhớ.
Tạo con trỏ cursor để
cursor = connection.cursor()
thực thi các lệnh SQL.
Tạo bảng foo với hai
cursor.execute('''CREATE TABLE foo cột Kiểu số nguyên
(id INTEGER PRIMARY KEY
(INTEGER), tự động AUTOINCREMENT, tăng (AUTOINCREMENT), làm khóa chính. bar: Kiểu chuỗi bar TEXT)''') (TEXT). 15
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
Chuẩn bị lệnh SQL để
sql = 'INSERT INTO foo (bar) values (?)'
chèn giá trị vào bảng foo. Thêm 5 bản ghi vào for i in range(5):
bảng foo, giá trị bar từ 1 đến 5.
cursor.execute(sql, (i+1,))
Trả về con trỏ cursor, return(cursor)
giúp thực hiện các truy
vấn tiếp theo trên dữ
liệu đã chuẩn bị.
def process_data(cursor):
Lấy tất cả bản ghi từ
cursor.execute('SELECT * from foo') bảng foo.
Tạo danh sách trống data = list() để lưu dữ l ệ i u đã xử lý.
Duyệt qua từng dòng
for row in cursor.fetchall():
trong kết quả truy vấn
# here process the row, e.g. concatenate, compute, replace, etc. Thêm mỗi dòng vào data.append(row) danh sách data.
Trả về danh sách data return(data)
chứa các dòng dữ liệu từ bảng foo. 16
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
def show_data(parent, data):
Tạo một Listbox và đặt listbox = Listbox(parent)
nó trong cửa sổ chính (parent).
Hiển thị Listbox trên listbox.pack() giao diện
Duyệt qua từng dòng for row in data: dữ l ệ i u trong data
Chèn giá trị id (row[0])
listbox.insert(END, row[0])
từ mỗi dòng vào cuối Listbox.
Gọi prepare_data để
cursor = prepare_data()
tạo cơ sở dữ l ệ i u, bảng
và thêm dữ liệu; sau đó
trả về con trỏ cursor.
Gọi process_data để
data_processed = process_data(cursor)
lấy và xử lý dữ l ệ i u từ cơ sở dữ liệu.
Gọi show_data để hiển
show_data(master, data_processed)
thị dữ liệu trong
Listbox của giao diện. mainloop()
view rawstep_2.py hosted with by GitHub
Màn hình kết quả : 17
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn 18
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
Sau một số lần dọn dẹp, chúng tôi chia chức năng của mã thành các
hàm prepare_data , process_data và show_data . Đây là các hàm đơn giản mô hình hóa
nhiệm vụ thông thường của một số ứng dụng: chúng thu thập dữ l ệ
i u, xử lý dữ l ệ i u và hiển
thị kết quả. Các hàm trao đổi dữ liệu bằng cách sử dụng các cấu trúc con trỏ hoặc danh
sách . Những thay đổi này làm tăng thêm một số độ phức tạp cho mã nhưng cũng giúp việc
đưa ra các thay đổi dễ dàng hơn hoặc cho phép thử nghiệm hiệu quả hơn. Bây giờ chúng ta
đã sẵn sàng để thêm phần Flask, bao gồm lớp FlaskMyForm và
hàm flask_index . FlaskMyForm biểu thị một biểu mẫu nhóm các điều khiển HTML,
nhưng trong trường hợp đơn giản của chúng ta, nó chỉ có một tiện ích di
chuyển SelectField . Hàm flask_index đảm nhiệm việc cung cấp dữ liệu cho SelectField và
hiển thị dữ liệu đó trên một trang web. 1 ĐIỂM
Giải thích mã nguồn LỆNH THỰC HIỆN import threading
Tạo giao diện đồ họa
from tkinter import Tk, Listbox, Button, END, mainloop với Tkinter
Tạo cơ sở dữ liệu trong import sqlite3
bộ nhớ và truy xuất dữ liệu.
Tạo ứng dụng web với
from flask import Flask, render_template_string
Flask, cho phép hiển thị b ể i u mẫu HTML
trực tiếp từ chuỗi. Tạo dropdown
from wtforms import SelectField (SelectField) trong Flask.
Mở trình duyệt web. import webbrowser 19
KIỂM TRA GKL2 PYTHON NÂNG CAO
Nhóm:0202,MaSV:2274802010318, Họ và Tên:Nguyễn Nhật Huy
Thời gian: 3g35-6g00 chiều, ngày 05/11/2024.
Nộp bài lên fit-lAB VÀ gửi đến email: anh.th@vlu.edu.vn
Cung cấp tính năng tạo from flask_wtf import FlaskForm
biểu mẫu trong Flask và yêu cầu
flask_app = Flask(__name__)
Để bảo mật CSRF.
flask_app.secret_key = 'SHH!' def prepare_data():
Kết nối đến một cơ sở
connection = sqlite3.connect(':memory:') dữ l ệ i u SQLite trong bộ nhớ (:memory:)
cursor = connection.cursor()
Tạo bảng foo với cột id
cursor.execute('''CREATE TABLE foo
tự động tăng và cột bar
chứa dữ liệu kiểu TEXT.
(id INTEGER PRIMARY KEY AUTOINCREMENT, bar TEXT)''') Chèn 5 bản ghi vào
sql = 'INSERT INTO foo (bar) values (?)'
bảng foo với các giá trị
từ 1 đến 5 cho bar. for i in range(5): 20