Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist
View multidb.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
"""
With :class:`~multidb.SlaveQuerySet` and :class:`~multidb.SlaveMixin`, all read
queries will go to a slave database; all inserts, updates, and deletes will do
to the ``default`` database.
First, define ``SLAVE_DATABASES`` in your settings. It should be a list of
database aliases that can be found in ``DATABASES``::
DATABASES = {
'default': {...},
'shadow-1': {...},
'shadow-2': {...},
}
SLAVE_DATABASES = ['shadow-1', 'shadow-2']
Then add a :class:`multidb.SlaveManager` to your model and inherit from
:class:`multidb.SlaveMixin`::
from django.db import models
import multidb
class Slurpee(multidb.SlaveMixin, models.Model):
number = models.IntegerField()
objects = multidb.SlaveManager()
Instead of a normal :class:`~django.db.models.query.QuerySet`, the
``SlaveManager`` will return a ``SlaveQuerySet`` that sends all traffic to one
of the slaves.
The slave databases will be chosen in round-robin fashion.
"""
import itertools
import random
 
from django.conf import settings
from django.db import models, DEFAULT_DB_ALIAS
 
 
if getattr(settings, 'SLAVE_DATABASES'):
# Shuffle the list so the first slave db isn't slammed during startup.
dbs = list(settings.SLAVE_DATABASES)
random.shuffle(dbs)
slaves = itertools.cycle(dbs)
else:
slaves = itertools.repeat(DEFAULT_DB_ALIAS)
 
 
class SlaveManager(models.Manager):
"""Returns a SlaveQuerySet instead of a normal QuerySet."""
 
def get_query_set(self):
return SlaveQuerySet(self.model)
 
 
class SlaveQuerySet(models.query.QuerySet):
"""
Sends SELECTs to one of the slave databases in a round-robin schedule.
A specific database can be selected with the ``using`` statement.
"""
 
@property
def db(self):
if self._db is None:
self._db = slaves.next()
return self._db
 
 
class SlaveMixin(object):
"""Sends all INSERTs, UPDATEs, and DELETEs to the default database."""
 
def save(self, force_insert=False, force_update=False, using=None):
using = using or DEFAULT_DB_ALIAS
return super(SlaveMixin, self).save(force_insert, force_update, using)
 
def delete(self, using=None):
using = using or DEFAULT_DB_ALIAS
return super(SlaveMixin, self).delete(using)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.