I'm trying to use the rom
Python ORM for storing objects in Redis.
I have the following model:
import rom
class Repository(rom.Model):
id = rom.PrimaryKey()
topics = rom.Json()
And I would like to create an instance where I can manually set the primary key, such as the following:
repo = Repository()
repo.id = 1337
repo.topics = ["topic1", "topic2"]
Nevertheless, when I try to do that I get the following error:
Traceback (most recent call last): [...] raise InvalidOperation("Cannot update primary key value") rom.exceptions.InvalidOperation: Cannot update primary key value
Essentially, I would like to be able to set the primary key's value so that in the database the entries can look like:
127.0.0.1:6379[1]> KEYS *
1) "Repository:243"
2) "Repository:1337"
3) "Repository:9001"
Rather than:
127.0.0.1:6379[1]> KEYS *
1) "Repository:1"
2) "Repository:2"
3) "Repository:3"
Yes, there is a way, though not by default as you have found. As long as you're using Integers, there is a bit of magic you can do to make it happen.
First off, this is normally not possible because the Model's metaclass forces Primary keys, and forces the attribute to be unset on initialization. However, based on the internal and undocumented API that I promise not to change (I use it too), you can:
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)
There are a couple internal hooks in there if you want to bypass the session or other things, check out the internal args as used and peppered through the __init__
method: https://github.com/josiahcarlson/rom/blob/master/rom/model.py#L247