Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

rorm-py

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

rorm-py

A simple ORM cache library for redis

  • 1.0.0
  • PyPI
  • Socket score

Maintainers
1

RORM

基于Redis的结构化存储驱动,使用者只需要定义数据模型,即可实现数据的持久化和缓存

rorm中,ORMModel作为数据模型使用,ORMCache将持有ORMModel的实例,并提供数据的持久化和缓存功能

注意事项与基本原理

  • ORMModel的子类需要实现unique_id方法,以便ORMCache能够正确的管理数据
  • 每个ORMCache实例都会对应redis中的一个hash结构,hash名为ORMCacheunique_id
    • keyORMCache的属性名与对应ORMModel的类型名以及ORMModelunique_id
    • valueORMModeljson序列化结果
  • 在调用ORMCache对象的save_all方法时,会将ORMCache实例中的所有ORMModel的实例保存到redis
    • ORMModel实现的标脏检查,只有数据发生变化时才会序列化并保存,因此不用担心序列化性能和访问redis过于频繁的问题

Example

定义ORMModel和ORMCache

@ORMCache.register
class RoleInfo(ORMModel):
    role_id: int = Field(0, title="角色id")
    role_name: str = Field("", title="角色名")
    role_level: int = Field(0, title="角色等级")

    def __init__(self,  /, **data) -> None:
        super().__init__(**data)

    def unique_id(self) -> str:
        return f"{self.role_id}"


@ORMCache.register
class ItemInfo(ORMModel):
    item_id: int = Field(0, title="物品id")
    item_name: str = Field("", title="物品名")
    item_count: int = Field(0, title="物品数量")

    def __init__(self,  /, **data) -> None:
        super().__init__(**data)

    def unique_id(self) -> str:
        return f"{self.item_id}"


@ORMCache.register
class MailInfo(ORMModel):
    mail_id: int = Field(0, title="邮件id")
    mail_title: str = Field("", title="邮件标题")
    mail_content: str = Field("", title="邮件内容")
    attarchments: list[ItemInfo] = []

    def __init__(self,  /, **data) -> None:
        super().__init__(**data)

    def unique_id(self) -> str:
        return f"{self.mail_id}"

class Player(ORMCache):

    role: RoleInfo = RoleInfo()
    items: dict[str, ItemInfo] = {}
    mails: list[MailInfo] = []
    tmp: list[str] = []

    def __init__(self, client: Redis, user_id: int) -> None:
        super().__init__(client)
        self.__user_id = user_id

    def unique_id(self) -> str:
        return f"{self.__class__.__qualname__}:{self.__user_id}"

存储数据

async def test_save(self):
    client = await Redis.from_url("redis://localhost:6379/0")
    player = Player(client, 10001)
    player.role = RoleInfo(
        role_id=10001, role_name="rorm-py", role_level=1)
    for i in range(1, 6):
        player.items[f"{i}"] = ItemInfo(
            item_id=i, item_name=f"item-{i}", item_count=i)
    for i in range(1, 6):
        player.mails.append(MailInfo(
            mail_id=i,
            mail_title=f"mail-{i}",
            mail_content=f"mail-{i}",
            attarchments=[ItemInfo(
                item_id=i,
                item_name=f"item-{i}",
                item_count=i)]
        ))
    player.tmp.append("not save")
    await player.save_all()
    await client.close()

注意 只有ORMModel类型的数据才会被存储

127.0.0.1:6379> KEYS *
1) "Player:10001"
127.0.0.1:6379> HGETALL Player:10001
 1) "mails:MailInfo:1"
 2) "{\"mail_id\":1,\"mail_title\":\"mail-1\",\"mail_content\":\"mail-1\",\"attarchments\":[{\"item_id\":1,\"item_name\":\"item-1\",\"item_count\":1}]}"
 3) "items:ItemInfo:1"
 4) "{\"item_id\":1,\"item_name\":\"item-1\",\"item_count\":1}"
 5) "items:ItemInfo:3"
 6) "{\"item_id\":3,\"item_name\":\"item-3\",\"item_count\":3}"
 7) "mails:MailInfo:2"
 8) "{\"mail_id\":2,\"mail_title\":\"mail-2\",\"mail_content\":\"mail-2\",\"attarchments\":[{\"item_id\":2,\"item_name\":\"item-2\",\"item_count\":2}]}"
 9) "items:ItemInfo:4"
10) "{\"item_id\":4,\"item_name\":\"item-4\",\"item_count\":4}"
11) "role:RoleInfo:10001"
12) "{\"role_id\":10001,\"role_name\":\"rorm-py\",\"role_level\":1}"
13) "mails:MailInfo:3"
14) "{\"mail_id\":3,\"mail_title\":\"mail-3\",\"mail_content\":\"mail-3\",\"attarchments\":[{\"item_id\":3,\"item_name\":\"item-3\",\"item_count\":3}]}"
15) "mails:MailInfo:4"
16) "{\"mail_id\":4,\"mail_title\":\"mail-4\",\"mail_content\":\"mail-4\",\"attarchments\":[{\"item_id\":4,\"item_name\":\"item-4\",\"item_count\":4}]}"
17) "items:ItemInfo:2"
18) "{\"item_id\":2,\"item_name\":\"item-2\",\"item_count\":2}"
19) "items:ItemInfo:5"
20) "{\"item_id\":5,\"item_name\":\"item-5\",\"item_count\":5}"
21) "mails:MailInfo:5"
22) "{\"mail_id\":5,\"mail_title\":\"mail-5\",\"mail_content\":\"mail-5\",\"attarchments\":[{\"item_id\":5,\"item_name\":\"item-5\",\"item_count\":5}]}"

读取数据

async def test_load(self):
    client = await Redis.from_url("redis://localhost:6379/0")
    player = Player(client, 10001)
    await player.load_from_redis()
    print(player.model_dump_json())
    await client.close()
{
    "role":{"role_id":10001,"role_name":"rorm-py","role_level":1},
    "items":{
        "1":{"item_id":1,"item_name":"item-1","item_count":1},
        "3":{"item_id":3,"item_name":"item-3","item_count":3},
        "4":{"item_id":4,"item_name":"item-4","item_count":4},
        "2":{"item_id":2,"item_name":"item-2","item_count":2},
        "5":{"item_id":5,"item_name":"item-5","item_count":5}
    },
    "mails":[
        {"mail_id":1,"mail_title":"mail-1","mail_content":"mail-1","attarchments":[{"item_id":1,"item_name":"item-1","item_count":1}]},
        {"mail_id":2,"mail_title":"mail-2","mail_content":"mail-2","attarchments":[{"item_id":2,"item_name":"item-2","item_count":2}]},
        {"mail_id":3,"mail_title":"mail-3","mail_content":"mail-3","attarchments":[{"item_id":3,"item_name":"item-3","item_count":3}]},
        {"mail_id":4,"mail_title":"mail-4","mail_content":"mail-4","attarchments":[{"item_id":4,"item_name":"item-4","item_count":4}]},
        {"mail_id":5,"mail_title":"mail-5","mail_content":"mail-5","attarchments":[{"item_id":5,"item_name":"item-5","item_count":5}]}],
    "tmp":[]
}

修改与删除数据

async def test_modify(self):
    client = await Redis.from_url("redis://localhost:6379/0")
    player = Player(client, 10001)
    await player.load_from_redis()

    player.role.role_level = 2
    for item in player.items.values():
        item.item_count += 1

    for mail in player.mails:
        mail.mail_content = "modify"
        for item in mail.attarchments:
            item.item_count += 1

    await player.save_all()

async def test_delete(self):
    client = await Redis.from_url("redis://localhost:6379/0")
    player = Player(client, 10001)
    await player.load_from_redis()

    player.role = RoleInfo()
    for key in list(player.items.keys()):
        if int(key) % 2 == 0:
            del player.items[key]

    for mail in list(player.mails):
        if mail.mail_id % 2 == 0:
            player.mails.remove(mail)

    await player.save_all()
127.0.0.1:6379> HGETALL Player:10001
 1) "role:RoleInfo:10001"
 2) "{\"role_id\":10001,\"role_name\":\"rorm-py\",\"role_level\":2}"
 3) "mails:MailInfo:3"
 4) "{\"mail_id\":3,\"mail_title\":\"mail-3\",\"mail_content\":\"modify\",\"attarchments\":[{\"item_id\":3,\"item_name\":\"item-3\",\"item_count\":4}]}"
 5) "role:RoleInfo:0"
 6) "{\"role_id\":0,\"role_name\":\"\",\"role_level\":0}"
 7) "mails:MailInfo:1"
 8) "{\"mail_id\":1,\"mail_title\":\"mail-1\",\"mail_content\":\"modify\",\"attarchments\":[{\"item_id\":1,\"item_name\":\"item-1\",\"item_count\":2}]}"
 9) "items:ItemInfo:5"
10) "{\"item_id\":5,\"item_name\":\"item-5\",\"item_count\":6}"
11) "items:ItemInfo:3"
12) "{\"item_id\":3,\"item_name\":\"item-3\",\"item_count\":4}"
13) "items:ItemInfo:1"
14) "{\"item_id\":1,\"item_name\":\"item-1\",\"item_count\":2}"
15) "mails:MailInfo:5"
16) "{\"mail_id\":5,\"mail_title\":\"mail-5\",\"mail_content\":\"modify\",\"attarchments\":[{\"item_id\":5,\"item_name\":\"item-5\",\"item_count\":6}]}"

License

This project is licensed under the MIT License - see the LICENSE file for details.

FAQs


Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc