Package: redis-simple-orm
WARNING: Old data might be replaced with new one without warningRedis Simple ORMRedis ORM in Simple Way.As an inspiration and a very good alternative,
please take a look onwalrus.NOTE: Please be aware, Your data might be replaced without warning.InstallationSync and Async withRedis-Pypipinstallredis_simple_orm[redis-py]ORUsingtxredisapipipinstallredis_simple_orm[txredisapi]Usage Example IntroWe are going to save data of users which listed ontests/data.py.
Please go take a look.
Copytests/data.pyto current directory.Then we are going to make theModeland save it toredis.
We also make the redis data is searchable byid,username,emailandgroup_id.Usage ExampleModelmodel.pyfromdataclassesimportdataclass,fieldfromredisimportRedisfromRSO.indeximportHashIndex,SetIndexfromRSO.modelimportModelfromtests.dataimportUSERSREDIS_MODEL_PREFIX=None@dataclassclassUserModel(Model):__prefix__=REDIS_MODEL_PREFIX__model_name__='user'__key__='user_id'user_id:intusername:stremail:str=field(default=None)group_id:int=field(default=None)defto_redis(self):result={}forkey,valueinself.dict().items():# email and group_id might be NoneifvalueisNone:continueelse:result[key]=valuereturnresult"""For easier access, we create some searching method"""@classmethoddefsearch_by_username(cls,redis:Redis,username:str):returnSingleIndexUsername.search_model(redis,username)@classmethoddefsearch_by_email(cls,redis:Redis,email:str):returnSingleIndexEmail.search_model(redis,email)@classmethoddefsearch_group_member(cls,redis:Redis,group_id:int):returnSetIndexGroupID.search_models(redis,group_id)classSingleIndexUsername(HashIndex):__prefix__=REDIS_MODEL_PREFIX__model__=UserModel__key__='username'classSingleIndexEmail(HashIndex):__prefix__=REDIS_MODEL_PREFIX__model__=UserModel__key__='email'classSetIndexGroupID(SetIndex):__prefix__=REDIS_MODEL_PREFIX__model__=UserModel__key__='group_id'UserModel.__indexes__=[SingleIndexUsername,SingleIndexEmail,SetIndexGroupID]CRUDcrud.pyimportosfromredisimportRedisfromtests.dataimportUSERSfrommodelimportUserModelredis=Redis(db=int(os.getenv('REDIS_DB',15)),password=os.getenv('REDIS_PASS','RedisPassword'),decode_responses=True)defcreate_user(redis:Redis,user_data:dict):user=UserModel(**user_data)user.save(redis)returnuserdefmain():# save all userforuser_datainUSERS:user=create_user(redis,user_data)user.save(redis)"""Now see how is the model and index data saved on redis :)"""# search by iduser=UserModel.search(redis,1)assertuserisnotNone# search by usernameuser=UserModel.search_by_username(redis,'first_user')assertuserisnotNoneuser=UserModel.search_by_username(redis,'not_exist')assertuserisNone# search by emailuser=UserModel.search_by_email(redis,'first_user@contoh.com')assertuserisnotNoneuser=UserModel.search_by_email(redis,'not_exist@contoh.com')assertuserisNone# search by group idusers=UserModel.search_group_member(redis,1)assertlen(users)==3users=UserModel.search_group_member(redis,2)assertlen(users)==2users=UserModel.search_group_member(redis,1_000_000)assertlen(users)==0main()Usage Example (asyncioversion, also works withaioredisv.2.x)Modelmodel.pyfromdataclassesimportdataclass,fieldfromredis.asyncioimportRedisfromRSO.asyncio.indeximport(HashIndexasAsyncHashIndex,SetIndexasAsyncSetIndex)fromRSO.asyncio.modelimportModelasAsyncModelfromtests.dataimportUSERSREDIS_MODEL_PREFIX=None@dataclassclassAsyncUserModel(AsyncModel):__prefix__=REDIS_MODEL_PREFIX__model_name__='user'__key__='user_id'user_id:intusername:stremail:str=field(default=None)group_id:int=field(default=None)defto_redis(self):result={}forkey,valueinself.dict().items():ifvalueisNone:continueresult[key]=valuereturnresult"""For easier access, we create some searching method"""@classmethodasyncdefsearch_by_username(cls,redis:Redis,username:str):returnawaitAsyncSingleIndexUsername.search_model(redis,username)@classmethodasyncdefsearch_by_email(cls,redis:Redis,email:str):returnawaitAsyncSingleIndexEmail.search_model(redis,email)@classmethodasyncdefsearch_group_member(cls,redis:Redis,group_id:int):returnawaitAsyncSetIndexGroupID.search_models(redis,group_id)classAsyncSingleIndexUsername(AsyncHashIndex):__prefix__=REDIS_MODEL_PREFIX__model__=AsyncUserModel__key__='username'classAsyncSingleIndexEmail(AsyncHashIndex):__prefix__=REDIS_MODEL_PREFIX__model__=AsyncUserModel__key__='email'classAsyncSetIndexGroupID(AsyncSetIndex):__prefix__=REDIS_MODEL_PREFIX__model__=AsyncUserModel__key__='group_id'AsyncUserModel.__indexes__=[AsyncSingleIndexUsername,AsyncSingleIndexEmail,AsyncSetIndexGroupID]CRUDcrud.pyimportasyncioimportos# from aioredis import Redisfromredis.asyncioimportRedisfromtests.dataimportUSERSfrommodelimportAsyncUserModelredis=Redis.from_url('redis://localhost',decode_responses=True,db=int(os.getenv('REDIS_DB',15)),password=os.getenv('REDIS_PASS','RedisPassword'),)asyncdefmain():# save all userforuser_datainUSERS:user=AsyncUserModel(**user_data)awaituser.save(redis)"""Now see how is the model and index data saved on redis :)"""# search by iduser=awaitAsyncUserModel.search(redis,1)assertuserisnotNone# search by usernameuser=awaitAsyncUserModel.search_by_username(redis,'first_user')assertuserisnotNoneuser=awaitAsyncUserModel.search_by_username(redis,'not_exist')assertuserisNone# search by emailuser=awaitAsyncUserModel.search_by_email(redis,'first_user@contoh.com')assertuserisnotNoneuser=awaitAsyncUserModel.search_by_email(redis,'not_exist@contoh.com')assertuserisNone# search by group idusers=awaitAsyncUserModel.search_group_member(redis,1)assertlen(users)==3users=awaitAsyncUserModel.search_group_member(redis,2)assertlen(users)==2users=awaitAsyncUserModel.search_group_member(redis,1_000_000)assertlen(users)==0asyncio.run(main())Usage Example (twistedversion)Modelmodel.pyfromdataclassesimportdataclass,fieldfromtwisted.internet.deferimportinlineCallbacksfromtxredisapiimportConnectionHandlerfromRSO.txredisapi.indeximportHashIndex,SetIndexfromRSO.txredisapi.modelimportModelREDIS_MODEL_PREFIX=None@dataclassclassUserModel(Model):__prefix__=REDIS_MODEL_PREFIX__model_name__='user'__key__='user_id'user_id:intusername:stremail:str=field(default=None)group_id:int=field(default=None)@classmethod@inlineCallbacksdefsearch_by_username(cls,redis:ConnectionHandler,username:str):result=yieldSingleIndexUsername.search_model(redis,username)returnresult@classmethod@inlineCallbacksdefsearch_by_email(cls,redis:ConnectionHandler,email:str):result=yieldSingleIndexEmail.search_model(redis,email)returnresult@classmethod@inlineCallbacksdefsearch_by_email(cls,redis:ConnectionHandler,group_id:int):result=yieldSetIndexGroupID.search_models(redis,group_id)returnresult@classmethod@inlineCallbacksdefsearch_group_member(cls,redis:ConnectionHandler,group_id:int):result=yieldSetIndexGroupID.search_models(redis,group_id)returnresultclassSingleIndexUsername(HashIndex):__prefix__=REDIS_MODEL_PREFIX__model__=UserModel__key__='username'classSingleIndexEmail(HashIndex):__prefix__=REDIS_MODEL_PREFIX__model__=UserModel__key__='email'classSetIndexGroupID(SetIndex):__prefix__=REDIS_MODEL_PREFIX__model__=UserModel__key__='group_id'UserModel.__indexes__=[SingleIndexUsername,SingleIndexEmail,SetIndexGroupID,]CRUDcrud.pyimporttxredisapifromtwisted.internetimportreactorfromtwisted.internet.deferimportinlineCallbacksfromtests.dataimportUSERSfrommodelimportUserModel@inlineCallbacksdefmain():redis=yieldtxredisapi.Connection(dbid=15,password='RedisPassword')foruser_datainUSERS:user=UserModel(**user_data)yielduser.save(redis)user=yieldUserModel.search(redis,1)assertuserisnotNone# search by usernameuser=yieldUserModel.search_by_username(redis,'first_user')assertuserisnotNoneuser=yieldUserModel.search_by_username(redis,'not_found')assertuserisNone# search by emailuser=yieldUserModel.search_by_email(redis,'first_user@contoh.com')assertuserisnotNoneuser=yieldUserModel.search_by_email(redis,'not_exist@contoh.com')assertuserisNone# search by group idusers=yieldUserModel.search_group_member(redis,1)assertlen(users)==3users=yieldUserModel.search_group_member(redis,2)assertlen(users)==2users=yieldUserModel.search_group_member(redis,1_000_000)assertlen(users)==0if__name__=="__main__":main()\.addCallback(lambdaign:reactor.stop())\.addErrback(lambdaign:reactor.stop())reactor.run()