无法使用连接服务文件从 Django 连接到 Postgres(在 Windows 上)

Dav*_*veB 8 python django postgresql

[注意:这是使用 Django 4.0.2、Python 3.8.2 和 Postgres 14.2。]

我已经成功设置了 Django 和 Postgres,当我将所有 Postgres 参数放入 Django settings.py 文件中时,我可以让它们一起工作。但是,如Django 文档所示,我想改用 Postgres 连接服务文件。我创建了一个服务文件 (C:\Program Files\PostgreSQL\14\etc\pg_service.conf),如下所示:

[test_svc_1]
host=localhost
user=django_admin
dbname=MyDbName
port=5432
Run Code Online (Sandbox Code Playgroud)

使用此文件从命令行启动 Postgres 似乎工作正常,因为它提示我输入密码:

> psql service=test_svc_1
Password for user django_admin:
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用 Django 进行迁移时,出现以下错误:

Traceback (most recent call last):
File "C:\...\django\db\backends\base\base.py", line 219, in ensure_connection
   self.connect()
File "C:\...\django\utils\asyncio.py", line 26, in inner
   return func(*args, **kwargs)
File "C:\...\django\db\backends\base\base.py", line 200, in connect
   self.connection = self.get_new_connection(conn_params)
File "C:\...\django\utils\asyncio.py", line 26, in inner
   return func(*args, **kwargs)
File "C:\...\django\db\backends\postgresql\base.py", line 187, in get_new_connection
   connection = Database.connect(**conn_params)
File "C:\Users\...\psycopg2\__init__.py",line 122, in connect
   conn = _connect(dsn, connection_factory=connection_factory, **kwasync) 
psycopg2.OperationalError: definition of service "test_svc_1" not found
Run Code Online (Sandbox Code Playgroud)

还有与此相关的其他例外情况,例如:

django.db.utils.OperationalError: definition of service "test_svc_1" not found
Run Code Online (Sandbox Code Playgroud)

但他们都指出没有找到服务“test_svc_1”。

这是我的 Django settings.py 文件的摘录。添加 NAME 参数让我更进一步,但是一旦 Django(?) 找到连接服务文件,我就不需要包含它了。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'HOST': 'localhost',
        'NAME': 'MyDbName',
        'OPTIONS': {
            'service': 'test_svc_1',
            'passfile': '.my_pgpass',
        },
    },
}
Run Code Online (Sandbox Code Playgroud)

对我所缺少的有什么想法吗?最坏的情况是,我想我可以恢复使用环境变量并让 settings.py 文件引用它们。但我想了解我做错了什么而不是放弃。

感谢您的任何指导。

Dav*_*veB 4

如果有人遇到这个问题,由于 Ken Whitesell 在 Django 论坛上的一些指导,我终于让它可以与服务和密码文件一起使用。这是我需要做的:

\n

我必须为 PGPASSFILE 和 PSERVICEFILE 创建指向这两个文件的 Windows 环境变量。我将它们都放在 C:\\Program Files\\PostgreSQL\\14\\etc 中,尽管我\xe2\x80\x99m 猜测只要环境变量指向它们,它们就可以进入其他目录。\n下一步,我必须在 Django 的 settings.py 中修改我的数据库记录,如下所示(这与 Django 文档指定的不同):

\n
DATABASES = {\n    \'default\': {\n        \'ENGINE\': \'django.db.backends.postgresql\',\n        \'HOST\': \'localhost\',\n        \'NAME\': \'MyDbName\',\n        \'OPTIONS\': {\n            \'service\': \'test_svc_1\',\n        },\n    },\n}\n
Run Code Online (Sandbox Code Playgroud)\n

OPTIONS 中的服务名称需要与 PGSERVICEFILE 中的服务名称匹配。

\n \n与 Django 文档的两个区别:\n
    \n
  • 我需要包含数据库名称。
  • \n
  • 我无法\xe2\x80\x99t 让它与 OPTIONS 字典中的 \xe2\x80\x98passfile\xe2\x80\x99 条目一起使用,但当我删除它时它确实有效。也许我做错了什么,但我尝试了几个不同的选项和文件夹。\n
  • \n
\n

编辑:让我添加一些解释点以避免误解。

\n

Django 文档是正确的,但我会添加一个关于在 Windows 上定义路径的注释(使用正斜杠/),正如他们在其他文档中指出的那样,需要将路径写入文件。

\n

上面的方法(没有passfile密钥是有效的,因为您添加了PGPASSFILE环境变量并psycopg2从中读取路径。

\n

pgpass.conf但您可以直接指定路径(或从环境变量中检索它,请参阅下面的注释行)

\n

数据库主机和数据库名称也应放置在.pg_service.conf文件中。请参阅PostgreSQL 文档中的所有参数关键字。

\n

考虑到这一点,以下文件示例应该有效(采用您的设置值)

\n
DATABASES = {\n    \'default\': {\n        \'ENGINE\': \'django.db.backends.postgresql\',\n        \'HOST\': \'localhost\',\n        \'NAME\': \'MyDbName\',\n        \'OPTIONS\': {\n            \'service\': \'test_svc_1\',\n        },\n    },\n}\n
Run Code Online (Sandbox Code Playgroud)\n
# C:\\Program Files\\PostgreSQL\\14\\etc\\.pg_service.conf\n\n[test_svc_1]\nhost=localhost\nuser=django_admin\ndbname=MyDbName\nport=5432\n
Run Code Online (Sandbox Code Playgroud)\n

当然,pgpass.conf必须存在正确的凭据:

\n
# Django `settings.py`\nimport os\n\nDATABASES = {\n    \'default\': {\n        \'ENGINE\': \'django.db.backends.postgresql\',\n        \'OPTIONS\': {\n            \'service\': \'test_svc_1\',\n            # \'passfile\': os.getenv("PGPASSFILE"),\n            \'passfile\': "C:/Program Files/PostgreSQL/14/etc/pgpass.conf",\n        },\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n