Запись html в Sqllite3 из под PyQt5
При попытке записать в бд html из QTextBrowser.toHtml() происходит ошибка sqlite3.OperationalError.
В интернете нарыл только метод с использованием QString, но в PyQt5 его нет. Ссылка.
Минимально воспроизводимый пример:
import sqlite3
from PyQt5 import QtWidgets
import sys
from PyQt5.QtGui import QTextCharFormat, QFont
conn = sqlite3.connect("testdb.db")
cursor = conn.cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS texts
(content TEXT)
""")
conn.commit()
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
box = QtWidgets.QVBoxLayout()
self.textbrowser = QtWidgets.QTextBrowser()
self.textbrowser.setFixedSize(300, 300)
self.textbrowser.setReadOnly(False)
self.make_bold_button = QtWidgets.QPushButton('set bold')
self.make_bold_button.clicked.connect(self.set_bold_foo)
self.save_button = QtWidgets.QPushButton('save')
self.save_button.clicked.connect(self.save_text_foo)
box.addWidget(self.textbrowser)
box.addWidget(self.make_bold_button)
box.addWidget(self.save_button)
self.setLayout(box)
def set_bold_foo(self):
cursor = self.textbrowser.textCursor()
text_char_format = QTextCharFormat()
text_char_format.setFontWeight(QFont.Bold)
cursor.mergeCharFormat(text_char_format)
def save_text_foo(self):
cursor.execute(f"""INSERT INTO texts
VALUES ('{self.textbrowser.toHtml()}')"""
)
conn.commit()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.show()
app.exec_()
Ответы (2 шт):
Автор решения: Sergey Tatarincev
→ Ссылка
А вы не думали что будет когда в html встретится символ закрывающей кавычки?
У вас прямо классический пример для демонстрации атак с использованием sql инъекции.
Используйте QSqlQuery с передачей параметров через bindValue. В этом случае sql драйвер сам позаботится https://doc.qt.io/qtforpython/overviews/sql-sqlstatements.html
В вашем случае соответственно
from PyQt5.QtSql import QSqlDatabase, QSqlQuery
...
db = QSqlDatabase.addDatabase('QSQLITE')
db.setDatabaseName('testdb.db')
db.open()
...
query = QSqlQuery()
query.prepare("INSERT INTO texts VALUES (:content)")
query.bindValue(":content", self.textbrowser.toHtml())
query.exec()
Автор решения: gil9red
→ Ссылка
Дополнение к соседнему ответу, для sqlite3 из python binding-параметры передавайте через ?:
cursor.execute("INSERT INTO texts VALUES (?)", [self.textbrowser.toHtml()])
conn.commit()