Python 在react app调用的flask api中使用Sqlite和sqlalchemy的线程和递归问题
我正在开发一个web应用程序,使用Flask进行API和数据访问,并与MaterialUI进行交互。一般来说,我已经成功地在UI中使用了React组件,使用FlaskAPI从Sqlite获取数据。Flask应用程序设置为将未知请求代理到Flask API 我无法创建代码沙盒,因为我无法为Flask或SQLAlchemy添加依赖项 应用程序几乎完成了;我能够使用Flask和API从几个不同的表中获取数据。然后,我添加了一个数据过滤器选择组件和一个对API的调用,以从设置表中获取最后一个过滤器选择,该简单调用以两种方式中断:Python 在react app调用的flask api中使用Sqlite和sqlalchemy的线程和递归问题,python,reactjs,sqlite,flask,sqlalchemy,Python,Reactjs,Sqlite,Flask,Sqlalchemy,我正在开发一个web应用程序,使用Flask进行API和数据访问,并与MaterialUI进行交互。一般来说,我已经成功地在UI中使用了React组件,使用FlaskAPI从Sqlite获取数据。Flask应用程序设置为将未知请求代理到Flask API 我无法创建代码沙盒,因为我无法为Flask或SQLAlchemy添加依赖项 应用程序几乎完成了;我能够使用Flask和API从几个不同的表中获取数据。然后,我添加了一个数据过滤器选择组件和一个对API的调用,以从设置表中获取最后一个过滤器选择,
"proxy": "http://localhost:5000"
app.js
import React, { useState, useEffect } from 'react';
import Users from './Components/Users/Users';
export default function UserManager() {
const [Filter, setFilter] = useState('all');
useEffect(() => {
fetch('/api/getFilter').then(res => res.text()).then(data => {
console.log(new Date() + "Filter useEffect data = " + data);
setFilter(data);
console.log(new Date() + "Filter useEffect set to: " + Filter)
});
}
)
const filterChanged = (event, selectedFilter) => {
alert('app.js filter changed! Filter=' + Filter + ' and selectedFilter=' + selectedFilter);
setFilter(selectedFilter);
};
return (
<div>
<Users
filterChanged={filterChanged.bind(this)}
filter={ Filter }
/>
</div>
)
}
我确保没有任何其他实例接触数据库文件;关闭所有VSCode窗口、所有资源管理器窗口,甚至重新启动,然后重新启动React和Flask应用程序。非常奇怪的是,这段代码只会导致问题,而我的其他数据库调用代码都不会
我知道在没有codesandbox的情况下评估这是一个复杂的场景,但我肯定会非常感谢任何帮助。我知道欣赏不如啤酒好,但这是我现在所得到的一切。模块范围内的session=DBSession()是线程问题的根源,因为session实例不是线程安全的。在适当的范围内创建会话,或者如果使用线程作为例如请求范围,则使用。简要回顾:引擎是连接池的便捷外壳,它是线程安全的。另一方面,连接不是,所以不要在线程之间共享这些连接。会话也不是线程安全的,因此没有共享。所以在模块范围和会话工厂中创建引擎,而不是会话。就是这样。它解决了递归问题和线程问题。非常感谢。
import React, { useState, useEffect } from 'react';
import Users from './Components/Users/Users';
export default function UserManager() {
const [Filter, setFilter] = useState('all');
useEffect(() => {
fetch('/api/getFilter').then(res => res.text()).then(data => {
console.log(new Date() + "Filter useEffect data = " + data);
setFilter(data);
console.log(new Date() + "Filter useEffect set to: " + Filter)
});
}
)
const filterChanged = (event, selectedFilter) => {
alert('app.js filter changed! Filter=' + Filter + ' and selectedFilter=' + selectedFilter);
setFilter(selectedFilter);
};
return (
<div>
<Users
filterChanged={filterChanged.bind(this)}
filter={ Filter }
/>
</div>
)
}
import React, { Component } from 'react'
import FilterSelector from './FilterSelector'
export class Users extends Component {
render() {
const filter = this.props.filter;
console.log(this.props.filter)
console.log("Users render - " + this.props.filter);
return (<FilterSelector filter={filter} filterChanged={this.props.filterChanged.bind(this)}/>)
}
}
export default Users
import React from 'react';
import Radio from '@material-ui/core/Radio';
import RadioGroup from '@material-ui/core/RadioGroup';
import FormControlLabel from '@material-ui/core/FormControlLabel';
import FormControl from '@material-ui/core/FormControl';
import FormLabel from '@material-ui/core/FormLabel';
export default function FilterSelector(props) {
return (
<FormControl component="fieldset">
<FormLabel component="legend">Filter</FormLabel>
<RadioGroup aria-label="filters" name="filter1" value={ props.filter } onChange={ props.filterChanged }>
<FormControlLabel value="favorites" control={<Radio />} label="Favorites" />
<FormControlLabel value="included" control={<Radio />} label="Included" />
<FormControlLabel value="all" control={<Radio />} label="All" />
</RadioGroup>
</FormControl>
);
}
import time
from flask import Flask
import userdata
import json
import datetime
import subprocess
app = Flask(__name__)
@app.route('/api/getFilter')
#sample: http://localhost:5000/api/getFilter
def getFilter():
print ("In getFilter")
#return "favorites"
filter = userdata.getSetting('filter')
print ("{0}In api getFilter(). Filterdata from db is: {1}".format(datetime.datetime.now(), filter))
if filter is None:
#userdata.updateSetting('channelfilter', 'all')
filter = 'favorites'
print ("In getfilter2")
return filter
"""
@app.route('/api/saveFilter/<filterValue>')
#sample: http://localhost:5000/api/saveFilter/favorites
def saveFilter(filterValue):
userdata.updateSetting('filter', filterValue)
return filterValue
"""
#Below route is for development testing only, remove for production.
@app.route('/api/getUsers')
#sample: http://localhost:5000/api/getUsers
def getUsersFromDB():
return json.loads(userdata.GetUsers())
@app.route('/api/getUsers/<filter>')
#sample: http://localhost:5000/api/getUsers/favorites
def getUsersFromDBFiltered(filter):
print("In getUsersFiltered. filter = {0}".format(filter))
return json.loads(userdata.GetUsers())
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
from sqlalchemy import Column, ForeignKeyConstraint, UniqueConstraint
from sqlalchemy import PrimaryKeyConstraint, Integer, String, Boolean, DateTime, func
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
import json
import os
Base = declarative_base()
Engine = create_engine('sqlite:///data/users.db')
Base.metadata.bind = Engine
DBSession = sessionmaker(bind=Engine)
session = DBSession()
class Settings(Base):
__tablename__ = "settings"
settingname = Column(String(80), primary_key=True)
settingvalue = Column(String(80), nullable=False)
def ResultSetQueryToJson(resultSet):
print ('Not Yet Implemented.')
return resultSet
def ResultSetDeclarativeToJson(resultSet):
jsontext = "{{\n\t\"{0}\": [".format(resultSet[0].__table__.name)
for datarow in resultSet:
rowsdata = ""
columncount = len(datarow.__table__.columns)
if jsontext.endswith("}"):
jsontext += ","
jsontext += "{\n"
for c in datarow.__table__.columns:
columncount -= 1
rowsdata = rowsdata + "\n\t\t\"{0}\": \"{1}\"".format(c.key, getattr(datarow, c.key))
if columncount > 0:
rowsdata += ","
jsontext += rowsdata
jsontext += "\n\t}"
return jsontext + "]\n}"
def getSettings():
print("Start getSettings())")
return session.query(Settings).all()
def getSetting(sname):
print("Starting userdata.getSetting() for {0}.".format(sname))
result = session.query(Settings).filter(Settings.settingname == sname).one_or_none()
print ("in getSetting. Query Result = {0}".format(result))
if result is not None:
svalue = result.settingvalue
print('Got setting {0}: {1}'.format(sname, svalue))
return svalue
return None
"""
def updateSetting(sname, svalue):
setting = Settings()
setting.settingname = sname
setting.settingvalue = svalue
session.merge(setting)
session.commit()
"""
class Apps(Base):
__tablename__ = 'apps'
appid = Column(String(24), primary_key=True)
name = Column(String(250), nullable=False)
vendor = Column(String(80), nullable=True)
version = Column(String(50), nullable=False)
isDeleted = Column(Boolean, nullable=False)
class Users(Base):
__tablename__ = 'users'
userid = Column(String(80), primary_key=True)
lastname = Column(String(40), nullable=False)
firstname = Column(String(40), nullable=False)
emailaddress = Column(String(80), nullable=False)
def ReflectTableColumns(DbEngine, meta, targetTable):
tableschema = Table(targetTable, meta, autoload=True, autoload_with=DbEngine)
cols = dict()
for c in tableschema.columns:
print("{0}\t|\t{1}".format(c.name, c.type))
cols[c.name] = c.type
return cols
def GetUsers():
DBSession = sessionmaker(bind=Engine)
session = DBSession()
results = session.query(Users).all()
ShowTableData(results, 'users')
return ResultSetDeclarativeToJson(results)