典型的stream 二级页面打开 显示图片

涉及知识点

  • 排版 columns :c1 ,c2,c3 ,c4= st.columns([3,1, 1,1]) 使用with显示
  • 单页面交互之button ,交互需要先定义函数 button按下后触发函数,然后使用st.cache_data.clear() 清除缓存 st.rerun() 及返回,感觉就像AJAX交互一样
  • HTML原始标签之markdown页面解析 a标签 img标签,且可以放DataFrame格式数据,以表格显示。
  • 查询数据使用pd.DataFrame(rows,columns=cols),及使用lambda处理数据 df['path']=df['path'].apply( lambda name :f'<img src="{base_url}/{name}">' )
  • 缓存 @st.cache_data(show_spinner=False, ttl=300) 会把查询信息保存到文件url相同的情况下,不去数据库读取,上面设置是300秒

坑点 A标签不能包裹button 需要CSS来修改

import streamlit as st
from datetime import datetime
import sqlite3
import pathlib
import json,time,os
import pandas as pd




if 'conn' not in st.session_state:
    st.session_state.conn=sqlite3.connect(
        'ocr.sqlite',
        timeout=30.0,
        check_same_thread=False
    )
    st.session_state.cursor=st.session_state.conn.cursor()


def get_id(id):
    st.session_state.cursor.execute("SELECT id,done FROM pdf WHERE id=(?) AND done>0",(id,))
    if st.session_state.cursor.fetchone():
        st.session_state.cursor.execute("SELECT * FROM img WHERE pdf_id=(?)",(id,))
        rows=st.session_state.cursor.fetchall()
        cols=[desc[0] for desc in st.session_state.cursor.description]
        # cols=[desc[0] for desc in st.session_state.cursor.description]#获取键名
        return pd.DataFrame(rows,columns=cols)

    return False

# streamlit.query_params.get(‘id’)
id=st.query_params.get('id')
if not id:
    id=56
base_url = "/app/static/img"   
df=get_id(id)
df['path']=df['path'].apply(
    lambda name :f'<img src="{base_url}/{name}">'
)

st.markdown(
    df.to_html(escape=False, index=False),
    unsafe_allow_html=True
)
st.write()

更新代码

import streamlit as st
from datetime import datetime
import sqlite3, json, pathlib, time, os
import pandas as pd

# ---------- 数据库连接 ----------
if "conn" not in st.session_state:
    st.session_state.conn = sqlite3.connect(
        "ocr.sqlite", timeout=30.0, check_same_thread=False
    )
    st.session_state.cursor = st.session_state.conn.cursor()

# ---------- 工具函数 ----------
#@st.cache_data(show_spinner=False)
@st.cache_data(show_spinner=False, ttl=300)   # 5 分钟后自动失效
def get_id(_id: int) -> pd.DataFrame:
    """根据 pdf.id 拉取所属 img 记录"""
    cur = st.session_state.cursor
    cur.execute("SELECT * FROM pdf WHERE id=? AND done>0", (_id,))
    if not cur.fetchone():
        return pd.DataFrame()

    cur.execute(
        """SELECT id, path, CASE WHEN done>0 THEN datetime(done,'unixepoch','localtime') ELSE '未执行' END as 状态,
                  info, done
           FROM img
           WHERE pdf_id=?""",
        (_id,),
    )
    rows = cur.fetchall()
    cols = [desc[0] for desc in cur.description]
    df = pd.DataFrame(rows, columns=cols)
    # info 是 json 字符串,解析成 dict 方便后面展示
    df["info"] = df["info"].apply(json.loads)
    return df


def reset_done(img_id: int):
    """把单条 img 的 done 置 0"""
    st.session_state.cursor.execute("UPDATE img SET done=0 WHERE id=?", (img_id,))
    st.session_state.conn.commit()
    # 让缓存失效,重新拉数据
    st.cache_data.clear()


# ---------- 主流程 ----------
id = st.query_params.get("id")
if not id:
    id = 56
else:
    id = int(id)

df = get_id(id)
if df.empty:
    st.warning("该 pdf 未找到已处理完成的图片")
    st.stop()

# st.write(id)
base_url = "/app/static/img"

# ---------- 方案 A:每行一个按钮 ----------
st.subheader("逐行重置")
for _, row in df.iterrows():
    c1 ,c2,c3 ,c4= st.columns([3,1, 1,1])
    # 查看图片
    with c1:
        st.markdown(
            f'<a href="{base_url}/{row["path"]}" target="_blank">查看图片</a>',
            unsafe_allow_html=True,
        )
    # 当前 done
    with c2:
        st.write(row["done"])
    with c3:
        st.write(row['状态'])
    # 重置按钮
    with c4:
        if st.button("重置", key=f"reset_{row['id']}"):
            reset_done(row["id"])
            st.rerun()          # 立刻刷新页面


# 如果用户改过 done,点“保存”才生效
if st.button("保存修改"):
    for _, r in edited.iterrows():
        st.session_state.cursor.execute(
            "UPDATE img SET done=? WHERE id=?", (r["done"], r["id"])
        )
    st.session_state.conn.commit()
    st.success("已保存")
    st.cache_data.clear()
    st.rerun()
此条目发表在None分类目录。将固定链接加入收藏夹。

发表回复