From 8be6dd5d7b066741966233aa50a4b324ba8a0516 Mon Sep 17 00:00:00 2001 From: Jan De Bleser Date: Mon, 19 Mar 2018 17:27:20 +0100 Subject: [PATCH 1/2] Not caching the creation of a cursor This gives problems if you have more than 1 connection in your DATABASES variable in settings.py. The cursor will be closed and give a "cursor already closed" error. --- architect/orms/django/features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architect/orms/django/features.py b/architect/orms/django/features.py index 75ee77b..7d36871 100644 --- a/architect/orms/django/features.py +++ b/architect/orms/django/features.py @@ -20,7 +20,7 @@ class ConnectionMixin(object): def database(self): return self.options.get('db', router.db_for_write(self.model_cls)) - @cached_property + @property def connection(self): db = self.database From 050fc3adfe8507ac08f404a914257b41a7d00306 Mon Sep 17 00:00:00 2001 From: Jan De Bleser Date: Fri, 23 Mar 2018 11:30:57 +0100 Subject: [PATCH 2/2] Fixed issue with always creating a new connection. --- architect/orms/django/features.py | 32 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/architect/orms/django/features.py b/architect/orms/django/features.py index 7d36871..e5c06d1 100644 --- a/architect/orms/django/features.py +++ b/architect/orms/django/features.py @@ -1,12 +1,12 @@ """ Defines features for the Django ORM. """ +from contextlib import closing from django.conf import settings from django.db import router, connections, transaction from django.db.models.fields import FieldDoesNotExist from django.db.utils import ConnectionDoesNotExist -from django.utils.functional import cached_property from ..bases import BasePartitionFeature, BaseOperationFeature from ...exceptions import PartitionColumnError, OptionNotSetError, OptionValueError @@ -31,9 +31,12 @@ def connection(self): class OperationFeature(ConnectionMixin, BaseOperationFeature): - def execute(self, sql, autocommit=True): + def execute(self, sql, autocommit=True, connection=None): + if connection is None: + connection = self.connection + if not autocommit: - return self.connection.execute(sql) + return connection.execute(sql) try: autocommit = transaction.atomic # Django >= 1.6 @@ -45,22 +48,23 @@ def execute(self, sql, autocommit=True): autocommit = transaction.commit_on_success # Django <= 1.5 with autocommit(using=self.database): - return self.connection.execute(sql) + return connection.execute(sql) def select_one(self, sql): - self.execute(sql) - result = self.connection.fetchone() - return result[0] if result is not None else result + with closing(self.connection) as connection: + self.execute(sql, connection=connection) + result = connection.fetchone() + return result[0] if result is not None else result def select_all(self, sql, as_dict=False): - self.execute(sql) - - if as_dict: - result = [dict(zip([c[0] for c in self.connection.description], row)) for row in self.connection.fetchall()] - else: - result = self.connection.fetchall() + with closing(self.connection) as connection: + self.execute(sql, connection=connection) + if as_dict: + result = [dict(zip([c[0] for c in connection.description], row)) for row in connection.fetchall()] + else: + result = connection.fetchall() - return result + return result class PartitionFeature(ConnectionMixin, BasePartitionFeature):