使用FastAPI实现简单的点赞功能

726 字
4 分钟
使用FastAPI实现简单的点赞功能

前言#

因为给博客整了说说页面,想弄个点赞功能,经过一番搜寻,最终选择用FastAPI来搭建 存储方面选用SQLite,适合单独存储点赞数据 FastAPI是一个基于Python的Web框架,能快速构建API

环境搭建#

在linux系统中,最好使用虚拟环境来隔离Python项目

Terminal window
python -m venv .venv

运行该命令后Python会在当前目录下创建一个.venv文件夹,存放虚拟环境的相关配置。 使用下面的命令激活虚拟环境:

Terminal window
source .venv/bin/activate

安装FastAPI和所需的依赖:

Terminal window
pip install fastapi[standard] slowapi

如需停用虚拟环境,可使用这个命令:

Terminal window
deactivate

数据库表设计如下:

字段类型允许为空主键备注
idint自动递增
page_namevarchar
guest_datavarchar
tsint
ipvarchar

代码#

import time
import sqlite3
from pydantic import BaseModel
from fastapi import FastAPI, Depends, Request
from fastapi.middleware.cors import CORSMiddleware
from slowapi import Limiter, _rate_limit_exceeded_handler
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
DATABASE_PATH = "reactions.db"
def get_db_connection():
connection = sqlite3.connect(DATABASE_PATH, check_same_thread=False)
connection.row_factory = sqlite3.Row
return connection
def init_db():
conn = get_db_connection()
conn.execute("""
CREATE TABLE IF NOT EXISTS likes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
page_name TEXT NOT NULL,
guest_data TEXT NOT NULL,
ts INTEGER NOT NULL,
ip TEXT
)
""")
conn.commit()
conn.close()
init_db()
def get_db():
connection = get_db_connection()
db = connection.cursor()
try:
yield db
finally:
db.close()
connection.close()
class Like(BaseModel):
page_name: str
guest_data: str
ts: str | None = None
ip: str | None = None
limiter = Limiter(key_func=get_remote_address)
app = FastAPI(docs_url=None, redoc_url=None)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
app.add_middleware(
CORSMiddleware,
allow_origins=["https://blog.dotuoodo.top","http://localhost:1313"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.head("/")
@app.get("/")
def root():
return "ok"
@app.get("/like/count")
def get_likes_count(
page_name: str,
db: sqlite3.Cursor = Depends(get_db)
):
db.execute("SELECT COUNT(*) FROM likes WHERE page_name = ?", (page_name,))
result = db.fetchone()
return {"page": page_name, "likes": result[0] if result else 0}
@app.get("/like/pages")
def get_likes_pages(
page_names: str,
like_id: str | None = None,
db: sqlite3.Cursor = Depends(get_db)
):
page_list = page_names.split(',')
placeholders = ', '.join(['?'] * len(page_list))
query = f"""
SELECT page_name, COUNT(*) AS likes
FROM likes
WHERE page_name IN ({placeholders})
GROUP BY page_name
"""
db.execute(query, tuple(page_list))
results = db.fetchall()
result_dict = {row[0]: row[1] for row in results}
response_data = {name: result_dict.get(name, 0) for name in page_list}
if like_id is not None:
liked_query = f"""
SELECT page_name
FROM likes
WHERE guest_data = ?
AND page_name IN ({placeholders})
"""
db.execute(liked_query, (like_id, *page_list))
liked_pages = [row[0] for row in db.fetchall()]
return {"data": response_data, "liked": liked_pages}
return {"data": response_data}
@app.post("/like/toggle")
@limiter.limit("20/minute")
def toggle_like(
request: Request,
like: Like,
db: sqlite3.Cursor = Depends(get_db)
):
try:
client_host = request.headers.get("CF-Connecting-IP")
db.execute(
"SELECT id FROM likes WHERE page_name = ? AND guest_data = ?",
(like.page_name, like.guest_data)
)
existing = db.fetchone()
if existing:
db.execute("DELETE FROM likes WHERE id = ?", (existing[0],))
action = "unliked"
else:
db.execute(
"INSERT INTO likes (page_name, guest_data, ts, ip) VALUES (?, ?, ?, ?)",
(like.page_name, like.guest_data, int(time.time()), client_host)
)
action = "liked"
db.connection.commit()
db.execute("SELECT COUNT(*) FROM likes WHERE page_name = ?", (like.page_name,))
result = db.fetchone()
return {"status": "success", "action": action, "like": result[0]}
except Exception as e:
db.connection.rollback()
return {"status": "error", "detail": str(e)}

部署#

将以上代码保存为 api.py,使用

Terminal window
fastapi run api.py

在浏览器中打开输出的地址,如果一切正常即可看到“ok”

开机自启#

在Debian中使用service文件让脚本实现开机自启,先写一个bash脚本,用于切换到虚拟环境并启动FastAPI:

#!/bin/sh
cd /root/.venv
. bin/activate
cd /root
fastapi run api.py

然后将api.service文件放在/etc/systemd/system目录下

[Unit]
Description=API Service (FastAPI)
After=network.target
[Service]
Type=simple
User=root
Group=root
WorkingDirectory=/root
ExecStart=/bin/sh /root/api.sh
Restart=always
RestartSec=3
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target

最后使用

Terminal window
systemctl enable api
systemctl start api

即可实现开机自启

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

使用FastAPI实现简单的点赞功能
https://blog.dotuoodo.top/posts/fastapi-like/
作者
DOTUOODO
发布于
2026-04-25
许可协议
CC BY-NC-SA 4.0

评论

Profile Image of the Author
DOTUOODO
Nothing is immortal, but at least we can be extraordinary.
公告
欢迎来到我的博客!目前还在施工中...
分类
标签

文章目录