简体   繁体   English

在 Django 中使用多个数据库

[英]Using Multiple Databases with django

I have to use multiple databases in my project but there is a problem.我必须在我的项目中使用多个数据库,但有一个问题。 Model can't see my database.模型看不到我的数据库。

when i go localhost:port/admin/app/accounts it says me no such table: accounts.当我去 localhost:port/admin/app/accounts 它说我没有这样的表:帐户。 model looking default database.模型寻找默认数据库。 not accounts.db how can i do that?不是accounts.db 我该怎么做?

I tried multiple thins in what i saw in internet but nothing happend.我在互联网上看到的内容中尝试了多种方法,但没有任何反应。

settings.py :
.....
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },

    'accounts': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'accounts.db')
    }
}
.....


models.py:
.....
class Accounts(models.Model):     

    email = models.TextField(blank=True, null=True)                                                                                                                    
    phone = models.TextField(blank=True, null=True)                                                                                                                    
    name = models.TextField(blank=True, null=True)                                                                                                                     
    password = models.TextField(blank=True, null=True)                                                                                                                 
    verify = models.IntegerField(blank=True, null=True)                                                                                                                

    class Meta:                                                                                                                                                        
        managed = False

        db_table = 'accounts'
....


Environment:


Request Method: GET
Request URL: http://localhost:port/admin/hede/accounts/

Django Version: 1.11.23
Python Version: 2.7.15
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'hede']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in wrapper
  552.                 return self.admin_site.admin_view(view)(*args, **kwargs)

File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "/usr/local/lib/python2.7/dist-packages/django/views/decorators/cache.py" in _wrapped_view_func
  57.         response = view_func(request, *args, **kwargs)

File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/sites.py" in inner
  224.             return view(request, *args, **kwargs)

File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapper
  67.             return bound_func(*args, **kwargs)

File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in _wrapped_view
  149.                     response = view_func(request, *args, **kwargs)

File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py" in bound_func
  63.                 return func.__get__(self, type(self))(*args2, **kwargs2)

File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/options.py" in changelist_view
  1564.                 self.list_max_show_all, self.list_editable, self,

File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/views/main.py" in __init__
  79.         self.get_results(request)

File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/views/main.py" in get_results
  177.         result_count = paginator.count

File "/usr/local/lib/python2.7/dist-packages/django/utils/functional.py" in __get__
  35.         res = instance.__dict__[self.name] = self.func(instance)

File "/usr/local/lib/python2.7/dist-packages/django/core/paginator.py" in count
  79.             return self.object_list.count()

File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py" in count
  364.         return self.query.get_count(using=self.db)

File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py" in get_count
  499.         number = obj.get_aggregation(using, ['__count'])['__count']

File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/query.py" in get_aggregation
  480.         result = compiler.execute_sql(SINGLE)

File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py" in execute_sql
  899.             raise original_exception

Exception Type: OperationalError at /admin/hede/accounts/
Exception Value: no such table: accounts

To use multiple databases you have to tell Django about the database server you will be using, but adding them in the settings.py.要使用多个数据库,您必须告诉 Django 您将使用的数据库服务器,但将它们添加到 settings.py 中。

Multiple databases 多个数据库

    'default': {
        'NAME': 'app_data',
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres_user',
        'PASSWORD': 's3krit'
    },
    'users': {
        'NAME': 'user_data',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'priv4te'
    }
}

The migrate management command operates on one database at a time. migrate 管理命令一次对一个数据库进行操作。 By default, it operates on the default database, but by providing the --database option, you can tell it to synchronize a different database.默认情况下,它在默认数据库上运行,但通过提供 --database 选项,您可以告诉它同步不同的数据库。

$ ./manage.py migrate --database=users
$ ./manage.py migrate --database=customers

You can manually select the database in your queries queries eg您可以在查询查询中手动选择数据库,例如

user = User(....)
user.save(using='users')

Customer.objects.all().using('users')

Using raw cursor使用原始游标

with connections['users'].cursor() as cursor:
     cursor.execute("SELECT * FROM users__users")

You have to route queries to the database too (emphasis is mine):您也必须将查询路由到数据库(重点是我的):

The easiest way to use multiple databases is to set up a database routing scheme.使用多个数据库的最简单方法是设置数据库路由方案。 The default routing scheme ensures that objects remain 'sticky' to their original database (ie, an object retrieved from the foo database will be saved on the same database).默认路由方案确保对象保持“粘性”到其原始数据库(即,从 foo 数据库检索的对象将保存在同一数据库中)。

The default routing scheme ensures that if a database isn't specified, all queries fall back to the default database .默认路由方案确保如果未指定数据库,则所有查询都回退到默认数据库

https://docs.djangoproject.com/en/2.1/topics/db/multi-db/#automatic-database-routing https://docs.djangoproject.com/en/2.1/topics/db/multi-db/#automatic-database-routing

NB: the db_table in your model's Meta is for the name of the database table , not the name of the database itself !-)注意:模型 Meta 中的db_table用于数据库的名称,而不是数据库本身的名称!-)

As far as I know, your models can see the database, but aren't using 'accounts' database because it's set to use 'default' db.据我所知,您的模型可以看到数据库,但没有使用“帐户”数据库,因为它设置为使用“默认”数据库。 You can change this by creating custom database router.您可以通过创建自定义数据库路由器来更改此设置。

Here, I am assuming that your directory structure for django project is:在这里,我假设您的 django 项目目录结构是:

    ./mainapp/
    |--- mainapp/
    |    |--- settings.py
    |    |___ # .....
    |
    |--- app/
    |    |--- apps.py
    |    |--- dbrouters.py # [new file], we will be creating soon.
    |    |--- models.py
    |    |--- views.py
    |    |___ # .....
    |
    |--- manage.py
    |___ # .....

Full example:完整示例:

    # app/models.py:
    class Accounts (models.Model):
       # .....
    
    # app/dbrouters.py: # [new file]
    from .models import Accounts
    
    class AccountsDBRouter:
       def db_for_read (self, model, **hints):
          if (model == Accounts):
             # your model name as in settings.py/DATABASES
             return 'accounts'
          return None
       
       def db_for_write (self, model, **hints):
          if (model == Accounts):
             # your model name as in settings.py/DATABASES
             return 'accounts'
          return None
    
    # mainapp/settings.py:
    # .....
    
    INSTALLED_APPS = [
       'app.apps.AppConfig',
       # .....
    ]
    
    # .....
    
    DATABASE_ROUTERS = (
       'app.dbrouters.AccountsDBRouter',
    )
    
    DATABASES = {
       # .....
       'accounts' : {
          # .....
       },
    }
    
    # .....

Change the above code as per your requirement or specifications.根据您的要求或规格更改上述代码。

Then, do the following:然后,执行以下操作:

$ python3 manage.py makemigrations
$ python3 manage.py migrate --database=accounts
$ python3 manage.py migrate

Now, you should be able to use it without using('accounts') in code as follows:现在,您应该可以不using('accounts')在代码中使用它,如下所示:

    # app/views.py:
    # .....
    from .models import Accounts
    
    def someview (request):
       accounts = Accounts.objects.all()
       # See, in above line, you're not using:
       # accounts = Accounts.objects.using('accounts').all()
       # as your 'AccountsDBRouter' is already routing read and write
       # db requests to 'accounts' database.
       # Though you can still use "using('accounts')", as it will
       # also provide same results.
    
    def someotherview (request):
       # You can even use the following:
       account = Account(
          email="<email>",
          phone="<phone>",
          # .....
       )
       account.save()
       # Again, this will save directly in 'accounts'.

References:参考:

Hope that answers you.希望能回答你。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM