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
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file django-db-readonly-0.3.1.tar.gz
.
File metadata
- Download URL: django-db-readonly-0.3.1.tar.gz
- Upload date:
- Size: 5.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9ea633bdae96fd0a7ef92cd24d3aa9258aed2e64d55943863442285ad2e312cf |
|
MD5 | e706ddd216e9c9c3f66390870853c25e |
|
BLAKE2b-256 | d0b813bb0a2ede550e8cabbf371a5913d1858d6055c1819b3cde732bf70a0cbc |