24
24
no_type_check ,
25
25
)
26
26
27
+ from more_itertools import ichunked
27
28
from pydantic import BaseModel , validator
28
29
from pydantic .fields import FieldInfo as PydanticFieldInfo
29
30
from pydantic .fields import ModelField , Undefined , UndefinedType
@@ -1117,9 +1118,17 @@ def key(self):
1117
1118
return self .make_primary_key (pk )
1118
1119
1119
1120
@classmethod
1120
- async def delete (cls , pk : Any ) -> int :
1121
+ async def _delete (cls , db , * pks ):
1122
+ return await db .delete (* pks )
1123
+
1124
+ @classmethod
1125
+ async def delete (
1126
+ cls , pk : Any , pipeline : Optional [redis .client .Pipeline ] = None
1127
+ ) -> int :
1121
1128
"""Delete data at this key."""
1122
- return await cls .db ().delete (cls .make_primary_key (pk ))
1129
+ db = cls ._get_db (pipeline )
1130
+
1131
+ return await cls ._delete (db , cls .make_primary_key (pk ))
1123
1132
1124
1133
@classmethod
1125
1134
async def get (cls , pk : Any ) -> "RedisModel" :
@@ -1137,10 +1146,7 @@ async def save(
1137
1146
async def expire (
1138
1147
self , num_seconds : int , pipeline : Optional [redis .client .Pipeline ] = None
1139
1148
):
1140
- if pipeline is None :
1141
- db = self .db ()
1142
- else :
1143
- db = pipeline
1149
+ db = self ._get_db (pipeline )
1144
1150
1145
1151
# TODO: Wrap any Redis response errors in a custom exception?
1146
1152
await db .expire (self .make_primary_key (self .pk ), num_seconds )
@@ -1232,16 +1238,7 @@ async def add(
1232
1238
pipeline : Optional [redis .client .Pipeline ] = None ,
1233
1239
pipeline_verifier : Callable [..., Any ] = verify_pipeline_response ,
1234
1240
) -> Sequence ["RedisModel" ]:
1235
- if pipeline is None :
1236
- # By default, send commands in a pipeline. Saving each model will
1237
- # be atomic, but Redis may process other commands in between
1238
- # these saves.
1239
- db = cls .db ().pipeline (transaction = False )
1240
- else :
1241
- # If the user gave us a pipeline, add our commands to that. The user
1242
- # will be responsible for executing the pipeline after they've accumulated
1243
- # the commands they want to send.
1244
- db = pipeline
1241
+ db = cls ._get_db (pipeline , bulk = True )
1245
1242
1246
1243
for model in models :
1247
1244
# save() just returns the model, we don't need that here.
@@ -1255,6 +1252,31 @@ async def add(
1255
1252
1256
1253
return models
1257
1254
1255
+ @classmethod
1256
+ def _get_db (
1257
+ self , pipeline : Optional [redis .client .Pipeline ] = None , bulk : bool = False
1258
+ ):
1259
+ if pipeline is not None :
1260
+ return pipeline
1261
+ elif bulk :
1262
+ return self .db ().pipeline (transaction = False )
1263
+ else :
1264
+ return self .db ()
1265
+
1266
+ @classmethod
1267
+ async def delete_many (
1268
+ cls ,
1269
+ models : Sequence ["RedisModel" ],
1270
+ pipeline : Optional [redis .client .Pipeline ] = None ,
1271
+ ) -> int :
1272
+ db = cls ._get_db (pipeline )
1273
+
1274
+ for chunk in ichunked (models , 100 ):
1275
+ pks = [cls .make_primary_key (model .pk ) for model in chunk ]
1276
+ await cls ._delete (db , * pks )
1277
+
1278
+ return len (models )
1279
+
1258
1280
@classmethod
1259
1281
def redisearch_schema (cls ):
1260
1282
raise NotImplementedError
@@ -1293,10 +1315,8 @@ async def save(
1293
1315
self , pipeline : Optional [redis .client .Pipeline ] = None
1294
1316
) -> "HashModel" :
1295
1317
self .check ()
1296
- if pipeline is None :
1297
- db = self .db ()
1298
- else :
1299
- db = pipeline
1318
+ db = self ._get_db (pipeline )
1319
+
1300
1320
document = jsonable_encoder (self .dict ())
1301
1321
# TODO: Wrap any Redis response errors in a custom exception?
1302
1322
await db .hset (self .key (), mapping = document )
@@ -1467,10 +1487,8 @@ async def save(
1467
1487
self , pipeline : Optional [redis .client .Pipeline ] = None
1468
1488
) -> "JsonModel" :
1469
1489
self .check ()
1470
- if pipeline is None :
1471
- db = self .db ()
1472
- else :
1473
- db = pipeline
1490
+ db = self ._get_db (pipeline )
1491
+
1474
1492
# TODO: Wrap response errors in a custom exception?
1475
1493
await db .execute_command ("JSON.SET" , self .key (), "." , self .json ())
1476
1494
return self
0 commit comments