Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article)
Trong phần trước của loạt bài hướng dẫn này, chúng ta đã điền dữ liệu vào trang dashboard của ứng dụng bằng những mong muốn được tạo bởi những người dùng khác nhau. Chúng ta cũng gắn một nút like vào mỗi mong ước để người dùng có thể like một mong ước cụ thể.
Trong phần này của loạt bài, chúng ta sẽ xem cách like hoặc bỏ like và hiển thị tổng số lượt like của một mong ước muốn cụ thể.
Bắt đầu
Hãy bắt đầu bằng cách clone mã nguồn của phần trước của hướng dẫn từ GitHub.
1 |
git clone https://github.com/jay3dec/PythonFlaskMySQLApp_Part7.git |
Khi mã nguồn đã được clone, điều hướng đến thư mục dự án và khởi động máy chủ web.
1 |
cd PythonFlaskMySQLApp_Part7
|
2 |
python app.py |
Trỏ trình duyệt của bạn đến http://localhost:5002/ và bạn sẽ thấy ứng dụng đang chạy.
Thêm Bộ đếm Like
Chúng ta sẽ bắt đầu bằng cách cài đặt một tính năng để hiển thị tổng số lượt like mà một mong ước cụ thể đã thu được. Khi một mong ước mới được thêm vào, chúng ta sẽ tạo một mục dữ liệu trong bảng tbl_likes
. Do đó, hãy sửa đổi thủ tục lưu trữ MySQL sp_addWish
để thêm một mục dữ liệu vào bảng tbl_likes
.
1 |
DELIMITER $$ |
2 |
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_addWish`( |
3 |
IN p_title varchar(45), |
4 |
IN p_description varchar(1000), |
5 |
IN p_user_id bigint, |
6 |
IN p_file_path varchar(200), |
7 |
IN p_is_private int, |
8 |
IN p_is_done int |
9 |
)
|
10 |
BEGIN
|
11 |
insert into tbl_wish( |
12 |
wish_title, |
13 |
wish_description, |
14 |
wish_user_id, |
15 |
wish_date, |
16 |
wish_file_path, |
17 |
wish_private, |
18 |
wish_accomplished
|
19 |
)
|
20 |
values
|
21 |
(
|
22 |
p_title, |
23 |
p_description, |
24 |
p_user_id, |
25 |
NOW(), |
26 |
p_file_path, |
27 |
p_is_private, |
28 |
p_is_done
|
29 |
);
|
30 |
|
31 |
SET @last_id = LAST_INSERT_ID(); |
32 |
insert into tbl_likes( |
33 |
wish_id, |
34 |
user_id, |
35 |
wish_like
|
36 |
)
|
37 |
values( |
38 |
@last_id, |
39 |
p_user_id, |
40 |
0
|
41 |
);
|
42 |
|
43 |
|
44 |
END$$ |
45 |
DELIMITER ; |
Như đã thấy trong code của thủ tục lưu trữ ở trên, sau khi thêm mong ước vào bảng tbl_wish
, chúng ta truy vấn ID
và dữ liệu vừa được chèn vào bảng tbl_likes
.
Tiếp theo, chúng ta cần sửa đổi thủ tục lưu trữ sp_GetAllWishes
để bao gồm số lượng like mà mỗi mong ước thu được. Chúng ta sẽ tận dụng một hàm MySQL để lấy tổng số mong ước. Do đó hãy tạo một hàm gọi là getSum
, nó sẽ lấy ID
của mong ước và trả về tổng số lượt like.
1 |
DELIMITER $$ |
2 |
CREATE DEFINER=`root`@`localhost` FUNCTION `getSum`( |
3 |
p_wish_id int |
4 |
) RETURNS int(11) |
5 |
BEGIN
|
6 |
select sum(wish_like) into @sm from tbl_likes where wish_id = p_wish_id; |
7 |
RETURN @sm; |
8 |
END$$ |
9 |
DELIMITER ; |
Bây giờ, hãy gọi hàm MySQL getSum
ở trên trong thủ tục lưu trữ sp_GetAllWish
để lấy tổng số lượt like cho mỗi mong ước.
1 |
DELIMITER $$ |
2 |
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_GetAllWishes`() |
3 |
BEGIN
|
4 |
select wish_id,wish_title,wish_description,wish_file_path,getSum(wish_id) |
5 |
from tbl_wish where wish_private = 0; |
6 |
END$$ |
7 |
DELIMITER ; |
Sửa đổi phương thức Python getAllWishes
để bao gồm số lượt like. Khi lượt qua kết quả trả về từ thủ tục lưu trữ MySQL, hãy bao gồm trường like như sau:
1 |
for wish in result: |
2 |
wish_dict = { |
3 |
'Id': wish[0], |
4 |
'Title': wish[1], |
5 |
'Description': wish[2], |
6 |
'FilePath': wish[3], |
7 |
'Like':wish[4]} |
8 |
wishes_dict.append(wish_dict) |
Sửa đổi phương thức JavaScript CreateThumb
để tạo thêm một phần tử span mà chúng ta sẽ sử dụng để hiển thị số lượng like.
1 |
var likeSpan = $('<span>').attr('aria-hidden','true').html(' '+like+' like(s)'); |
Và nối likeSpan
vào phần tử cha p
. Đây là hàm CreateThumb
đã được chỉnh sửa.
1 |
function CreateThumb(id, title, desc, filepath, like) { |
2 |
var mainDiv = $('<div>').attr('class', 'col-sm-4 col-md-4'); |
3 |
var thumbNail = $('<div>').attr('class', 'thumbnail'); |
4 |
var img = $('<img>').attr({ |
5 |
'src': filepath, |
6 |
'data-holder-rendered': true, |
7 |
'style': 'height: 150px; width: 150px; display: block' |
8 |
});
|
9 |
var caption = $('<div>').attr('class', 'caption'); |
10 |
var title = $('<h3>').text(title); |
11 |
var desc = $('<p>').text(desc); |
12 |
|
13 |
|
14 |
var p = $('<p>'); |
15 |
var btn = $('<button>').attr({ |
16 |
'id': 'btn_' + id, |
17 |
'type': 'button', |
18 |
'class': 'btn btn-danger btn-sm' |
19 |
});
|
20 |
var span = $('<span>').attr({ |
21 |
'class': 'glyphicon glyphicon-thumbs-up', |
22 |
'aria-hidden': 'true' |
23 |
});
|
24 |
|
25 |
var likeSpan = $('<span>').attr('aria-hidden', 'true').html(' ' + like + ' like(s)'); |
26 |
|
27 |
p.append(btn.append(span)); |
28 |
p.append(likeSpan); |
29 |
|
30 |
|
31 |
caption.append(title); |
32 |
caption.append(desc); |
33 |
caption.append(p); |
34 |
|
35 |
thumbNail.append(img); |
36 |
thumbNail.append(caption); |
37 |
mainDiv.append(thumbNail); |
38 |
return mainDiv; |
39 |
|
40 |
|
41 |
}
|
Hãy bao gồm tham số like
khi gọi hàm CreateThumb
trong callback success trong jQuery AJAX khi gọi đến /getAllWishes
.
1 |
CreateThumb(data[i].Id,data[i].Title,data[i].Description,data[i].FilePath,data[i].Like) |
Lưu các thay đổi và khởi động lại máy chủ. Một khi đã đăng nhập vào ứng dụng, bạn sẽ thấy số lượng like tương ứng với từng mong ước.



Hiện thị một Mong ước được Like hay không
Việc nhìn thấy các like ở bên dưới mỗi mong ước không thật sự rõ ràng lắm cho dù người dùng đăng nhập đã like mong ước hay chưa. Vì vậy, chúng ta sẽ hiển thị một thông điệp thích hợp giống như You & 20 Others
. Để cài đặt cái đó, chúng ta cần phải sửa đổi sp_GetAllWishes
để bao gồm một ít code xác định người dùng đã đăng nhập có like một mong ước cụ thể hay không. Để kiểm tra xem một mong ước có được like hay không, chúng ta sẽ gọi một hàm. Hãy tạo một hàm gọi là hasLiked
nhận ID
của người dùng và ID
của mong ước như là các tham số và trả về kết quả mong ước có được like bởi người dùng hay không.
1 |
DELIMITER $$ |
2 |
CREATE DEFINER=`root`@`localhost` FUNCTION `hasLiked`( |
3 |
p_wish int, |
4 |
p_user int |
5 |
) RETURNS int(11) |
6 |
BEGIN
|
7 |
|
8 |
select wish_like into @myval from tbl_likes where wish_id = p_wish and user_id = p_user; |
9 |
RETURN @myval; |
10 |
END$$ |
11 |
DELIMITER ; |
Bây giờ gọi hàm MySQL hasLiked
ở trên bên trong sp_GetAllWishes
để trả về một trường phụ trong bộ dữ liệu trả về xác định trạng thái like của người dùng.
1 |
DELIMITER $$ |
2 |
|
3 |
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_GetAllWishes`( |
4 |
p_user int |
5 |
)
|
6 |
BEGIN
|
7 |
select wish_id,wish_title,wish_description,wish_file_path,getSum(wish_id),hasLiked(wish_id,p_user) |
8 |
from tbl_wish where wish_private = 0; |
9 |
END
|
Mở app.py
và sửa đổi việc gọi thủ tục lưu trữ MySQL sp_GetAllWishes
để bao gồm ID
của người dùng như là một tham số.
1 |
_user = session.get('user') |
2 |
conn = mysql.connect() |
3 |
cursor = conn.cursor() |
4 |
cursor.callproc('sp_GetAllWishes',(_user,)) |
Bây giờ hãy sửa đổi phương thức getAllWishes
để bao gồm trạng thái like của người dùng đối với một mong ước cụ thể. Hãy sửa đổi code để bao gồm hasLiked
trong dictionary đã được tạo.
1 |
for wish in result: |
2 |
wish_dict = { |
3 |
'Id': wish[0], |
4 |
'Title': wish[1], |
5 |
'Description': wish[2], |
6 |
'FilePath': wish[3], |
7 |
'Like':wish[4], |
8 |
'HasLiked':wish[5]} |
9 |
wishes_dict.append(wish_dict) |
Bên trong hàm JavaScript CreateThumb
, chúng ta sẽ kiểm tra HasLiked
và thêm HTML tương ứng.
1 |
if (hasLiked == "1") { |
2 |
likeSpan.html(' You & ' + (Number(like) - 1) + ' Others'); |
3 |
} else { |
4 |
likeSpan.html(' ' + like + ' like(s)'); |
5 |
}
|
Như đã thấy trong đoạn code trên, chúng ta sẽ hiển thị số lượt like nếu người dùng không like một mong ước cụ thể. Nếu người dùng đã like mong ước thì chúng ta sẽ hiển thị một thông điệp mang tính mô tả hơn.



Làm mới Số lượt Like
Vào thời điểm này, khi chúng ta nhấp vào nút like, trạng thái like được cập nhật trong cơ sở dữ liệu, nhưng không thay đổi trong dashboard. Vì vậy, hãy cập nhật nó trong hàm callback success trong hàm AJAX khi nút like
được nhấp vào.
Chúng ta sẽ bắt đầu bằng cách thực hiện một thay đổi trong thủ tục lưu trữ MySQL sp_AddUpdateLikes
. Trước đó chúng ta đã truyền vào một trạng thái like, 1 cho một like và 0 là không like. Chúng ta sẽ sửa đổi điều đó và cài đặt like hoặc không like trong thủ tục lưu trữ. Mở sp_AddUpdateChuyển
và gán trạng thái like vào một biến và kiểm tra trạng thái của biến. Nếu trạng thái biến là một like, chúng ta sẽ cập nhật trạng thái thành unlike và ngược lại. Dưới đây là thủ tục lưu trữ sp_AddUpdateLikes
đã được sửa đổi.
1 |
-- --------------------------------------------------------------------------------
|
2 |
-- Routine DDL
|
3 |
-- Note: comments before and after the routine body will not be stored by the server
|
4 |
-- --------------------------------------------------------------------------------
|
5 |
DELIMITER $$ |
6 |
|
7 |
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_AddUpdateLikes`( |
8 |
p_wish_id int, |
9 |
p_user_id int, |
10 |
p_like int |
11 |
)
|
12 |
BEGIN
|
13 |
|
14 |
if (select exists (select 1 from tbl_likes where wish_id = p_wish_id and user_id = p_user_id)) then |
15 |
|
16 |
|
17 |
select wish_like into @currentVal from tbl_likes where wish_id = p_wish_id and user_id = p_user_id; |
18 |
|
19 |
if @currentVal = 0 then |
20 |
update tbl_likes set wish_like = 1 where wish_id = p_wish_id and user_id = p_user_id; |
21 |
else
|
22 |
update tbl_likes set wish_like = 0 where wish_id = p_wish_id and user_id = p_user_id; |
23 |
end if; |
24 |
|
25 |
else
|
26 |
|
27 |
insert into tbl_likes( |
28 |
wish_id, |
29 |
user_id, |
30 |
wish_like
|
31 |
)
|
32 |
values( |
33 |
p_wish_id, |
34 |
p_user_id, |
35 |
p_like
|
36 |
);
|
37 |
|
38 |
|
39 |
end if; |
40 |
END
|
Trong hàm JavaScript CreateThumb
, gán một ID
cho phần tử likeSpan
mà chúng ta đã tạo ra trước đó để chúng ta có thể cập nhật trạng thái theo yêu cầu.
1 |
var likeSpan = $('<span>').attr({'aria-hidden':'true','id':'span_'+id}); |
Mở app.py
. Bên trong phương thức addUpdateLike
, khi dữ liệu đã được cập nhật thành công, chúng ta sẽ truy vấn số lượt like và trạng thái của mong ước bằng cách gọi một thủ tục lưu trữ khác. Tôi tạo ra một thủ tục lưu trữ MySQL gọi là sp_getLikeStatus
. Bên trong sp_getLikeStatus
chúng ta sẽ gọi các hàm MySQL đã được tạo ra bao gồm getSum
và hasLiked
để lấy trạng thái.
1 |
DELIMITER $$ |
2 |
CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_getLikeStatus`( |
3 |
IN p_wish_id int, |
4 |
IN p_user_id int |
5 |
)
|
6 |
BEGIN
|
7 |
select getSum(p_wish_id),hasLiked(p_wish_id,p_user_id); |
8 |
END$$ |
9 |
DELIMITER ; |
Khi gọi đến sp_AddUpdateLikes
từ phương thức Python addUpdateLike
đã được thực hiện, hãy đóng con trỏ và kết nối.
1 |
if len(data) is 0: |
2 |
conn.commit() |
3 |
cursor.close() |
4 |
conn.close() |
Bây giờ hãy gọi đến thủ tục lưu trữ sp_getLikeStatus
.
1 |
conn = mysql.connect() |
2 |
cursor = conn.cursor() |
3 |
cursor.callproc('sp_getLikeStatus',(_wishId,_user)) |
4 |
result = cursor.fetchall() |
Trả về số lượt like và trạng thái like cùng với phản hồi.
1 |
return json.dumps({'status':'OK','total':result[0][0],'likeStatus':result[0][1]}) |
Bên trong dashboard.html
, trong callback success của hàm AJAX được thực hiện cho phương thức addUpdateLike
, phân tích phản hồi được trả về và dựa vào trạng thái like để hiển thị số lượt like.
1 |
success: function(response) { |
2 |
|
3 |
var obj = JSON.parse(response); |
4 |
|
5 |
if (obj.likeStatus == "1") { |
6 |
$('#span_' + spId).html(' You & ' + (Number(obj.total) - 1) + ' Others'); |
7 |
} else { |
8 |
$('#span_' + spId).html(' ' + obj.total + ' like(s)'); |
9 |
}
|
10 |
|
11 |
}
|
Lưu các thay đổi, khởi động lại máy chủ và đăng nhập bằng các thông tin xác thực hợp lệ. Một khi ở trong trang dashboard, hãy thử like một mong ước cụ thể và xem trạng thái like được cập nhật như thế nào.
Tóm tắt
Trong phần này của loạt bài, chúng ta đã cài đặt tính năng like/unlike cho những mong ước được hiển thị trong trang dashboard. Trong phần tiếp theo của loạt bài, chúng ta sẽ cài đặt thêm một số tính năng mới trong ứng dụng và tinh chỉnh một số tính năng hiện có.
Hãy cho chúng tôi biết những suy nghĩ và đề xuất của bạn hoặc bất kỳ hiệu chỉnh nào trong bình luận bên dưới nhé. Mã nguồn từ hướng dẫn này có sẵn trên GitHub.