I am trying to make a social media website, (similar to TikTok) but the watch page keeps refreshing.
My JS sends JSON like this to the backend, which keeps track of likes, dislikes, views, etc. in a SQLite database:
{
"action": {action e.g. like, dislike, view}
"id": {video_id e.g. 1)
}
Then, the backend processes it with this function:
@app.route('/trackStatistics', methods=['POST'])
def track_statistics():
try:
# Get the JSON data from the request
data = request.get_json()
# Validate the action and id
if 'action' not in data or 'id' not in data:
return jsonify({'error': 'Invalid request'}), 400
action = data['action']
video_id = data['id']
data = get_video(video_id)
print(data)
if action == "like":
data["likes"] = int(data["likes"]) + 1
elif action == "dislike":
data["dislikes"] = int(data["dislikes"]) + 1
elif action == "unlike":
data["likes"] = int(data["likes"]) - 1
elif action == "undislike":
data["dislikes"] = int(data["dislikes"]) - 1
elif action == "view":
data["views"] = int(data["views"]) + 1
update_video(video_id, data["publisher"], data["title"], data["likes"], data["dislikes"], data["views"], data["comments"], False)
print(data)
# Return the updated data
return jsonify(data), 200
except Exception as e:
print(str(e))
return jsonify({'error': str(e)}), 500
Here’s the file with my update_video
, get_video
, and create_video
functions defined:
import sqlite3
import json
from datetime import datetime
def get_video(video_id):
conn = sqlite3.connect('../databases/videos.db')
c = conn.cursor()
c.execute("SELECT * FROM videos WHERE id = ?", (video_id,))
video = c.fetchone()
comments = json.loads(video[6]) if video[6] else []
video = list(video)
video[6] = comments
conn.close()
return {
"id": video[0],
"publisher": video[1],
"title": video[2],
"likes": video[3],
"dislikes": video[4],
"views": video[5],
"comments": video[6],
"created_at": video[7],
"updated_at": video[8]
}
def create_video(publisher, title, likes, dislikes, views, comments):
conn = sqlite3.connect('../databases/videos.db')
c = conn.cursor()
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
comments_json = json.dumps(comments)
c.execute("INSERT INTO videos (publisher, title, likes, dislikes, views, comments, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
(publisher, title, likes, dislikes, views, comments_json, now, now))
conn.commit()
conn.close()
return c.lastrowid
def update_video(video_id, publisher, title, likes, dislikes, views, comments, update_time):
conn = sqlite3.connect('../databases/videos.db')
c = conn.cursor()
# Get the current updated_at time
c.execute("SELECT updated_at FROM videos WHERE id = ?", (video_id,))
last_updated = c.fetchone()[0]
if update_time:
now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
else:
now = last_updated
comments_json = json.dumps(comments)
c.execute("UPDATE videos SET publisher = ?, title = ?, likes = ?, dislikes = ?, views = ?, comments = ?, updated_at = ? WHERE id = ?",
(publisher, title, likes, dislikes, views, comments_json, now, video_id))
conn.commit()
conn.close()
I tried to keep track of the video stats and the server seems to work, it prints the correct data! But, after giving code 200 success, it refreshes the page.
Here’s the JS I’m using to interact with the backend:
let liked = false;
let disliked = false;
let followed = false;
let commentsOpen = false;
const url = window.location.search;
const urlParams = new URLSearchParams(url);
const id = urlParams.get('c');
const trackStatisticsRoute = 'http://localhost:5005/trackStatistics';
$(document).ready(() => {
if (id) {
document.title = "ByteClips - " + id;
}
const vidFile = `../videos/${id}/video.mp4`;
console.log(vidFile);
$('#vidSrc').attr('src', vidFile);
$('.video')[0].load();
updateRating('view', id);
$('.video-buttons div button').hover(
() => {
$(this).find('i').css('opacity', 0);
$(this).find('.counter').css('opacity', 1);
},
() => {
$(this).find('i').css('opacity', 1);
$(this).find('.counter').css('opacity', 0);
}
);
});
function updateRating(action, id) {
const requestData = {
action,
id
};
$.ajax({
type: 'POST',
url: trackStatisticsRoute,
data: JSON.stringify(requestData),
contentType: 'application/json',
success: data => {
updateUI(data);
},
error: (jqXHR, textStatus, errorThrown) => {
console.log('AJAX request error:', textStatus, errorThrown);
console.log('Response:', jqXHR.responseText);
}
});
}
function updateUI(data) {
const newData = typeof data === 'string' ? JSON.parse(data) : data;
$('#like .counter').text(newData.likes);
$('#dislike .counter').text(newData.dislikes);
$('#share .counter').text(newData.views);
$('#comment .counter').text(newData.comments.length);
}
$('#like').css('background', liked ? '#fff' : '#26daa5');
$('#like').css('color', liked ? '#26daa5' : '#fff');
$('#dislike').css('background', disliked ? '#fff' : '#26daa5');
$('#dislike').css('color', disliked ? '#26daa5' : '#fff');
$('#follow').css('background', followed ? '#fff' : '#26daa5');
$('#follow').css('color', followed ? '#26daa5' : '#fff');
$('#follow i').attr('class', followed ? 'fa-solid fa-user-minus' : 'fa-solid fa-user-plus');
$('#like').on('click', () => {
if (liked) {
liked = false;
updateRating('unlike', id);
} else {
if (disliked) {
updateRating('undislike', id);
}
liked = true;
disliked = false;
updateRating('like', id);
}
updateLikeDislike();
});
$('#dislike').on('click', () => {
if (disliked) {
disliked = false;
updateRating('undislike', id);
} else {
if (liked) {
updateRating('unlike', id);
}
disliked = true;
liked = false;
updateRating('dislike', id);
}
updateLikeDislike();
});
$('#follow').on('click', () => {
followed = !followed;
$('#follow i').attr('class', followed ? 'fa-solid fa-user-minus' : 'fa-solid fa-user-plus');
$('#follow').css('background', followed ? '#fff' : '#26daa5');
$('#follow').css('color', followed ? '#26daa5' : '#fff');
});
$('#comment').on('click', () => {
console.log('comments opened');
commentsOpen = !commentsOpen;
$('#comment').css('background', commentsOpen ? '#fff' : '#26daa5');
$('#comment').css('color', commentsOpen ? '#26daa5' : '#fff');
});
function updateLikeDislike() {
$('#like').css('background', liked ? '#fff' : '#26daa5');
$('#like').css('color', liked ? '#26daa5' : '#fff');
$('#dislike').css('background', disliked ? '#fff' : '#26daa5');
$('#dislike').css('color', disliked ? '#26daa5' : '#fff');
}