{"id":29182606,"url":"https://github.com/antonglyzin/query_tables","last_synced_at":"2025-08-17T12:43:16.090Z","repository":{"id":299805659,"uuid":"1004219492","full_name":"AntonGlyzin/query_tables","owner":"AntonGlyzin","description":"CORMless","archived":false,"fork":false,"pushed_at":"2025-06-28T05:02:01.000Z","size":184,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-06T01:32:16.361Z","etag":null,"topics":["asyncio","cache","orm","postgres","python","python3","redis","sql","sqlite","table"],"latest_commit_sha":null,"homepage":"https://query-tables.readthedocs.io/ru/latest/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AntonGlyzin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-06-18T09:46:39.000Z","updated_at":"2025-06-28T05:01:37.000Z","dependencies_parsed_at":null,"dependency_job_id":"37df1246-b780-4fef-96ad-66a6200cf8ca","html_url":"https://github.com/AntonGlyzin/query_tables","commit_stats":null,"previous_names":["antonglyzin/query_tables"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/AntonGlyzin/query_tables","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonGlyzin%2Fquery_tables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonGlyzin%2Fquery_tables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonGlyzin%2Fquery_tables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonGlyzin%2Fquery_tables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AntonGlyzin","download_url":"https://codeload.github.com/AntonGlyzin/query_tables/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AntonGlyzin%2Fquery_tables/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270850079,"owners_count":24656448,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asyncio","cache","orm","postgres","python","python3","redis","sql","sqlite","table"],"created_at":"2025-07-01T20:07:00.709Z","updated_at":"2025-08-17T12:43:16.076Z","avatar_url":"https://github.com/AntonGlyzin.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Запросы в объектном стиле без моделей с поддержкой кеша данных (CORMless).\n\nИдея библиотеки заключается, чтобы освободить разработчика от написания моделей. Если вам нравятся запросы ORM от django или sqlalchemy, но при этом вам не хочется создавать модели, то данная библиотека может вам понравиться. Также в ней присутствует функция кеширования данных, что может ускорить выдачу результатов. На данный момент кеширование предусмотренно либо на уровне процесса, либо в редисе. Библиотека расчитана на работу в синхронном и асинхронном режиме.\n\n1. [Установка](#установка)\n2. [Работа с таблицами](#работа-с-таблицами)\n3. [Запросы к таблицам](#запросы-к-таблицам)\n4. [Работа с кешем](#работа-с-кешем)\n5. [Работа с БД в асинхронном режиме](#работа-с-бд-в-асинхронном-режиме)\n6. [Асинхронный режим с удаленным кешем](#асинхронный-режим-с-удаленным-кешем)\n6. [Выполнение сырых SQL запросов](#выполнение-сырых-sql-запросов)\n\n## Установка\n\n```\npip install query-tables\n```\n\n## Работа с таблицами.\n\nРабота библиотеки будет продемонстрирована на этих таблицах:\n\nТаблица `address`.\n\n| Поле  |  Тип | Описание  |\n| ------------ | ------------ | ------------ |\n|  id | INTEGER  | Ключ  |\n|  street | TEXT  |  Улица |\n|  building |  INTEGER |  Здание |\n\n\nТаблица `company`.\n\n| Поле  |  Тип | Описание  |\n| ------------ | ------------ | ------------ |\n|  id | INTEGER  | Ключ  |\n|  name | TEXT  |  Название |\n| ref_address  | INTEGER  | Ссылка на адрес  |\n| registration  |  TEXT |  Время в формате ИСО |\n\n\nТаблица `employees`.\n\n| Поле  |  Тип | Описание  |\n| ------------ | ------------ | ------------ |\n|  id |  INTEGER |  Ключ |\n| ref_person  | INTEGER  | Ссылка на персону  |\n|  ref_company | INTEGER  | Ссылка на компанию  |\n| hired  | INTEGER  |  Время в формате unix epoch |\n|  dismissed | INTEGER  |  Время в формате unix epoch |\n\n\nТаблица `person`.\n\n| Поле  |  Тип | Описание  |\n| ------------ | ------------ | ------------ |\n|  id |  INTEGER | Ключ  |\n| login  | TEXT  | Логин  |\n| name  |  TEXT |  Имя |\n|   ref_address| INTEGER  |  Ссылка на адрес |\n| age  |  INTEGER | Возраст  |\n\nБиблиотека поддерживает работу с двумя БД: `sqlite` и `postgres`.\n\nРабота с `sqlite`. \n```python\nfrom query_tables import Tables\nfrom query_tables.db import SQLiteQuery\n\nsqlite = SQLiteQuery(tests_dir / 'test_tables.db')\ntable = Tables(sqlite) # кеш отключен по умолчанию\n# или так\ntable = Tables(sqlite, non_expired=True) # включен вечный кеш\n# или так\ntable = Tables(sqlite, cache_ttl=300) # включен временный кеш на 300 сек.\n# или так\nconnect = RedisConnect() # параметры соединения с редисом\nredis_cache = RedisCache(connect)\ntables = Tables(sqlite, cache=redis_cache)# кеш redis\n```\nПри создание экземпляра `Tables` будут получен доступ ко всем таблицам.\n\nРабота с `postgres` в многопоточном режиме. \n```python\nfrom query_tables import Tables\nfrom query_tables.db import DBConfigPg, PostgresQuery\nfrom query_tables.cache import RedisCache, RedisConnect\n\npostgres = PostgresQuery(\n    DBConfigPg('localhost', 'test', 'postgres', 'postgres')\n)\ntable = Tables(postgres) # кеш отключен по умолчанию\n# или так\ntable = Tables(postgres, non_expired=True) # включен вечный кеш\n# или так\ntable = Tables(postgres, cache_ttl=300) # включен временный кеш на 300 сек.\n# или так\nconnect = RedisConnect() # параметры соединения с редисом\nredis_cache = RedisCache(connect)\ntables = Tables(postgres, cache=redis_cache)# кеш redis\n\n```\nПри создание экземпляра `Tables` будет получен доступ к таблицам из схемы `public`. При желание вы можете передать другую схему.\n\nЕсли нужен доступ к ограниченному числу таблиц из БД `postgres`:\n```python\ntable = Tables(postgres, tables=['operators', 'opright'], non_expired=True)\n```\n\nКогда создается экземпляр `Tables` с использованием кеша на основе `redis` или другого удаленного кеша, то в этот момент структуры таблиц сохраняются в кеш. При повторном создание экземпляра `Tables` все таблицы будут взяты из кеша. Это может понадобиться, если вы работаете с веб-сервером. \n\nПараметры `Tables`:\n- `db`: Объект для доступа к БД.\n- `prefix_table`: Префикс таблиц которые нужно загрузить. По умолчанию - пустая строка.\n- `tables`: Список подключаемых таблиц. По умолчанию - нет.\n- `table_schema`: Схема данных. По умолчанию - `public`.\n- `cache_ttl`: Время кеширования данных. По умолчанию 0 секунд - кеширование отключено.\n- `non_expired`: Вечный кеш без времени истечения. По умолчанию - выключен.\n- `cache_maxsize`: Размер элементов в кеше.\n- `cache`: Пользовательская реализация кеша.\n\nПараметры `RedisConnect`:\n- `host`: Хост редиса. По умолчанию - `127.0.0.1`\n- `user`: Пользователь. По умолчанию - нет.\n- `password`: Пароль. По умолчанию - нет.\n- `port`: Порт. По умолчанию - 6379.\n- `db`: БД. По умолчанию - 0.\n\nПараметры `DBConfigPg`:\n- `host`: Хост БД. По умолчанию - `127.0.0.1`\n- `database`: Название БД. По умолчанию - нет. \n- `user`: Пользователь. По умолчанию - нет.\n- `password`: Пароль. По умолчанию - нет.\n- `port`: Порт. По умолчанию - 5432\n- `minconn`: Минимальное количество подключений в пуле - 1\n- `maxconn`: Максимальное количество подключений в пуле - 10\n\nКогда у вас есть экземпляр `Tables`, доступ к таблицам можно получить так:\n```python\ntable['person']\n```\n        \n## Запросы к таблицам.\n\nПосле того, как вы создали экземпляр `Tables`, вы можете получать доступ к данным из таблиц.\n\n```python\nres = table['person'].filter(id=2).get()\nprint(res)\n\"\"\"\n[{'person.id': 2, 'person.login': 'mix', 'person.name': 'Anton 2', 'person.ref_address': 2, 'person.age': 30}]\n\"\"\"\n\nres = table['person'].filter(name__like='%%4').get()\nprint(res)\n\"\"\"\n[{'person.id': 4, 'person.login': 'ytr', 'person.name': 'Anton 4', 'person.ref_address': 2, 'person.age': 35}]\n\"\"\"\n\nres = table['person'].filter(age__in=[30]).get()\nprint(res)\n\"\"\"\n[{'person.id': 2, 'person.login': 'mix', 'person.name': 'Anton 2', 'person.ref_address': 2, 'person.age': 30}]\n\"\"\"\n\nres = table['person'].filter(age__between=(30, 31)).order_by(id='asc').get()\nprint(res)\n\"\"\"\n[{'person.id': 1, 'person.login': 'ant', 'person.name': 'Anton 1', 'person.ref_address': 1, 'person.age': 31}, \n{'person.id': 2, 'person.login': 'mix', 'person.name': 'Anton 2', 'person.ref_address': 2, 'person.age': 30}]\n\"\"\"\n\nres = table['person'].filter(age__gte=35).get()\nprint(res)\n\"\"\"\n[{'person.id': 4, 'person.login': 'ytr', 'person.name': 'Anton 4', 'person.ref_address': 2, 'person.age': 35}]\n\"\"\"\n\nres = table['company'].filter(registration__between=('2020-01-04', '2020-01-05')).get()\nprint(res)\n\"\"\"\n[{'company.id': 2, 'company.name': 'Hex', 'company.ref_address': 4, 'company.registration': '2020-01-05'}]\n\"\"\"\n\nres = table['person'].order_by(id='desc').limit(1).get()\nprint(res)\n\"\"\"\n[{'person.id': 4, 'person.login': 'ytr', 'person.name': 'Anton 4', 'person.ref_address': 2, 'person.age': 35}]\n\"\"\"\n\nfrom query_tables.query import Join, LeftJoin\n\nres = table['person'].join(\n    Join(table['address'], 'id', 'ref_address')\n).filter(age__between=(25, 31)).get()\nprint(res)\n\"\"\"\n[{'person.id': 1, 'person.login': 'ant', 'person.name': 'Anton 1', 'person.ref_address': 1, 'person.age': 31, 'address.id': 1, 'address.street': 'Пушкина', 'address.building': 10}, \n{'person.id': 2, 'person.login': 'mix', 'person.name': 'Anton 2', 'person.ref_address': 2, 'person.age': 30, 'address.id': 2, 'address.street': 'Наумова', 'address.building': 33}]\n\"\"\"\n\nres = table['person'].filter(id=2).join(\n    Join(table['address'], 'id', 'ref_address')\n).join(\n    LeftJoin(table['employees'], 'ref_person', 'id').select(['id', 'ref_person', 'ref_company', 'hired']).join(\n        Join(table['company'], 'id', 'ref_company').join(\n            Join(table['address'], 'id', 'ref_address', 'compony_addr')\n        ).filter(registration__between=('2020-01-02', '2020-01-06'))\n    )\n).select(['id', 'name', 'age']).order_by(age='desc').get()\nprint(res)\n\"\"\"\n[{'address.id': 2, 'address.street': 'Наумова', 'address.building': 33, 'employees.id': 2, 'employees.ref_person': 2, 'employees.ref_company': 2, 'employees.hired': 1612588507, 'company.id': 2, 'company.name': 'Hex', 'company.ref_address': 4, 'company.registration': '2020-01-05', 'compony_addr.id': 4, 'compony_addr.street': 'Приморская', 'compony_addr.building': 8, 'person.id': 2, 'person.name': 'Anton 2', 'person.age': 30}]\n\"\"\"\n```\n\nДля изменения метода фильтрации в условие можно добавить к модификатору `filter` параметр.\n\nЕсть следующие виды параметров в методе `filter`:\n\n| Параметр | Оператор sql | Пример значений |\n| :-------- | :------- | :--------\n| `ilike` | `ilike` |  `name__ilike='Ant%%'`|\n| `like` | `like` |  `name__ilike='Ant%%'`|\n| `in` | `in` |  `id__in=[1,2,3,4]`|\n| `gt` | `\u003e` |  `age__gt=3`|\n| `gte` | `\u003e=` |  `age__gte=3`|\n| `lt` | `\u003c` |  `age__lt=3`|\n| `lte` | `\u003c=` |  `age__lte=3`|\n| `between` | `between` |  `age__between=(5,6)`|\n| `isnull` | `is null` |  `name__isnull=None`|\n| `isnotnull` | `is not null` |  `name__isnotnull=None`|\n| `notequ` | `!=` |  `age__notequ=5`|\n\n\nДоступные методы для конструирования запроса SQL из таблицы `table['person']`, а также из`Join` и `LeftJoin`. Данные методы не взаимодействют с БД, они только помогают собрать запрос:\n- `select`: Для выбора выводимых полей.\n- `join`: Объединение таблиц.\n- `filter`: Правила фильтрации.\n- `order_by`: Сортировка для полей.\n- `limit`: Ограничения по количеству.\n\nДля связывания таблиц используется две обертки:\n```python\nfrom query_tables.query import Join, LeftJoin\n```\n- `Join`: Если вам нужно выводит записи, только если они есть в join таблице.\n- `LeftJoin`: Если вам нужно вывести записи, даже если их нет в join таблице.\n\nПараметры для `Join`, `LeftJoin`:\n- `join_table`: Таблица которая соединяется с другой таблицей.\n- `join_field`: Поле join таблицы.\n- `ext_field`: Поле внешней таблицы, с которой идет соединение.\n- `table_alias`: Псевдоним для таблицы (*когда \n    одна и та же таблицы соединяется больше одного раза*).\n\nЕсли ваш экземпляр `Tables` будет кешировать данные, то здесь нужно учитывать, когда и в какой момент нужно очищать кеш.\nПредположим есть три запроса к БД, которые были созданы, но еще не выполнены. Пока данных нет, кеш пуст.\n```python\nquery1 = table['person'].join(\n    Join(table['address'], 'id', 'ref_address')\n).filter(age__between=(30, 33), name__like='Anton%%').order_by(id='desc')\n\nquery2 = table['person'].filter(id=2).join(\n    Join(table['address'], 'id', 'ref_address')\n).join(\n    LeftJoin(table['employees'], 'ref_person', 'id').join(\n        Join(table['company'], 'id', 'ref_company').join(\n            Join(table['address'], 'id', 'ref_address', 'compony_addr')\n        ).filter(registration__between=('2020-01-02', '2020-01-06'))\n    )\n).order_by(age='desc')\n\nquery3 = table['person'].filter(id=3).join(\n    LeftJoin(table['employees'], 'ref_person', 'id')\n)\n```\nВыполним запросы. Получение данных из БД.\n```python\nres = query1.get()\nres = query2.get()\nres = query3.get()\n```\nТеперь в следующий раз, когда вы захотите получить данные, они будут браться из кеша.\n```python\nres = query1.get()\nres = query2.get()\nres = query3.get()\n```\n\nНо что если вы измените данные в таблице? Если это сделать вручную из БД, то данные у нас остануться не актуальными. Изменение данных в БД нужно проводить через методы изменения данных по выбранной таблице.\n\n```python\n# вставка записей в БД\ntable['address'].insert([dict(\n    street='123',\n    building=777\n)])\n# обновление записей в БД\ntable['address'].filter(id=1).update(building=11)\n# удаление записей из БД\ntable['address'].filter(id=1).delete()\n```\nВ этом случае кеш запросов `query1` и `query2` будут очищены, так как они используют таблицу, в которой произошли изменения.\nТакже заметьте, что для вставки записей в БД мы используем список словарей. Это значит, что можно вставлять больше одной записи в БД за раз.\n\nПолучаем снова данные из БД.\n```python\nres = query1.get()\nres = query2.get()\n```\n\nЕсли вам не нужно изменять данные в БД, но вы желаете, чтобы запросы в кеше, которые используют таблицу `address` были очищены, то можно сделать так:\n```python\ntable['address'].delete_cache_table()\n```\n\nПолучаем снова данные из БД.\n```python\nres = query1.get()\nres = query2.get()\n```\n\n## Работа с кешем.\n\n\u003e Не пытайтесь получить доступ к кешу, если он у вас выключен. Это приведет к ошибке.\n\nДавайте снова выполним запрос.\n```python\n# сохраняем запрос\nquery = table['person'].join(\n    Join(table['address'], 'id', 'ref_address')\n).filter(age__between=(30, 33), name__like='Anton%%').order_by(id='desc')\nquery.get() # получаем данные по запросу\nres = query.cache.get() # потом можно взять из кеша\n# либо\nres = query.get() # если кеш включен\nprint(res)\n\"\"\" \n[{'person.id': 3, 'person.login': 'geg', 'person.name': 'Anton 3', 'person.ref_address': 3, 'person.age': 33, 'address.id': 3, 'address.street': 'Гринвич', 'address.building': 12}, \n{'person.id': 2, 'person.login': 'mix', 'person.name': 'Anton 2', 'person.ref_address': 2, 'person.age': 30, 'address.id': 2, 'address.street': 'Наумова', 'address.building': 33}, \n{'person.id': 1, 'person.login': 'ant', 'person.name': 'Anton 1', 'person.ref_address': 1, 'person.age': 31, 'address.id': 1, 'address.street': 'Пушкина', 'address.building': 10}]\n\"\"\"\n```\n\nТеперь ваши данные находятся в кеше. Но что если вам нужно получить или изменить эти данные с учетов фильтрации кеша?\n\n```python\n# Получить список данных по выборке. \n# В фильтре доступно только строгое равенство полей.\nres = query.cache.filter({'person.id': 1}).get()\n# Обновление данных по условию.\nquery.cache.filter({'person.id': 1}).update({'person.name': 'Tony 1', 'person.age': 32})\n# Вставить новую запись в кеш.\nquery.cache.insert({\n    'person.id': 6, \n    'person.login': 'qqq', \n    'person.name': 'Anton 6', \n    'person.ref_address': 0, \n    'person.age': 0,\n    'address.id': 6,\n    'address.street': 'ytutyu',\n    'address.building': 567\n})\n# Удалить запись из кеша.\nquery.cache.filter({'person.id': 6}).delete()\n```\n\nИзменение данных через кеш не влечет за собой изменение данных в БД. В данном случае вы сами должны получить из БД данные и изменить их в кеше, чтобы не сбрасывать кеш.\n\nМы знаем, что запись с ИД 9 была изменена. Давайте ее получим: \n```python\nquery_9 = table['person'].join(\n    Join(table['address'], 'id', 'ref_address')\n).filter(id=9)\nres: list = query_9.get()\n# Теперь обновим наш кеш из прошлого запроса.\nquery.cache.filter({'person.id': 9}).update(**res[0])\n```\n\nЗапрос query_9 будет закеширован. Давай сброси кеш по конкретному запросу.\n```python\nquery_9.delete_cache_query()\n```\n\nДля очищение всего кеша используйте:\n```python\ntable.clear_cache()\n```\n\n## Работа с БД в асинхронном режиме.\n\nКонструктор запросов остался без изменений. Но запросы к БД будут выглядить по другому, к ним нужно добавить `await`.\n\nСоздаем экземпляр `TablesAsync`.\n```python\nfrom query_tables import TablesAsync\nfrom query_tables.cache import RedisConnect, AsyncRedisCache\nfrom query_tables.db import (\n    AsyncSQLiteQuery, \n    DBConfigPg, \n    AsyncPostgresQuery\n)\n\nsqlite_async = AsyncSQLiteQuery(tests_dir / 'test_db.db')\n\npostgres_async = AsyncPostgresQuery(\n    DBConfigPg('localhost', 'test', 'postgres', 'postgres')\n)\n\ntable = TablesAsync(sqlite_async, non_expired=True)\nawait table.init()\n# или так\ntable = TablesAsync(postgres_async, non_expired=True)\nawait table.init()\n# или так\nredis = AsyncRedisCache(RedisConnect())\ntable = TablesAsync(postgres_async, cache=redis)\nawait table.init()\n\n```\n\nПолучаем данные и проводим изменения в БД.\n```python\nres1 = await table['person'].filter(id=2).get()\nres2 = await table['person'].filter(id=4).join(\n    Join(table['employees'], 'ref_person', 'id')\n).get()\n\nquery = table['person'].filter(id=4).join(\n    LeftJoin(table['employees'], 'ref_person', 'id')\n)\nres3 = await query.get()\n\nawait table['person'].insert([dict(\n    login='tt',\n    name='Ton',\n    ref_address=1,\n    age=55\n)])\n\nawait table['person'].filter(id=9).update(login='ant2', age=32)\nawait table['person'].filter(id=9).delete()\n```\n\n## Асинхронный режим с удаленным кешем.\nПринцип доступка к данным из локального кеша, который находится в памяти процесса, не изменился. Но получение доступка к удаленному кешу был изменен.\n\nСоздаем экземпляр `TablesAsync`.\n```python\nfrom query_tables import TablesAsync\nfrom query_tables.cache import RedisConnect, AsyncRedisCache\nfrom query_tables.db import (\n    DBConfigPg, \n    AsyncPostgresQuery\n)\n\npostgres_async = AsyncPostgresQuery(\n    DBConfigPg('localhost', 'test', 'postgres', 'postgres')\n)\n\nredis = AsyncRedisCache(RedisConnect())\ntable = TablesAsync(postgres_async, cache=redis)\nawait table.init()\n\n```\n\nЗапросы на получения и изменения данных в кеше.\n```python\n# сохраняем запрос\nquery = table['person'].join(\n    Join(table['address'], 'id', 'ref_address')\n).filter(age__between=(30, 33), name__like='Anton%%').order_by(id='desc')\nawait query.get() # получаем данные по запросу из БД\nres = await query.cache.get() # потом можно взять из кеша\n# либо\nres = await query.get() # если кеш включен\nprint(res)\n\"\"\" \n[{'person.id': 3, 'person.login': 'geg', 'person.name': 'Anton 3', 'person.ref_address': 3, 'person.age': 33, 'address.id': 3, 'address.street': 'Гринвич', 'address.building': 12}, \n{'person.id': 2, 'person.login': 'mix', 'person.name': 'Anton 2', 'person.ref_address': 2, 'person.age': 30, 'address.id': 2, 'address.street': 'Наумова', 'address.building': 33}, \n{'person.id': 1, 'person.login': 'ant', 'person.name': 'Anton 1', 'person.ref_address': 1, 'person.age': 31, 'address.id': 1, 'address.street': 'Пушкина', 'address.building': 10}]\n\"\"\"\n\n# обновляем запись в кеше по id\nawait query.cache.filter({'person.id': 1}).update({'person.name': 'Tony 1', 'person.age': 32})\n\n# вставка новой записи в кеш\nawait query.cache.insert({\n\t'person.id': 6, \n\t'person.login': 'qqq', \n\t'person.name': 'Anton 6', \n\t'person.ref_address': 0, \n\t'person.age': 0,\n\t'address.id': 6,\n\t'address.street': 'ytutyu',\n\t'address.building': 567\n})\n\n# удаление этой записи из кеша\nawait query.cache.filter({'person.id': 6}).delete()\n\n# удаление данных по запросу из кеша\nawait query.delete_cache_query()\n\n# очищение кеша\nawait table.clear_cache()\n```\n\n## Выполнение сырых SQL запросов.\n\nЭто может понадобиться, потому как ваш запрос может быть большой или вы хотели бы получить данные не из кеша.\nДля выполнение сырых sql запросов нужно выполнить метод `query` со строкой sql запроса.\n\n```python\nfrom query_tables import Tables\nfrom query_tables.db import DBConfigPg, PostgresQuery\nfrom query_tables.cache import RedisCache, RedisConnect\n\npostgres = PostgresQuery(\n    DBConfigPg('localhost', 'test', 'postgres', 'postgres')\n)\nconnect = RedisConnect() # параметры соединения с редисом\nredis_cache = RedisCache(connect)\ntables = Tables(postgres, cache=redis_cache)# кеш redis\n\n# получение списка кортежей\nrows = tables.query('select * from person')\n```\n\nЕсли все же вы хотели бы его закешировать. \n```python\nquery = 'select * from person'\nrows = tables.query(query, cache=True)\n```\nЭто извлекает данные из БД и сразу их кеширует по sql запросу.\n\nВ следующий раз получаем данные из кеша:\n```python\nrows = tables.query(query, cache=True)\n```\n\nПредположим вы знаете, что в таблице были изменения, и вы хотели бы снова получить их из БД в кеш.\nДля этого нужно установить флаг `delete_cache`. Это удалит старые данные из кеша.\n\n```python\nrows = tables.query(query, cache=True, delete_cache=True)\n```\n\nЕсли же нужно просто удалить данные из кеша по запросу. \n```python\nrows = tables.query(query, delete_cache=True)\n```\n\nВ следующий раз получаем данные из БД:\n```python\nrows = tables.query(query, cache=True)\n```\n\nДля асинхронного режима добавляем `await`:\n```python\nfrom query_tables import TablesAsync\nfrom query_tables.cache import RedisConnect, AsyncRedisCache\nfrom query_tables.db import (\n    DBConfigPg, \n    AsyncPostgresQuery\n)\n\npostgres_async = AsyncPostgresQuery(\n    DBConfigPg('localhost', 'test', 'postgres', 'postgres')\n)\n\nredis = AsyncRedisCache(RedisConnect())\ntable = TablesAsync(postgres_async, cache=redis)\nawait table.init()\nquery = 'select * from person'\nrows = await tables.query(query)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantonglyzin%2Fquery_tables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fantonglyzin%2Fquery_tables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fantonglyzin%2Fquery_tables/lists"}