Thursday, February 2, 2012

Re: Routing to database based on user

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.17 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQEcBAEBAgAGBQJPKxyOAAoJELi8GfiSMn9yWrcH/RrMvWJVjUD9K49rzEJat4Ue
pCO281Sr4t52iVQPxlxHx7qUlWtVtejoFuFl7+es09idYZfDhuL6qmXgjeINihu6
32Fnkp6VNyIv3POBuUGAdGrrEgXIWlg7WiAQWY9m3UX2/B4EazgCKrjRMVfK7Twv
uUhCjGcaUVFqeu5pmHD3DZJWFMdvlk8DsVULc4gziS8sOuQ3oW22AutpY3pVTOFE
clj31MT9kpUHjuIfOfMwjs5F1bI7EUBxqTS/ABI4KfqLdV51O+ZNXIHqGyBWnQVe
erDSOQMxNi5ZaU2343s/ytzla50UpUpwSCbIqwIj4dxPwPr1tbOzHhknmajryrc=
=3YuQ
-----END PGP SIGNATURE-----
On 31/01/12 11:45, akaariai wrote:
> On Jan 31, 12:01 am, Tom Eastman <t...@catalyst.net.nz> wrote:
>> Hey guys,
>>
>> I'm writing a django project that will require me to route queries to
>> certain large databases based on who the logged in user is.
>>
>> So all the tables for django.contrib.auth and session and stuff will be
>> in the 'central' database, as well as a table that maps users to which
>> database they need to use for the main app.
>>
>> Can you help me come up with a way of routing database queries this way
>> using a Django database router?
>>
>> At the start of the view could I take the logged in user from
>> request.user or wherever it is, and some how provide that variable to my
>> database router for the rest of the request?
>>
>> All suggestions welcome.

>
> I think the best solution forward is to use threading.local to store
> the request.user. So, something like this should work:
> - have a middleware that stores the request.user in threading.local
> - database routers just fetch the request.user from the
> threading.local storage.


Thanks Anssi!

Here is my solution, I wonder if you could just tell me if you think
there's a major problem with it.

In simplistic terms, the goal is "whenever a model from wxdatabase is
accessed, route the query to the database specified in the user's
organization's field".

It consists of a piece of django middleware and a db_router.

I guess my main question is: am I using threading.local() correctly?

Cheers!

Tom


##################################
##################################
import threading

_local = threading.local()

class WXDatabaseMiddleware(object):
def process_request(self, request):
_local.wx_database_label = None

try:
profile = request.user.get_profile()
_local.wx_database_label = profile.organization.database.label
except:
## This exception needs to be logged!
pass


class WxRouter(object):
def _get_database_label(self):
return _local.wx_database_label

def read_and_write(self, model, **hints):
if model._meta.app_label == "wxdatabase":
return self._get_database_label()
else:
return None

db_for_read = read_and_write
db_for_write = read_and_write

###################################
###################################

No comments:

Post a Comment