如何在django中检查数据库与mysql的连接

时间:2015-08-19 14:48:03

标签: python django django-settings

我该怎么办?

我想,我可以从数据库中读取一些内容,但它看起来太多了,有什么类似的吗?:

settings.DATABASES['default'].check_connection()

8 个答案:

答案 0 :(得分:21)

您需要做的就是启动一个应用程序,如果它没有连接,它将失败。您可以尝试的其他方式是在shell上尝试以下 -

from django.db import connections
from django.db.utils import OperationalError
db_conn = connections['default']
try:
    c = db_conn.cursor()
except OperationalError:
    connected = False
else:
    connected = True

答案 1 :(得分:4)

这是一个老问题,但需要更新的答案

python manage.py check --database default

如果您不使用默认值,或者您想测试设置中列出的其他数据库,只需将其命名即可。

它从 3.1 + 版本开始可用

检查 documentation

答案 2 :(得分:1)

我使用以下名为wait_for_db的Django管理命令:

import time

from django.db import connection
from django.db.utils import OperationalError
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    """Django command that waits for database to be available"""

    def handle(self, *args, **options):
        """Handle the command"""
        self.stdout.write('Waiting for database...')
        db_conn = None
        while not db_conn:
            try:
                connection.ensure_connection()
                db_conn = True
            except OperationalError:
                self.stdout.write('Database unavailable, waiting 1 second...')
                time.sleep(1)

        self.stdout.write(self.style.SUCCESS('Database available!'))

答案 3 :(得分:1)

假定您由于docker而需要此功能,但BUT不仅限于docker,请记住这是在Bash结束时,因此可以在所有* NIX上使用。

您首先需要使用django-environ,因为这样做会更加容易。

DATABASE_URL环境变量将在Django应用中以及此处使用。您的设置如下所示:

import environ

env = environ.Env()

...

DATABASES = {
    'default': env.db('DATABASE_URL'),
    'other': env.db('DATABASE_OTHER_URL')  # for illustration purposes
}

...

您的环境变量应如下所示:(更多信息here

# This works with ALL the databases django supports ie (mysql/mssql/sqlite/...)
DATABASE_URL=postgres://user:pass@name_of_box:5432/database_name
DATABASE_OTHER_URL=oracle://user:pass@/(description=(address=(host=name_of_box)(protocol=tcp)(port=1521))(connect_data=(SERVICE_NAME=EX)))

在您的entrypoint.sh内执行以下操作:

function database_ready() {
  # You need to pass a single argument called "evironment_dsn"
  python << EOF
import sys
import environ
from django.db.utils import ConnectionHandler, OperationalError

env = environ.Env()
try:
   ConnectionHandler(databases={'default': env.db('$1')})['default'].ensure_connection()
except (OperationalError, DatabaseError):
   sys.exit(-1)
sys.exit(0)
EOF
}

然后,假设您要等待主数据库(在这种情况下为postgres),则将其添加到entrypoint.sh函数下的同一database_ready内。

until database_ready DATABASE_URL; do
  >&2 echo "Main DB is unavailable - sleeping"
  sleep 1
done

只有在postgres已启动并正在运行时,此操作才会继续。甲骨文呢?同样,在上面的代码下,我们添加:

until database_ready DATABASE_OTHER_URL; do
  >&2 echo "Secondary DB is unavailable - sleeping"
  sleep 1
done

以这种方式进行操作将为您带来一些好处:

  1. 您无需担心二进制文件之类的其他依赖项。

  2. 您可以切换数据库,而不必担心这种中断。 (代码是100%与数据库无关的)

答案 4 :(得分:1)

运行外壳

python manage.py shell

执行此脚本

import django
print(django.db.connection.ensure_connection())

如果打印None表示一切正常,否则如果您的数据库连接发生问题,它将抛出错误

答案 5 :(得分:1)

import time
from django.core.management.base import BaseCommand
from django.db import connection
from django.db.utils import OperationalError
from django.utils.translation import ngettext


class Command(BaseCommand):
    help = "Checks database connection"

    def add_arguments(self, parser):
        parser.add_argument(
            "--seconds",
            nargs="?",
            type=int,
            const=1,
            help="Number of seconds to wait before retrying",
            default=1,
        )

    def handle(self, *args, **options):
        wait = options["seconds"]
        while True:
            try:
                connection.ensure_connection()
                break
            except OperationalError:
                plural_time = ngettext("second", "seconds", wait)
                self.stdout.write(
                    self.style.WARNING(
                        f"Database unavailable, retrying after {wait} {plural_time}!"
                    )
                )
                time.sleep(wait)
        self.stdout.write(self.style.SUCCESS("Database connections successful"))
python manage.py waitdb --seconds 5 
python manage.py waitdb # defaults to 1 seconds

答案 6 :(得分:0)

我有一个更复杂的情况,我在djongo模块和RDS mysql后面使用mongodb。因此,不仅是多个数据库,而且djongo还会引发SQLDecode错误。我还必须执行并获取才能正常工作:

from django.conf import settings

if settings.DEBUG:
    # Quick database check here
    from django.db import connections
    from django.db.utils import OperationalError
    dbs = settings.DATABASES.keys()
    for db in dbs:
        db_conn = connections[db]  # i.e. default
        try:
            c = db_conn.cursor()
            c.execute("""SELECT "non_existent_table"."id" FROM "non_existent_table" LIMIT 1""")
            c.fetchone()
            print("Database '{}' connection ok.".format(db))  # This case is for djongo decoding sql ok
        except OperationalError as e:
            if 'no such table' in str(e):
                print("Database '{}' connection ok.".format(db))  # This is ok, db is present
            else:
                raise  # Another type of op error
        except Exception:  # djongo sql decode error
            print("ERROR: Database {} looks to be down.".format(db))
            raise

我将其加载到我的应用__init__.py中,因为我希望它仅在启用DEBUG的情况下在启动时运行一次。希望对您有帮助!

答案 7 :(得分:0)

似乎哈维尔的答案不再起作用。假设您有psycopg2库可用(例如,您正在运行Django应用程序),他就是我一起在Docker入口点中执行检查数据库可用性的任务的人:

function database_ready() {
    python << EOF
import psycopg2
try:
    db = psycopg2.connect(host="$1", port="$2", dbname="$3", user="$4", password="$5")
except:
    exit(1)

exit(0)
EOF
}

until database_ready $DATABASE_HOST $DATABASE_PORT $DATABASE_NAME $DATABASE_USER $DATABASE_PASSWORD; do
  >&2 echo "Database is unavailable at $DATABASE_HOST:$DATABASE_PORT/$DATABASE_NAME - sleeping..."
  sleep 1
done
echo "Database is ready - $DATABASE_HOST:$DATABASE_PORT/$DATABASE_NAME"```
相关问题