1

你好,

我的 django 网站中只有多个数据库。每个用户使用不同的数据库,在 UserProfile 中设置。

我的问题是:

如何设置 modelForm 以使用特定的数据库?

我收到这些错误:表 XX 不存在。因为 django 尝试使用我的身份验证数据库。我尝试使用路由器,但我在互联网上找到的所有示例都没有使用来自 UserProfile 的数据库名称。

这是我的表格:

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

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

这是我的回溯:

Environment:


Request Method: POST
Request URL: http://127.0.0.1:8000/cadastro/pessoa/novo/

Django Version: 1.5.1
Python Version: 2.7.2
Installed Applications:
('django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.admin',
 'django_evolution',
 'debug_toolbar',
 'pagination',
 'bootstrap_toolkit',
 'web_core')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'debug_toolbar.middleware.DebugToolbarMiddleware',
 'pagination.middleware.PaginationMiddleware')


Traceback:
File "/Library/Python/2.7/site-packages/django/core/handlers/base.py" in get_response
  115.                         response = callback(request, *callback_args, **callback_kwargs)
File "/Users/fellipeh/PycharmProjects/webconflex/cadastros/views.py" in EditaPessoa
  47.             if formPessoa.is_valid():
File "/Library/Python/2.7/site-packages/django/forms/forms.py" in is_valid
  126.         return self.is_bound and not bool(self.errors)
File "/Library/Python/2.7/site-packages/django/forms/forms.py" in _get_errors
  117.             self.full_clean()
File "/Library/Python/2.7/site-packages/django/forms/forms.py" in full_clean
  274.         self._post_clean()
File "/Library/Python/2.7/site-packages/django/forms/models.py" in _post_clean
  344.             self.validate_unique()
File "/Library/Python/2.7/site-packages/django/forms/models.py" in validate_unique
  353.             self.instance.validate_unique(exclude=exclude)
File "/Library/Python/2.7/site-packages/django/db/models/base.py" in validate_unique
  731.         errors = self._perform_unique_checks(unique_checks)
File "/Library/Python/2.7/site-packages/django/db/models/base.py" in _perform_unique_checks
  826.             if qs.exists():
File "/Library/Python/2.7/site-packages/django/db/models/query.py" in exists
  596.             return self.query.has_results(using=self.db)
File "/Library/Python/2.7/site-packages/django/db/models/sql/query.py" in has_results
  442.         return bool(compiler.execute_sql(SINGLE))
File "/Library/Python/2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
  840.         cursor.execute(sql, params)
File "/Library/Python/2.7/site-packages/django/db/backends/util.py" in execute
  41.             return self.cursor.execute(sql, params)
File "/Library/Python/2.7/site-packages/firebird/base.py" in execute
  158.             six.reraise(utils.DatabaseError, utils.DatabaseError(*self.error_info(e, query, params)), sys.exc_info()[2])
File "/Library/Python/2.7/site-packages/firebird/base.py" in execute
  150.             return self.cursor.execute(q, params)
File "/Library/Python/2.7/site-packages/fdb/fbcore.py" in execute
  3322.                                     PreparedStatement(operation, self, True))
File "/Library/Python/2.7/site-packages/fdb/fbcore.py" in __init__
  1934.                 "Error while preparing SQL statement:")

Exception Type: DatabaseError at /cadastro/pessoa/novo/
Exception Value: ('Error while preparing SQL statement:\n- SQLCODE: -204\n- Dynamic SQL Error\n- SQL error code = -204\n- Table unknown\n- PESSOA\n- At line 1, column 41', u'-204 -- SELECT FIRST 1 (1) AS "A" FROM "PESSOA" WHERE "PESSOA"."IDPESSOA" = -1')

这是我的佩索阿模型:

class Pessoa(models.Model):
    idsys_point_cliente = models.CharField(max_length=28, primary_key=True)
    idpessoa = models.IntegerField(verbose_name=u'Código', primary_key=True, default=-1)
    data_cadastro = models.DateTimeField(u'Data/Hora Cadastro', default=datetime.now, blank=True, editable=False)
    data_atualizacao = models.DateTimeField(verbose_name=u'Data/Hora da Última Atualização', default=datetime.now,
                                        blank=True)
    status = models.CharField(verbose_name=u'Status',
                          max_length=1,
                          default='A',
                          choices=Ativo_Inativo_CHOICE)
    razao_social = models.CharField(u'Razão Social *', max_length=70, null=False)
    nome_fantasia = models.CharField(u'Nome Fantasia', max_length=70, blank=True, null=True)
    endereco = models.CharField(u'Endereço *', max_length=150, null=False)
    numero = models.CharField(u'Número *', max_length=30, null=False)
    bairro = models.CharField(u'Bairro *', max_length=40, null=False)
    complemento = models.CharField(u'Complemento', max_length=30, blank=True, null=True)
    idcidade = models.ForeignKey('web_core.Cidade', verbose_name="Cidade *",
                             db_column='idcidade', null=False, blank=False)
    email = models.EmailField(u'E-Mail', max_length=100, blank=True, null=True)
    fisico_juridico = models.CharField('Tipo Cadastro *',
                                   max_length=1,
                                   default='F',
                                   choices=FIS_JUR_CHOICE)
    fis_cpf = models.CharField(u'CPF', max_length=14, null=True, blank=True)
    jur_cnpj = models.CharField(u'CNPJ', max_length=18, null=True, blank=True)
    telefone1 = models.CharField(u'Telefone', max_length=14)
    idrepresentante = models.IntegerField(u'Representante', null=True, blank=True, editable=False)

    class Meta:
        ordering = ['razao_social']
        managed = False
        db_table = 'pessoa'

    def __unicode__(self):
        return self.razao_social
4

1 回答 1

1

回答我自己的问题...

做到这一点的唯一方法是制作一个中间件来获取数据库名称并与本地人一起使用,如下所示:

文件:中间件.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

在此之后,在您的settings.py中添加middleware.py

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

最后,再制作一个文件来获取 db router:

文件:作者:

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

注意:我需要在每个 def 中添加import,因为 Django 1.5.1 有一个错误,如果您将 import 放入文件顶部.. 循环导入..

在此之后,再次更改您的settings.py以添加路由器:

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

记住

我这样做是因为我有一个数据库,仅用于身份验证.. 每个用户都可以访问不同的数据库,具体取决于 dbname 字段中保存的内容。

如果您有其他解决方案,请告诉我!

谢谢大家。

于 2013-08-02T15:30:56.430 回答