Не могу сделать sql запрос с внутренней переменной python

def data_print(self):
        return{
            "exams_id1": self.ui.cmbBoxFirstExam.currentData().id,
            "exam_id2": self.ui.cmbBoxSecondExam.currentData().id,
            "exam_id3": self.ui.cmbBoxThirdExam.currentData().id,
            "degrees_id": self.ui.cmbBoxQualif.currentData().id,
            "educationform_id":self.ui.cmbBoxFormEduc.currentData().id 
        }
           
        

        
    def onBtnAccClick(self):
        data = MainWindow.data_print(self)
        with Session(self.engine) as s:
            query = """
            SELECT direction, profile,budget,commerce,min
            FROM directions
            WHERE d_id = %(degress_id)s
            """
        rows = s.execute(text(query))
        for r in rows:
            item = QListWidgetItem()
            item.setData(QtCore.Qt.ItemDataRole.UserRole, r)
            self.ui.listWidget.addItem(item)

это кусок кода. Вся суть в том, что мне нужно сравнить d_id(переменная хранится в базе данных directions) с переменной которую я извлекаю из combobox. Но при выполнении кода в консоль выходит следующая ошибка:

sqlalchemy.exc.StatementError: (builtins.KeyError) 'degress_id'
[SQL:
SELECT direction, profile,budget,commerce,min
FROM directions
WHERE d_id = ?
]
[parameters: [{}]]

Ответы (1 шт):

Автор решения: sxmrxk

Первое: Вы создали соединение с базой данных с помощью контекстного менеджера with Session(self.session) as s:, но при этом обращаетесь к соединению s уже вне блока with

Правильный вариант выглядит так:

query = """
        SELECT direction, profile,budget,commerce,min
        FROM directions
        WHERE d_id = %(degress_id)s
        """
with Session(self.engine) as s:
    rows = s.execute(text(query))  # Обращение к соединению происходит внутри контекстного менеджера

По поводу вставки переменных в запрос, приведу маленький пример:

query = text("""
        SELECT direction, profile,budget,commerce,min
        FROM directions
        WHERE d_id= :degress_id
        """)
with Session(self.engine) as s:
    rows = s.execute(query, {"degress_id": 3})

В этом примере: для безопасной вставки переменных я использую не встроенный в python метод format. Это не безопасно! Можно будет легко провести атаку XSS потому что не происходит экранирования.

Вы используете sqlalchemy, а он предоставляет собственный функционал подставления переменных в сырой запрос, а именно вы указываете переменную с помощью имени и символа : перед ней, и уже перед самим выполнением передаете dict пар "переменная": значение. И сам sqlalchemy за Вас проделает оставшуюся работу.

Готов ответить на вопросы, если они возникнут.

→ Ссылка