Привет, сообщество, я новичок здесь и хорошо, относительно новичок в разработке! Я стремлюсь стать разработчиком полного стека однажды И я с нетерпением жду всего вдохновения, поддержки и руководства на этом пути.
Сегодня на работе я наткнулся на действительно интересное требование, которое, честно говоря, сначала было сложным, но для меня было скорее открытым глазами о моем самом Статический Подход к запросам SQL. В любое время, когда я должен был запросить базу данных, вот как я бы это сделал:
SELECT * FROM details WHERE firstName='John' AND lastName='Doe';
Я хочу означать, что я бы использовал статический запрос, потому что я всегда буду знать о параметрах (имена столбцов, Значения столбца и разные положения тоже! ) Но сегодня я должен был искать через таблицу, основанную исключительно на вводе пользователя, то есть поиск по конкретной таблице, не зная ничего о записях в этой таблице или поисково -запросе. Сначала сами понятие использования пользовательских входов в качестве параметров поиска сбило меня за собой. Я не знал о возможности работы с динамическими запросами SQL (эй, в моей защите, я просто разработчик бэкэнд-любителя), но, поскольку это было не подлежащим обсуждению, я решил сделать это.
Для этого конкретного проекта я работаю с:
- Django (Python Web Framework – Backend)
- PostgreSQL (RDBMS – База данных)
- React (библиотека JavaScript – Frontend)
Проект, над которым я работаю, довольно сложный, поэтому я постараюсь сохранить процесс поток настолько простым, насколько я могу, и сосредоточиться на фактической логике, чтобы решить проблему под рукой. Пользовательские входы фиксируются в видах вида с различными возможными именами поля для поиска вместе с окном поиска для каждого поля. Затем они отправляются на бэкэнд в качестве объекта запроса, когда пользователь достигает кнопки поиска следующим образом:
const res= await axios.get("http://127.0.0.1:8000/application/search/?query=" + JSON.stringify(queryObj));
Если вам любопытно узнать, как выглядит объект запроса, вот возможный пример поискового запроса, сгенерированный из входов- Имя: Иоанн Фамилия: DOE
let queryObj={firstName:"John", lastName:"Doe",};
В бэкэнд ( внутри приложения Django \ views.py ) QueryOBJ обрабатывается следующим образом:
from django.http import JsonResponse import psycopg2 import ast def search_table(request): search_query=request.GET.get('query') queryparam=ast.literal_eval(search_query)
На случай, если вам интересно, почему я использовал встроенную функцию ast.literal_eval (search_query) Здесь это потому, что search_query-это строковый объект, а не словарь Python из пар клавиш. Эта функция помогает преобразовать ключи объекта строки в search_query в реальные ключи словаря Python.
Двигаясь дальше, установив соединение с базой данных PostgreSQL с использованием PSYCOPG2:
from django.http import JsonResponse import psycopg2 import ast def search_table(request): search_query=request.GET.get('query') queryparam=ast.literal_eval(search_query) con=psycopg2.connect(database="database_name",user="user_name",password="pwd",host="0.0.0.0",port="12345") cursor=con.cursor() and_clause=[] for k,v in queryparam.items(): and_clause.append("%s = '%s'" % (k,v)) and_clause_str=' AND '.join(and_clause) sql_query='SELECT * FROM table_name WHERE ' + and_clause_str print(sql_query) cursor.execute(sql_query) result=cursor.fetchall() return JsonResponse(result)
Итак, код здесь довольно пояснительный, но просто для того, чтобы быстро провести вас через логику –
Я объявил список строк с именем and_clause который хранит Query_param Ключи словаря, которые будут использоваться в качестве названий столбцов и Query_param Словарь значения как фактическое значение, которое будет искать, разделенное = чтобы структурировать его как запрос SQL.
Если в Query_param Словарь, т. Е. Когда пользователь хочет искать на основе нескольких параметров или столбцов, я соединяю эти строки, используя «и» и храню ее в новой строковой переменной с именем and_clause_str Анкет
Вот как будет выглядеть окончательное заявление SQL:
Функция прямо сейчас не генерирует полностью динамические запросы. Если бы вы заметили, я все еще указываю имя таблицы, а также имею обязательное место. У меня это специально по двум причинам:
- Проект, над которым я работаю, стремится выполнить поисковые операции в базах данных, поэтому пункт «где» должен присутствовать, поскольку он действует как параметр поиска.
- Имя таблицы в моем проекте будет очень стандартным и общим названием таблицы, которое будет поддерживаться как одно и то же имя в разных базах данных, поэтому у меня есть запрос с жестким именем таблицы.
Насколько я понимаю в инъекциях SQL, все еще очень плохое, и я согласен, что этот код может быть подвержен инъекциям SQL, я планирую оптимизировать его дальше, чтобы предотвратить любую возможность быть подверженной таким атакам.
Если вам интересно, что, если пользователь предоставил ввод, не является фактическим именем столбца в таблице, то я хотел бы сообщить вам, что поля столбца формы генерируются из бэкэнда и отправляются на бренд для включения поиска. Таким образом, в некотором смысле, только существующие имена столбцов заполнены.
Я надеюсь, что я отдал должное своему самым первым сообщениям в блоге! Я действительно надеюсь, что это окажется полезным или чем -то новым для всех, кто читает это. Я открыт для предложений по дальнейшему улучшению кода и хотел бы услышать ваши мысли или вопросы по динамическим запросам SQL.
Спасибо за чтение!
Оригинал: “https://dev.to/bhavanaeh/python-function-to-work-with-dynamic-sql-queries-25gk”