马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
简介
由于streamlit可以同时在实现前后端结合,非常方便,但是这也造成了user难以方便的对页面的组件举行位置控制,本文将使用streamlit+flask,实现平凡按钮触发与携带信息
不携带信息的触发
隐蔽指定st.button(label, key)
这里给出隐蔽指定button的方法
- hidden_button_class = 'div[data-testid="stElementContainer"].st-key-hidden_trigger button[data-testid="stBaseButton-secondary"]'
- hide_button_style = f"""
- <style>
- {hidden_button_class} {{
- display: none;
- }}
- </style>
- """ # 如果已经使用f方法,想使用花括号就必须使用{{代替{
- st.markdown(hide_button_style, unsafe_allow_html=True)
复制代码 hidden_button中的st-key-hidden_trigger可以根据你的button的key举行修改
假如key = “test”, 这里就改为st-key-test,就可以实现对某个指定button的隐蔽!
固然,把.st-key-{key_name}删掉,就可以直接隐蔽所有button
触发button的html
通过在页面插入iframe,在iframe内举行JavaScript使用,实现对隐蔽button的模仿点击
- all_html = f"""
- <script>
- function handleButtonClick(event) {{
- // 查找隐藏的streamlit按钮按钮
- const hiddenButton = parent.document.querySelector(
- 'div[data-testid="stElementContainer"].st-key-hidden_trigger button[data-testid="stBaseButton-secondary"]'
- );
- if (hiddenButton) {{
- // 触发点击
- hiddenButton.click();
- }}
- }}
- // 事件委托处理点击
- document.addEventListener('click', function(event) {{
- if (event.target.matches('.detail-btn')) {{
- handleButtonClick(event);
- }}
- }});
- </script>
- <button class="detail-btn" data-title="test">点我</button> // 这里button的样式可以随便修改,根据需求
- """
- st.components.v1.html(all_html)
复制代码 但是须要留意:外部的button样式对v1.html的样式不见效,内部的button样式对v1.html同样不见效
以是所有内部样式css必须写入all_html中
代码汇总
假如想要实现
- import streamlit as st
- hide_button_style = """
- <style>
- div[data-testid="stElementContainer"].st-key-hidden_trigger button[data-testid="stBaseButton-secondary"] {
- display: none;
- }
- </style>
- """
- st.markdown(hide_button_style, unsafe_allow_html=True)
- def generate_button():
- all_html = f"""
- <script>
- function handleButtonClick(event) {{
- // 查找隐藏按钮
- const hiddenButton = parent.document.querySelector(
- 'div[data-testid="stElementContainer"].st-key-hidden_trigger button[data-testid="stBaseButton-secondary"]'
- );
- if (hiddenButton) {{
- // 触发点击
- hiddenButton.click();
- }}
- }}
- // 事件委托处理点击
- document.addEventListener('click', function(event) {{
- if (event.target.matches('.detail-btn')) {{
- handleButtonClick(event);
- }}
- }});
- </script>
- <button class="detail-btn" data-title="test">点我</button>
- """
- st.components.v1.html(all_html)
- return
- generate_button()
- if st.button("hidden_trigger", key="hidden_trigger"):
- st.success("可以修改为你想实现的功能~")
- st.button("no_hidden_trigger", key="no_hidden_trigger")
复制代码 css样式指定隐蔽的button
我们在点击自己设定的button后,触发了隐蔽的button,没有触发不隐蔽的button
携带信息的触发
为什么须要携带信息
假设有这么一个股票信息管理界面,很明显,假如使用streamlit原生的组件,将难以实现检察详情的按钮效果(嵌入在内容卡片中),而一支股票有很多信息(意味着更多的检察详情),为每一个检察详情都提供一个隐蔽button,会导致偶然义的内存占用,以是可以通过设置一个隐蔽按钮,并通过flask后端处置惩罚数据,接收并通报信息
前端JavaScript修改
- def generate_button():
- all_html = f"""
- <script>
- function handleButtonClick(event) {{
- const title = event.target.dataset.title;
- // 查找隐藏按钮
- const hiddenButton = parent.document.querySelector(
- 'div[data-testid="stElementContainer"].st-key-hidden_trigger button[data-testid="stBaseButton-secondary"]'
- );
- if (hiddenButton) {{
- // 触发点击
- hiddenButton.click();
- // 发送数据到Flask
- fetch('http://localhost:8000/api/data', {{
- method: 'POST',
- headers: {{
- 'Content-Type': 'application/json',
- }},
- body: JSON.stringify({{title, stock}}),
- }})
- .then(response => response.json())
- .then(data => console.log('Success:', data))
- .catch(error => console.error('Error:', error));
- }}
- }}
- // 事件委托处理点击
- document.addEventListener('click', function(event) {{
- if (event.target.matches('.detail-btn')) {{
- handleButtonClick(event);
- }}
- }});
- </script>
- <button class="detail-btn" data-title="test">点我</button>
- """
- st.components.v1.html(all_html)
- return
复制代码 关键在于向flask发送一个post请求,携带我们须要通报的信息(发送json串,剖析为dict)
event.target.dataset是(<button class=“detail-btn” data-title=“test”>点我</button>)中,data-title的值
以是:event.target.dataset.title = “test”
使用这个属性来通报信息
flask处置惩罚
- from flask import Flask, request, jsonify
- from flask_cors import CORS
- import requests
- app = Flask(__name__)
- CORS(app)
- @app.route('/api/data', methods=['POST'])
- def receive_data():
- data = request.get_json()
- title = process_data(data["title"])
- with open("data.txt", "w", encoding="utf-8") as f:
- f.write(title)
- return jsonify({200: "成功"})
- def process_data(data):
- # 数据处理逻辑
- return data.upper()
- if __name__ == '__main__':
- app.run(port=8000, debug=True)
复制代码 肯定须要CORS(),这意味着能不能实现跨域接收信息,只有加上这个才能实现网页发送信息,而flask后端能够接收网页发送的信息
同时在接收信息之后,能够将信息写入data.txt供其他文件调用(信息通报)
提示
flask的返回值是返回给客户端的,好比从客户端向flask发送了post信息,flask乐成接收后会向客户端发送jsonify({200: “乐成”}),代表了状态码200,携带值为乐成
总代码
- import time
- import streamlit as st
- def generate_button():
- all_html = f"""
- <script>
- function handleButtonClick(event) {{
- const title = event.target.dataset.title;
- const stock = event.target.dataset.stock;
- // 查找隐藏按钮
- const hiddenButton = parent.document.querySelector(
- 'div[data-testid="stElementContainer"].st-key-hidden_trigger button[data-testid="stBaseButton-secondary"]'
- );
- if (hiddenButton) {{
- // 触发点击
- hiddenButton.click();
- // 发送数据到Flask
- fetch('http://localhost:8000/api/data', {{
- method: 'POST',
- headers: {{
- 'Content-Type': 'application/json',
- }},
- body: JSON.stringify({{title, stock}}),
- }})
- .then(response => response.json())
- .then(data => console.log('Success:', data))
- .catch(error => console.error('Error:', error));
- }}
- }}
- // 事件委托处理点击
- document.addEventListener('click', function(event) {{
- if (event.target.matches('.detail-btn')) {{
- handleButtonClick(event);
- }}
- }});
- </script>
- <button class="detail-btn" data-title="test">点我</button>
- """
- st.components.v1.html(all_html)
- return
- generate_button()
- if st.button("hidden_trigger", key="hidden_trigger"):
- time.sleep(0.05) # 让flask能够写入信息,设置一小段时间延时
- with open("data.txt", "r", encoding="utf-8") as fr:
- content = fr.read() # 读取携带的信息
- st.success("接收到信息:" + content)
复制代码 |