Skip to main content

Add a global database read-only setting.

Project description

## About

An way to globally disable writes to your database. This works by
inserting a cursor wrapper between Django's `CursorWrapper` and
the database connection's cursor wrapper. So many cursor wrappers!


## Installation

I uploaded it to [PyPi][pypi], so you can grab it there if you'd like with

```bash
pip install django-db-readonly
```

or install with pip the git address:

```bash
pip install git+git@github.com:streeter/django-db-readonly.git
```

You're choice. Then add `readonly` to your `INSTALLED_APPS`.

```python
INSTALLED_APPS = (
# ...
'readonly',
# ...
)
```


## Usage

You shouldn't notice this at all, _unless_ you add the following line
to your `settings.py`:

```python
# Set to False to allow writes
SITE_READ_ONLY = True
```

When you do this, any write action to your databases will generate an
exception. You should catch this exception and deal with it somehow. Or
let Django display an [error 500 page][error500]. The exception you will
want to catch is `readonly.exceptions.DatabaseWriteDenied` which inherits
from `django.db.utils.DatabaseError`.

There is also a middleware class that will handle the exceptions and attempt
to handle them smartly. Add the following line in your `settings.py`:

```python
MIDDLEWARE_CLASSES = (
# ...
'readonly.middleware.DatabaseReadOnlyMiddleware',
# ...
)
```

This will then enable the middleware which will catch `DatabaseWriteDenied`
exceptions. If the request is a POST request, we will redirect the user to the
same URL, but as a GET request. If the request is not a POST (ie. a GET), we
will just display a `HttpResponse` with text telling the user the site
is in read-only mode.

In addition, the middleware class can add an error-type message using the
`django.contrib.messages` module. Add:

```python
# Enable
DB_READ_ONLY_MIDDLEWARE_MESSAGE = True
```

to your `settings.py` and then on POST requests that generate a
`DatabaseWriteDenied` exception, we will add an error message informing the
user that the site is in read-only mode.

For additional messaging, there is a context processor that adds
`SITE_READ_ONLY` into the context. Add the following line in your `settings.py`:

```python
TEMPLATE_CONTEXT_PROCESSORS = (
# ...
'readonly.context_processors.readonly',
# ...
)
```

And use it as you would any boolean in the template, e.g. `{% if SITE_READ_ONLY
%} We're down for maintenance. {% endif %}`

## Testing

There aren't any tests included, yet. Run it at your own peril.


## Caveats

This will work with [Django Debug Toolbar][ddt]. In fact, I was inspired
by [DDT's sql panel][sql-panel] when writing this app.

However, in order for both DDT _and_ django-db-readonly to work, you need
to make sure that you have `readonly` before `debug_toolbar` in your
`INSTALLED_APPS`. Otherwise, you are responsible for debugging what is
going on. Of course, I'm not sure why you'd be running DDT in production
and running django-db-readonly in development, but whatever, I'm not you.

More generally, if you have any other apps that modifies either
`django.db.backends.util.CursorWrapper` or
`django.db.backends.util.CursorDebugWrapper`, you need to make sure
that `readonly` is placed _before_ of those apps in `INSTALLED_APPS`.


## The Nitty Gritty

How does this do what it does? Well, django-db-readonly sits between
Django's own cursor wrapper at `django.db.backends.util.CursorWrapper` and
the database specific cursor at `django.db.backends.*.base.*CursorWrapper`.
It overrides two specific methods: `execute` and `executemany`. If the
site is in read-only mode, then the SQL is examined to see if it
contains any write actions (defined in
`readonly.ReadOnlyCursorWrapper.SQL_WRITE_BLACKLIST`). If a write is
detected, an exception is raised.


[pypi]: http://pypi.python.org/pypi/django-db-readonly/
[error500]: http://docs.djangoproject.com/en/1.3/topics/http/urls/#handler500
[ddt]: https://github.com/robhudson/django-debug-toolbar
[sql-panel]: https://github.com/robhudson/django-debug-toolbar/blob/master/debug_toolbar/panels/sql.py

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-db-readonly-0.3.0.tar.gz (5.4 kB view details)

Uploaded Source

File details

Details for the file django-db-readonly-0.3.0.tar.gz.

File metadata

File hashes

Hashes for django-db-readonly-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d1348a4de783bafa19cab721c81d9d3fdea6045d1621333baa93a443b558301e
MD5 8d3a7a461bd4579be5ef32ccd363a42e
BLAKE2b-256 73b674cdef83fbfba40b79e2285531a1b0c9430b09e27bdfd170cb8c4128104c

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page