nonebot-plugin-sqlalchemy


Namenonebot-plugin-sqlalchemy JSON
Version 0.2.2 PyPI version JSON
download
home_pagehttps://github.com/ssttkkl/nonebot-plugin-sqlalchemy
Summary
upload_time2023-07-20 03:51:38
maintainer
docs_urlNone
authorssttkkl
requires_python>=3.9,<4.0
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <!-- markdownlint-disable MD033 MD036 MD041 -->

<p align="center">
  <a href="https://v2.nonebot.dev/"><img src="https://v2.nonebot.dev/logo.png" width="200" height="200" alt="nonebot"></a>
</p>

<div align="center">

nonebot-plugin-sqlalchemy
============

_✨ NoneBot SQLAlchemy 封装插件 ✨_

</div>

<p align="center">
  <a href="https://raw.githubusercontent.com/ssttkkl/nonebot-plugin-sqlalchemy/master/LICENSE">
    <img src="https://img.shields.io/github/license/ssttkkl/nonebot-plugin-sqlalchemy.svg" alt="license">
  </a>
  <a href="https://pypi.python.org/pypi/nonebot-plugin-sqlalchemy">
    <img src="https://img.shields.io/pypi/v/nonebot-plugin-sqlalchemy.svg" alt="pypi">
  </a>
  <img src="https://img.shields.io/badge/python-3.9+-blue.svg" alt="python">
</p>

为插件封装SQLAlchemy数据库访问,一个插件使用一个数据库。

对于数据存储较简单的场景,推荐使用[he0119/nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore)

## Get Started

### 1、定义data_source

```python
from nonebot import get_driver, require

# 注意必须先require再import
require("nonebot_plugin_sqlalchemy")
from nonebot_plugin_sqlalchemy import DataSource

# 必须使用支持asyncio的驱动器
db_conn_url = "postgresql+asyncpg://username:password@localhost:5432/database"
data_source = DataSource(get_driver(), db_conn_url)
```

### 2、定义映射
```python
from sqlalchemy.orm import mapped_column

@data_source.registry.mapped
class UserOrm:
    __tablename__ = 'users'

    id: int = mapped_column(primary_key=True, autoincrement=True)
    username: str
    password: str
    nickname: str
```

### 3、在Matcher中使用

```python
from nonebot import on_command
from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.internal.matcher import Matcher
from sqlalchemy import select

login_matcher = on_command("login")


@login_matcher.handle()
async def handler(event: MessageEvent, matcher: Matcher):
    username, password = event.get_plaintext().split(" ")

    session = data_source.session()
    
    stmt = select(UserOrm).where(UserOrm.username == username, UserOrm.password == password)
    result = await session.execute(stmt)
    user = result.scalar_one_or_none()

    if user is not None:
        await matcher.send(f"Hello, {user.nickname}")
```

通过`data_source.session()`获取AsyncSession对象,此处获取的session实际上是async_scoped_session。

在Matcher的一次执行过程中,多次调用`data_source.session()`获得的是同一个session,并且会在Matcher执行完毕后自动关闭。也就是说我们可以像下面这样使用:

```python
from nonebot import on_command
from nonebot.adapters.onebot.v11 import MessageEvent
from nonebot.internal.matcher import Matcher
from sqlalchemy import select
from typing import Optional

async def login(username: str, password: str) -> Optional[User]:
    session = data_source.session()
    
    stmt = select(UserOrm).where(UserOrm.username == username, UserOrm.password == password)
    result = await session.execute(stmt)
    user = result.scalar_one_or_none()

    return user


login_matcher = on_command("login")


@login_matcher.handle()
async def handler(event: MessageEvent, matcher: Matcher):
    username, password = event.get_plaintext().split(" ")
    user = await login(username, password)
    if user is not None:
        await matcher.send(f"Hello, {user.nickname}")
```

参考:https://docs.sqlalchemy.org/en/14/orm/extensions/asyncio.html#using-asyncio-scoped-session

注意:务必保证一次Matcher执行过程不会在不同的Task中调用`data_source.session()`获取session(即不要使用`create_task()`或`ensure_future()`创建Task),否则可能出现错误。若有这样的需求,请参考下文的方法手动创建并管理session。


### 4、在Matcher之外使用

在Matcher之外(如on_bot_connect等钩子函数中,或者是APScheduler的定时任务中)则必须通过`AsyncSession(data_source.engine)`创建session。

```python
async def do_something():
    async with AsyncSession(data_source.engine) as session:
        # ...
```


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/ssttkkl/nonebot-plugin-sqlalchemy",
    "name": "nonebot-plugin-sqlalchemy",
    "maintainer": "",
    "docs_url": null,
    "requires_python": ">=3.9,<4.0",
    "maintainer_email": "",
    "keywords": "",
    "author": "ssttkkl",
    "author_email": "huang.wen.long@hotmail.com",
    "download_url": "https://files.pythonhosted.org/packages/d7/22/db73b2b63cbc11ba94802e7ba49776358bafe213dff06fde86810e0b6149/nonebot_plugin_sqlalchemy-0.2.2.tar.gz",
    "platform": null,
    "description": "<!-- markdownlint-disable MD033 MD036 MD041 -->\n\n<p align=\"center\">\n  <a href=\"https://v2.nonebot.dev/\"><img src=\"https://v2.nonebot.dev/logo.png\" width=\"200\" height=\"200\" alt=\"nonebot\"></a>\n</p>\n\n<div align=\"center\">\n\nnonebot-plugin-sqlalchemy\n============\n\n_\u2728 NoneBot SQLAlchemy \u5c01\u88c5\u63d2\u4ef6 \u2728_\n\n</div>\n\n<p align=\"center\">\n  <a href=\"https://raw.githubusercontent.com/ssttkkl/nonebot-plugin-sqlalchemy/master/LICENSE\">\n    <img src=\"https://img.shields.io/github/license/ssttkkl/nonebot-plugin-sqlalchemy.svg\" alt=\"license\">\n  </a>\n  <a href=\"https://pypi.python.org/pypi/nonebot-plugin-sqlalchemy\">\n    <img src=\"https://img.shields.io/pypi/v/nonebot-plugin-sqlalchemy.svg\" alt=\"pypi\">\n  </a>\n  <img src=\"https://img.shields.io/badge/python-3.9+-blue.svg\" alt=\"python\">\n</p>\n\n\u4e3a\u63d2\u4ef6\u5c01\u88c5SQLAlchemy\u6570\u636e\u5e93\u8bbf\u95ee\uff0c\u4e00\u4e2a\u63d2\u4ef6\u4f7f\u7528\u4e00\u4e2a\u6570\u636e\u5e93\u3002\n\n\u5bf9\u4e8e\u6570\u636e\u5b58\u50a8\u8f83\u7b80\u5355\u7684\u573a\u666f\uff0c\u63a8\u8350\u4f7f\u7528[he0119/nonebot-plugin-datastore](https://github.com/he0119/nonebot-plugin-datastore)\n\n## Get Started\n\n### 1\u3001\u5b9a\u4e49data_source\n\n```python\nfrom nonebot import get_driver, require\n\n# \u6ce8\u610f\u5fc5\u987b\u5148require\u518dimport\nrequire(\"nonebot_plugin_sqlalchemy\")\nfrom nonebot_plugin_sqlalchemy import DataSource\n\n# \u5fc5\u987b\u4f7f\u7528\u652f\u6301asyncio\u7684\u9a71\u52a8\u5668\ndb_conn_url = \"postgresql+asyncpg://username:password@localhost:5432/database\"\ndata_source = DataSource(get_driver(), db_conn_url)\n```\n\n### 2\u3001\u5b9a\u4e49\u6620\u5c04\n```python\nfrom sqlalchemy.orm import mapped_column\n\n@data_source.registry.mapped\nclass UserOrm:\n    __tablename__ = 'users'\n\n    id: int = mapped_column(primary_key=True, autoincrement=True)\n    username: str\n    password: str\n    nickname: str\n```\n\n### 3\u3001\u5728Matcher\u4e2d\u4f7f\u7528\n\n```python\nfrom nonebot import on_command\nfrom nonebot.adapters.onebot.v11 import MessageEvent\nfrom nonebot.internal.matcher import Matcher\nfrom sqlalchemy import select\n\nlogin_matcher = on_command(\"login\")\n\n\n@login_matcher.handle()\nasync def handler(event: MessageEvent, matcher: Matcher):\n    username, password = event.get_plaintext().split(\" \")\n\n    session = data_source.session()\n    \n    stmt = select(UserOrm).where(UserOrm.username == username, UserOrm.password == password)\n    result = await session.execute(stmt)\n    user = result.scalar_one_or_none()\n\n    if user is not None:\n        await matcher.send(f\"Hello, {user.nickname}\")\n```\n\n\u901a\u8fc7`data_source.session()`\u83b7\u53d6AsyncSession\u5bf9\u8c61\uff0c\u6b64\u5904\u83b7\u53d6\u7684session\u5b9e\u9645\u4e0a\u662fasync_scoped_session\u3002\n\n\u5728Matcher\u7684\u4e00\u6b21\u6267\u884c\u8fc7\u7a0b\u4e2d\uff0c\u591a\u6b21\u8c03\u7528`data_source.session()`\u83b7\u5f97\u7684\u662f\u540c\u4e00\u4e2asession\uff0c\u5e76\u4e14\u4f1a\u5728Matcher\u6267\u884c\u5b8c\u6bd5\u540e\u81ea\u52a8\u5173\u95ed\u3002\u4e5f\u5c31\u662f\u8bf4\u6211\u4eec\u53ef\u4ee5\u50cf\u4e0b\u9762\u8fd9\u6837\u4f7f\u7528\uff1a\n\n```python\nfrom nonebot import on_command\nfrom nonebot.adapters.onebot.v11 import MessageEvent\nfrom nonebot.internal.matcher import Matcher\nfrom sqlalchemy import select\nfrom typing import Optional\n\nasync def login(username: str, password: str) -> Optional[User]:\n    session = data_source.session()\n    \n    stmt = select(UserOrm).where(UserOrm.username == username, UserOrm.password == password)\n    result = await session.execute(stmt)\n    user = result.scalar_one_or_none()\n\n    return user\n\n\nlogin_matcher = on_command(\"login\")\n\n\n@login_matcher.handle()\nasync def handler(event: MessageEvent, matcher: Matcher):\n    username, password = event.get_plaintext().split(\" \")\n    user = await login(username, password)\n    if user is not None:\n        await matcher.send(f\"Hello, {user.nickname}\")\n```\n\n\u53c2\u8003\uff1ahttps://docs.sqlalchemy.org/en/14/orm/extensions/asyncio.html#using-asyncio-scoped-session\n\n\u6ce8\u610f\uff1a\u52a1\u5fc5\u4fdd\u8bc1\u4e00\u6b21Matcher\u6267\u884c\u8fc7\u7a0b\u4e0d\u4f1a\u5728\u4e0d\u540c\u7684Task\u4e2d\u8c03\u7528`data_source.session()`\u83b7\u53d6session\uff08\u5373\u4e0d\u8981\u4f7f\u7528`create_task()`\u6216`ensure_future()`\u521b\u5efaTask\uff09\uff0c\u5426\u5219\u53ef\u80fd\u51fa\u73b0\u9519\u8bef\u3002\u82e5\u6709\u8fd9\u6837\u7684\u9700\u6c42\uff0c\u8bf7\u53c2\u8003\u4e0b\u6587\u7684\u65b9\u6cd5\u624b\u52a8\u521b\u5efa\u5e76\u7ba1\u7406session\u3002\n\n\n### 4\u3001\u5728Matcher\u4e4b\u5916\u4f7f\u7528\n\n\u5728Matcher\u4e4b\u5916\uff08\u5982on_bot_connect\u7b49\u94a9\u5b50\u51fd\u6570\u4e2d\uff0c\u6216\u8005\u662fAPScheduler\u7684\u5b9a\u65f6\u4efb\u52a1\u4e2d\uff09\u5219\u5fc5\u987b\u901a\u8fc7`AsyncSession(data_source.engine)`\u521b\u5efasession\u3002\n\n```python\nasync def do_something():\n    async with AsyncSession(data_source.engine) as session:\n        # ...\n```\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "",
    "version": "0.2.2",
    "project_urls": {
        "Homepage": "https://github.com/ssttkkl/nonebot-plugin-sqlalchemy",
        "Repository": "https://github.com/ssttkkl/nonebot-plugin-sqlalchemy"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "f297d7b87eee47f6c9beabcea61991c0c03134f947010729d204c71e7b0177da",
                "md5": "d773b78f06463d4bd4dc632b13b257ed",
                "sha256": "4ec310daafdea259cd0b81171313a8a3fc23d90edf18f75f298d14c58c7d4327"
            },
            "downloads": -1,
            "filename": "nonebot_plugin_sqlalchemy-0.2.2-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d773b78f06463d4bd4dc632b13b257ed",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9,<4.0",
            "size": 5310,
            "upload_time": "2023-07-20T03:51:36",
            "upload_time_iso_8601": "2023-07-20T03:51:36.974013Z",
            "url": "https://files.pythonhosted.org/packages/f2/97/d7b87eee47f6c9beabcea61991c0c03134f947010729d204c71e7b0177da/nonebot_plugin_sqlalchemy-0.2.2-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "d722db73b2b63cbc11ba94802e7ba49776358bafe213dff06fde86810e0b6149",
                "md5": "1eb77247f7b762308ceea2252af7d188",
                "sha256": "2b3f76768d9c08f8715d2d892499d3ca36a2b7a37eabe2eff06617551b04cf06"
            },
            "downloads": -1,
            "filename": "nonebot_plugin_sqlalchemy-0.2.2.tar.gz",
            "has_sig": false,
            "md5_digest": "1eb77247f7b762308ceea2252af7d188",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9,<4.0",
            "size": 4688,
            "upload_time": "2023-07-20T03:51:38",
            "upload_time_iso_8601": "2023-07-20T03:51:38.342309Z",
            "url": "https://files.pythonhosted.org/packages/d7/22/db73b2b63cbc11ba94802e7ba49776358bafe213dff06fde86810e0b6149/nonebot_plugin_sqlalchemy-0.2.2.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2023-07-20 03:51:38",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "ssttkkl",
    "github_project": "nonebot-plugin-sqlalchemy",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "nonebot-plugin-sqlalchemy"
}
        
Elapsed time: 0.10259s