classic-sql-tools


Nameclassic-sql-tools JSON
Version 0.4.3 PyPI version JSON
download
home_pageNone
SummaryNone
upload_time2025-08-25 06:22:17
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseNone
keywords jinja2 sql python template
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Генерация SQL-запросов используя Jinja-шаблон #

Идея библиотеки заключается в попытке работать с SQL-запросами как с шаблонами Jinja.
Вдохновлено [embrace](https://pypi.org/project/embrace/) и 
[jinjasql](https://pypi.org/project/jinjasql/), оттуда же бралась часть кода.

## Установка:
```shell
pip install classic-sql-tools
```

## Quickstart:

```python
from classic.sql_tools import Module
import psycopg

# Модуль - точка входа во все функции библиотеки.
# При инстанцировании запоминает указанный путь,
# дальнейшие обращения будут
queries = Module('path/to/sql/templates/dir')

# Создадим подключение к БД
conn = psycopg.connect('posgresql:///some_db')

# Применим схему:
queries.tasks.ddl(conn)

# Сохранение данных
queries.tasks.save_task(conn, [
    {'title': 'Some Task', 'body': 'Do something'},
    {'title': 'Another Task', 'body': 'Do anything'},
])

# Получение данных
task = queries.tasks.get_by_id(conn, id=1).one()
# (1, 'Some Task', 'Do something')
```

В директории sql рядом с .py файлом надо разместить 3 файла
(можно найти в директории test/example):

`sql/tasks/ddl.sql`:
```sql
CREATE TABLE tasks (
    id serial PRIMARY KEY,
    title text,
    body text
);
```

`sql/tasks/get_by_id.sql`:
```sql
SELECT id, title, body FROM tasks WHERE id = {{ id }};
```

`sql/tasks/save_task.sql`:
```sql
INSERT INTO tasks (title, body) VALUES ({{ title }}, {{ body }});
```

## Возможности


```python
# Класс Module - точка входа во все функции библиотеки.
from classic.sql_tools import Module


# При инстанцировании ему обязательно нужно 
# передать путь до директории с шаблонами.
queries = Module('path/to/sql')

# Затем можно получить шаблон запроса, лежащего,
# например, в `./sql/some_file.sql`:
query = queries.some_file

# Module поддерживает обращение имен директорий в Python.
# То есть объект-запрос можно получить, 
# обратившись к атрибуту Module с названием директории.
# Например, файл, лежащий в `./sql/some_dir/some_file.sql`:
query = queries.some_dir.some_file

#Вложенность может быть любой:
query = queries.some_dir.another_dir.etc.some_file

#Также можно получить объект запроса, 
#напрямую обратившись по его относительному пути:
query = queries.from_file('sql/some_dir/some_file.sql')

# И можно получить объект запроса из строкового литерала:
query = queries.from_str('SELECT id FROM tasks')

# После получения объект запроса можно выполнить 
# с использованием соединения или курсора:
import psycopg

conn = psycopg.connect('posgresql:///some_db')

result = queries.tasks.get_by_id(conn)
# Либо
cursor = conn.cursor()
result = queries.tasks.get_by_id(cursor)

# Также можно выполнить запрос через метод .execute:
query = queries.tasks.get_by_id
query.execute(conn)

# Объект результата нужен для удобного представления 
# результатов запроса. У него есть методы для представления набора строк, 
# единичных строк и единичных значений - 
# .many(), .one() и .scalar() соответственно

# Вернет список кортежей:
result = queries.from_str('SELECT * FROM tasks').execute(conn)
print(result.many())

# Вернет до 100 строк. При повторном вызове вернет следующие 100:
result = queries.from_str('SELECT * FROM tasks').execute(conn)
print(result.many(100))
print(result.many(100))

# Вернет один кортеж или None:
result = queries.from_str(
    'SELECT * FROM tasks WHERE id = 1'
).execute(conn)
print(result.one())

# Вернет один кортеж или исключение ValueError, 
# если в БД ничего не нашлось:
result = queries.from_str('SELECT * FROM tasks WHERE id = 1').execute(conn)
print(result.one(raising=True))

# Вернет один кортеж или None:
result = queries.from_str(
    'SELECT id FROM tasks WHERE id = 1'
).execute(conn).scalar()
print(result.scalar())

# Аналогично .one() вернет один кортеж или 
# исключение ValueError, если в БД ничего не нашлось:
result = queries.from_str('SELECT id FROM tasks WHERE id = 1').execute(conn)
print(result.scalar(raising=True))
```

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "classic-sql-tools",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "Jinja2, SQL, Python, Template",
    "author": null,
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/cd/0f/a0d9ace7b56ad201c6ac71052e0f6da5280ceffc88abf8e680d289edc33b/classic_sql_tools-0.4.3.tar.gz",
    "platform": null,
    "description": "# \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Jinja-\u0448\u0430\u0431\u043b\u043e\u043d #\n\n\u0418\u0434\u0435\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043a\u0430\u043a \u0441 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438 Jinja.\n\u0412\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d\u043e [embrace](https://pypi.org/project/embrace/) \u0438 \n[jinjasql](https://pypi.org/project/jinjasql/), \u043e\u0442\u0442\u0443\u0434\u0430 \u0436\u0435 \u0431\u0440\u0430\u043b\u0430\u0441\u044c \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u0434\u0430.\n\n## \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430:\n```shell\npip install classic-sql-tools\n```\n\n## Quickstart:\n\n```python\nfrom classic.sql_tools import Module\nimport psycopg\n\n# \u041c\u043e\u0434\u0443\u043b\u044c - \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0432\u043e \u0432\u0441\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.\n# \u041f\u0440\u0438 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0439 \u043f\u0443\u0442\u044c,\n# \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0438\u0435 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442\nqueries = Module('path/to/sql/templates/dir')\n\n# \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0411\u0414\nconn = psycopg.connect('posgresql:///some_db')\n\n# \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0441\u0445\u0435\u043c\u0443:\nqueries.tasks.ddl(conn)\n\n# \u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\nqueries.tasks.save_task(conn, [\n    {'title': 'Some Task', 'body': 'Do something'},\n    {'title': 'Another Task', 'body': 'Do anything'},\n])\n\n# \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\ntask = queries.tasks.get_by_id(conn, id=1).one()\n# (1, 'Some Task', 'Do something')\n```\n\n\u0412 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 sql \u0440\u044f\u0434\u043e\u043c \u0441 .py \u0444\u0430\u0439\u043b\u043e\u043c \u043d\u0430\u0434\u043e \u0440\u0430\u0437\u043c\u0435\u0441\u0442\u0438\u0442\u044c 3 \u0444\u0430\u0439\u043b\u0430\n(\u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 test/example):\n\n`sql/tasks/ddl.sql`:\n```sql\nCREATE TABLE tasks (\n    id serial PRIMARY KEY,\n    title text,\n    body text\n);\n```\n\n`sql/tasks/get_by_id.sql`:\n```sql\nSELECT id, title, body FROM tasks WHERE id = {{ id }};\n```\n\n`sql/tasks/save_task.sql`:\n```sql\nINSERT INTO tasks (title, body) VALUES ({{ title }}, {{ body }});\n```\n\n## \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438\n\n\n```python\n# \u041a\u043b\u0430\u0441\u0441 Module - \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u0432\u043e \u0432\u0441\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438.\nfrom classic.sql_tools import Module\n\n\n# \u041f\u0440\u0438 \u0438\u043d\u0441\u0442\u0430\u043d\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0435\u043c\u0443 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u043d\u043e \n# \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u043f\u0443\u0442\u044c \u0434\u043e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u0441 \u0448\u0430\u0431\u043b\u043e\u043d\u0430\u043c\u0438.\nqueries = Module('path/to/sql')\n\n# \u0417\u0430\u0442\u0435\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0448\u0430\u0431\u043b\u043e\u043d \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043b\u0435\u0436\u0430\u0449\u0435\u0433\u043e,\n# \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 `./sql/some_file.sql`:\nquery = queries.some_file\n\n# Module \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u043d \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0439 \u0432 Python.\n# \u0422\u043e \u0435\u0441\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442-\u0437\u0430\u043f\u0440\u043e\u0441 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \n# \u043e\u0431\u0440\u0430\u0442\u0438\u0432\u0448\u0438\u0441\u044c \u043a \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0443 Module \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438.\n# \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0444\u0430\u0439\u043b, \u043b\u0435\u0436\u0430\u0449\u0438\u0439 \u0432 `./sql/some_dir/some_file.sql`:\nquery = queries.some_dir.some_file\n\n#\u0412\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u044e\u0431\u043e\u0439:\nquery = queries.some_dir.another_dir.etc.some_file\n\n#\u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \n#\u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043e\u0431\u0440\u0430\u0442\u0438\u0432\u0448\u0438\u0441\u044c \u043f\u043e \u0435\u0433\u043e \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438:\nquery = queries.from_file('sql/some_dir/some_file.sql')\n\n# \u0418 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u0437 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u043b\u0438\u0442\u0435\u0440\u0430\u043b\u0430:\nquery = queries.from_str('SELECT id FROM tasks')\n\n# \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \n# \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u043a\u0443\u0440\u0441\u043e\u0440\u0430:\nimport psycopg\n\nconn = psycopg.connect('posgresql:///some_db')\n\nresult = queries.tasks.get_by_id(conn)\n# \u041b\u0438\u0431\u043e\ncursor = conn.cursor()\nresult = queries.tasks.get_by_id(cursor)\n\n# \u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0442\u043e\u0434 .execute:\nquery = queries.tasks.get_by_id\nquery.execute(conn)\n\n# \u041e\u0431\u044a\u0435\u043a\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u043d\u0443\u0436\u0435\u043d \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u043d\u043e\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \n# \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0423 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0431\u043e\u0440\u0430 \u0441\u0442\u0440\u043e\u043a, \n# \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u044b\u0445 \u0441\u0442\u0440\u043e\u043a \u0438 \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 - \n# .many(), .one() \u0438 .scalar() \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\n\n# \u0412\u0435\u0440\u043d\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u0440\u0442\u0435\u0436\u0435\u0439:\nresult = queries.from_str('SELECT * FROM tasks').execute(conn)\nprint(result.many())\n\n# \u0412\u0435\u0440\u043d\u0435\u0442 \u0434\u043e 100 \u0441\u0442\u0440\u043e\u043a. \u041f\u0440\u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u0435 \u0432\u0435\u0440\u043d\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 100:\nresult = queries.from_str('SELECT * FROM tasks').execute(conn)\nprint(result.many(100))\nprint(result.many(100))\n\n# \u0412\u0435\u0440\u043d\u0435\u0442 \u043e\u0434\u0438\u043d \u043a\u043e\u0440\u0442\u0435\u0436 \u0438\u043b\u0438 None:\nresult = queries.from_str(\n    'SELECT * FROM tasks WHERE id = 1'\n).execute(conn)\nprint(result.one())\n\n# \u0412\u0435\u0440\u043d\u0435\u0442 \u043e\u0434\u0438\u043d \u043a\u043e\u0440\u0442\u0435\u0436 \u0438\u043b\u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 ValueError, \n# \u0435\u0441\u043b\u0438 \u0432 \u0411\u0414 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c:\nresult = queries.from_str('SELECT * FROM tasks WHERE id = 1').execute(conn)\nprint(result.one(raising=True))\n\n# \u0412\u0435\u0440\u043d\u0435\u0442 \u043e\u0434\u0438\u043d \u043a\u043e\u0440\u0442\u0435\u0436 \u0438\u043b\u0438 None:\nresult = queries.from_str(\n    'SELECT id FROM tasks WHERE id = 1'\n).execute(conn).scalar()\nprint(result.scalar())\n\n# \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e .one() \u0432\u0435\u0440\u043d\u0435\u0442 \u043e\u0434\u0438\u043d \u043a\u043e\u0440\u0442\u0435\u0436 \u0438\u043b\u0438 \n# \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 ValueError, \u0435\u0441\u043b\u0438 \u0432 \u0411\u0414 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043d\u0430\u0448\u043b\u043e\u0441\u044c:\nresult = queries.from_str('SELECT id FROM tasks WHERE id = 1').execute(conn)\nprint(result.scalar(raising=True))\n```\n",
    "bugtrack_url": null,
    "license": null,
    "summary": null,
    "version": "0.4.3",
    "project_urls": null,
    "split_keywords": [
        "jinja2",
        " sql",
        " python",
        " template"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "cd0fa0d9ace7b56ad201c6ac71052e0f6da5280ceffc88abf8e680d289edc33b",
                "md5": "60514a6ec65410a229eb4912a3a8cc69",
                "sha256": "d8d21e3398e127c3f30b7baec0fbeb2e9c2fb6e0aaebd001d0480541fb0cf207"
            },
            "downloads": -1,
            "filename": "classic_sql_tools-0.4.3.tar.gz",
            "has_sig": false,
            "md5_digest": "60514a6ec65410a229eb4912a3a8cc69",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 11793,
            "upload_time": "2025-08-25T06:22:17",
            "upload_time_iso_8601": "2025-08-25T06:22:17.691061Z",
            "url": "https://files.pythonhosted.org/packages/cd/0f/a0d9ace7b56ad201c6ac71052e0f6da5280ceffc88abf8e680d289edc33b/classic_sql_tools-0.4.3.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-25 06:22:17",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "classic-sql-tools"
}
        
Elapsed time: 1.64638s