我有一系列集成级别的测试,它们在我的Django项目中作为管理命令运行。这些测试验证了从外部源摄入我的数据库的大量天气数据的完整性。因为我有如此大量的数据,所以我真的必须对我的生产数据库进行测试才能使测试有意义。我想弄清楚的是我如何定义一个特定于该命令或连接对象的只读数据库连接。我还应该补充一点,这些测试不能通过ORM,所以我需要执行原始SQL。
我的测试结构如下所示
class Command(BaseCommand):
help = 'Runs Integration Tests and Query Tests against Prod Database'
def handle(self,*args, **options):
suite = unittest.TestLoader().loadTestsFromTestCase(TestWeatherModel)
ret = unittest.TextTestRunner().run(suite)
if(len(ret.failures) != 0):
sys.exit(1)
else:
sys.exit(0)
class TestWeatherModel(unittest.TestCase):
def testCollectWeatherDataHist(self):
wm = WeatherManager()
wm.CollectWeatherData()
self.assertTrue(wm.weatherData is not None)
WeatherManager.CollectWeatherData()方法如下所示:
def CollecWeatherData(self):
cur = connection.cursor()
cur.execute(<Raw SQL Query>)
wm.WeatherData = cur.fetchall()
cur.close()
我想以某种方式愚蠢地证明这一点,以便其他人(或我)可以在以后出现并意外地编写一个可以修改生产数据库的测试。
答案 0 :(得分:2)
男人,在我发布问题之前,我应该再仔细阅读文档。我可以在设置文件中定义与生产数据库的只读连接,然后直接从docs:
如果您使用多个数据库,则可以使用django.db.connections获取特定数据库的连接(和游标)。 django.db.connections是一个类似字典的对象,允许您使用别名检索特定连接:
from django.db import connections
cursor = connections['my_db_alias'].cursor()
# Your code here...
答案 1 :(得分:1)
你可以通过挂钩Django的connection_created
信号来实现这一目标
然后将事务设为只读。
以下适用于PostgreSQL:
from django.db.backends.signals import connection_created
class MyappConfig(AppConfig):
def ready(self):
def connection_created_handler(connection, **kwargs):
with connection.cursor() as cursor:
cursor.execute('SET default_transaction_read_only = true;')
connection_created.connect(connection_created_handler, weak=False)
这对某些特定的Django设置很有用(例如,运行开发
代码runserver
针对生产数据库),您不想这样做
创建一个真正的只读数据库用户。
答案 2 :(得分:0)
如果您为模型添加序列化程序,您可以专门使用以只读模式工作的序列化程序
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'users', 'created')
read_only_fields = ('account_name',)
来自http://www.django-rest-framework.org/api-guide/serializers/#specifying-read-only-fields
答案 3 :(得分:0)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'mydb',
'USER': 'myusername',
'PASSWORD': 'mypassword',
'HOST': 'myhost',
'OPTIONS': {
'options': '-c default_transaction_read_only=on'
}
}
}