Files

130 lines
4.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""PostgreSQL 测试库准备(一次性)。
做三件事:
1. 探测本机 PostgreSQL 连接(默认 127.0.0.1:5433,用户 postgres);
2. 创建 `dealerhub`(开发)与 `dealerhub_test`(测试)两个库(幂等);
3. 应用迁移到开发库,使 `DJANGO_SETTINGS_MODULE=config.settings.dev` 能直接连 PG 跑。
用法:
python scripts/setup_pg.py # 用默认凭据探测
PG_PORT=5432 PG_USER=me PG_PASSWORD=xx python scripts/setup_pg.py
"""
from __future__ import annotations
import os
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
PG_HOST = os.environ.get("PG_HOST", "127.0.0.1")
PG_PORT = int(os.environ.get("PG_PORT", "5433"))
PG_USER = os.environ.get("PG_USER", "postgres")
PG_PASSWORD = os.environ.get("PG_PASSWORD", "postgres")
DEV_DB = os.environ.get("PG_DEV_DB", "dealerhub")
TEST_DB = os.environ.get("PG_TEST_DB", "dealerhub_test")
# 常见本地 PG 密码(只用于"探测",不做暴力破解)
PASSWORD_CANDIDATES = [PG_PASSWORD, "", "postgres", "123456", "root", "pg123456", "admin"]
def probe_connection() -> str | None:
"""返回可用密码;失败返回 None。"""
try:
import psycopg
except ImportError:
print("✗ 未安装 psycopg:pip install 'psycopg[binary]'")
return None
seen = []
for pw in PASSWORD_CANDIDATES:
if pw in seen:
continue
seen.append(pw)
try:
conn = psycopg.connect(
host=PG_HOST, port=PG_PORT, user=PG_USER, password=pw,
dbname="postgres", connect_timeout=3,
)
conn.close()
return pw
except Exception as exc:
print(f" · {PG_USER}/{pw or '(空)'} → {str(exc)[:70]}")
return None
def ensure_databases(password: str) -> bool:
import psycopg
ok = True
conn = psycopg.connect(
host=PG_HOST, port=PG_PORT, user=PG_USER, password=password,
dbname="postgres", autocommit=True,
)
cur = conn.cursor()
for db in (DEV_DB, TEST_DB):
cur.execute("SELECT 1 FROM pg_database WHERE datname = %s", (db,))
if cur.fetchone():
print(f" · {db} 已存在")
else:
cur.execute(f'CREATE DATABASE "{db}"')
print(f" ✓ 创建 {db}")
cur.close()
conn.close()
return ok
def apply_migrations_to_dev(password: str) -> bool:
"""把迁移应用到开发库(让 dev 设置能直接用 PG)。"""
os.environ.update({
"DATABASE_URL": f"postgres://{PG_USER}:{password}@{PG_HOST}:{PG_PORT}/{DEV_DB}",
"DJANGO_SETTINGS_MODULE": "config.settings.dev",
})
import django
django.setup()
from django.core.management import call_command
call_command("migrate", "--noinput", verbosity=0)
return True
def main() -> int:
print(f"探测 PostgreSQL · {PG_HOST}:{PG_PORT} · user={PG_USER}")
pw = probe_connection()
if pw is None:
print("\n✗ 无法连接。请确认:")
print(" 1. PostgreSQL 服务已启动")
print(" 2. 端口正确(PG_PORT=5433 是本机 PG 16 的常见端口)")
print(" 3. 凭据正确(PG_USER / PG_PASSWORD)")
return 1
print(f" ✓ 连接成功(密码:{pw or '(空)'})")
print("\n创建数据库")
ensure_databases(pw)
print("\n应用迁移到开发库")
apply_migrations_to_dev(pw)
print(f" ✓ {DEV_DB} 迁移完成")
print(f"""
准备完成。运行方式:
# 开发/手工验证(连 PG)
export DATABASE_URL="postgres://{PG_USER}:{pw}@{PG_HOST}:{PG_PORT}/{DEV_DB}"
DJANGO_SETTINGS_MODULE=config.settings.dev granian config.asgi:application --interface asgi --port 8000
# 全量测试(含并发,PG 行锁语义)
DJANGO_SETTINGS_MODULE=config.settings.pgtest python -m pytest tests/ -p no:cacheprovider
# 只跑并发用例
DJANGO_SETTINGS_MODULE=config.settings.pgtest python -m pytest tests/test_concurrency.py -p no:cacheprovider -m postgres
""")
return 0
if __name__ == "__main__":
sys.exit(main())