Тестирование доступности базы данных postgres от django - PullRequest
2 голосов
/ 26 сентября 2011

Я использую django ORM с базой данных postgres.Небольшая группа пользователей взаимодействует с ним, используя сценарии импорта и экспорта.База данных доступна только в нашей внутренней сети.Если кто-то пытается использовать базу данных, когда postgres недоступен, сценарии зависают.Прежде чем пытаться обработать какие-либо данные, я хотел бы проверить, доступны ли базы данных.

Я могу подключиться к базе данных с помощью оболочки, импортировать модель и попытаться сделать запрос:

from myapp.models import mymodel
mymodel.objects.count()

это приводит к большой задержке, но затем django вызывает OperationalError с информативным сообщением («Не удалось подключиться к серверу: сеть недоступна ...»).

Я думалпроверить доступ к базе данных, выполнив минимальный запрос к базе данных, например:

from django.db import connection
cursor = connection.cursor()
cursor.execute("select 1")

, но это никогда не выходит за пределы строки cursor = connection.cursor().Нет сообщения об ошибке.

  • Почему один из этих запросов вызывает ошибку, а не другой?
  • Какой лучший способ проверить из сценария, доступна ли база данных?
  • Как я могу гарантировать, что возникнет ошибка, если соединение не будет установлено в течение разумного (возможно, указанного пользователем) времени?

Это не веб-приложение, поэтомупромежуточное программное обеспечение а-ля Как проверить соединение с базой данных в Django? невозможно.

Редактировать

Следуя предложению @ benjaoming, яЯ сделал функцию для проверки соединения:

import socket

def test_connection():
    """Test whether the postgres database is available. Usage:

        if "--offline" in sys.argv:
            os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings.offline'
        else:
            os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings.standard'
            from myapp.functions.connection import test_connection
            test_connection()
    """
    try:
        s = socket.create_connection(("example.net", 5432), 5)
        s.close()
    except socket.timeout:
        msg = """Can't detect the postgres server. If you're outside the
        intranet, you might need to turn the VPN on."""
        raise socket.timeout(msg)

Это, кажется, делает свое дело.

Ответы [ 2 ]

3 голосов
/ 28 сентября 2014

Использование множественной маршрутизации базы данных ,

Хитрость заключается в проверке доступности базы данных во время инициализации django, а затем route всех запросов ORM к резервной базе данных.

Один из способов проверить, существует ли база данных или нет, - выполнить запрос ORM внутри блока try .. except и установить переменную, которая доступна в вашем routers.py

from django.db import connections
conn = connections['default']
try:
    c = conn.cursor() #this will take some time if error
except OperationalError:
    reachable = False
else:
    reachable = True

Вы можете поместить этот код в urls.py или в routers.py.

, настраиваемый маршрутизатор проверит, установлена ​​ли переменная, и направить к вашей резервной базе данных db

class AppRouter(object):
    def db_for_read(self, model, **hints):
       if reachable :
           return 'actual_db'
       else:
           return 'fallback_db'

    # define db_for_write likewise
3 голосов
/ 28 сентября 2011

Вы можете использовать другой метод, чтобы узнать, доступен ли сервер postgres: например, модуль сокета - просто выполните socket.create_connection (("server", port)) и посмотрите, какие исключения он вызывает ...

...