<p align="center">
<h1 align="center">Cherry ORM</h1>
<p align="center">Python 异步 ORM</p>
</p>
<p align="center">
<a href="./LICENSE">
<img src="https://img.shields.io/github/license/CMHopeSunshine/cherry-orm.svg" alt="license">
</a>
<a href="https://pypi.python.org/pypi/cherry-orm">
<img src="https://img.shields.io/pypi/v/cherry-orm.svg" alt="pypi">
</a>
<a href="https://www.python.org/">
<img src="https://img.shields.io/badge/python-3.9+-blue.svg" alt="python">
</a>
</p>
<p align="center">
<strong>简体中文</strong>
·
<a href="https://github.com/CMHopeSunshine/cherry-orm/blob/master/README_EN.md">English</a>
</p>
## 简介
`Cherry ORM` 是一个 Python 的异步对象关系映射(ORM)库,它基于 [SQLAlchemy Core](https://www.sqlalchemy.org/) 和 [Pydantic V2](https://docs.pydantic.dev/latest/) 构建。
它的一切设计都是为了简单易用,极大地减少开发者的数据库操作成本,提高开发效率,让开发者更专注于业务逻辑的实现。
## 安装
- 使用 pip: `pip install cherry-orm`
- 使用 Poetry: `poetry add cherry-orm`
- 使用 PDM: `pdm add cherry-orm`
## 文档
-> [文档地址](https://cherry.cherishmoon.top)
## 示例
```python
from datetime import date
from typing import List, Optional
import cherry
db = cherry.Database("sqlite+aiosqlite:///:memory:")
class Student(cherry.Model):
id: int = cherry.Field(primary_key=True)
name: str = cherry.Field(unique=True, index=True)
age: int
birthday: date = cherry.Field(default_factory=date.today)
school: cherry.ForeignKey[Optional["School"]] = None
cherry_config = cherry.CherryConfig(tablename="student", database=db)
class School(cherry.Model):
id: cherry.PrimaryKey[int]
name: str = cherry.Field(unique=True, index=True)
students: cherry.ReverseRelation[List[Student]] = []
cherry_config = cherry.CherryConfig(tablename="school", database=db)
async def main():
await db.init()
# 插入
school = await School(id=1, name="school 1").insert()
student1 = await Student(id=1, name="student 1", age=15, school=school).insert()
await Student(id=2, name="student 2", age=18, school=school).insert()
await Student(id=3, name="student 3", age=20, school=school).insert()
# 更新
student1.age += 1
await student1.save()
# or
await student1.update(age=19)
# 获取关联的模型
await school.fetch_related(School.students)
assert len(school.students) == 3
# 条件查询
# Pythonic 风格
student2: Student = await Student.filter(Student.name == "student 2").get()
# Django 风格
student2: Student = await Student.filter(name="student 2").get()
students: List[Student] = await Student.filter(Student.age >= 18).all()
# 聚合查询
student_nums: int = await Student.filter(Student.age >= 18).count()
assert len(students) == student_nums
student_age_avg: Optional[int] = await Student.select().avg(Student.age)
# 查询时预取关联模型
student_with_school: Student = (
await Student.filter(Student.name == "student 3")
.prefetch_related(Student.school)
.get()
)
# 选择更新
await Student.select().update(birthday=date(2023, 10, 1))
# 选择删除
await Student.filter(Student.age >= 20).delete()
```
Raw data
{
"_id": null,
"home_page": null,
"name": "cherry-orm",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": "database, orm, sqlalchemy, pydantic, asyncio",
"author": "CMHopeSunshine",
"author_email": "277073121@qq.com",
"download_url": "https://files.pythonhosted.org/packages/f5/b9/e16a159caa7d0bca2c967efd497bc9ef72f3a14651754018ac3ca176fc89/cherry_orm-1.0.0.tar.gz",
"platform": null,
"description": "<p align=\"center\">\n <h1 align=\"center\">Cherry ORM</h1>\n <p align=\"center\">Python \u5f02\u6b65 ORM</p>\n</p>\n<p align=\"center\">\n <a href=\"./LICENSE\">\n <img src=\"https://img.shields.io/github/license/CMHopeSunshine/cherry-orm.svg\" alt=\"license\">\n </a>\n <a href=\"https://pypi.python.org/pypi/cherry-orm\">\n <img src=\"https://img.shields.io/pypi/v/cherry-orm.svg\" alt=\"pypi\">\n </a>\n <a href=\"https://www.python.org/\">\n <img src=\"https://img.shields.io/badge/python-3.9+-blue.svg\" alt=\"python\">\n </a>\n</p>\n\n<p align=\"center\">\n <strong>\u7b80\u4f53\u4e2d\u6587</strong>\n \u00b7\n <a href=\"https://github.com/CMHopeSunshine/cherry-orm/blob/master/README_EN.md\">English</a>\n</p>\n\n## \u7b80\u4ecb\n\n`Cherry ORM` \u662f\u4e00\u4e2a Python \u7684\u5f02\u6b65\u5bf9\u8c61\u5173\u7cfb\u6620\u5c04\uff08ORM\uff09\u5e93\uff0c\u5b83\u57fa\u4e8e [SQLAlchemy Core](https://www.sqlalchemy.org/) \u548c [Pydantic V2](https://docs.pydantic.dev/latest/) \u6784\u5efa\u3002\n\n\u5b83\u7684\u4e00\u5207\u8bbe\u8ba1\u90fd\u662f\u4e3a\u4e86\u7b80\u5355\u6613\u7528\uff0c\u6781\u5927\u5730\u51cf\u5c11\u5f00\u53d1\u8005\u7684\u6570\u636e\u5e93\u64cd\u4f5c\u6210\u672c\uff0c\u63d0\u9ad8\u5f00\u53d1\u6548\u7387\uff0c\u8ba9\u5f00\u53d1\u8005\u66f4\u4e13\u6ce8\u4e8e\u4e1a\u52a1\u903b\u8f91\u7684\u5b9e\u73b0\u3002\n\n## \u5b89\u88c5\n\n- \u4f7f\u7528 pip: `pip install cherry-orm`\n- \u4f7f\u7528 Poetry: `poetry add cherry-orm`\n- \u4f7f\u7528 PDM: `pdm add cherry-orm`\n\n## \u6587\u6863\n\n-> [\u6587\u6863\u5730\u5740](https://cherry.cherishmoon.top)\n\n## \u793a\u4f8b\n\n```python\nfrom datetime import date\nfrom typing import List, Optional\n\nimport cherry\n\ndb = cherry.Database(\"sqlite+aiosqlite:///:memory:\")\n\n\nclass Student(cherry.Model):\n id: int = cherry.Field(primary_key=True)\n name: str = cherry.Field(unique=True, index=True)\n age: int\n birthday: date = cherry.Field(default_factory=date.today)\n school: cherry.ForeignKey[Optional[\"School\"]] = None\n\n cherry_config = cherry.CherryConfig(tablename=\"student\", database=db)\n\n\nclass School(cherry.Model):\n id: cherry.PrimaryKey[int]\n name: str = cherry.Field(unique=True, index=True)\n students: cherry.ReverseRelation[List[Student]] = []\n\n cherry_config = cherry.CherryConfig(tablename=\"school\", database=db)\n\n\nasync def main():\n await db.init()\n\n # \u63d2\u5165\n school = await School(id=1, name=\"school 1\").insert()\n student1 = await Student(id=1, name=\"student 1\", age=15, school=school).insert()\n await Student(id=2, name=\"student 2\", age=18, school=school).insert()\n await Student(id=3, name=\"student 3\", age=20, school=school).insert()\n\n # \u66f4\u65b0\n student1.age += 1\n await student1.save()\n # or\n await student1.update(age=19)\n\n # \u83b7\u53d6\u5173\u8054\u7684\u6a21\u578b\n await school.fetch_related(School.students)\n assert len(school.students) == 3\n\n # \u6761\u4ef6\u67e5\u8be2\n # Pythonic \u98ce\u683c\n student2: Student = await Student.filter(Student.name == \"student 2\").get()\n # Django \u98ce\u683c\n student2: Student = await Student.filter(name=\"student 2\").get()\n\n students: List[Student] = await Student.filter(Student.age >= 18).all()\n\n # \u805a\u5408\u67e5\u8be2\n student_nums: int = await Student.filter(Student.age >= 18).count()\n assert len(students) == student_nums\n student_age_avg: Optional[int] = await Student.select().avg(Student.age)\n\n # \u67e5\u8be2\u65f6\u9884\u53d6\u5173\u8054\u6a21\u578b\n student_with_school: Student = (\n await Student.filter(Student.name == \"student 3\")\n .prefetch_related(Student.school)\n .get()\n )\n\n # \u9009\u62e9\u66f4\u65b0\n await Student.select().update(birthday=date(2023, 10, 1))\n # \u9009\u62e9\u5220\u9664\n await Student.filter(Student.age >= 20).delete()\n```\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Python asynchronous ORM based on SQLAlchemy and Pydantic.",
"version": "1.0.0",
"project_urls": null,
"split_keywords": [
"database",
" orm",
" sqlalchemy",
" pydantic",
" asyncio"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "3a583ff6b2c80b2a0b165351e49316fc0a0f00c9de6b3e5a41607b2a2adf3915",
"md5": "674198c891003cae59debfee95122578",
"sha256": "2549e96e1e0d45555c9a95e212c1924af4418eb4925e02e8621abe529cd5a0f0"
},
"downloads": -1,
"filename": "cherry_orm-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "674198c891003cae59debfee95122578",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 28797,
"upload_time": "2024-05-16T03:17:47",
"upload_time_iso_8601": "2024-05-16T03:17:47.611253Z",
"url": "https://files.pythonhosted.org/packages/3a/58/3ff6b2c80b2a0b165351e49316fc0a0f00c9de6b3e5a41607b2a2adf3915/cherry_orm-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "f5b9e16a159caa7d0bca2c967efd497bc9ef72f3a14651754018ac3ca176fc89",
"md5": "0004dc496463260a5e645c33d1349824",
"sha256": "e98034100a0d04057e1a524a30bcac1e15e9eb60dea4700626e69237710cf846"
},
"downloads": -1,
"filename": "cherry_orm-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "0004dc496463260a5e645c33d1349824",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 25040,
"upload_time": "2024-05-16T03:17:48",
"upload_time_iso_8601": "2024-05-16T03:17:48.748409Z",
"url": "https://files.pythonhosted.org/packages/f5/b9/e16a159caa7d0bca2c967efd497bc9ef72f3a14651754018ac3ca176fc89/cherry_orm-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-05-16 03:17:48",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "cherry-orm"
}