用Python Streamlit sqlite3 写一个简单博客
图片:

依赖:
streamlit
pandas
matplotlib
代码blog_app.py:
import streamlit as st
import sqlite3
import pandas as pd
from datetime import datetime
import os# 确保中文正常显示# 数据库初始化函数
def init_db():conn = sqlite3.connect('blog.db')c = conn.cursor()# 创建博客文章表c.execute('''CREATE TABLE IF NOT EXISTS posts (id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT NOT NULL,content TEXT NOT NULL,created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,category TEXT,tags TEXT)''')conn.commit()conn.close()# 添加新博客文章
def add_post(title, content, category='未分类', tags=''):conn = sqlite3.connect('blog.db')c = conn.cursor()c.execute('''INSERT INTO posts (title, content, category, tags) VALUES (?, ?, ?, ?)''', (title, content, category, tags))conn.commit()conn.close()# 获取所有博客文章
def get_all_posts():conn = sqlite3.connect('blog.db')# 使用pandas读取数据,确保中文正常显示posts = pd.read_sql_query('SELECT * FROM posts ORDER BY created_at DESC', conn)conn.close()return posts# 获取单篇博客文章
def get_post(post_id):conn = sqlite3.connect('blog.db')c = conn.cursor()c.execute('SELECT * FROM posts WHERE id = ?', (post_id,))post = c.fetchone()conn.close()return post# 更新博客文章
def update_post(post_id, title, content, category, tags):conn = sqlite3.connect('blog.db')c = conn.cursor()c.execute('''UPDATE posts SET title = ?, content = ?, category = ?, tags = ? WHERE id = ?''', (title, content, category, tags, post_id))conn.commit()conn.close()# 删除博客文章
def delete_post(post_id):conn = sqlite3.connect('blog.db')c = conn.cursor()c.execute('DELETE FROM posts WHERE id = ?', (post_id,))conn.commit()conn.close()# 获取分类统计
def get_category_stats():conn = sqlite3.connect('blog.db')stats = pd.read_sql_query('SELECT category, COUNT(*) as count FROM posts GROUP BY category', conn)conn.close()return stats# 主应用函数
def main():# 初始化数据库init_db()st.title('我的博客')# 创建侧边栏导航menu = ['首页', '写文章', '管理文章', '统计']choice = st.sidebar.selectbox('选择功能', menu)if choice == '首页':st.subheader('博客文章')# 显示分类筛选categories = pd.read_sql_query('SELECT DISTINCT category FROM posts', sqlite3.connect('blog.db'))['category'].tolist()categories.insert(0, '全部')selected_category = st.selectbox('按分类筛选', categories)# 获取并显示文章列表if selected_category == '全部':posts = get_all_posts()else:conn = sqlite3.connect('blog.db')posts = pd.read_sql_query('SELECT * FROM posts WHERE category = ? ORDER BY created_at DESC', conn, params=(selected_category,))conn.close()if not posts.empty:for _, post in posts.iterrows():# 使用expander折叠显示文章内容with st.expander(f"{post['title']} ({post['created_at']})"):st.write(f"**分类:** {post['category']}")if post['tags']:st.write(f"**标签:** {post['tags']}")st.write(post['content'])else:st.info('暂无博客文章')elif choice == '写文章':st.subheader('写新文章')with st.form(key='post_form'):title = st.text_input('标题')category = st.text_input('分类', '未分类')tags = st.text_input('标签(用逗号分隔)')content = st.text_area('内容', height=300)submit_button = st.form_submit_button(label='发布文章')if submit_button:if title and content:add_post(title, content, category, tags)st.success('文章发布成功!')else:st.error('请填写标题和内容')elif choice == '管理文章':st.subheader('管理文章')# 显示所有文章进行管理posts = get_all_posts()if not posts.empty:# 创建一个下拉框让用户选择要编辑/删除的文章post_options = {f"{post['title']} ({post['id']})": post['id'] for _, post in posts.iterrows()}selected_post_title = st.selectbox('选择文章', list(post_options.keys()))if selected_post_title:post_id = post_options[selected_post_title]post = get_post(post_id)if post:# 显示文章信息st.write(f"**ID:** {post[0]}")st.write(f"**创建时间:** {post[3]}")# 编辑表单with st.form(key='edit_form'):new_title = st.text_input('标题', post[1])new_category = st.text_input('分类', post[4])new_tags = st.text_input('标签', post[5])new_content = st.text_area('内容', post[2], height=300)col1, col2 = st.columns(2)with col1:update_button = st.form_submit_button(label='更新文章')with col2:delete_button = st.form_submit_button(label='删除文章', type='primary')# 处理表单提交if update_button:if new_title and new_content:update_post(post_id, new_title, new_content, new_category, new_tags)st.success('文章更新成功!')st.experimental_rerun()else:st.error('请填写标题和内容')if delete_button:delete_post(post_id)st.success('文章删除成功!')st.experimental_rerun()else:st.info('暂无文章可管理')elif choice == '统计':st.subheader('博客统计')# 显示文章总数posts = get_all_posts()st.write(f"**文章总数:** {len(posts)}")# 显示分类统计图表try:import matplotlib.pyplot as pltplt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号stats = get_category_stats()if not stats.empty:st.write('**分类统计:**')fig, ax = plt.subplots()stats.plot.pie(y='count', labels=stats['category'], autopct='%1.1f%%', ax=ax)ax.set_ylabel('')st.pyplot(fig)else:st.info('暂无统计数据')except Exception as e:st.error(f'生成统计图表时出错: {e}')if __name__ == '__main__':main()运行:
streamlit run blog_app.py

