使用FastAPI实现简单的点赞功能
726 字
4 分钟
使用FastAPI实现简单的点赞功能
前言
因为给博客整了说说页面,想弄个点赞功能,经过一番搜寻,最终选择用FastAPI来搭建 存储方面选用SQLite,适合单独存储点赞数据 FastAPI是一个基于Python的Web框架,能快速构建API
环境搭建
在linux系统中,最好使用虚拟环境来隔离Python项目
python -m venv .venv运行该命令后Python会在当前目录下创建一个.venv文件夹,存放虚拟环境的相关配置。 使用下面的命令激活虚拟环境:
source .venv/bin/activate安装FastAPI和所需的依赖:
pip install fastapi[standard] slowapi如需停用虚拟环境,可使用这个命令:
deactivate数据库表设计如下:
| 字段 | 类型 | 允许为空 | 主键 | 备注 |
|---|---|---|---|---|
| id | int | 否 | 是 | 自动递增 |
| page_name | varchar | 否 | 否 | |
| guest_data | varchar | 否 | 否 | |
| ts | int | 是 | 否 | |
| ip | varchar | 是 | 否 |
代码
import timeimport sqlite3from pydantic import BaseModelfrom fastapi import FastAPI, Depends, Requestfrom fastapi.middleware.cors import CORSMiddlewarefrom slowapi import Limiter, _rate_limit_exceeded_handlerfrom slowapi.util import get_remote_addressfrom 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 = limiterapp.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,使用
fastapi run api.py
在浏览器中打开输出的地址,如果一切正常即可看到“ok”
开机自启
在Debian中使用service文件让脚本实现开机自启,先写一个bash脚本,用于切换到虚拟环境并启动FastAPI:
#!/bin/shcd /root/.venv. bin/activatecd /rootfastapi run api.py然后将api.service文件放在/etc/systemd/system目录下
[Unit]Description=API Service (FastAPI)After=network.target
[Service]Type=simpleUser=rootGroup=rootWorkingDirectory=/rootExecStart=/bin/sh /root/api.shRestart=alwaysRestartSec=3StandardOutput=journalStandardError=journal
[Install]WantedBy=multi-user.target最后使用
systemctl enable apisystemctl start api即可实现开机自启
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
使用FastAPI实现简单的点赞功能
https://blog.dotuoodo.top/posts/fastapi-like/最后更新于 2026-04-25
部分内容可能已过时











