Redis使用Python ORM ROM手动设置主键

问题描述

我正在尝试使用 rom Python ORM 在 Redis 中存储对象。

我有以下模型:

import rom

class Repository(rom.Model):
    id = rom.PrimaryKey()
    topics = rom.Json()

我想创建一个可以手动设置主键的实例,如下所示:

repo = Repository()
repo.id = 1337
repo.topics = ["topic1","topic2"]

然而,当我尝试这样做时,我收到以下错误

回溯(最近一次调用最后一次): [...] raise InvalidOperation("无法更新主键值") rom.exceptions.InvalidOperation:无法更新主键值

本质上,我希望能够设置主键的值,以便在数据库中的条目看起来像:

127.0.0.1:6379[1]> KEYS *
1) "Repository:243"
2) "Repository:1337"
3) "Repository:9001"

而不是:

127.0.0.1:6379[1]> KEYS *
1) "Repository:1"
2) "Repository:2"
3) "Repository:3"

解决方法

是的,有一种方法,尽管不是您发现的默认情况。只要您使用整数,就可以使用一些魔法来实现它。

首先,这通常是不可能的,因为模型的元类强制主键,并强制在初始化时取消设置属性。但是,基于我保证不会更改的内部和未记录的 API(我也使用它),您可以:

def load_and_save_with_known_pk(model,data):
    """
    WARNING: will likely overwrite anything in Redis without a lock / check.
    WARNING: "data" may need to be encoded like how rom gets data out of
        Redis. It's probably something like: {"attr": json.dumps(<val>).encode(),...}
    """
    # I am how rom loads models from Redis itself,wow!
    entity = model(_loading=True,**data)
    # this is how you make sure that the data is persisted
    entity.save(force=True)

如果你想绕过会话或其他事情,那里有几个内部钩子,检查使用的内部参数并通过 __init__ 方法:https://github.com/josiahcarlson/rom/blob/master/rom/model.py#L247