Skip to content

Commit 09e53a1

Browse files
committed
Add support for hashmaps
1 parent d94a7f9 commit 09e53a1

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

changelog.d/598.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support HashMaps

django_redis/cache.py

+20
Original file line numberDiff line numberDiff line change
@@ -184,3 +184,23 @@ def close(self, **kwargs):
184184
@omit_exception
185185
def touch(self, *args, **kwargs):
186186
return self.client.touch(*args, **kwargs)
187+
188+
@omit_exception
189+
def hset(self, *args, **kwargs):
190+
return self.client.hset(*args, **kwargs)
191+
192+
@omit_exception
193+
def hdel(self, *args, **kwargs):
194+
return self.client.hdel(*args, **kwargs)
195+
196+
@omit_exception
197+
def hlen(self, *args, **kwargs):
198+
return self.client.hlen(*args, **kwargs)
199+
200+
@omit_exception
201+
def hkeys(self, *args, **kwargs):
202+
return self.client.hkeys(*args, **kwargs)
203+
204+
@omit_exception
205+
def hexists(self, *args, **kwargs):
206+
return self.client.hexists(*args, **kwargs)

django_redis/client/default.py

+76
Original file line numberDiff line numberDiff line change
@@ -813,3 +813,79 @@ def touch(
813813
# Convert to milliseconds
814814
timeout = int(timeout * 1000)
815815
return bool(client.pexpire(key, timeout))
816+
817+
def hset(
818+
self,
819+
name: str,
820+
key: KeyT,
821+
value: EncodableT,
822+
version: Optional[int] = None,
823+
client: Optional[Redis] = None,
824+
) -> int:
825+
"""
826+
Set the value of hash name at key to value.
827+
Returns the number of fields added to the hash.
828+
"""
829+
if client is None:
830+
client = self.get_client(write=True)
831+
nkey = self.make_key(key, version=version)
832+
nvalue = self.encode(value)
833+
return int(client.hset(name, nkey, nvalue))
834+
835+
def hdel(
836+
self,
837+
name: str,
838+
key: KeyT,
839+
version: Optional[int] = None,
840+
client: Optional[Redis] = None,
841+
) -> int:
842+
"""
843+
Remove keys from hash name.
844+
Returns the number of fields deleted from the hash.
845+
"""
846+
if client is None:
847+
client = self.get_client(write=True)
848+
nkey = self.make_key(key, version=version)
849+
return int(client.hdel(name, nkey))
850+
851+
def hlen(
852+
self,
853+
name: str,
854+
client: Optional[Redis] = None,
855+
) -> int:
856+
"""
857+
Return the number of items in hash name.
858+
"""
859+
if client is None:
860+
client = self.get_client(write=False)
861+
return int(client.hlen(name))
862+
863+
def hkeys(
864+
self,
865+
name: str,
866+
client: Optional[Redis] = None,
867+
) -> List:
868+
"""
869+
Return a list of keys in hash name.
870+
"""
871+
if client is None:
872+
client = self.get_client(write=False)
873+
try:
874+
return [self.reverse_key(k.decode()) for k in client.hkeys(name)]
875+
except _main_exceptions as e:
876+
raise ConnectionInterrupted(connection=client) from e
877+
878+
def hexists(
879+
self,
880+
name: str,
881+
key: KeyT,
882+
version: Optional[int] = None,
883+
client: Optional[Redis] = None,
884+
) -> bool:
885+
"""
886+
Return True if key exists in hash name, else False.
887+
"""
888+
if client is None:
889+
client = self.get_client(write=False)
890+
nkey = self.make_key(key, version=version)
891+
return bool(client.hexists(name, nkey))

tests/test_backend.py

+38
Original file line numberDiff line numberDiff line change
@@ -797,3 +797,41 @@ def test_clear(self, cache: RedisCache):
797797
cache.clear()
798798
value_from_cache_after_clear = cache.get("foo")
799799
assert value_from_cache_after_clear is None
800+
801+
def test_hset(self, cache: RedisCache):
802+
cache.hset("foo_hash1", "foo1", "bar1")
803+
cache.hset("foo_hash1", "foo2", "bar2")
804+
assert cache.hlen("foo_hash1") == 2
805+
assert cache.hexists("foo_hash1", "foo1")
806+
assert cache.hexists("foo_hash1", "foo2")
807+
808+
def test_hdel(self, cache: RedisCache):
809+
cache.hset("foo_hash2", "foo1", "bar1")
810+
cache.hset("foo_hash2", "foo2", "bar2")
811+
assert cache.hlen("foo_hash2") == 2
812+
deleted_count = cache.hdel("foo_hash2", "foo1")
813+
assert deleted_count == 1
814+
assert cache.hlen("foo_hash2") == 1
815+
assert not cache.hexists("foo_hash2", "foo1")
816+
assert cache.hexists("foo_hash2", "foo2")
817+
818+
def test_hlen(self, cache: RedisCache):
819+
assert cache.hlen("foo_hash3") == 0
820+
cache.hset("foo_hash3", "foo1", "bar1")
821+
assert cache.hlen("foo_hash3") == 1
822+
cache.hset("foo_hash3", "foo2", "bar2")
823+
assert cache.hlen("foo_hash3") == 2
824+
825+
def test_hkeys(self, cache: RedisCache):
826+
cache.hset("foo_hash4", "foo1", "bar1")
827+
cache.hset("foo_hash4", "foo2", "bar2")
828+
cache.hset("foo_hash4", "foo3", "bar3")
829+
keys = cache.hkeys("foo_hash4")
830+
assert len(keys) == 3
831+
for i in range(len(keys)):
832+
assert keys[i] == f"foo{i + 1}"
833+
834+
def test_hexists(self, cache: RedisCache):
835+
cache.hset("foo_hash5", "foo1", "bar1")
836+
assert cache.hexists("foo_hash5", "foo1")
837+
assert not cache.hexists("foo_hash5", "foo")

0 commit comments

Comments
 (0)