1
0
mirror of https://github.com/django/django.git synced 2025-10-25 14:46:09 +00:00

[soc2009/multidb] A couple of cleanups of multi-db support for raw queries, including a using() call on raw query sets. Patch from Russell Keith-Magee.

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/multidb@11930 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Alex Gaynor
2009-12-21 19:30:49 +00:00
parent e4f8015112
commit 928e1f1f33
6 changed files with 39 additions and 19 deletions

View File

@@ -91,7 +91,7 @@ class Manager(object):
obj = copy.copy(self) obj = copy.copy(self)
obj._db = alias obj._db = alias
return obj return obj
@property @property
def db(self): def db(self):
return self._db or DEFAULT_DB_ALIAS return self._db or DEFAULT_DB_ALIAS
@@ -189,7 +189,7 @@ class Manager(object):
def using(self, *args, **kwargs): def using(self, *args, **kwargs):
return self.get_query_set().using(*args, **kwargs) return self.get_query_set().using(*args, **kwargs)
def exists(self, *args, **kwargs): def exists(self, *args, **kwargs):
return self.get_query_set().exists(*args, **kwargs) return self.get_query_set().exists(*args, **kwargs)
@@ -199,9 +199,8 @@ class Manager(object):
def _update(self, values, **kwargs): def _update(self, values, **kwargs):
return self.get_query_set()._update(values, **kwargs) return self.get_query_set()._update(values, **kwargs)
def raw(self, query, params=None, *args, **kwargs): def raw(self, raw_query, params=None, *args, **kwargs):
kwargs["using"] = self.db return RawQuerySet(raw_query=raw_query, model=self.model, params=params, using=self.db, *args, **kwargs)
return RawQuerySet(model=self.model, query=query, params=params, *args, **kwargs)
class ManagerDescriptor(object): class ManagerDescriptor(object):
# This class ensures managers aren't accessible via model instances. # This class ensures managers aren't accessible via model instances.

View File

@@ -711,10 +711,10 @@ class QuerySet(object):
return False return False
ordered = property(ordered) ordered = property(ordered)
@property
def db(self): def db(self):
"Return the database that will be used if this query is executed now" "Return the database that will be used if this query is executed now"
return self._db or DEFAULT_DB_ALIAS return self._db or DEFAULT_DB_ALIAS
db = property(db)
################### ###################
# PRIVATE METHODS # # PRIVATE METHODS #
@@ -1154,11 +1154,12 @@ class RawQuerySet(object):
Provides an iterator which converts the results of raw SQL queries into Provides an iterator which converts the results of raw SQL queries into
annotated model instances. annotated model instances.
""" """
def __init__(self, query, model=None, query_obj=None, params=None, def __init__(self, raw_query, model=None, query=None, params=None,
translations=None, using=None): translations=None, using=None):
self.raw_query = raw_query
self.model = model self.model = model
self.using = using self._db = using
self.query = query_obj or sql.RawQuery(sql=query, connection=connections[using], params=params) self.query = query or sql.RawQuery(sql=raw_query, using=self.db, params=params)
self.params = params or () self.params = params or ()
self.translations = translations or {} self.translations = translations or {}
@@ -1167,7 +1168,21 @@ class RawQuerySet(object):
yield self.transform_results(row) yield self.transform_results(row)
def __repr__(self): def __repr__(self):
return "<RawQuerySet: %r>" % (self.query.sql % self.params) return "<RawQuerySet: %r>" % (self.raw_query % self.params)
@property
def db(self):
"Return the database that will be used if this query is executed now"
return self._db or DEFAULT_DB_ALIAS
def using(self, alias):
"""
Selects which database this Raw QuerySet should excecute it's query against.
"""
return RawQuerySet(self.raw_query, model=self.model,
query=self.query.clone(using=alias),
params=self.params, translations=self.translations,
using=alias)
@property @property
def columns(self): def columns(self):
@@ -1232,8 +1247,8 @@ class RawQuerySet(object):
for field, value in annotations: for field, value in annotations:
setattr(instance, field, value) setattr(instance, field, value)
instance._state.db = self.using instance._state.db = self.query.using
return instance return instance

View File

@@ -29,13 +29,16 @@ class RawQuery(object):
A single raw SQL query A single raw SQL query
""" """
def __init__(self, sql, connection, params=None): def __init__(self, sql, using, params=None):
self.validate_sql(sql) self.validate_sql(sql)
self.params = params or () self.params = params or ()
self.sql = sql self.sql = sql
self.connection = connection self.using = using
self.cursor = None self.cursor = None
def clone(self, using):
return RawQuery(self.sql, using, params=self.params)
def get_columns(self): def get_columns(self):
if self.cursor is None: if self.cursor is None:
self._execute_query() self._execute_query()
@@ -56,7 +59,7 @@ class RawQuery(object):
return "<RawQuery: %r>" % (self.sql % self.params) return "<RawQuery: %r>" % (self.sql % self.params)
def _execute_query(self): def _execute_query(self):
self.cursor = self.connection.cursor() self.cursor = connections[self.using].cursor()
self.cursor.execute(self.sql, self.params) self.cursor.execute(self.sql, self.params)

View File

@@ -23,7 +23,7 @@ Performing raw queries
The ``raw()`` manager method can be used to perform raw SQL queries that The ``raw()`` manager method can be used to perform raw SQL queries that
return model instances: return model instances:
.. method:: Manager.raw(query, params=None, translations=None) .. method:: Manager.raw(raw_query, params=None, translations=None)
This method method takes a raw SQL query, executes it, and returns model This method method takes a raw SQL query, executes it, and returns model
instances. instances.

View File

@@ -10,7 +10,7 @@ class RawQueryTests(TestCase):
""" """
Execute the passed query against the passed model and check the output Execute the passed query against the passed model and check the output
""" """
results = list(model.objects.raw(query=query, params=params, translations=translations)) results = list(model.objects.raw(query, params=params, translations=translations))
self.assertProcessed(results, expected_results, expected_annotations) self.assertProcessed(results, expected_results, expected_annotations)
self.assertAnnotations(results, expected_annotations) self.assertAnnotations(results, expected_annotations)
@@ -111,7 +111,7 @@ class RawQueryTests(TestCase):
query = "SELECT * FROM raw_query_author WHERE first_name = %s" query = "SELECT * FROM raw_query_author WHERE first_name = %s"
author = Author.objects.all()[2] author = Author.objects.all()[2]
params = [author.first_name] params = [author.first_name]
results = list(Author.objects.raw(query=query, params=params)) results = list(Author.objects.raw(query, params=params))
self.assertProcessed(results, [author]) self.assertProcessed(results, [author])
self.assertNoAnnotations(results) self.assertNoAnnotations(results)
self.assertEqual(len(results), 1) self.assertEqual(len(results), 1)

View File

@@ -619,7 +619,7 @@ class QueryTestCase(TestCase):
self.assertEquals(learn.get_next_by_published().title, "Dive into Python") self.assertEquals(learn.get_next_by_published().title, "Dive into Python")
self.assertEquals(dive.get_previous_by_published().title, "Learning Python") self.assertEquals(dive.get_previous_by_published().title, "Learning Python")
def test_raw(self): def test_raw(self):
"test the raw() method across databases" "test the raw() method across databases"
dive = Book.objects.using('other').create(title="Dive into Python", dive = Book.objects.using('other').create(title="Dive into Python",
@@ -627,6 +627,9 @@ class QueryTestCase(TestCase):
val = Book.objects.db_manager("other").raw('SELECT id FROM "multiple_database_book"') val = Book.objects.db_manager("other").raw('SELECT id FROM "multiple_database_book"')
self.assertEqual(map(lambda o: o.pk, val), [dive.pk]) self.assertEqual(map(lambda o: o.pk, val), [dive.pk])
val = Book.objects.raw('SELECT id FROM "multiple_database_book"').using('other')
self.assertEqual(map(lambda o: o.pk, val), [dive.pk])
class UserProfileTestCase(TestCase): class UserProfileTestCase(TestCase):
def setUp(self): def setUp(self):