Является ли SQLAlchemy по-прежнему рекомендуемым, если он используется только для сырого SQL-запроса?

Используя Flask, мне любопытно узнать, является ли SQLAlchemy лучшим методом для запроса моей базы данных с необработанным SQL (прямая SELECT x FROM table WHERE ... ) вместо использования ORM или если есть более простая, но мощная альтернатива ?

Спасибо за ваш ответ.

2 Solutions collect form web for “Является ли SQLAlchemy по-прежнему рекомендуемым, если он используется только для сырого SQL-запроса?”

Я использую SQLAlchemy для прямых запросов все время.

Первичное преимущество: он дает вам лучшую защиту от атак SQL-инъекций. SQLAlchemy делает правильную вещь независимо от параметров, которые вы бросаете на нее.

Я нахожу, что это творит чудеса для настройки сгенерированного SQL на основе условий. Отображение набора результатов с несколькими фильтрами над ним? Просто создайте свой запрос в наборе конструкций if / elif / else, и вы знаете, что ваш SQL будет по-прежнему золотым.

Вот выдержка из какого-то живого кода (более старая версия SA, поэтому синтаксис может немного отличаться):

 # Pull start and end dates from form # ... # Build a constraint if `start` and / or `end` have been set. created = None if start and end: created = sa.sql.between(msg.c.create_time_stamp, start.replace(hour=0, minute=0, second=0), end.replace(hour=23, minute=59, second=59)) elif start: created = (msg.c.create_time_stamp >= start.replace(hour=0, minute=0, second=0)) elif end: created = (msg.c.create_time_stamp <= end.replace(hour=23, minute=59, second=59)) # More complex `from_` object built here, elided for example # [...] # Final query build query = sa.select([unit.c.eli_uid], from_obj=[from_]) query = query.column(count(msg.c.id).label('sent')) query = query.where(current_store) if created: query = query.where(created) 

Код, из которого это происходит, намного сложнее, но я хотел бы выделить здесь код диапазона дат. Если бы мне пришлось строить SQL с использованием форматирования строк, я бы, вероятно, представил где-то SQL-инъекцию, так как гораздо легче забыть цитировать значения.

После того, как я работал над небольшим проектом, я решил попробовать использовать MySQLDB без SQL Alchemy.

Он отлично работает, и его довольно просто использовать, вот пример (я создал небольшой класс, который обрабатывает всю работу в базе данных)

 import MySQLdb from MySQLdb.cursors import DictCursor class DatabaseBridge(): def __init__(self, *args, **kwargs): kwargs['cursorclass'] = DictCursor self.cnx = MySQLdb.connect (**kwargs) self.cnx.autocommit(True) self.cursor = self.cnx.cursor() def query_all(self, query, *args): self.cursor.execute(query, *args) return self.cursor.fetchall() def find_unique(self, query, *args): rows = self.query_all(query, *args); if len(rows) == 1: return rows[0] return None def execute(self, query, params): self.cursor.execute(query, params) return self.cursor.rowcount def get_last_id(self): return self.cnx.insert_id() def close(self): self.cursor.close() self.cnx.close() database = DatabaseBridge(**{ 'user': 'user', 'passwd': 'password', 'db': 'my_db' }) rows = database.query_all("SELECT id, name, email FROM users WHERE is_active = %s AND project = %s", (1, "My First Project")) 

(Это глупый пример).

Это работает как шарм, но вы должны учитывать это:

  • Многопоточность не поддерживается! Это нормально, если вы не работаете с multiprocessing с Python.
  • У вас не будет всех преимуществ SQLAlchemy (оболочка базы данных для класса (модели), генерация запроса (select, where, order_by и т. Д.)). Это ключевой момент, как вы хотите работать с вашей базой данных.

Но, с другой стороны, и, как и SQLAlchemy, существуют защиты от SQL-атак:

Основной запрос будет следующим:

 cursor.execute("SELECT * FROM users WHERE data = %s" % "Some value") # THIS IS DANGEROUS 

Но вы должны сделать:

 cursor.execute("SELECT * FROM users WHERE data = %s", "Some value") # This is secure! 

Видела разницу? Прочитай заново 😉

Разница в том, что я заменил % , by:: Мы передаем аргументы как … аргументы execute, и они экранированы. При использовании % аргументы не экранируются, что позволяет атаковать SQL Injection!

Последнее слово здесь заключается в том, что это зависит от вашего использования и того, что вы планируете делать с вашим проектом. Для меня SQLAlchemy был переполнен (это основной скрипт оболочки!), Поэтому MysqlDB был идеальным.

  • Каковы некоторые стратегии для поддержания общей схемы базы данных с командой разработчиков и без администратора баз данных?
  • используя колбу-sqlalchemy без подкласса декларативной базы
  • Наследование Postgres с SQLAlchemy
  • Запрос PostgreSQL ILIKE с SQLAlchemy
  • Есть ли побочные эффекты от вызова SQLAlchemy flush () в коде?
  • Принуждение sqlalchemy ORM get () вне карты идентификации
  • SQLAlchemy, как фильтровать по детям от многих до многих
  • Получение SQLAlchemy для выпуска CREATE SCHEMA на create_all
  • SQLAlchemy с count, group_by и order_by с использованием ORM
  • SQLAlchemy - модификация Mixin vs MetaClass
  • SQLAlchemy по умолчанию DateTime
  •  
    Interesting Posts for Van-Lav

    Почему вы можете опустить окружающие круглые скобки для генераторов в Python при передаче его в функцию?

    Python3 целочисленное разделение

    Python mulitprocessing queue не удерживает всех занятых

    Сохранение и загрузка объектов и использование рассола

    Ошибка выполнения griddata – Python / SciPy (Интерполяция)

    Python list.index выдает исключение, если индекс не найден

    Используйте fnmatch.filter для фильтрации файлов более чем одним возможным расширением файла

    Итерации над строкой 2 (или n) символов за раз в Python

    как показать правильное слово в моем коде, мой код: os.urandom (64)

    pysvn получить последний номер версии для конкретного каталога (не голова)

    Список полезных команд python для Vim?

    Добавление базового класса в существующий объект в python

    Выполнение readonly для существующего поля, но позволяющее добавлять при создании новой встроенной строки в django admin

    Класс не имеет указанной таблицы или имени табуляции и не наследует от существующего класса с табличным отображением

    subprocess.call с использованием строки vs с использованием списка

    Python - лучший язык программирования в мире.