首页 > 解决方案 > Redis 使用 Python ORM ROM 手动设置主键

问题描述

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

我有以下模型:

import rom

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

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

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

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

Traceback(最近一次调用最后一次):[...] raise InvalidOperation("Cannot update primary key value") rom.exceptions.InvalidOperation: Cannot update primary key value

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

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"

标签: python-3.xredisormredis-py

解决方案


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

首先,这通常是不可能的,因为模型的元类强制主键,并强制属性在初始化时取消设置。但是,基于我保证不会更改的内部和未记录的 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/模型.py#L247


推荐阅读