문제 설명
sqlalchemy 쿼리 필터에 변수를 추가하고 문자열 쿼리로 변환하려면 어떻게 합니까? (How do I add a variable to a sqlalchemy query filter and convert it to a string query?)
Flask 앱의 pandas 데이터 프레임에 넣으려고 하는 요약된 쿼리가 있습니다. sqlalchemy 쿼리를 pandas가 데이터 프레임으로 읽을 수 있는 문자열 쿼리로 변환하는 방법을 알아냈습니다. 변수에 문자열로 변환된 날짜 값이 있습니다.
제가 겪고 있는 문제는 필터에서 변수를 사용하려고 하는데 이를 쿼리 문자열로 변환할 때 변수가 그대로 남아 있다는 것입니다. 값을 제공하지 않은 것처럼 변수를 출력합니다. 그 결과 sqlalchemy.exc.programmingerror가 발생합니다.
여기에 내 날짜 변수가 있습니다.
this_week = datetime.strftime(get_friday(datetime.now().date()),'%m/%d/%Y')
get_friday() 함수는 주어진 날짜에서 요일의 금요일을 가져옵니다. 이 경우에는 현재 주만 보고 있습니다.
여기에 내 쿼리가 변수로 설정되어 있습니다.
grouped_entries = Entry.query \
.with_entities(Entry.entry_date.label('entry_date'), \
Entry.client.label('client'),Entry.day.label('day'), \
func.sum(Entry.total_time).label('time_sum')) \
.filter(Entry.week_end == this_week) \
.group_by(Entry.client,Entry.entry_date,Entry.day) \
.order_by(Entry.entry_date.asc())
여기' s pandas 코드는 쿼리를 문자열 쿼리로 변환하여 데이터 프레임으로 읽어들입니다.
pd.read_sql(str(grouped_entries.statement.compile(dialect=sqlite.dialect())), db.engine)
실행하려고 할 때 발생하는 오류는 다음과 같습니다.
6sqlalchemy.exc.ProgrammingError: (sqlite3.ProgrammingError) Incorrect number of bindings supplied. The current statement uses 1, and there are 0 supplied.[SQL: 'SELECT entry.entry_date AS entry_date, entry.client AS client, entry.day AS day, sum(entry.total_time) AS time_sum \nFROM entry \nWHERE entry.week_end = ? GROUP BY entry.client, entry.entry_date, entry.day ORDER BY entry.entry_date ASC']
쿼리가 작동한다는 것을 알고 있습니다. 자체적으로는 sqlalchemy 쿼리이지만 문자열 쿼리로 변환되면 ? filter/where 절의 변수 값 대신. SQL 인젝션을 위한 일종의 보안 조치라고 생각하지만 문자열 쿼리에서 변수 값을 가져오는 방법을 알 수 없는 것 같습니다.
그것은 추가? filter/where 절의 변수 값 대신. SQL 인젝션을 위한 일종의 보안 조치라고 생각하지만 문자열 쿼리에서 변수 값을 가져오는 방법을 알 수 없는 것 같습니다. 그것은 추가? filter/where 절의 변수 값 대신. SQL 인젝션을 위한 일종의 보안 조치라고 생각하지만 문자열 쿼리에서 변수 값을 가져오는 방법을 알 수 없는 것 같습니다.참조 솔루션
방법 1:
Well, after several more hours of digging (and some rest), I managed to figure it out.
The easiest way I found to insert the variable into the statement was to utilize the read_sql function in pandas and set the variable as a parameter.
data = pd.read_sql(str(grouped_entries), db.engine, params=[this_week])
This will insert the variable(s) into the string query.
After solving the initial issue, I then ran into an issue with the filter. Turns out, when you try to cast a datetime as a date cast(Entry.week_end,Date)
in sqlite (which is what I needed to do to make the filter work properly), it only returns the year and will throw a ValueError saying it can't parse the date string. To get around this, I found that you can apply a date function to the column in sqlalchemy, similar to this issue.
Here was my final code:
this_week = datetime.strftime(get_friday(datetime.now()),'%Y‑%m‑%d')
grouped_entries = Entry.query \
.with_entities(Entry.client.label('client'), \
Entry.day.label('day'), \
func.sum(Entry.total_time).label('time')) \
.filter(func.DATE(Entry.week_end) == this_week) \
.group_by(Entry.client,Entry.day) \
.order_by(Entry.day.asc())
data = pd.read_sql(str(grouped_entries), db.engine, params=[this_week])