1

I have this ModelForm:

class ClienteForm(ModelForm):
   class Meta:
     model = Pessoa

   def __init__(self, *args, **kwargs):
     vUserProfile = kwargs.pop('vUserProfile', None)
     super(ClienteForm, self).__init__(*args, **kwargs)

How can I force to use a specific database?

I can't use db router, because the "specific" database is setting in my User profile, and I don't know how to get UserProfile in db-router class..

I know I can use in ClienteForm.save(using=XXX), but when I try ClienteForm.is_valid I got error, because django is try to use "default" database.

thanks

1

1 Answer 1

1

Reply my own question...

The only way to get this right is make one middleware to get database name and work with locals, like this:

File: middleware.py

from threading import local
from django.contrib.sessions.models import Session
from django.contrib.auth.models import User
from web_core.models import UserProfile

my_local_global = local()


class CustomerMiddleware(object):
    def process_request(self, request):
        my_local_global.database_name = get_database_name(request)


def get_database_name(request):
    session_key = request.session.session_key
    try:
        session = Session.objects.get(session_key=session_key)
        uid = session.get_decoded().get('_auth_user_id')
        user = User.objects.get(pk=uid)

        profile = UserProfile.objects.get(pk=uid)

        if profile:
            return profile.dbname
        else:
            return None
    except:
        return None

after this, add middleware.py in your settings.py:

MIDDLEWARE_CLASSES = (
(..)
    'middleware.CustomerMiddleware',
)

to finish, make one more file to get db router:

File: authrouter:

class PadraoRouter(object):
    def db_for_read(self, model, **hints):
        from middleware import my_local_global
        return my_local_global.database_name

    def db_for_write(self, model, **hints):
        from middleware import my_local_global
        return my_local_global.database_name

    def allow_relation(self, obj1, obj2, **hints):
        return None

    def allow_syncdb(self, db, model):
        return True


class AuthRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'auth':
            return 'auth_db'
        if model._meta.app_label == 'sessions':
            return 'auth_db'
        if model._meta.app_label == 'web_core':
            return 'auth_db'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'auth':
            return 'auth_db'
        if model._meta.app_label == 'sessions':
            return 'auth_db'
        if model._meta.app_label == 'web_core':
            return 'auth_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'auth' or\
           obj2._meta.app_label == 'auth':
            return True
        if obj1._meta.app_label == 'sessions' or\
           obj2._meta.app_label == 'sessions':
            return True
        if obj1._meta.app_label == 'web_core' or\
           obj2._meta.app_label == 'web_core':
            return True
        return None

    def allow_syncdb(self, db, model):
        if db == 'auth_db':
            return model._meta.app_label == 'auth'
        elif model._meta.app_label == 'auth':
            return False
        return None

NOTE: I need to put import in each def, because Django 1.5.1 has a bug, if you put import into top of file.. cycle imports..

after this, change again your settings.py to add the router:

DATABASE_ROUTERS = ['authrouter.AuthRouter',
                    'authrouter.PadraoRouter']

Remember

I make this way, because I have one database, only for auth.. each user can access a different database, depending what is save in dbname field.

If you have other solution, please let's me know!

Thanks to everybody.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.