{"id":16804356,"url":"https://github.com/he0119/nonebot-plugin-datastore","last_synced_at":"2025-04-05T15:03:50.196Z","repository":{"id":37279587,"uuid":"450687124","full_name":"he0119/nonebot-plugin-datastore","owner":"he0119","description":"适用于 NoneBot2 的数据存储插件","archived":false,"fork":false,"pushed_at":"2025-01-06T22:43:10.000Z","size":824,"stargazers_count":60,"open_issues_count":3,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-29T14:07:26.732Z","etag":null,"topics":["alembic","nonebot2","plugin","sqlmodel"],"latest_commit_sha":null,"homepage":"","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/he0119.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2022-01-22T01:23:42.000Z","updated_at":"2025-01-04T06:46:11.000Z","dependencies_parsed_at":"2024-02-28T09:36:57.045Z","dependency_job_id":"01e0a7a7-d926-4719-8720-230301136cbe","html_url":"https://github.com/he0119/nonebot-plugin-datastore","commit_stats":{"total_commits":150,"total_committers":4,"mean_commits":37.5,"dds":"0.16000000000000003","last_synced_commit":"1f472fdc651015b367d3e24e7cf6d3e830720fbb"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/he0119%2Fnonebot-plugin-datastore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/he0119%2Fnonebot-plugin-datastore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/he0119%2Fnonebot-plugin-datastore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/he0119%2Fnonebot-plugin-datastore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/he0119","download_url":"https://codeload.github.com/he0119/nonebot-plugin-datastore/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247353729,"owners_count":20925329,"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","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":["alembic","nonebot2","plugin","sqlmodel"],"created_at":"2024-10-13T09:44:51.824Z","updated_at":"2025-04-05T15:03:50.168Z","avatar_url":"https://github.com/he0119.png","language":"Python","readme":"\u003c!-- markdownlint-disable MD033 MD036 MD041 --\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://v2.nonebot.dev/\"\u003e\u003cimg src=\"https://v2.nonebot.dev/logo.png\" width=\"200\" height=\"200\" alt=\"nonebot\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n# NoneBot Plugin DataStore\n\n_✨ NoneBot 数据存储插件 ✨_\n\n\u003c/div\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://raw.githubusercontent.com/he0119/nonebot-plugin-datastore/main/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/he0119/nonebot-plugin-datastore.svg\" alt=\"license\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://pypi.python.org/pypi/nonebot-plugin-datastore\"\u003e\n    \u003cimg src=\"https://img.shields.io/pypi/v/nonebot-plugin-datastore.svg\" alt=\"pypi\"\u003e\n  \u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/python-3.9+-blue.svg\" alt=\"python\"\u003e\n  \u003ca href=\"https://codecov.io/gh/he0119/nonebot-plugin-datastore\"\u003e\n    \u003cimg src=\"https://codecov.io/gh/he0119/nonebot-plugin-datastore/branch/main/graph/badge.svg?token=jd5ufc1alv\"/ alt=\"python\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://jq.qq.com/?_wv=1027\u0026k=7zQUpiGp\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/QQ%E7%BE%A4-730374631-orange?style=flat-square\" alt=\"QQ Chat Group\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n## 安装\n\n- 使用 nb-cli\n\n```sh\nnb plugin install nonebot-plugin-datastore\n```\n\n- 使用 pip\n\n```sh\npip install nonebot-plugin-datastore\n```\n\n## 使用方式\n\n先在插件代码最前面声明依赖\n\n```python\nfrom nonebot import require\nrequire(\"nonebot_plugin_datastore\")\n```\n\n### 插件数据相关功能\n\n```python\nfrom nonebot_plugin_datastore import get_plugin_data\n\nplugin_data = get_plugin_data()\n\n# 获取插件缓存目录\nplugin_data.cache_dir\n# 获取插件配置目录\nplugin_data.config_dir\n# 获取插件数据目录\nplugin_data.data_dir\n\n# 读取配置\nawait plugin_data.config.get(key)\n# 存储配置\nawait plugin_data.config.set(key, value)\n```\n\n### 数据库相关功能，详细用法见 [SQLAlchemy](https://docs.sqlalchemy.org/orm/quickstart.html)\n\n```python\nfrom nonebot import on_command\nfrom nonebot.params import Depends\nfrom sqlalchemy.ext.asyncio.session import AsyncSession\nfrom sqlalchemy.orm import Mapped, mapped_column\n\nfrom nonebot_plugin_datastore import get_plugin_data, get_session\n\n# 定义模型\nModel = get_plugin_data().Model\n\nclass Example(Model):\n    \"\"\"示例模型\"\"\"\n\n    id: Mapped[int] = mapped_column(primary_key=True)\n    message: Mapped[str]\n\nmatcher = on_command(\"test\")\n\n# 数据库相关操作\n@matcher.handle()\nasync def handle(session: AsyncSession = Depends(get_session)):\n    example = Example(message=\"matcher\")\n    session.add(example)\n    await session.commit()\n\n# 因为 driver.on_startup 无法保证函数运行顺序\n# 如需在 NoneBot 启动时且数据库初始化后运行的函数\n# 请使用 post_db_init 而不是 Nonebot 的 on_startup\nfrom nonebot_plugin_datastore.db import post_db_init\n\n\n@post_db_init\nasync def do_something():\n  pass\n```\n\n### 命令行支持（需安装 [nb-cli 1.0+](https://github.com/nonebot/nb-cli)）\n\n如果使用 pipx 安装的 nb-cli，则需要运行 `pip install nonebot-plugin-datastore[cli]` 安装命令行所需依赖。\n\n#### 数据存储路径\n\n```shell\n# 获取当前数据存储路径\nnb datastore dir\n# 获取指定插件的数据存储路径\nnb datastore dir --name plugin_name\n```\n\n#### 数据库管理，详细用法见 [Alembic](https://alembic.sqlalchemy.org/en/latest/)\n\n生成迁移文件\n\n```shell\n# 生成项目内所有启用数据库插件的迁移文件（不包括 site-packages 中的插件）\nnb datastore migrate\n# 生成指定插件的迁移文件\nnb datastore migrate --name plugin_name -m example\n```\n\n升级插件数据库\n\n```shell\n# 升级所有启用数据库插件的数据库\nnb datastore upgrade\n# 升级指定插件的数据库\nnb datastore upgrade --name plugin_name\n# 升级至指定版本\nnb datastore upgrade --name plugin_name revision\n```\n\n降级插件数据库\n\n```shell\n# 降级所有启用数据库插件的数据库\nnb datastore downgrade\n# 降级指定插件的数据库\nnb datastore downgrade --name plugin_name\n# 降级至指定版本\nnb datastore downgrade --name plugin_name revision\n```\n\n## 注意\n\n### 数据库迁移\n\n推荐启动机器人前运行 `nb datastore upgrade` 升级数据库至最新版本。因为当前插件自动迁移依赖 `NoneBot` 的 `on_startup` 钩子，很容易受到其他插件影响。\n\n这里推荐 [tiangolo/uvicorn-gunicorn](https://github.com/tiangolo/uvicorn-gunicorn-docker) 镜像，通过配置 `prestart.sh` 可确保启动机器人前运行迁移脚本。具体的例子可参考 [CoolQBot](https://github.com/he0119/CoolQBot/)。\n\n### MySQL 数据库连接丢失\n\n当使用 `MySQL` 时，你可能会遇到 `2013: lost connection to mysql server during query` 的报错。\n\n如果遇到这种错误，可以尝试设置 `pool_recycle` 为一个小于数据库超时的值。或者设置 `pool_pre_ping` 为 `True`。\n\n```env\nDATASTORE_ENGINE_OPTIONS={\"pool_recycle\": 3600}\nDATASTORE_ENGINE_OPTIONS={\"pool_pre_ping\": true}\n```\n\n详细介绍可查看 `SQLAlchemy` 文档的 [dealing-with-disconnects](https://docs.sqlalchemy.org/en/20/core/pooling.html#dealing-with-disconnects) 章节。\n\n### SQLite 数据库已锁定\n\n使用 `SQLite` 数据库时，如果在写入时遇到 `(sqlite3.OperationalError) database is locked` 错误。可尝试将 `poolclass` 设置为 `StaticPool`，保持有且仅有一个连接。不过这样设置之后，在程序运行期间，你的数据库文件都将被占用。\n\n### 不同插件间表的关联关系\n\ndatastore 默认会给每个插件的 Base 模型提供独立的 registry，所以不同插件间的表无法建立关联关系。如果你需要与其他插件的表建立关联关系，请在需要关联的两个插件中都调用 use_global_registry 函数使用全局 registry。\n\n```python\n# 定义模型\ndb = get_plugin_data()\ndb.use_global_registry()\n\nclass Example(db.Model):\n    \"\"\"实例函数\"\"\"\n\n    id: Mapped[int] = mapped_column(primary_key=True)\n    message: Mapped[str]\n\n    tests: Mapped[\"Test\"] = relationship(back_populates=\"example\")\n\n\nclass Test(db.Model):\n    id: Mapped[int] = mapped_column(primary_key=True)\n\n    example_id: Mapped[int] = mapped_column(ForeignKey(\"plugin_example.id\"))\n    example: Mapped[Example] = relationship(back_populates=\"tests\")\n\n# 注意，为了避免不同插件的模型同名而报错，请一定要加上这一行，避免如下报错\n# sqlalchemy.exc.InvalidRequestError: Multiple classes found for path \"Test\" in the registry of this declarative base. Please use a fully module-qualified path.\nExample.tests = relationship(Test, back_populates=\"example\")\n```\n\n## 配置项\n\n配置方式：直接在 `NoneBot` 全局配置文件中添加以下配置项即可。\n\n### datastore_cache_dir\n\n- 类型: `Path`\n- 默认:\n  - macOS: ~/Library/Caches/nonebot2\n  - Unix: ~/.cache/nonebot2 (XDG default)\n  - Windows: C:\\Users\\\u003cusername\u003e\\AppData\\Local\\nonebot2\\Cache\n- 说明: 缓存目录\n\n### datastore_config_dir\n\n- 类型: `Path`\n- 默认:\n  - macOS: same as user_data_dir\n  - Unix: ~/.config/nonebot2\n  - Win XP (roaming): C:\\Documents and Settings\\\u003cusername\u003e\\Local Settings\\Application Data\\nonebot2\n  - Win 7 (roaming): C:\\Users\\\u003cusername\u003e\\AppData\\Roaming\\nonebot2\n- 说明: 配置目录\n\n### datastore_data_dir\n\n- 类型: `Path`\n- 默认:\n  - macOS: ~/Library/Application Support/nonebot2\n  - Unix: ~/.local/share/nonebot2 or in $XDG_DATA_HOME, if defined\n  - Win XP (not roaming): C:\\Documents and Settings\\\u003cusername\u003e\\Application Data\\nonebot2\n  - Win 7 (not roaming): C:\\Users\\\u003cusername\u003e\\AppData\\Local\\nonebot2\n- 说明: 数据目录\n\n### datastore_enable_database\n\n- 类型: `bool`\n- 默认: `True`\n- 说明: 是否启动数据库\n\n### datastore_database_url\n\n- 类型: `str`\n- 默认: `sqlite+aiosqlite:///data_dir/data.db`\n- 说明: 数据库连接字符串，默认使用 SQLite 数据库\n\n### datastore_database_echo\n\n- 类型: `bool`\n- 默认: `False`\n- 说明: `echo` 和 `echo_pool` 的默认值，是否显示数据库执行的语句与其参数列表，还有连接池的相关信息\n\n### datastore_engine_options\n\n- 类型: `dict[str, Any]`\n- 默认: `{}`\n- 说明: 向 `sqlalchemy.ext.asyncio.create_async_engine()` 传递的参数\n\n### datastore_config_provider\n\n- 类型: `str`\n- 默认: `~json`\n- 说明: 选择存放配置的类型，当前支持 json, yaml, toml, database 四种类型，也可设置为实现 `ConfigProvider` 的自定义类型。\n\n## 鸣谢\n\n- [`NoneBot Plugin LocalStore`](https://github.com/nonebot/plugin-localstore): 提供了默认的文件存储位置\n- [`Flask-SQLAlchemy`](https://github.com/pallets-eco/flask-sqlalchemy/): 借鉴了数据库的实现思路\n- [`Flask-Alembic`](https://github.com/davidism/flask-alembic): 借鉴了命令行的实现思路\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhe0119%2Fnonebot-plugin-datastore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhe0119%2Fnonebot-plugin-datastore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhe0119%2Fnonebot-plugin-datastore/lists"}