搭建Django测试环境时如何创建外部数据库?
Posted
技术标签:
【中文标题】搭建Django测试环境时如何创建外部数据库?【英文标题】:How to create an external database when setting up Django test environment? 【发布时间】:2016-02-17 09:57:54 【问题描述】:我的 Django 应用程序需要连接一个非托管(非 Django)外部 Postgres 数据库。
为了测试我的项目,我需要使用原始 SQL 创建外部数据库和表,然后删除数据库。
通过阅读 Django 文档,可以使用现有的 DiscoverRunner
类创建您自己的 TestRunner 类。可以重写 setup_test_environment
和 teardown_test_environment
方法以执行 SQL 以创建外部数据库:
from psycopg2 import connect
from django.test.runner import DiscoverRunner
class CustomTestRunner(DiscoverRunner):
"""
Test runner that helps to setup external db if doesn`t exist.
"""
def setup_test_environment(self, *args, **kwargs):
conn = connect(database='postgres', host='localhost', user='my_user', password='password123')
try:
with conn.cursor() as c:
query = """CREATE DATABASE "test_db" """
query += """WITH OWNER = my_user """
query += """ENCODING = 'UTF8' TABLESPACE = pg_default """
query += """LC_COLLATE = 'en_ZA.UTF-8' LC_CTYPE = 'en_ZA.UTF-8' """
query += """CONNECTION LIMIT = -1;"""
c.execute(query)
except Exception as e:
print e
conn.close()
super(CustomTestRunner, self).setup_test_environment(*args,
**kwargs)
def teardown_test_environment(self, *args, **kwargs):
super(CustomTestRunner, self).teardown_test_environment(*args,
**kwargs)
# Delete external database after tests
try:
conn = connect(database='postgres', host='localhost', user='my_user', password='password123')
with conn.cursor() as c:
query = """DROP DATABASE test_db;"""
c.execute(query)
except Exception as e:
print e
conn.close()
conn.close()
但是,当我运行测试时,我收到以下错误消息:
CREATE DATABASE cannot run inside a transaction block
是否可以在 Django TestRunner 中运行和提交 SQL?如果没有,在哪里创建这样一个外部数据库的合适位置?
【问题讨论】:
【参考方案1】:某些数据库命令(例如 CREATE DATABASE
)无法在事务中运行。您需要在数据库连接上设置适当的隔离级别:
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
见http://initd.org/psycopg/docs/extensions.html#isolation-level-constants。
还可以在测试运行程序中运行和提交 SQL。更合适的地方是setup_databses
和teardown_databases
方法。这是一个例子
def setup_databases(self, **kwargs):
conn = connect(database='postgres', host='localhost', ...)
try:
# set the proper isolation level so CREATE DATABASE works
conn.set_isolation_level(psycopg2.extensions.ISOLATION_LEVEL_AUTOCOMMIT)
with conn.cursor() as cur:
# execute SQL in here
query = 'create database TEST_DB'
cur.execute(query)
finally:
conn.close()
return super(CustomTestRunner, self).setup_databases(**kwargs)
teardown_databases
的实现应该非常相似。
【讨论】:
我已经测试了您的解决方案,效果很好。非常感谢! 作为脚注,必须记住返回return super(CustomTestRunner, self).setup_databases(*args, **kwargs)
。请注意 super 中的*args
。以上是关于搭建Django测试环境时如何创建外部数据库?的主要内容,如果未能解决你的问题,请参考以下文章
python测试开发django-157.celery异步与redis环境搭建
CentOS + Python3.6+ Django2.0 + uwsgi + nginx + mysql web发布环境搭建