Metadata-Version: 2.1
Name: django-cache-mock
Version: 0.0.1
Summary: 
Author: Iuri de Silvio
Author-email: iurisilvio@gmail.com
Requires-Python: >=3.8,<4.0
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Provides-Extra: fakeredis
Provides-Extra: mockcache
Provides-Extra: redislite
Requires-Dist: django (>=3,<5)
Description-Content-Type: text/markdown

# django-cache-mock

Use in-process mocks to avoid setting up external caches for Django during
development.

Django has a limited built-in `django.core.cache.backends.locmem.LocMemCache`,
to help development, but Django do some magic to always give you a working
connection.

I have some reasons to abuse Django cache this way:

* Thread safety: Django spin one connection per thread to avoid issues with
thread unsafe drivers.
* Good defaults: Django run connections with good defaults.
* Connection reuse: Django already have a pool running and in most cases it is
better to use it.

## Install

```shell
$ pip install django-cache-mock
```

Also, it is possible to install with the backends you want.

For `mockcache`, it installs a fork of the original package because it doesn´t
work for new versions of Python.

```shell
$ pip install django-cache-mock[mockcache]
$ pip install django-cache-mock[fakeredis]
$ pip install django-cache-mock[redislite]
```

## How to use

In your Django settings you already have `CACHES` defined.

For `memcached`, it's something like that:

```python
CACHES = {
    "default": {
        "BACKEND": "django.core.cache.backends.memcached.PyMemcacheCache",
        "LOCATION": os.getenv("MEMCACHED_HOSTS"),
        "OPTIONS": {
            "no_delay": True,
            "ignore_exc": True,
            "max_pool_size": 4,
            "use_pooling": True,
        },
    },
}
```

Just make a call to `django_cache_mock.patch` to replace with a mock backend.

**The lib will patch only when cache LOCATION is not defined.**

```python
import django_cache_mock

if DEBUG:  # Apply it only in debug mode to be extra careful.
    django_cache_mock.patch(CACHES, "default", "mockcache")
```

This patch replace cache with a mocked one. For mockcache,

## Custom cache options

The `patch` function accepts custom params. It can be used to override mock
behaviours, like the db file `redislite` will use, defined by `LOCATION`:

```python
django_cache_mock.patch(CACHES, "default", "redislite", {"LOCATION": "data/redis.db"})
```

## How to access connections

To get Django memcached and redis clients from cache:

```python
from django.core.cache import caches

def give_me_memcached():
    return caches["memcached"]._cache

# for django.core.cache.backends.redis
def give_me_primary_redis():
    return caches["redis"]._cache.get_client()

def give_me_secondary_redis():
    return caches["redis"]._cache.get_client(write=False)

# for django-redis
def give_me_primary_redis():
    return caches["redis"].client.get_client()

def give_me_secondary_redis():
    return caches["redis"].client.get_client(write=False)
```

