Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist
View Django MultiDB selection from URL
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 82 83 84 85
"""
Select database based on URL variable
 
Inspired by this Django snipped:
 
https://djangosnippets.org/snippets/2037/
 
It's assumed that any view in the system with a cfg keyword argument passed to
it from the urlconf may be routed to a separate database. for example:
 
url( r'^(?P<db>\w+)/account/$', 'views.account' )
 
The middleware and router will select a database whose alias is <db>,
"default" if no db argument is given and raise a 404 exception if not listed in
settings.DATABASES, all completely transparent to the view itself.
"""
import threading
from django.http import Http404
 
request_cfg = threading.local()
 
 
class MultiDbRouterMiddleware(object):
"""
The Multidb router middelware.
 
he middleware process_view (or process_request) function sets some context
from the URL into thread local storage, and process_response deletes it. In
between, any database operation will call the router, which checks for this
context and returns an appropriate database alias.
 
Add this to your middleware, for example:
 
MIDDLEWARE_CLASSES += ['bananaproject.multidb.MultiDbRouterMiddleware']
"""
def process_view(self, request, view_func, args, kwargs):
if 'db' in kwargs:
request_cfg.db = kwargs['db']
request.SELECTED_DATABASE = request_cfg.db
 
def process_response(self, request, response):
if hasattr(request_cfg, 'db'):
del request_cfg.db
return response
 
 
class MultiDbRouter(object):
"""
The multiple database router.
 
Add this to your Django database router configuration, for example:
 
DATABASE_ROUTERS += ['bananaproject.multidb.MultiDbRouter']
"""
def _multi_db(self):
from django.conf import settings
if hasattr(request_cfg, 'db'):
if request_cfg.db in settings.DATABASES:
return request_cfg.db
else:
raise Http404
else:
return 'default'
 
def db_for_read(self, model, **hints):
if model._meta.app_label != 'banana':
return 'default'
return self._multi_db()
 
db_for_write = db_for_read
 
 
def multidb_context_processor(request):
"""
This context processor will add a db_name to the request.
 
Add this to your Django context processors, for example:
 
TEMPLATE_CONTEXT_PROCESSORS +=[
'bananaproject.multidb.multidb_context_processor']
"""
if hasattr(request, 'SELECTED_DATABASE'):
return {'db_name': request.SELECTED_DATABASE}
else:
return {}
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.