Ticket #4747: mymultidb_trunk7534_20080521.diff
File mymultidb_trunk7534_20080521.diff, 137.3 KB (added by , 16 years ago) |
---|
-
django/test/utils.py
1 1 import sys, time, os 2 from django.conf import settings 3 from django.db import connection , get_creation_module2 from django.conf import settings, UserSettingsHolder 3 from django.db import connections, get_creation_module, _default 4 4 from django.core import mail 5 5 from django.core.management import call_command 6 6 from django.dispatch import dispatcher … … 78 78 elif hasattr(connection.connection, "set_isolation_level"): 79 79 connection.connection.set_isolation_level(0) 80 80 81 def get_mysql_create_suffix( ):81 def get_mysql_create_suffix(settings): 82 82 suffix = [] 83 if settings. TEST_DATABASE_CHARSET:84 suffix.append('CHARACTER SET %s' % settings. TEST_DATABASE_CHARSET)85 if settings. TEST_DATABASE_COLLATION:86 suffix.append('COLLATE %s' % settings. TEST_DATABASE_COLLATION)83 if settings.DATABASE_CHARSET: 84 suffix.append('CHARACTER SET %s' % settings.DATABASE_CHARSET) 85 if settings.DATABASE_COLLATION: 86 suffix.append('COLLATE %s' % settings.DATABASE_COLLATION) 87 87 return ' '.join(suffix) 88 88 89 89 def get_postgresql_create_suffix(): 90 assert settings. TEST_DATABASE_COLLATION is None, "PostgreSQL does not support collation setting at database creation time."91 if settings. TEST_DATABASE_CHARSET:92 return "WITH ENCODING '%s'" % settings. TEST_DATABASE_CHARSET90 assert settings.DATABASE_COLLATION is None, "PostgreSQL does not support collation setting at database creation time." 91 if settings.DATABASE_CHARSET: 92 return "WITH ENCODING '%s'" % settings.DATABASE_CHARSET 93 93 return '' 94 94 95 95 def create_test_db(verbosity=1, autoclobber=False): 96 97 if settings.DATABASE_ENGINE == "sqlite3": 98 if settings.TEST_DATABASE_NAME and settings.TEST_DATABASE_NAME != ":memory:": 99 TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME 100 else: 101 TEST_DATABASE_NAME = ":memory:" 102 else: 103 if settings.TEST_DATABASE_NAME: 104 TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME 105 else: 106 TEST_DATABASE_NAME = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 107 108 settings.DATABASE_NAME = TEST_DATABASE_NAME 109 settings.DATABASE_CHARSET = settings.TEST_DATABASE_CHARSET 110 settings.DATABASE_COLLATION = settings.TEST_DATABASE_COLLATION 111 112 # default database 113 _create_test_db(settings, verbosity=verbosity, autoclobber=autoclobber) 114 115 # other databases 116 settings.OTHER_DATABASES = settings.TEST_OTHER_DATABASES 117 for db in settings.OTHER_DATABASES: 118 info = settings.OTHER_DATABASES[db] 119 database = UserSettingsHolder(settings) 120 for k, v in info.items(): 121 setattr(database, k, v) 122 _create_test_db(database, verbosity=verbosity, autoclobber=autoclobber, connection_name=db) 123 124 ## for cnx in connections: 125 ## connections[cnx].connection.close() 126 127 call_command('syncdb', verbosity=verbosity, interactive=False) 128 129 if settings.CACHE_BACKEND.startswith('db://'): 130 cache_name = settings.CACHE_BACKEND[len('db://'):] 131 call_command('createcachetable', cache_name) 132 133 # Get a cursor (even though we don't need one yet). This has 134 # the side effect of initializing the test database. 135 ## for cnx in connections: 136 ## cursor = connections[cnx].connection.cursor() 137 ## cursor = connection.cursor() 138 139 return TEST_DATABASE_NAME 140 141 def _create_test_db(settings, verbosity=1, autoclobber=False, connection_name=_default): 96 142 """ 97 143 Creates a test database, prompting the user for confirmation if the 98 144 database already exists. Returns the name of the test database created. 99 145 """ 146 connection = connections[connection_name].connection 100 147 # If the database backend wants to create the test DB itself, let it 101 creation_module = get_creation_module()148 creation_module = connections[connection_name].get_creation_module() 102 149 if hasattr(creation_module, "create_test_db"): 103 150 creation_module.create_test_db(settings, connection, verbosity, autoclobber) 104 151 return … … 109 156 # in-memory database. Using the TEST_DATABASE_NAME setting you can still choose 110 157 # to run on a physical database. 111 158 if settings.DATABASE_ENGINE == "sqlite3": 112 if settings.TEST_DATABASE_NAME and settings.TEST_DATABASE_NAME != ":memory:": 113 TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME 159 if settings.DATABASE_NAME != ":memory:": 114 160 # Erase the old test database 115 161 if verbosity >= 1: 116 162 print "Destroying old test database..." 117 if os.access( TEST_DATABASE_NAME, os.F_OK):163 if os.access(settings.DATABASE_NAME, os.F_OK): 118 164 if not autoclobber: 119 confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % TEST_DATABASE_NAME)165 confirm = raw_input("Type 'yes' if you would like to try deleting the test database '%s', or 'no' to cancel: " % settings.DATABASE_NAME) 120 166 if autoclobber or confirm == 'yes': 121 167 try: 122 168 if verbosity >= 1: 123 169 print "Destroying old test database..." 124 os.remove( TEST_DATABASE_NAME)170 os.remove(settings.DATABASE_NAME) 125 171 except Exception, e: 126 172 sys.stderr.write("Got an error deleting the old test database: %s\n" % e) 127 173 sys.exit(2) … … 130 176 sys.exit(1) 131 177 if verbosity >= 1: 132 178 print "Creating test database..." 133 else:134 TEST_DATABASE_NAME = ":memory:"135 179 else: 136 180 suffix = { 137 181 'postgresql': get_postgresql_create_suffix, 138 182 'postgresql_psycopg2': get_postgresql_create_suffix, 139 183 'mysql': get_mysql_create_suffix, 140 184 'mysql_old': get_mysql_create_suffix, 141 }.get(settings.DATABASE_ENGINE, lambda: '')() 142 if settings.TEST_DATABASE_NAME: 143 TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME 144 else: 145 TEST_DATABASE_NAME = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 185 }.get(settings.DATABASE_ENGINE, lambda: '')(settings) 146 186 187 connection = connections[connection_name].connection 147 188 qn = connection.ops.quote_name 148 189 149 190 # Create the test database and connect to it. We need to autocommit … … 172 213 print "Tests cancelled." 173 214 sys.exit(1) 174 215 175 connection.close()176 settings.DATABASE_NAME = TEST_DATABASE_NAME177 216 178 call_command('syncdb', verbosity=verbosity, interactive=False) 217 def destroy_test_db(old_database_name, old_databases, verbosity=1): 218 if verbosity >= 1: 219 print "Destroying test database(s)..." 220 ## connection.close() 221 for cnx in connections.keys(): 222 connections[cnx].close() 223 ## connections.reset() 224 TEST_DATABASE_NAME = settings.DATABASE_NAME 225 settings.DATABASE_NAME = old_database_name 226 _destroy_test_db(settings, TEST_DATABASE_NAME, verbosity=verbosity) 227 TEST_OTHER_DATABASES = settings.OTHER_DATABASES 228 settings.OTHER_DATABASES = old_databases 229 for db in TEST_OTHER_DATABASES: 230 info = TEST_OTHER_DATABASES[db] 231 database = UserSettingsHolder(settings) 232 for k, v in info.items(): 233 setattr(database, k, v) 234 if db in old_databases: 235 _destroy_test_db(database, info['DATABASE_NAME'], verbosity=verbosity, connection_name=db) 179 236 180 if settings.CACHE_BACKEND.startswith('db://'): 181 cache_name = settings.CACHE_BACKEND[len('db://'):] 182 call_command('createcachetable', cache_name) 183 184 # Get a cursor (even though we don't need one yet). This has 185 # the side effect of initializing the test database. 186 cursor = connection.cursor() 187 188 return TEST_DATABASE_NAME 189 190 def destroy_test_db(old_database_name, verbosity=1): 237 def _destroy_test_db(settings, TEST_DATABASE_NAME, verbosity=1, connection_name=_default): 238 connection = connections[connection_name].connection 191 239 # If the database wants to drop the test DB itself, let it 192 creation_module = get_creation_module()240 creation_module = connections[connection_name].get_creation_module() 193 241 if hasattr(creation_module, "destroy_test_db"): 194 242 creation_module.destroy_test_db(settings, connection, old_database_name, verbosity) 195 243 return 196 244 197 if verbosity >= 1:198 print "Destroying test database..."199 connection.close()200 TEST_DATABASE_NAME = settings.DATABASE_NAME201 settings.DATABASE_NAME = old_database_name202 245 if settings.DATABASE_ENGINE == "sqlite3": 203 246 if TEST_DATABASE_NAME and TEST_DATABASE_NAME != ":memory:": 204 247 # Remove the SQLite database file 205 os.remove(TEST_DATABASE_NAME) 248 ## os.remove(TEST_DATABASE_NAME) 249 pass 206 250 else: 207 251 # Remove the test database to clean up after 208 252 # ourselves. Connect to the previous database (not the test database) -
django/test/simple.py
138 138 for test in extra_tests: 139 139 suite.addTest(test) 140 140 141 old_name = settings.DATABASE_NAME 141 old_database_name = settings.DATABASE_NAME 142 old_other_databases = settings.OTHER_DATABASES 142 143 create_test_db(verbosity, autoclobber=not interactive) 143 144 result = unittest.TextTestRunner(verbosity=verbosity).run(suite) 144 destroy_test_db(old_ name, verbosity)145 destroy_test_db(old_database_name, old_other_databases, verbosity) 145 146 146 147 teardown_test_environment() 147 148 -
django/db/models/sql/where.py
4 4 import datetime 5 5 6 6 from django.utils import tree 7 from django.db import connection8 7 from django.db.models.fields import Field 9 8 from django.db.models.query_utils import QueryWrapper 10 9 from datastructures import EmptyResultSet, FullResultSet 11 10 11 from copy import deepcopy 12 12 13 # Connection types 13 14 AND = 'AND' 14 15 OR = 'OR' … … 26 27 """ 27 28 default = AND 28 29 30 def __init__(self, connection, *args, **kwargs): 31 self.connection = connection 32 super(WhereNode, self).__init__(*args, **kwargs) 33 34 def __deepcopy__(self, memo): 35 x = WhereNode.__new__(WhereNode) 36 memo[id(self)] = x 37 for n, v in self.__dict__.iteritems(): 38 if n != 'connection': 39 setattr(x, n, deepcopy(v, memo)) 40 else: 41 setattr(x, n, self.connection) 42 return x 43 29 44 def as_sql(self, node=None, qn=None): 30 45 """ 31 46 Returns the SQL version of the where clause and the value to be … … 38 53 if node is None: 39 54 node = self 40 55 if not qn: 41 qn = connection.ops.quote_name56 qn = self.connection.ops.quote_name 42 57 if not node.children: 43 58 return None, [] 44 59 result = [] … … 99 114 lhs = '%s.%s' % (qn(table_alias), qn(name)) 100 115 else: 101 116 lhs = qn(name) 102 db_type = field and field.db_type() or None103 field_sql = connection.ops.field_cast_sql(db_type) % lhs104 117 118 db_type = field and field.db_type(self.connection.connection_name) or None 119 field_sql = self.connection.ops.field_cast_sql(db_type) % lhs 120 105 121 if isinstance(value, datetime.datetime): 106 cast_sql = connection.ops.datetime_cast_sql()122 cast_sql = self.connection.ops.datetime_cast_sql() 107 123 else: 108 124 cast_sql = '%s' 109 125 … … 116 132 else: 117 133 extra = '' 118 134 119 if lookup_type in connection.operators:120 format = "%s %%s %s" % ( connection.ops.lookup_cast(lookup_type),135 if lookup_type in self.connection.operators: 136 format = "%s %%s %s" % (self.connection.ops.lookup_cast(lookup_type), 121 137 extra) 122 138 return (format % (field_sql, 123 connection.operators[lookup_type] % cast_sql), params)139 self.connection.operators[lookup_type] % cast_sql), params) 124 140 125 141 if lookup_type == 'in': 126 142 if not value: … … 132 148 elif lookup_type in ('range', 'year'): 133 149 return ('%s BETWEEN %%s and %%s' % field_sql, params) 134 150 elif lookup_type in ('month', 'day'): 135 return ('%s = %%s' % connection.ops.date_extract_sql(lookup_type,151 return ('%s = %%s' % self.connection.ops.date_extract_sql(lookup_type, 136 152 field_sql), params) 137 153 elif lookup_type == 'isnull': 138 154 return ('%s IS %sNULL' % (field_sql, (not value and 'NOT ' or '')), 139 155 params) 140 156 elif lookup_type == 'search': 141 return ( connection.ops.fulltext_search_sql(field_sql), params)157 return (self.connection.ops.fulltext_search_sql(field_sql), params) 142 158 elif lookup_type in ('regex', 'iregex'): 143 return connection.ops.regex_lookup(lookup_type) % (field_sql, cast_sql), params159 return self.connection.ops.regex_lookup(lookup_type) % (field_sql, cast_sql), params 144 160 145 161 raise TypeError('Invalid lookup_type: %r' % lookup_type) 146 162 -
django/db/models/sql/query.py
60 60 # SQL-related attributes 61 61 self.select = [] 62 62 self.tables = [] # Aliases in the order they are created. 63 self.where = where( )63 self.where = where(self.connection) 64 64 self.where_class = where 65 65 self.group_by = [] 66 66 self.having = [] … … 215 215 obj.related_select_cols = [] 216 216 obj.related_select_fields = [] 217 217 if obj.distinct and len(obj.select) > 1: 218 obj = self.clone(CountQuery, _query=obj, where=self.where_class( ),218 obj = self.clone(CountQuery, _query=obj, where=self.where_class(self.connection), 219 219 distinct=False) 220 220 obj.select = [] 221 221 obj.extra_select = {} … … 346 346 self.where.add(EverythingNode(), AND) 347 347 elif self.where: 348 348 # rhs has an empty where clause. 349 w = self.where_class( )349 w = self.where_class(self.connection) 350 350 w.add(EverythingNode(), AND) 351 351 else: 352 w = self.where_class( )352 w = self.where_class(self.connection) 353 353 self.where.add(w, connector) 354 354 355 355 # Selection columns and extra extensions are those provided by 'rhs'. -
django/db/models/sql/subqueries.py
47 47 for related in cls._meta.get_all_related_many_to_many_objects(): 48 48 if not isinstance(related.field, generic.GenericRelation): 49 49 for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): 50 where = self.where_class( )50 where = self.where_class(self.connection) 51 51 where.add((None, related.field.m2m_reverse_name(), 52 52 related.field, 'in', 53 53 pk_list[offset : offset+GET_ITERATOR_CHUNK_SIZE]), … … 55 55 self.do_query(related.field.m2m_db_table(), where) 56 56 57 57 for f in cls._meta.many_to_many: 58 w1 = self.where_class( )58 w1 = self.where_class(self.connection) 59 59 if isinstance(f, generic.GenericRelation): 60 60 from django.contrib.contenttypes.models import ContentType 61 61 field = f.rel.to._meta.get_field(f.content_type_field_name) 62 62 w1.add((None, field.column, field, 'exact', 63 63 ContentType.objects.get_for_model(cls).id), AND) 64 64 for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): 65 where = self.where_class( )65 where = self.where_class(self.connection) 66 66 where.add((None, f.m2m_column_name(), f, 'in', 67 67 pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]), 68 68 AND) … … 79 79 lot of values in pk_list. 80 80 """ 81 81 for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): 82 where = self.where_class( )82 where = self.where_class(self.connection) 83 83 field = self.model._meta.pk 84 84 where.add((None, field.column, field, 'in', 85 85 pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]), AND) … … 178 178 179 179 # Now we adjust the current query: reset the where clause and get rid 180 180 # of all the tables we don't need (since they're in the sub-select). 181 self.where = self.where_class( )181 self.where = self.where_class(self.connection) 182 182 if self.related_updates or must_pre_select: 183 183 # Either we're using the idents in multiple update queries (so 184 184 # don't want them to change), or the db backend doesn't support … … 202 202 This is used by the QuerySet.delete_objects() method. 203 203 """ 204 204 for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): 205 self.where = self.where_class( )205 self.where = self.where_class(self.connection) 206 206 f = self.model._meta.pk 207 207 self.where.add((None, f.column, f, 'in', 208 208 pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]), -
django/db/models/options.py
53 53 self.module_name = self.object_name.lower() 54 54 self.verbose_name = get_verbose_name(self.object_name) 55 55 56 self.model = cls 57 56 58 # Next, apply any overridden values from 'class Meta'. 57 59 if self.meta: 58 60 meta_attrs = self.meta.__dict__.copy() … … 84 86 del self.meta 85 87 86 88 def _prepare(self, model): 87 from django.db import connection88 89 from django.db.backends.util import truncate_name 90 from django.db import connections, connection_name_app_model 89 91 if self.order_with_respect_to: 90 92 self.order_with_respect_to = self.get_field(self.order_with_respect_to) 91 93 self.ordering = ('_order',) … … 107 109 # If the db_table wasn't provided, use the app_label + module_name. 108 110 if not self.db_table: 109 111 self.db_table = "%s_%s" % (self.app_label, self.module_name) 110 self.db_table = truncate_name(self.db_table, connection.ops.max_name_length()) 112 connection_name = connection_name_app_model(self.app_label, self.object_name) 113 self.db_table = truncate_name(self.db_table, connections[connection_name].connection.ops.max_name_length()) 111 114 112 115 def add_field(self, field): 113 116 # Insert the given field in the order in which it was created, using -
django/db/models/fields/__init__.py
7 7 except ImportError: 8 8 from django.utils import _decimal as decimal # for Python 2.3 9 9 10 from django.db import get_creation_module10 from django.db import connections 11 11 from django.db.models import signals 12 12 from django.db.models.query_utils import QueryWrapper 13 13 from django.dispatch import dispatcher … … 144 144 """ 145 145 return value 146 146 147 def db_type(self ):147 def db_type(self, connection): 148 148 """ 149 149 Returns the database column data type for this field, taking into 150 150 account the DATABASE_ENGINE setting. … … 165 165 # can implement db_type() instead of get_internal_type() to specify 166 166 # exactly which wacky database column type you want to use. 167 167 try: 168 return get_creation_module().DATA_TYPES[self.get_internal_type()] % self.__dict__168 return connections[connection].get_creation_module().DATA_TYPES[self.get_internal_type()] % self.__dict__ 169 169 except KeyError: 170 170 return None 171 171 -
django/db/models/fields/related.py
1 from django.db import connection,transaction1 from django.db import transaction 2 2 from django.db.models import signals, get_model 3 3 from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, get_ul_class 4 4 from django.db.models.related import RelatedObject … … 368 368 # target_col_name: the PK colname in join_table for the target object 369 369 # *objs - objects to add. Either object instances, or primary keys of object instances. 370 370 371 connection = self.model._default_manager.db.connection 372 371 373 # If there aren't any objects, there is nothing to do. 372 374 if objs: 373 375 # Check that all the objects are of the right type … … 391 393 cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \ 392 394 (self.join_table, source_col_name, target_col_name), 393 395 [self._pk_val, obj_id]) 394 transaction.commit_unless_managed( )396 transaction.commit_unless_managed(connection) 395 397 396 398 def _remove_items(self, source_col_name, target_col_name, *objs): 397 399 # source_col_name: the PK colname in join_table for the source object 398 400 # target_col_name: the PK colname in join_table for the target object 399 401 # *objs - objects to remove 400 402 403 connection = self.model._default_manager.db.connection 404 401 405 # If there aren't any objects, there is nothing to do. 402 406 if objs: 403 407 # Check that all the objects are of the right type … … 413 417 (self.join_table, source_col_name, 414 418 target_col_name, ",".join(['%s'] * len(old_ids))), 415 419 [self._pk_val] + list(old_ids)) 416 transaction.commit_unless_managed( )420 transaction.commit_unless_managed(connection) 417 421 418 422 def _clear_items(self, source_col_name): 419 423 # source_col_name: the PK colname in join_table for the source object 424 connection = self.model._default_manager.db.connection 420 425 cursor = connection.cursor() 421 426 cursor.execute("DELETE FROM %s WHERE %s = %%s" % \ 422 427 (self.join_table, source_col_name), 423 428 [self._pk_val]) 424 transaction.commit_unless_managed( )429 transaction.commit_unless_managed(connection) 425 430 426 431 return ManyRelatedManager 427 432 … … 445 450 superclass = rel_model._default_manager.__class__ 446 451 RelatedManager = create_many_related_manager(superclass) 447 452 448 qn = connection.ops.quote_name453 qn = rel_model._default_manager.db.connection.ops.quote_name 449 454 manager = RelatedManager( 450 455 model=rel_model, 451 456 core_filters={'%s__pk' % self.related.field.name: instance._get_pk_val()}, … … 486 491 superclass = rel_model._default_manager.__class__ 487 492 RelatedManager = create_many_related_manager(superclass) 488 493 489 qn = connection.ops.quote_name494 qn = rel_model._default_manager.db.connection.ops.quote_name 490 495 manager = RelatedManager( 491 496 model=rel_model, 492 497 core_filters={'%s__pk' % self.field.related_query_name(): instance._get_pk_val()}, … … 673 678 defaults.update(kwargs) 674 679 return super(ForeignKey, self).formfield(**defaults) 675 680 676 def db_type(self ):681 def db_type(self, connection): 677 682 # The database column type of a ForeignKey is the column type 678 683 # of the field to which it points. An exception is if the ForeignKey 679 684 # points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField, 680 685 # in which case the column type is simply that of an IntegerField. 681 686 rel_field = self.rel.get_related_field() 682 687 if isinstance(rel_field, (AutoField, PositiveIntegerField, PositiveSmallIntegerField)): 683 return IntegerField().db_type( )684 return rel_field.db_type( )688 return IntegerField().db_type(connection) 689 return rel_field.db_type(connection) 685 690 686 691 class OneToOneField(ForeignKey): 687 692 """ … … 828 833 defaults['initial'] = [i._get_pk_val() for i in defaults['initial']] 829 834 return super(ManyToManyField, self).formfield(**defaults) 830 835 831 def db_type(self ):836 def db_type(self, connection): 832 837 # A ManyToManyField is not represented by a single column, 833 838 # so return None. 834 839 return None -
django/db/models/base.py
12 12 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField 13 13 from django.db.models.query import delete_objects, Q 14 14 from django.db.models.options import Options, AdminOptions 15 from django.db import connection,transaction15 from django.db import transaction 16 16 from django.db.models import signals 17 17 from django.db.models.loading import register_models, get_model 18 18 from django.dispatch import dispatcher … … 329 329 result = manager._insert(values, return_id=update_pk) 330 330 else: 331 331 # Create a new record with defaults for everything. 332 result = manager._insert([(meta.pk, connection.ops.pk_default_value())], return_id=update_pk, raw_values=True)332 result = manager._insert([(meta.pk, manager.db.connection.ops.pk_default_value())], return_id=update_pk, raw_values=True) 333 333 334 334 if update_pk: 335 335 setattr(self, meta.pk.attname, result) … … 419 419 def _get_next_or_previous_in_order(self, is_next): 420 420 cachename = "__%s_order_cache" % is_next 421 421 if not hasattr(self, cachename): 422 qn = connection.ops.quote_name422 qn = self._default_manager.db.connection.ops.quote_name 423 423 op = is_next and '>' or '<' 424 424 order = not is_next and '-_order' or '_order' 425 425 order_field = self._meta.order_with_respect_to -
django/db/models/manager.py
1 1 import copy 2 2 3 3 from django.db.models.query import QuerySet, EmptyQuerySet, insert_query 4 from django.db import ConnectionInfoDescriptor 4 5 from django.dispatch import dispatcher 5 from django.db.models import signals 6 from django.db.models import signals, get_apps, get_models 6 7 from django.db.models.fields import FieldDoesNotExist 7 8 8 9 def ensure_default_manager(sender): … … 22 23 # Tracks each time a Manager instance is created. Used to retain order. 23 24 creation_counter = 0 24 25 26 db = ConnectionInfoDescriptor() 27 25 28 def __init__(self): 26 29 super(Manager, self).__init__() 27 30 # Increase the creation counter, and save our local copy. -
django/db/models/__init__.py
1 1 from django.conf import settings 2 2 from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured 3 3 from django.core import validators 4 from django.db import connection5 4 from django.db.models.loading import get_apps, get_app, get_models, get_model, register_models 6 5 from django.db.models.query import Q 7 6 from django.db.models.manager import Manager -
django/db/models/query.py
1 1 import warnings 2 2 3 3 from django.conf import settings 4 from django.db import connection,transaction, IntegrityError4 from django.db import transaction, IntegrityError 5 5 from django.db.models.fields import DateField, FieldDoesNotExist 6 6 from django.db.models.query_utils import Q 7 7 from django.db.models import signals, sql … … 20 20 "Represents a lazy database lookup for a set of objects" 21 21 def __init__(self, model=None, query=None): 22 22 self.model = model 23 self.query = query or sql.Query(self.model, connection)23 self.query = query or sql.Query(self.model, self.model._default_manager.db.connection) 24 24 self._result_cache = None 25 25 self._iter = None 26 26 … … 689 689 instance=instance) 690 690 691 691 pk_list = [pk for pk,instance in seen_objs[cls]] 692 del_query = sql.DeleteQuery(cls, c onnection)692 del_query = sql.DeleteQuery(cls, cls._default_manager.db.connection) 693 693 del_query.delete_batch_related(pk_list) 694 694 695 update_query = sql.UpdateQuery(cls, c onnection)695 update_query = sql.UpdateQuery(cls, cls._default_manager.db.connection) 696 696 for field in cls._meta.fields: 697 697 if field.rel and field.null and field.rel.to in seen_objs: 698 698 update_query.clear_related(field, pk_list) … … 701 701 for cls in ordered_classes: 702 702 seen_objs[cls].reverse() 703 703 pk_list = [pk for pk,instance in seen_objs[cls]] 704 del_query = sql.DeleteQuery(cls, c onnection)704 del_query = sql.DeleteQuery(cls, cls._default_manager.db.connection) 705 705 del_query.delete_batch(pk_list) 706 706 707 707 # Last cleanup; set NULLs where there once was a reference to the … … 724 724 the InsertQuery class and is how Model.save() is implemented. It is not 725 725 part of the public API. 726 726 """ 727 query = sql.InsertQuery(model, connection)727 query = sql.InsertQuery(model, model._default_manager.db.connection) 728 728 query.insert_values(values, raw_values) 729 729 return query.execute_sql(return_id) 730 730 -
django/db/__init__.py
1 1 import os 2 from django.conf import settings 2 from django.conf import settings, UserSettingsHolder 3 3 from django.core import signals 4 4 from django.core.exceptions import ImproperlyConfigured 5 5 from django.dispatch import dispatcher 6 6 from django.utils.functional import curry 7 7 8 try: 9 # Only exists in Python 2.4+ 10 from threading import local 11 except ImportError: 12 # Import copy of _thread_local.py from Python 2.4 13 from django.utils._threading_local import local 14 8 15 __all__ = ('backend', 'connection', 'DatabaseError', 'IntegrityError') 9 16 17 18 # singleton to represent the default connection in connections 19 class dummy(object): 20 def __repr__(self): 21 return self.__str__() 22 def __str__(self): 23 return '<default>' 24 _default = dummy() 25 del dummy 26 27 28 # storage for local default connection 29 _local = local() 30 10 31 if not settings.DATABASE_ENGINE: 11 32 settings.DATABASE_ENGINE = 'dummy' 12 33 13 try: 14 # Most of the time, the database backend will be one of the official 15 # backends that ships with Django, so look there first. 16 _import_path = 'django.db.backends.' 17 backend = __import__('%s%s.base' % (_import_path, settings.DATABASE_ENGINE), {}, {}, ['']) 18 creation = __import__('%s%s.creation' % (_import_path, settings.DATABASE_ENGINE), {}, {}, ['']) 19 except ImportError, e: 20 # If the import failed, we might be looking for a database backend 21 # distributed external to Django. So we'll try that next. 22 try: 23 _import_path = '' 24 backend = __import__('%s.base' % settings.DATABASE_ENGINE, {}, {}, ['']) 25 creation = __import__('%s.creation' % settings.DATABASE_ENGINE, {}, {}, ['']) 26 except ImportError, e_user: 27 # The database backend wasn't found. Display a helpful error message 28 # listing all possible (built-in) database backends. 29 backend_dir = os.path.join(__path__[0], 'backends') 30 available_backends = [f for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.py') and not f.endswith('.pyc')] 31 available_backends.sort() 32 if settings.DATABASE_ENGINE not in available_backends: 33 raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \ 34 (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends))) 34 35 def connect(settings, name, **kw): 36 """Connect to the database specified in settings. Returns a 37 ConnectionInfo on success, raises ImproperlyConfigured if the 38 settings don't specify a valid database connection. 39 """ 40 return ConnectionInfo(settings, name, **kw) 41 42 43 class ConnectionInfo(object): 44 """Encapsulates all information about a connection and the backend 45 to which it belongs. Provides methods for loading backend 46 creation, introspection, and shell modules, closing the 47 connection, and resetting the connection's query log. 48 """ 49 def __init__(self, settings=None, name=_default, **kw): 50 super(ConnectionInfo, self).__init__(**kw) 51 if settings is None: 52 from django.conf import settings 53 if not settings.DATABASE_OPTIONS: 54 settings.DATABASE_OPTIONS = {} 55 self.settings = settings 56 self.name = name 57 self.backend = self.load_backend() 58 self.connection = self.backend.DatabaseWrapper(settings, name) 59 self.DatabaseError = self.backend.DatabaseError 60 61 # Register an event that closes the database connection 62 # when a Django request is finished. 63 dispatcher.connect(self.close, signal=signals.request_finished) 64 65 # Register an event that resets connection.queries 66 # when a Django request is started. 67 dispatcher.connect(self.reset_queries, signal=signals.request_started) 68 69 def __repr__(self): 70 return "Connection: %s, %r (ENGINE=%s NAME=%s)" \ 71 % (self.name, self.connection, 72 self.settings.DATABASE_ENGINE, 73 self.settings.DATABASE_NAME) 74 75 def name(self): 76 return self.name 77 78 def close(self): 79 """Close connection""" 80 self.connection.close() 81 82 def _import_database_module(self, import_path='', module_name=''): 83 """Lazily import a database module when requested.""" 84 return __import__('%s%s.%s' % (import_path, self.settings.DATABASE_ENGINE, module_name), {}, {}, ['']) 85 86 # We don't want to import the introspect module unless someone asks for it, so 87 # lazily load it on demmand. 88 def get_introspection_module(self): 89 return self._import_database_module(self._import_path, 'introspection') 90 91 def get_creation_module(self): 92 return self._import_database_module(self._import_path, 'creation') 93 94 def load_backend(self): 95 try: 96 # Most of the time, the database backend will be one of the official 97 # backends that ships with Django, so look there first. 98 self._import_path = 'django.db.backends.' 99 backend = __import__('%s%s.base' % (self._import_path, 100 self.settings.DATABASE_ENGINE), {}, {}, ['']) 101 except ImportError, e: 102 # If the import failed, we might be looking for a database backend 103 # distributed external to Django. So we'll try that next. 104 try: 105 _import_path = '' 106 backend = __import__('%s.base' % self.settings.DATABASE_ENGINE, {}, {}, ['']) 107 except ImportError, e_user: 108 # The database backend wasn't found. Display a helpful error message 109 # listing all possible (built-in) database backends. 110 backend_dir = os.path.join(__path__[0], 'backends') 111 available_backends = [f for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.py') and not f.endswith('.pyc')] 112 available_backends.sort() 113 if self.settings.DATABASE_ENGINE not in available_backends: 114 raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \ 115 (self.settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends))) 116 else: 117 raise # If there's some other error, this must be an error in Django itself. 118 return backend 119 120 # We want runshell() to work the same way, but we have to treat it a 121 # little differently (since it just runs instead of returning a module like 122 # the above) and wrap the lazily-loaded runshell() method. 123 def runshell(self): 124 return lambda: _import_database_module(_import_path, "client").runshell() 125 126 def reset_queries(self): 127 """Reset log of queries executed by connection""" 128 self.connection.queries = [] 129 130 class LazyConnectionManager(object): 131 """Manages named connections lazily, instantiating them as 132 they are requested. 133 """ 134 def __init__(self): 135 self.local = local() 136 self.local.connections = {} 137 138 # Reset connections on request finish, to make sure each request can 139 # load the correct connections for its settings 140 dispatcher.connect(self.reset, signal=signals.request_finished) 141 142 def __iter__(self): 143 # Iterates only over *active* connections, not all possible 144 # connections 145 return iter(self.local.connections.keys()) 146 147 def __getattr__(self, attr): 148 return getattr(self.local.connections, attr) 149 150 def __getitem__(self, k): 151 try: 152 return self.local.connections[k] 153 except (AttributeError, KeyError): 154 return self.connect(k) 155 156 def __setitem__(self, k, v): 157 try: 158 self.local.connections[k] = v 159 except AttributeError: 160 # First access in thread 161 self.local.connections = {k: v} 162 163 def connect(self, name): 164 """Return the connection with this name in 165 settings.OTHER_DATABASES. Creates the connection if it doesn't yet 166 exist. Reconnects if it does. If the name requested is the default 167 connection (a singleton defined in django.db), then the default 168 connection is returned. 169 """ 170 try: 171 cnx = self.local.connections 172 except AttributeError: 173 cnx = self.local.connections = {} 174 if name in cnx: 175 cnx[name].close() 176 if name is _default: 177 cnx[name] = connect(settings, _default) 178 return cnx[name] 179 try: 180 info = settings.OTHER_DATABASES[name] 181 except KeyError: 182 raise ImproperlyConfigured, \ 183 "No database connection '%s' has been configured" % name 184 except AttributeError: 185 raise ImproperlyConfigured, \ 186 "No OTHER_DATABASES in settings." 187 188 # In settings it's a dict, but connect() needs an object: 189 # pass global settings so that the default connection settings 190 # can be defaults for the named connections. 191 database = UserSettingsHolder(settings) 192 for k, v in info.items(): 193 setattr(database, k, v) 194 cnx[name] = connect(database, name) 195 return cnx[name] 196 197 def items(self): 198 # Iterates over *all possible* connections 199 items = [] 200 for key in self.keys(): 201 items.append((key, self[key])) 202 return items 203 204 def keys(self): 205 # Iterates over *all possible* connections 206 keys = [_default] 207 try: 208 keys.extend(settings.OTHER_DATABASES.keys()) 209 except AttributeError: 210 pass 211 return keys 212 213 def reset(self): 214 if not hasattr(self.local, 'connections'): 215 return 216 if settings.DATABASE_NAME == ':memory:': 217 ## try: 218 ## cnx = self.local.connections 219 ## except AttributeError: 220 ## cnx = self.local.connections = {} 221 self.local.connections = {_default: self.local.connections[_default]} 222 ## for c in cnx: 223 ## if c != _default: 224 ## del self.local.connections[c] 35 225 else: 36 raise # If there's some other error, this must be an error in Django itself.226 self.local.connections = {} 37 227 38 def _import_database_module(import_path='', module_name=''): 39 """Lazily import a database module when requested.""" 40 return __import__('%s%s.%s' % (import_path, settings.DATABASE_ENGINE, module_name), {}, {}, ['']) 228 def model_connection_name(klass): 229 """Get the connection name that a model is configured to use, with the 230 current settings. 231 """ 232 app = klass._meta.app_label 233 model = klass.__name__ 234 app_model = "%s.%s" % (app, model) 41 235 42 # We don't want to import the introspect module unless someone asks for it, so 43 # lazily load it on demmand. 44 get_introspection_module = curry(_import_database_module, _import_path, 'introspection') 236 # Quick exit if no OTHER_DATABASES defined 237 if (not hasattr(settings, 'OTHER_DATABASES') 238 or not settings.OTHER_DATABASES): 239 return _default 240 # Look in MODELS for the best match: app_label.Model. If that isn't 241 # found, take just app_label. If nothing is found, use the default 242 maybe = None 243 for name, db_def in settings.OTHER_DATABASES.items(): 244 if not 'MODELS' in db_def: 245 continue 246 mods = db_def['MODELS'] 247 # Can't get a better match than this 248 if app_model in mods: 249 return name 250 elif app in mods: 251 if maybe is not None: 252 raise ImproperlyConfigured, \ 253 "App %s appears in more than one OTHER_DATABASES " \ 254 "setting (%s and %s)" % (maybe, name) 255 maybe = name 256 if maybe: 257 return maybe 258 # No named connection for this model; use the default 259 return _default 45 260 46 def get_creation_module(): 47 return creation 261 def connection_name_app_model(app_label, model_name): 262 """Get the connection name that a model is configured to use, with the 263 current settings. 264 """ 265 app_model = "%s.%s" % (app_label, model_name) 48 266 49 # We want runshell() to work the same way, but we have to treat it a 50 # little differently (since it just runs instead of returning a module like 51 # the above) and wrap the lazily-loaded runshell() method. 52 runshell = lambda: _import_database_module(_import_path, "client").runshell() 267 # Quick exit if no OTHER_DATABASES defined 268 if (not hasattr(settings, 'OTHER_DATABASES') 269 or not settings.OTHER_DATABASES): 270 return _default 271 # Look in MODELS for the best match: app_label.Model. If that isn't 272 # found, take just app_label. If nothing is found, use the default 273 maybe = None 274 for name, db_def in settings.OTHER_DATABASES.items(): 275 if not 'MODELS' in db_def: 276 continue 277 mods = db_def['MODELS'] 278 # Can't get a better match than this 279 if app_model in mods: 280 return name 281 elif app_label in mods: 282 if maybe is not None: 283 raise ImproperlyConfigured, \ 284 "App %s appears in more than one OTHER_DATABASES " \ 285 "setting (%s and %s)" % (maybe, name) 286 maybe = name 287 if maybe: 288 return maybe 289 # No named connection for this model; use the default 290 return _default 53 291 54 # Convenient aliases for backend bits. 55 connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) 56 DatabaseError = backend.DatabaseError 57 IntegrityError = backend.IntegrityError 292 class ConnectionInfoDescriptor(object): 293 """Descriptor used to access database connection information from a 294 manager or other connection holder. Keeps a thread-local cache of 295 connections per instance, and always returns the same connection for an 296 instance in particular thread during a particular request. 58 297 59 # Register an event that closes the database connection 60 # when a Django request is finished.61 dispatcher.connect(connection.close, signal=signals.request_finished) 298 Any object that includes a ``model`` attribute that holds a model class 299 can use this descriptor to manage connections. 300 """ 62 301 63 # Register an event that resets connection.queries 64 # when a Django request is started. 302 def __init__(self): 303 self.local = local() 304 self.local.cnx = {} 305 dispatcher.connect(self.reset, signal=signals.request_finished) 306 307 def __get__(self, instance, type=None): 308 if instance is None: 309 raise AttributeError, \ 310 "ConnectionInfo is accessible only through an instance" 311 try: 312 instance_connection = self.local.cnx.get(instance, None) 313 except AttributeError: 314 # First access in this thread 315 self.local.cnx = {} 316 instance_connection = None 317 if instance_connection is None: 318 instance_connection = self.get_connection(instance) 319 self.local.cnx[instance] = instance_connection 320 return instance_connection 321 322 def __set__(self, instance, value): 323 try: 324 self.local.cnx[instance] = value 325 except AttributeError: 326 # First access in thread 327 self.local.cnx = {instance: value} 328 329 def __delete__(self, instance): 330 try: 331 del self.local.cnx[instance] 332 except (AttributeError, KeyError): 333 # Not stored, no need to reset 334 pass 335 336 def get_connection(self, instance): 337 return connections[model_connection_name(instance.model)] 338 339 def reset(self): 340 if not hasattr(self.local, 'cnx'): 341 return 342 self.local.cnx = {} 343 344 class LocalizingProxy: 345 """A lazy-initializing proxy. The proxied object is not 346 initialized until the first attempt to access it. This is used to 347 attach module-level properties to local storage. 348 """ 349 def __init__(self, name, storage, func, *arg, **kw): 350 self.__name = name 351 self.__storage = storage 352 self.__func = func 353 self.__arg = arg 354 self.__kw = kw 355 356 # We need to clear out this thread's storage at the end of each 357 # request, in case new settings are loaded with the next 358 def reset(stor=storage, name=name): 359 if hasattr(stor, name): 360 delattr(stor, name) 361 dispatcher.connect(reset, signal=signals.request_finished) 362 363 def __getattr__(self, attr): 364 # Private (__*) attributes are munged 365 if attr.startswith('_LocalizingProxy'): 366 return self.__dict__[attr] 367 try: 368 return getattr(getattr(self.__storage, self.__name), attr) 369 except AttributeError: 370 setattr(self.__storage, self.__name, self.__func(*self.__arg, 371 **self.__kw)) 372 return getattr(getattr(self.__storage, self.__name), attr) 373 374 def __setattr__(self, attr, val): 375 # Private (__*) attributes are munged 376 if attr.startswith('_LocalizingProxy'): 377 self.__dict__[attr] = val 378 return 379 try: 380 stor = getattr(self.__storage, self.__name) 381 except AttributeError: 382 stor = self.__func(*self.__arg) 383 setattr(self.__storage, self.__name, stor) 384 setattr(stor, attr, val) 385 386 387 # Create a manager for named connections 388 connections = LazyConnectionManager() 389 390 # Backwards compatibility: establish the default connection and set the 391 # default connection properties at module level, using the lazy proxy so that 392 # each thread may have a different default connection, if so configured 393 connection_info = LocalizingProxy('connection_info', _local, 394 lambda: connections[_default]) 395 connection = LocalizingProxy('connection', _local, 396 lambda: connections[_default].connection) 397 backend = LocalizingProxy('backend', _local, 398 lambda: connections[_default].backend) 399 DatabaseError = LocalizingProxy('DatabaseError', _local, 400 lambda: connections[_default].DatabaseError) 401 IntegrityError = LocalizingProxy('IntegrityError', _local, 402 lambda: connections[_default].IntegrityError) 403 get_introspection_module = LocalizingProxy( 404 'get_introspection_module', _local, 405 lambda: connections[_default].get_introspection_module) 406 get_creation_module = LocalizingProxy( 407 'get_creation_module', _local, 408 lambda: connections[_default].get_creation_module) 409 runshell = LocalizingProxy('runshell', _local, 410 lambda: connections[_default].runshell) 411 412 65 413 def reset_queries(): 66 connection.queries = [] 67 dispatcher.connect(reset_queries, signal=signals.request_started) 414 connections[_default].reset_queries() 415 for c in connections: 416 try: 417 c.reset_queries() 418 except: 419 pass 68 420 69 # Register an event that rolls back the connection421 # Register an event that rolls back all connections 70 422 # when a Django request has an exception. 71 423 def _rollback_on_exception(): 72 424 from django.db import transaction 73 425 transaction.rollback_unless_managed() 74 dispatcher.connect(_rollback_on_exception, signal=signals.got_request_exception) 426 dispatcher.connect(_rollback_on_exception, 427 signal=signals.got_request_exception) 428 -
django/db/backends/__init__.py
5 5 # Import copy of _thread_local.py from Python 2.4 6 6 from django.utils._threading_local import local 7 7 8 class BaseDatabaseWrapper( local):8 class BaseDatabaseWrapper(object): 9 9 """ 10 10 Represents a database connection. 11 11 """ 12 12 ops = None 13 def __init__(self, **kwargs): 13 def __init__(self, settings, connection_name): 14 self.settings = settings 15 self.connection_name = connection_name 16 self.options = settings.DATABASE_OPTIONS 14 17 self.connection = None 15 18 self.queries = [] 16 self.options = kwargs17 19 18 20 def _commit(self): 19 21 if self.connection is not None: … … 29 31 self.connection = None 30 32 31 33 def cursor(self): 32 from django.conf importsettings34 settings = self.settings 33 35 cursor = self._cursor(settings) 34 36 if settings.DEBUG: 35 37 return self.make_debug_cursor(cursor) -
django/db/backends/sqlite3/base.py
118 118 return self.connection.cursor(factory=SQLiteCursorWrapper) 119 119 120 120 def close(self): 121 from django.conf importsettings121 settings = self.settings 122 122 # If database is in memory, closing the connection destroys the 123 123 # database. To prevent accidental data loss, ignore close requests on 124 124 # an in-memory db. -
django/db/transaction.py
16 16 import thread 17 17 except ImportError: 18 18 import dummy_thread as thread 19 from django.db import connection20 19 from django.conf import settings 21 20 22 21 class TransactionManagementError(Exception): … … 116 115 Puts the transaction manager into a manual state: managed transactions have 117 116 to be committed explicitly by the user. If you switch off transaction 118 117 management and there is a pending commit/rollback, the data will be 119 commited. 118 commited. Note that managed state applies across all connections. 120 119 """ 121 120 thread_ident = thread.get_ident() 122 121 top = state.get(thread_ident, None) 123 122 if top: 124 123 top[-1] = flag 125 124 if not flag and is_dirty(): 126 connection._commit() 125 for cx in all_connections(): 126 cx._commit() 127 127 set_clean() 128 128 else: 129 129 raise TransactionManagementError("This code isn't under transaction management") 130 130 131 def commit_unless_managed( ):131 def commit_unless_managed(conns=None): 132 132 """ 133 133 Commits changes if the system is not in managed transaction mode. 134 134 """ 135 135 if not is_managed(): 136 connection._commit() 136 if conns is None: 137 conns = all_connections() 138 else: 139 conns = ensure_connections(conns) 140 for cx in conns: 141 cx._commit() 137 142 else: 138 143 set_dirty() 139 144 140 def rollback_unless_managed( ):145 def rollback_unless_managed(conns=None): 141 146 """ 142 147 Rolls back changes if the system is not in managed transaction mode. 143 148 """ 144 149 if not is_managed(): 145 connection._rollback() 150 if conns is None: 151 conns = all_connections() 152 else: 153 conns = ensure_connections(conns) 154 for cx in conns: 155 cx._rollback() 146 156 else: 147 157 set_dirty() 148 158 149 def commit( ):159 def commit(conns=None): 150 160 """ 151 161 Does the commit itself and resets the dirty flag. 152 162 """ 153 connection._commit() 163 if conns is None: 164 conns = all_connections() 165 else: 166 conns = ensure_connections(conns) 167 for cx in conns: 168 cx._commit() 154 169 set_clean() 155 170 156 def rollback( ):171 def rollback(conns=None): 157 172 """ 158 173 This function does the rollback itself and resets the dirty flag. 159 174 """ 160 connection._rollback() 175 if conns is None: 176 conns = all_connections() 177 else: 178 conns = ensure_connections(conns) 179 for cx in conns: 180 cx._rollback() 161 181 set_clean() 162 182 163 183 ############## … … 179 199 leave_transaction_management() 180 200 return _autocommit 181 201 182 def commit_on_success(func ):202 def commit_on_success(func, conns = None): 183 203 """ 184 204 This decorator activates commit on response. This way, if the view function 185 205 runs successfully, a commit is made; if the viewfunc produces an exception, … … 198 218 raise 199 219 else: 200 220 if is_dirty(): 201 commit( )221 commit(conns) 202 222 return res 203 223 finally: 204 224 leave_transaction_management() … … 220 240 leave_transaction_management() 221 241 222 242 return _commit_manually 243 244 ########### 245 # HELPERS # 246 ########### 247 248 def all_connections(): 249 from django.db import connection, connections 250 return [connection] + [ c.connection 251 for c in connections.values() ] 252 253 def ensure_connections(val): 254 from django.db import connections 255 conns = [] 256 if isinstance(val, basestring): 257 val = [val] 258 try: 259 iter(val) 260 except: 261 val = [val] 262 for cx in val: 263 if hasattr(cx, 'cursor'): 264 conns.append(cx) 265 elif hasattr(cx, 'connection'): 266 conns.append(cx.connection) 267 elif isinstance(cx, basestring): 268 conns.append(connections[cx].connection) 269 return conns 270 -
django/core/context_processors.py
33 33 context_extras = {} 34 34 if settings.DEBUG and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS: 35 35 context_extras['debug'] = True 36 from django.db import connection 37 context_extras['sql_queries'] = connection.queries 36 from django.db import connections 37 queries = [] 38 for conn in connections: 39 queries.extend(connections[conn].connection.queries) 40 context_extras['sql_queries'] = queries 38 41 return context_extras 39 42 40 43 def i18n(request): -
django/core/cache/backends/db.py
1 1 "Database cache backend." 2 2 3 3 from django.core.cache.backends.base import BaseCache 4 from django.db import connection , transaction, DatabaseError4 from django.db import connections, _default, transaction, DatabaseError 5 5 import base64, time 6 6 from datetime import datetime 7 7 try: … … 25 25 self._cull_frequency = 3 26 26 27 27 def get(self, key, default=None): 28 cursor = connection .cursor()28 cursor = connections[_default].connection.cursor() 29 29 cursor.execute("SELECT cache_key, value, expires FROM %s WHERE cache_key = %%s" % self._table, [key]) 30 30 row = cursor.fetchone() 31 31 if row is None: … … 46 46 def _base_set(self, mode, key, value, timeout=None): 47 47 if timeout is None: 48 48 timeout = self.default_timeout 49 cursor = connection .cursor()49 cursor = connections[_default].connection.cursor() 50 50 cursor.execute("SELECT COUNT(*) FROM %s" % self._table) 51 51 num = cursor.fetchone()[0] 52 52 now = datetime.now().replace(microsecond=0) … … 67 67 transaction.commit_unless_managed() 68 68 69 69 def delete(self, key): 70 cursor = connection .cursor()70 cursor = connections[_default].connection.cursor() 71 71 cursor.execute("DELETE FROM %s WHERE cache_key = %%s" % self._table, [key]) 72 72 transaction.commit_unless_managed() 73 73 74 74 def has_key(self, key): 75 cursor = connection .cursor()75 cursor = connections[_default].connection.cursor() 76 76 cursor.execute("SELECT cache_key FROM %s WHERE cache_key = %%s" % self._table, [key]) 77 77 return cursor.fetchone() is not None 78 78 -
django/core/management/commands/sqlall.py
7 7 8 8 def handle_app(self, app, **options): 9 9 from django.core.management.sql import sql_all 10 return '\n'.join(sql_all(app, self.style))10 return sql_all(app, self.style) -
django/core/management/commands/sqlcustom.py
7 7 8 8 def handle_app(self, app, **options): 9 9 from django.core.management.sql import sql_custom 10 return '\n'.join(sql_custom(app)) 10 return sql_custom(app) 11 -
django/core/management/commands/createcachetable.py
8 8 requires_model_validation = False 9 9 10 10 def handle_label(self, tablename, **options): 11 from django.db import connection , transaction, models11 from django.db import connections, transaction, models, _default 12 12 fields = ( 13 13 # "key" is a reserved word in MySQL, so use "cache_key" instead. 14 14 models.CharField(name='cache_key', max_length=255, unique=True, primary_key=True), … … 17 17 ) 18 18 table_output = [] 19 19 index_output = [] 20 qn = connection .ops.quote_name20 qn = connections[_default].connection.ops.quote_name 21 21 for f in fields: 22 field_output = [qn(f.name), f.db_type( )]22 field_output = [qn(f.name), f.db_type(_default)] 23 23 field_output.append("%sNULL" % (not f.null and "NOT " or "")) 24 24 if f.unique: 25 25 field_output.append("UNIQUE") … … 35 35 for i, line in enumerate(table_output): 36 36 full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) 37 37 full_statement.append(');') 38 curs = connection .cursor()38 curs = connection[_default].connection.cursor() 39 39 curs.execute("\n".join(full_statement)) 40 40 for statement in index_output: 41 41 curs.execute(statement) -
django/core/management/commands/sql.py
7 7 8 8 def handle_app(self, app, **options): 9 9 from django.core.management.sql import sql_create 10 return '\n'.join(sql_create(app, self.style))10 return sql_create(app, self.style) -
django/core/management/commands/sqlflush.py
1 from django.core.management.base import NoArgsCommand1 from django.core.management.base import ConnectionCommand 2 2 3 class Command( NoArgsCommand):3 class Command(ConnectionCommand): 4 4 help = "Returns a list of the SQL statements required to return all tables in the database to the state they were in just after they were installed." 5 5 6 6 output_transaction = True 7 7 8 def handle_ noargs(self, **options):8 def handle_connection(self, connection, **options): 9 9 from django.core.management.sql import sql_flush 10 return '\n'.join(sql_flush(self.style, only_django=True))10 return sql_flush(connection, self.style, only_django=True) -
django/core/management/commands/sqlreset.py
7 7 8 8 def handle_app(self, app, **options): 9 9 from django.core.management.sql import sql_reset 10 return '\n'.join(sql_reset(app, self.style))10 return sql_reset(app, self.style) -
django/core/management/commands/sqlclear.py
7 7 8 8 def handle_app(self, app, **options): 9 9 from django.core.management.sql import sql_delete 10 return '\n'.join(sql_delete(app, self.style))10 return sql_delete(app, self.style) -
django/core/management/commands/loaddata.py
21 21 def handle(self, *fixture_labels, **options): 22 22 from django.db.models import get_apps 23 23 from django.core import serializers 24 from django.db import connection, transaction 24 from django.db import connections, model_connection_name, transaction 25 # MULTIDB: TO REMOVE 26 from django.db import connection 25 27 from django.conf import settings 26 28 27 29 self.style = no_style() … … 39 41 # Get a cursor (even though we don't need one yet). This has 40 42 # the side effect of initializing the test database (if 41 43 # it isn't already initialized). 42 cursor = connection.cursor()44 ## cursor = connection.cursor() 43 45 44 46 # Start transaction management. All fixtures are installed in a 45 47 # single transaction to ensure that all references are resolved. … … 121 123 print "No %s fixture '%s' in %s." % \ 122 124 (format, fixture_name, humanize(fixture_dir)) 123 125 126 # MULTIDB TODO: use sql_sequence_reset 124 127 if object_count > 0: 125 128 sequence_sql = connection.ops.sequence_reset_sql(self.style, models) 126 129 if sequence_sql: -
django/core/management/commands/inspectdb.py
1 from django.core.management.base import NoArgsCommand, CommandError1 from django.core.management.base import ConnectionCommand, CommandError 2 2 3 class Command( NoArgsCommand):3 class Command(ConnectionCommand): 4 4 help = "Introspects the database tables in the given database and outputs a Django model module." 5 5 6 6 requires_model_validation = False 7 7 8 def handle_ noargs(self, **options):8 def handle_connection(self, connection, **options): 9 9 try: 10 for line in self.handle_inspection( ):10 for line in self.handle_inspection(connection): 11 11 print line 12 12 except NotImplementedError: 13 13 raise CommandError("Database inspection isn't supported for the currently selected database backend.") 14 14 15 def handle_inspection(self ):16 from django.db import connection , get_introspection_module15 def handle_inspection(self, conn): 16 from django.db import connections, get_introspection_module 17 17 import keyword 18 18 19 introspection_module = get_introspection_module() 19 connection = connections[conn].connection 20 introspection_module = connections[conn].get_introspection_module() 20 21 21 22 table2model = lambda table_name: table_name.title().replace('_', '') 22 23 -
django/core/management/commands/sqlindexes.py
7 7 8 8 def handle_app(self, app, **options): 9 9 from django.core.management.sql import sql_indexes 10 return '\n'.join(sql_indexes(app, self.style))10 return sql_indexes(app, self.style) -
django/core/management/commands/reset.py
10 10 help = "Executes ``sqlreset`` for the given app(s) in the current database." 11 11 args = '[appname ...]' 12 12 13 output_transaction = True14 15 13 def handle_app(self, app, **options): 16 from django.db import connection , transaction14 from django.db import connections, transaction, _default 17 15 from django.conf import settings 18 16 from django.core.management.sql import sql_reset 19 17 … … 21 19 22 20 self.style = no_style() 23 21 24 sql_ list = sql_reset(app, self.style)22 sql_dict = sql_reset(app, self.style) 25 23 26 if options.get('interactive'): 27 confirm = raw_input(""" 24 for connection_name, sql_list in sql_dict.items(): 25 if options.get('interactive'): 26 if connection_name == _default: 27 dbname = settings.DATABASE_NAME 28 else: 29 dbname = settings.OTHER_DATABASES[connection_name]['DATABASE_NAME'] 30 confirm = raw_input(""" 28 31 You have requested a database reset. 29 32 This will IRREVERSIBLY DESTROY any data for 30 33 the "%s" application in the database "%s". 31 34 Are you sure you want to do this? 32 35 33 Type 'yes' to continue, or 'no' to cancel: """ % (app_name, settings.DATABASE_NAME))34 else:35 confirm = 'yes'36 Type 'yes' to continue, or 'no' to cancel: """ % (app_name, dbname)) 37 else: 38 confirm = 'yes' 36 39 37 if confirm == 'yes':38 try:39 cursor =connection.cursor()40 for sql in sql_list:41 cursor.execute(sql)42 except Exception, e:43 transaction.rollback_unless_managed()44 raise CommandError("""Error: %s couldn't be reset. Possible reasons:40 if confirm == 'yes': 41 try: 42 cursor = connections[connection_name].connection.cursor() 43 for sql in sql_list: 44 cursor.execute(sql) 45 except Exception, e: 46 transaction.rollback_unless_managed() 47 raise CommandError("""Error: %s couldn't be reset. Possible reasons: 45 48 * The database isn't running or isn't configured correctly. 46 49 * At least one of the database tables doesn't exist. 47 50 * The SQL was invalid. 48 51 Hint: Look at the output of 'django-admin.py sqlreset %s'. That's the SQL this command wasn't able to run. 49 52 The full error: %s""" % (app_name, app_name, e)) 50 transaction.commit_unless_managed()51 else:52 print "Reset cancelled."53 transaction.commit_unless_managed() 54 else: 55 print "Reset cancelled." -
django/core/management/commands/syncdb.py
19 19 help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created." 20 20 21 21 def handle_noargs(self, **options): 22 from django.db import connection, transaction, models22 from django.db import model_connection_name, transaction, models, connections 23 23 from django.conf import settings 24 24 from django.core.management.sql import table_list, installed_models, sql_model_create, sql_for_pending_references, many_to_many_sql_for_model, custom_sql_for_model, sql_indexes_for_model, emit_post_sync_signal 25 25 … … 37 37 if not exc.args[0].startswith('No module named management'): 38 38 raise 39 39 40 cursor = connection.cursor()41 42 if connection.features.uses_case_insensitive_names:43 table_name_converter = lambda x: x.upper()44 else:45 table_name_converter = lambda x: x46 40 # Get a list of all existing database tables, so we know what needs to 47 41 # be added. 48 tables = [table_name_converter(name) for name in table_list()]49 42 tables = table_list() 43 50 44 # Get a list of already installed *models* so that references work right. 51 45 seen_models = installed_models(tables) 52 46 created_models = set() … … 59 53 for model in model_list: 60 54 # Create the model's database table, if it doesn't already exist. 61 55 if verbosity >= 2: 62 print "Processing %s.%s model" % (app_name, model._meta.object_name) 63 if table_name_converter(model._meta.db_table) in tables: 56 print "Processing %s.%s model (%s))" % (app_name, model._meta.object_name, model_connection_name(model)) 57 connection = model._default_manager.db.connection 58 cursor = connection.cursor() 59 if connection.features.uses_case_insensitive_names: 60 table_name_converter = lambda x: x.upper() 61 else: 62 table_name_converter = lambda x: x 63 ctables = [table_name_converter(name) for name in tables] 64 if table_name_converter(model._meta.db_table) in ctables: 64 65 continue 65 66 sql, references = sql_model_create(model, self.style, seen_models) 66 67 seen_models.add(model) … … 83 84 model_list = models.get_models(app) 84 85 for model in model_list: 85 86 if model in created_models: 87 connection = model._default_manager.db.connection 88 cursor = connection.cursor() 86 89 sql = many_to_many_sql_for_model(model, self.style) 87 90 if sql: 88 91 if verbosity >= 2: … … 102 105 app_name = app.__name__.split('.')[-2] 103 106 for model in models.get_models(app): 104 107 if model in created_models: 108 connection = model._default_manager.db.connection 109 cursor = connection.cursor() 105 110 custom_sql = custom_sql_for_model(model) 106 111 if custom_sql: 107 112 if verbosity >= 1: … … 121 126 app_name = app.__name__.split('.')[-2] 122 127 for model in models.get_models(app): 123 128 if model in created_models: 129 connection = model._default_manager.db.connection 130 cursor = connection.cursor() 124 131 index_sql = sql_indexes_for_model(model, self.style) 125 132 if index_sql: 126 133 if verbosity >= 1: -
django/core/management/commands/flush.py
1 from django.core.management.base import NoArgsCommand, CommandError1 from django.core.management.base import ConnectionCommand, CommandError 2 2 from django.core.management.color import no_style 3 3 from optparse import make_option 4 4 5 class Command( NoArgsCommand):6 option_list = NoArgsCommand.option_list + (5 class Command(ConnectionCommand): 6 option_list = ConnectionCommand.option_list + ( 7 7 make_option('--verbosity', action='store', dest='verbosity', default='1', 8 8 type='choice', choices=['0', '1', '2'], 9 9 help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), … … 12 12 ) 13 13 help = "Executes ``sqlflush`` on the current database." 14 14 15 def handle_ noargs(self, **options):15 def handle_connection(self, connection, **options): 16 16 from django.conf import settings 17 from django.db import connection, transaction, models17 from django.db import transaction, models, connections 18 18 from django.dispatch import dispatcher 19 19 from django.core.management.sql import sql_flush, emit_post_sync_signal 20 20 … … 31 31 except ImportError: 32 32 pass 33 33 34 sql_list = sql_flush( self.style, only_django=True)34 sql_list = sql_flush(connection, self.style, only_django=True) 35 35 36 36 if interactive: 37 37 confirm = raw_input("""You have requested a flush of the database. … … 39 39 and return each table to the state it was in after syncdb. 40 40 Are you sure you want to do this? 41 41 42 Type 'yes' to continue, or 'no' to cancel: """ % settings.DATABASE_NAME)42 Type 'yes' to continue, or 'no' to cancel: """ % connection) 43 43 else: 44 44 confirm = 'yes' 45 45 46 46 if confirm == 'yes': 47 47 try: 48 cursor = connection.cursor()49 48 for sql in sql_list: 49 cursor = connections[connection].connection.cursor() 50 50 cursor.execute(sql) 51 51 except Exception, e: 52 52 transaction.rollback_unless_managed() … … 55 55 * At least one of the expected database tables doesn't exist. 56 56 * The SQL was invalid. 57 57 Hint: Look at the output of 'django-admin.py sqlflush'. That's the SQL this command wasn't able to run. 58 The full error: %s""" % ( settings.DATABASE_NAME, e))58 The full error: %s""" % (connection, e)) 59 59 transaction.commit_unless_managed() 60 60 61 61 # Emit the post sync signal. This allows individual -
django/core/management/base.py
85 85 self.validate() 86 86 output = self.handle(*args, **options) 87 87 if output: 88 if self.output_transaction:89 # This needs to be imported here, because it relies on settings.90 from django.db import connection91 if connection.ops.start_transaction_sql():92 print self.style.SQL_KEYWORD(connection.ops.start_transaction_sql())93 88 print output 94 if self.output_transaction:95 print self.style.SQL_KEYWORD("COMMIT;")96 89 except CommandError, e: 97 90 sys.stderr.write(self.style.ERROR(str('Error: %s\n' % e))) 98 91 sys.exit(1) … … 124 117 args = '<appname appname ...>' 125 118 126 119 def handle(self, *app_labels, **options): 127 from django.db import models 120 from django.db import models, _default, connections 121 from django.core.management.sql import sql_collate 128 122 if not app_labels: 129 123 raise CommandError('Enter at least one appname.') 130 124 try: 131 125 app_list = [models.get_app(app_label) for app_label in app_labels] 132 126 except (ImproperlyConfigured, ImportError), e: 133 127 raise CommandError("%s. Are you sure your INSTALLED_APPS setting is correct?" % e) 134 output = []128 output = {} 135 129 for app in app_list: 136 130 app_output = self.handle_app(app, **options) 137 if app_output: 138 output.append(app_output) 139 return '\n'.join(output) 131 if isinstance(app_output, dict): 132 for connection_name, statements in app_output.items(): 133 f_output = output.setdefault(connection_name, []) 134 if self.output_transaction: 135 if connections[connection_name].connection.ops.start_transaction_sql(): 136 f_output.append(self.style.SQL_KEYWORD(connections[connection_name].connection.ops.start_transaction_sql())) 137 f_output.extend(statements) 138 if self.output_transaction: 139 f_output.append(self.style.SQL_KEYWORD("COMMIT;")) 140 else: 141 f_output = output.setdefault(_default, []) 142 f_output.append(app_output) 140 143 144 return sql_collate(output) 145 ## return '\n'.join(output) 146 141 147 def handle_app(self, app, **options): 142 148 raise NotImplementedError() 143 149 150 class ConnectionCommand(BaseCommand): 151 args = '<connectionname connectionname ...>' 152 153 def handle(self, *connection_labels, **options): 154 from django.conf import settings 155 from django.db import _default, connections 156 from django.core.management.sql import sql_collate 157 if not connection_labels: 158 connection_list = [_default] 159 connection_list.extend(settings.OTHER_DATABASES.keys()) 160 else: 161 # add check connection exists 162 connection_list = [] 163 for name in connection_labels: 164 if name == '_default': 165 connection_list.append(_default) 166 elif name in settings.OTHER_DATABASES: 167 connection_list.append(name) 168 output = {} 169 for connection_name in connection_list: 170 f_output = output.setdefault(connection_name, []) 171 connection_output = self.handle_connection(connection_name, **options) 172 if connection_output: 173 if self.output_transaction: 174 if connections[connection_name].connection.ops.start_transaction_sql(): 175 f_output.append(self.style.SQL_KEYWORD(connections[connection_name].connection.ops.start_transaction_sql())) 176 f_output.extend(connection_output) 177 if self.output_transaction: 178 f_output.append(self.style.SQL_KEYWORD("COMMIT;")) 179 return sql_collate(output) 180 181 def handle_connection(self, connection_name, **options): 182 raise NotImplementedError() 183 144 184 class LabelCommand(BaseCommand): 145 185 args = '<label label ...>' 146 186 label = 'label' -
django/core/management/sql.py
8 8 from sets import Set as set # Python 2.3 fallback 9 9 10 10 def table_list(): 11 "Returns a list of all table names that exist in the database." 12 from django.db import connection, get_introspection_module 13 cursor = connection.cursor() 14 return get_introspection_module().get_table_list(cursor) 11 """Returns a list of all table names that exist in the database.""" 12 from django.db import connections 13 table_list = [] 14 for conn in connections: 15 table_list.extend(table_list_conn(conn)) 16 return table_list 15 17 18 def table_list_conn(conn): 19 from django.db import connections 20 try: 21 cursor = connections[conn].connection.cursor() 22 return connections[conn].get_introspection_module().get_table_list(cursor) 23 except: 24 return [] 25 16 26 def django_table_list(only_existing=False): 17 27 """ 18 28 Returns a list of all table names that have associated Django models and … … 32 42 tables = [t for t in tables if t in existing] 33 43 return tables 34 44 45 def django_table_list_conn(conn, only_existing=False): 46 from django.db import models 47 from django.db import model_connection_name 48 tables = [] 49 for app in models.get_apps(): 50 for model in models.get_models(app): 51 if model_connection_name(model)==conn: 52 tables.append(model._meta.db_table) 53 tables.extend([f.m2m_db_table() for f in model._meta.many_to_many]) 54 if only_existing: 55 existing = table_list_conn(conn) 56 tables = [t for t in tables if t in existing] 57 return tables 58 35 59 def installed_models(table_list): 36 60 "Returns a set of all models that are installed, given a list of existing table names." 37 from django.db import connection,models61 from django.db import models 38 62 all_models = [] 39 63 for app in models.get_apps(): 40 64 for model in models.get_models(app): 41 all_models.append(model) 42 if connection.features.uses_case_insensitive_names: 43 converter = lambda x: x.upper() 44 else: 45 converter = lambda x: x 46 return set([m for m in all_models if converter(m._meta.db_table) in map(converter, table_list)]) 65 connection = model._default_manager.db.connection 66 if connection.features.uses_case_insensitive_names: 67 converter = lambda x: x.upper() 68 else: 69 converter = lambda x: x 70 if converter(model._meta.db_table) in map(converter, table_list): 71 all_models.append(converter(model)) 72 return set(all_models) 47 73 48 74 def sequence_list(): 49 75 "Returns a list of information about all DB sequences for all models in all apps." … … 66 92 67 93 def sql_create(app, style): 68 94 "Returns a list of the CREATE TABLE SQL statements for the given app." 69 from django.db import models 95 from django.db import models, model_connection_name, _default 70 96 from django.conf import settings 71 97 72 98 if settings.DATABASE_ENGINE == 'dummy': … … 81 107 # generate invalid SQL (leaving models out of known_models is harmless, so 82 108 # we can be conservative). 83 109 app_models = models.get_models(app) 84 final_output = []85 110 known_models = set([model for model in installed_models(table_list()) if model not in app_models]) 86 111 pending_references = {} 87 112 113 connection_output = {} 114 88 115 for model in app_models: 116 connection_name = model_connection_name(model) 117 f_output = connection_output.setdefault(connection_name, []) 89 118 output, references = sql_model_create(model, style, known_models) 90 f inal_output.extend(output)119 f_output.extend(output) 91 120 for refto, refs in references.items(): 92 121 pending_references.setdefault(refto, []).extend(refs) 93 122 if refto in known_models: 94 f inal_output.extend(sql_for_pending_references(refto, style, pending_references))95 f inal_output.extend(sql_for_pending_references(model, style, pending_references))123 f_output.extend(sql_for_pending_references(refto, style, pending_references)) 124 f_output.extend(sql_for_pending_references(model, style, pending_references)) 96 125 # Keep track of the fact that we've created the table for this model. 97 126 known_models.add(model) 98 127 99 128 # Create the many-to-many join tables. 100 129 for model in app_models: 101 final_output.extend(many_to_many_sql_for_model(model, style)) 130 connection_name = model_connection_name(model) 131 f_output = connection_output.setdefault(connection_name, []) 132 f_output.extend(many_to_many_sql_for_model(model,style)) 102 133 134 103 135 # Handle references to tables that are from other apps 104 136 # but don't exist physically. 105 137 not_installed_models = set(pending_references.keys()) 106 138 if not_installed_models: 139 f_output = connection_output.setdefault(_default, []) 107 140 alter_sql = [] 108 141 for model in not_installed_models: 109 142 alter_sql.extend(['-- ' + sql for sql in 110 143 sql_for_pending_references(model, style, pending_references)]) 111 144 if alter_sql: 112 f inal_output.append('-- The following references should be added but depend on non-existent tables:')113 f inal_output.extend(alter_sql)145 f_output.append('-- The following references should be added but depend on non-existent tables:') 146 f_output.extend(alter_sql) 114 147 115 return final_output148 return connection_output 116 149 117 150 def sql_delete(app, style): 118 151 "Returns a list of the DROP TABLE SQL statements for the given app." 119 from django.db import connection, models, get_introspection_module152 from django.db import models, model_connection_name 120 153 from django.db.backends.util import truncate_name 121 154 from django.contrib.contenttypes import generic 122 introspection = get_introspection_module()123 155 124 # This should work even if a connection isn't available 125 try: 126 cursor = connection.cursor() 127 except: 128 cursor = None 156 connection_output = {} 129 157 130 # Figure out which tables already exist131 if cursor:132 table_names = introspection.get_table_list(cursor)133 else:134 table_names = []135 if connection.features.uses_case_insensitive_names:136 table_name_converter = lambda x: x.upper()137 else:138 table_name_converter = lambda x: x139 140 output = []141 qn = connection.ops.quote_name142 143 158 # Output DROP TABLE statements for standard application tables. 144 159 to_delete = set() 145 160 146 161 references_to_delete = {} 147 162 app_models = models.get_models(app) 148 163 for model in app_models: 164 connection = model._default_manager.db.connection 165 introspection = model._default_manager.db.get_introspection_module() 166 # This should work even if a connection isn't available 167 try: 168 cursor = connection.cursor() 169 except: 170 cursor = None 171 # Figure out which tables already exist 172 if cursor: 173 table_names = introspection.get_table_list(cursor) 174 else: 175 table_names = [] 176 if connection.features.uses_case_insensitive_names: 177 table_name_converter = lambda x: x.upper() 178 else: 179 table_name_converter = lambda x: x 180 181 qn = connection.ops.quote_name 182 149 183 if cursor and table_name_converter(model._meta.db_table) in table_names: 150 184 # The table exists, so it needs to be dropped 151 185 opts = model._meta … … 156 190 to_delete.add(model) 157 191 158 192 for model in app_models: 193 connection = model._default_manager.db.connection 194 connection_name = model_connection_name(model) 195 introspection = model._default_manager.db.get_introspection_module() 196 197 output = connection_output.setdefault(connection_name, []) 198 199 # This should work even if a connection isn't available 200 try: 201 cursor = connection.cursor() 202 except: 203 cursor = None 204 # Figure out which tables already exist 205 if cursor: 206 table_names = introspection.get_table_list(cursor) 207 else: 208 table_names = [] 209 if connection.features.uses_case_insensitive_names: 210 table_name_converter = str.upper 211 else: 212 table_name_converter = lambda x: x 213 214 qn = connection.ops.quote_name 215 159 216 if cursor and table_name_converter(model._meta.db_table) in table_names: 160 217 # Drop the table now 161 218 output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), … … 180 237 181 238 # Output DROP TABLE statements for many-to-many tables. 182 239 for model in app_models: 240 connection = model._default_manager.db.connection 241 connection_name = model_connection_name(model) 242 introspection = model._default_manager.db.get_introspection_module() 243 244 output = connection_output.setdefault(connection_name, []) 245 246 # This should work even if a connection isn't available 247 try: 248 cursor = connection.cursor() 249 except: 250 cursor = None 251 # Figure out which tables already exist 252 if cursor: 253 table_names = introspection.get_table_list(cursor) 254 else: 255 table_names = [] 256 if connection.features.uses_case_insensitive_names: 257 table_name_converter = str.upper 258 else: 259 table_name_converter = lambda x: x 260 261 qn = connection.ops.quote_name 262 183 263 opts = model._meta 184 264 for f in opts.local_many_to_many: 185 265 if isinstance(f.rel, generic.GenericRel): … … 195 275 196 276 # Close database connection explicitly, in case this output is being piped 197 277 # directly into a database client, to avoid locking issues. 198 if cursor: 199 cursor.close() 200 connection.close() 278 for model in app_models: 279 connection = model._default_manager.db.connection 280 try: 281 cursor = connection.cursor() 282 except: 283 cursor = None 284 if cursor: 285 cursor.close() 286 connection.close() 201 287 202 return output[::-1] # Reverse it, to deal with table dependencies.288 return connection_output 203 289 204 290 def sql_reset(app, style): 205 291 "Returns a list of the DROP TABLE SQL, then the CREATE TABLE SQL, for the given module." 206 return sql_delete(app, style) + sql_all(app, style) 292 connection_output = {} 293 sql_dict = sql_delete(app, style) 294 for connection_name, sql_list in sql_dict.items(): 295 output = connection_output.setdefault(connection_name, []) 296 output.extend(sql_list) 297 sql_dict = sql_all(app, style) 298 for connection_name, sql_list in sql_dict.items(): 299 output = connection_output.setdefault(connection_name, []) 300 output.extend(sql_list) 301 return connection_output 207 302 208 def sql_flush( style, only_django=False):303 def sql_flush(connection, style, only_django=False): 209 304 """ 210 305 Returns a list of the SQL statements used to flush the database. 211 306 212 307 If only_django is True, then only table names that have associated Django 213 308 models and are in INSTALLED_APPS will be included. 214 309 """ 215 from django.db import connection 310 from django.db import connections 216 311 if only_django: 217 tables = django_table_list ()312 tables = django_table_list_conn(connection) 218 313 else: 219 tables = table_list() 220 statements = connection.ops.sql_flush(style, tables, sequence_list()) 221 return statements 314 tables = table_list_conn(connection) 315 return [f for f in connections[connection].connection.ops.sql_flush(style, tables, sequence_list())] 222 316 223 317 def sql_custom(app): 224 318 "Returns a list of the custom table modifying SQL statements for the given app." 225 319 from django.db.models import get_models 226 output = [] 320 from django.db import model_connection_name 321 connection_output = {} 227 322 228 323 app_models = get_models(app) 229 324 app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql')) 230 325 231 326 for model in app_models: 232 output.extend(custom_sql_for_model(model)) 327 connection_name = model_connection_name(model) 328 output = connection_output.setdefault(connection_name, []) 329 output.extend(map(str, custom_sql_for_model(model))) 330 return connection_output 233 331 234 return output235 236 332 def sql_indexes(app, style): 237 333 "Returns a list of the CREATE INDEX SQL statements for all models in the given app." 238 from django.db import models 239 output = [] 240 for model in models.get_models(app): 241 output.extend(sql_indexes_for_model(model, style)) 242 return output 334 from django.db import model_connection_name 335 from django.db.models import get_models 336 connection_output = {} 337 for model in get_models(app): 338 opts = model._meta 339 connection_name = model_connection_name(model) 340 output = connection_output.setdefault(connection_name, []) 341 output.extend(map(str, sql_indexes_for_model(model, style))) 342 return connection_output 243 343 244 344 def sql_all(app, style): 245 345 "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module." 246 return sql_create(app, style) + sql_custom(app) + sql_indexes(app, style) 346 connection_output = {} 347 sql_dict = sql_create(app, style) 348 for connection_name, sql_list in sql_dict.items(): 349 output = connection_output.setdefault(connection_name, []) 350 output.extend(sql_list) 351 sql_dict = sql_custom(app) 352 for connection_name, sql_list in sql_dict.items(): 353 output = connection_output.setdefault(connection_name, []) 354 output.extend(sql_list) 355 sql_dict = sql_indexes(app, style) 356 for connection_name, sql_list in sql_dict.items(): 357 output = connection_output.setdefault(connection_name, []) 358 output.extend(sql_list) 359 return connection_output 247 360 248 361 def sql_model_create(model, style, known_models=set()): 249 362 """ 250 363 Returns the SQL required to create a single model, as a tuple of: 251 364 (list_of_sql, pending_references_dict) 252 365 """ 253 from django.db import connection, models366 from django.db import models, model_connection_name, connections 254 367 255 368 opts = model._meta 256 369 final_output = [] 257 370 table_output = [] 258 371 pending_references = {} 372 connection_name = model_connection_name(model) 373 connection = connections[connection_name].connection 259 374 qn = connection.ops.quote_name 260 375 inline_references = connection.features.inline_fk_references 261 376 for f in opts.local_fields: 262 col_type = f.db_type( )377 col_type = f.db_type(connection_name) 263 378 tablespace = f.db_tablespace or opts.db_tablespace 264 379 if col_type is None: 265 380 # Skip ManyToManyFields, because they're not represented as … … 291 406 table_output.append(' '.join(field_output)) 292 407 if opts.order_with_respect_to: 293 408 table_output.append(style.SQL_FIELD(qn('_order')) + ' ' + \ 294 style.SQL_COLTYPE(models.IntegerField().db_type( )) + ' ' + \409 style.SQL_COLTYPE(models.IntegerField().db_type(connection_name)) + ' ' + \ 295 410 style.SQL_KEYWORD('NULL')) 296 411 for field_constraints in opts.unique_together: 297 412 table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \ … … 320 435 """ 321 436 Returns any ALTER TABLE statements to add constraints after the fact. 322 437 """ 323 from django.db import connection 438 from django.db import connections, model_connection_name 324 439 from django.db.backends.util import truncate_name 325 440 441 connection_name = model_connection_name(model) 442 connection = connections[connection_name].connection 326 443 qn = connection.ops.quote_name 444 ## if hasattr(connection.ops, 'max_constraint_length'): 445 ## mnl = connection.ops.max_constraint_length 446 ## else: 447 ## mnl = connection.ops.max_name_length 327 448 final_output = [] 328 449 if connection.features.supports_constraints: 329 450 opts = model._meta … … 345 466 return final_output 346 467 347 468 def many_to_many_sql_for_model(model, style): 348 from django.db import connection, models469 from django.db import models, connections, model_connection_name 349 470 from django.contrib.contenttypes import generic 350 471 from django.db.backends.util import truncate_name 351 472 352 473 opts = model._meta 353 474 final_output = [] 475 connection_name = model_connection_name(model) 476 connection = connections[connection_name].connection 354 477 qn = connection.ops.quote_name 355 478 inline_references = connection.features.inline_fk_references 356 479 for f in opts.local_many_to_many: … … 364 487 style.SQL_TABLE(qn(f.m2m_db_table())) + ' ('] 365 488 table_output.append(' %s %s %s%s,' % 366 489 (style.SQL_FIELD(qn('id')), 367 style.SQL_COLTYPE(models.AutoField(primary_key=True).db_type( )),490 style.SQL_COLTYPE(models.AutoField(primary_key=True).db_type(connection_name)), 368 491 style.SQL_KEYWORD('NOT NULL PRIMARY KEY'), 369 492 tablespace_sql)) 370 493 if inline_references: 371 494 deferred = [] 372 495 table_output.append(' %s %s %s %s (%s)%s,' % 373 496 (style.SQL_FIELD(qn(f.m2m_column_name())), 374 style.SQL_COLTYPE(models.ForeignKey(model).db_type( )),497 style.SQL_COLTYPE(models.ForeignKey(model).db_type(connection_name)), 375 498 style.SQL_KEYWORD('NOT NULL REFERENCES'), 376 499 style.SQL_TABLE(qn(opts.db_table)), 377 500 style.SQL_FIELD(qn(opts.pk.column)), 378 501 connection.ops.deferrable_sql())) 379 502 table_output.append(' %s %s %s %s (%s)%s,' % 380 503 (style.SQL_FIELD(qn(f.m2m_reverse_name())), 381 style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type( )),504 style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type(connection_name)), 382 505 style.SQL_KEYWORD('NOT NULL REFERENCES'), 383 506 style.SQL_TABLE(qn(f.rel.to._meta.db_table)), 384 507 style.SQL_FIELD(qn(f.rel.to._meta.pk.column)), … … 386 509 else: 387 510 table_output.append(' %s %s %s,' % 388 511 (style.SQL_FIELD(qn(f.m2m_column_name())), 389 style.SQL_COLTYPE(models.ForeignKey(model).db_type( )),512 style.SQL_COLTYPE(models.ForeignKey(model).db_type(connection_name)), 390 513 style.SQL_KEYWORD('NOT NULL'))) 391 514 table_output.append(' %s %s %s,' % 392 515 (style.SQL_FIELD(qn(f.m2m_reverse_name())), 393 style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type( )),516 style.SQL_COLTYPE(models.ForeignKey(f.rel.to).db_type(connection_name)), 394 517 style.SQL_KEYWORD('NOT NULL'))) 395 518 deferred = [ 396 519 (f.m2m_db_table(), f.m2m_column_name(), opts.db_table, … … 456 579 457 580 def sql_indexes_for_model(model, style): 458 581 "Returns the CREATE INDEX SQL statements for a single model" 459 from django.db import connection460 582 output = [] 461 583 584 connection = model._default_manager.db.connection 462 585 qn = connection.ops.quote_name 463 586 for f in model._meta.local_fields: 464 587 if f.db_index and not ((f.primary_key or f.unique) and connection.features.autoindexes_primary_keys): … … 489 612 dispatcher.send(signal=models.signals.post_syncdb, sender=app, 490 613 app=app, created_models=created_models, 491 614 verbosity=verbosity, interactive=interactive) 615 616 def sql_collate(connection_output, reverse=False): 617 from django.db import _default 618 final_output = [] 619 if len(connection_output.keys()) == 1: 620 # all for the default connection 621 for statements in connection_output.values(): 622 final_output.extend(statements) 623 if reverse: 624 final_output.reverse() 625 else: 626 for connection_name, statements in connection_output.items(): 627 if not statements: 628 continue 629 final_output.append(' -- The following statements are for connection: %s' % connection_name) 630 if reverse: 631 statements.reverse() 632 final_output.extend(statements) 633 final_output.append(' -- END statements for %s\n' % 634 connection_name) 635 return '\n'.join(map(str, final_output)) -
django/core/management/validation.py
19 19 Returns number of errors. 20 20 """ 21 21 from django.conf import settings 22 from django.db import models, connection22 from django.db import connections, models, model_connection_name 23 23 from django.db.models.loading import get_app_errors 24 24 from django.db.models.fields.related import RelatedObject 25 25 … … 30 30 31 31 for cls in models.get_models(app): 32 32 opts = cls._meta 33 connection_name = model_connection_name(cls) 34 connection = connections[connection_name].connection 33 35 34 36 # Do field-specific validation. 35 37 for f in opts.local_fields: … … 74 76 if f.rel: 75 77 if f.rel.to not in models.get_models(): 76 78 e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, f.rel.to)) 79 80 #MULTIDB TODO: Fix this to allow relations that span databases by splitting querys up 81 rel_connection = model_connection_name(f.rel.to) 82 if rel_connection != connection_name: 83 e.add(opts, "'%s' is configured to use connection '%s' but has relation with '%s', which is configured to use connection '%s'" % (cls.__name__, connection_name, f.rel.to.__name__, rel_connection)) 84 77 85 # it is a string and we could not find the model it refers to 78 86 # so skip the next section 79 87 if isinstance(f.rel.to, (str, unicode)): -
django/contrib/contenttypes/generic.py
4 4 5 5 from django import oldforms 6 6 from django.core.exceptions import ObjectDoesNotExist 7 from django.db import connection8 7 from django.db.models import signals 9 8 from django.db.models.fields.related import RelatedField, Field, ManyToManyRel 10 9 from django.db.models.loading import get_model … … 154 153 def get_internal_type(self): 155 154 return "ManyToManyField" 156 155 157 def db_type(self ):156 def db_type(self, connection): 158 157 # Since we're simulating a ManyToManyField, in effect, best return the 159 158 # same db_type as well. 160 159 return None … … 184 183 superclass = rel_model._default_manager.__class__ 185 184 RelatedManager = create_generic_related_manager(superclass) 186 185 187 qn = connection.ops.quote_name186 qn = rel_model._default_manager.db.connection.ops.quote_name 188 187 189 188 manager = RelatedManager( 190 189 model = rel_model, -
django/contrib/auth/backends.py
1 from django.db import connection2 1 from django.contrib.auth.models import User 3 2 4 3 try: … … 23 22 def get_group_permissions(self, user_obj): 24 23 "Returns a list of permission strings that this user has through his/her groups." 25 24 if not hasattr(user_obj, '_group_perm_cache'): 25 connection = User._default_manager.db.connection 26 26 cursor = connection.cursor() 27 27 # The SQL below works out to the following, after DB quoting: 28 28 # cursor.execute(""" -
django/conf/global_settings.py
122 122 DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. 123 123 DATABASE_OPTIONS = {} # Set to empty dictionary for default. 124 124 125 # Optional named database connections in addition to the default. 126 OTHER_DATABASES = {} 127 125 128 # Host for sending e-mail. 126 129 EMAIL_HOST = 'localhost' 127 130 … … 352 355 # If None, a name of 'test_' + DATABASE_NAME will be assumed 353 356 TEST_DATABASE_NAME = None 354 357 358 # Tuple of other test databases to create. Names in this tuple 359 # are suffixes that will be appended to TEST_DATABASE_NAME 360 TEST_DATABASES = [] 361 362 # Models to assign to each test database. This must be a list of 363 # dicts, with each dict key being a name from TEST_DATABASES and value 364 # a list of models or app_labels that will use that database. 365 TEST_DATABASE_MODELS = [] 366 367 355 368 # Strings used to set the character set and collation order for the test 356 369 # database. These values are passed literally to the server, so they are 357 370 # backend-dependent. If None, no special settings are sent (system defaults are -
tests/modeltests/multiple_databases/__init__.py
Property changes on: tests\modeltests\multiple_databases ___________________________________________________________________ Name: svn:ignore + *.pyc
1 pass -
tests/modeltests/multiple_databases/models.py
1 """ 2 XXX. Using multiple database connections 3 4 Django normally uses only a single database connection. However, 5 support is available for using any number of different, named 6 connections. Multiple database support is entirely optional and has 7 no impact on your application if you don't use it. 8 9 Named connections are defined in your settings module. Create a 10 `OTHER_DATABASES` variable that is a dict, mapping connection names to their 11 particulars. The particulars are defined in a dict with the same keys 12 as the variable names as are used to define the default connection, with one 13 addition: MODELS. 14 15 The MODELS item in an OTHER_DATABASES entry is a list of the apps and models 16 that will use that connection. 17 18 Access to named connections is through `django.db.connections`, which 19 behaves like a dict: you access connections by name. Connections are 20 established lazily, when accessed. `django.db.connections[database]` 21 holds a `ConnectionInfo` instance, with the attributes: 22 `DatabaseError`, `backend`, `get_introspection_module`, 23 `get_creation_module`, and `runshell`. 24 25 To access a model's connection, use its manager. The connection is available 26 at `model._default_manager.db.connection`. To find the backend or other 27 connection metadata, use `model._meta.db` to access the full ConnectionInfo 28 with connection metadata. 29 """ 30 31 from django.db import models 32 33 class Artist(models.Model): 34 name = models.CharField(max_length=100) 35 alive = models.BooleanField(default=True) 36 37 def __str__(self): 38 return self.name 39 40 41 class Opus(models.Model): 42 artist = models.ForeignKey(Artist) 43 name = models.CharField(max_length=100) 44 year = models.IntegerField() 45 46 def __str__(self): 47 return "%s (%s)" % (self.name, self.year) 48 49 50 class Widget(models.Model): 51 code = models.CharField(max_length=10, unique=True) 52 weight = models.IntegerField() 53 54 def __str__(self): 55 return self.code 56 57 58 class DooHickey(models.Model): 59 name = models.CharField(max_length=50) 60 widgets = models.ManyToManyField(Widget, related_name='doohickeys') 61 62 def __str__(self): 63 return self.name 64 65 66 class Vehicle(models.Model): 67 make = models.CharField(max_length=20) 68 model = models.CharField(max_length=20) 69 year = models.IntegerField() 70 71 def __str__(self): 72 return "%d %s %s" % (self.year, self.make, self.model) 73 74 75 __test__ = {'API_TESTS': """ 76 77 # See what connections are defined. django.db.connections acts like a dict. 78 >>> from django.db import connection, connections, _default, model_connection_name 79 >>> from django.conf import settings 80 81 # Connections are referenced by name 82 >>> connections['_a'] 83 Connection: ... 84 >>> connections['_b'] 85 Connection: ... 86 87 # Let's see what connections are available. The default connection is always 88 # included in connections as well, and may be accessed as connections[_default]. 89 90 >>> connection_names = connections.keys() 91 >>> connection_names.sort() 92 >>> connection_names 93 [<default>, '_a', '_b'] 94 95 # Invalid connection names raise ImproperlyConfigured 96 97 >>> connections['bad'] 98 Traceback (most recent call last): 99 ... 100 ImproperlyConfigured: No database connection 'bad' has been configured 101 102 # The model_connection_name() function will tell you the name of the 103 # connection that a model is configured to use. 104 105 >>> model_connection_name(Artist) 106 '_a' 107 >>> model_connection_name(Widget) 108 '_b' 109 >>> model_connection_name(Vehicle) is _default 110 True 111 >>> a = Artist(name="Paul Klee", alive=False) 112 >>> a.save() 113 >>> w = Widget(code='100x2r', weight=1000) 114 >>> w.save() 115 >>> v = Vehicle(make='Chevy', model='Camaro', year='1966') 116 >>> v.save() 117 >>> artists = Artist.objects.all() 118 >>> list(artists) 119 [<Artist: Paul Klee>] 120 121 # Models can access their connections through the db property of their 122 # default manager. 123 124 >>> paul = _[0] 125 >>> Artist.objects.db 126 Connection: ... (ENGINE=... NAME=...) 127 >>> paul._default_manager.db 128 Connection: ... (ENGINE=... NAME=...) 129 130 # When transactions are not managed, model save will commit only 131 # for the model's connection. 132 133 >>> from django.db import transaction 134 >>> transaction.enter_transaction_management() 135 >>> transaction.managed(False) 136 >>> a = Artist(name="Joan Miro", alive=False) 137 >>> w = Widget(code="99rbln", weight=1) 138 >>> a.save() 139 140 # Only connection '_a' is committed, so if we rollback 141 # all connections we'll forget the new Widget. 142 143 >>> transaction.rollback() 144 >>> list(Artist.objects.all()) 145 [<Artist: Paul Klee>, <Artist: Joan Miro>] 146 >>> list(Widget.objects.all()) 147 [<Widget: 100x2r>] 148 149 # Managed transaction state applies across all connections. 150 151 >>> transaction.managed(True) 152 153 # When managed, just as when using a single connection, updates are 154 # not committed until a commit is issued. 155 156 >>> a = Artist(name="Pablo Picasso", alive=False) 157 >>> a.save() 158 >>> w = Widget(code="99rbln", weight=1) 159 >>> w.save() 160 >>> v = Vehicle(make='Pontiac', model='Fiero', year='1987') 161 >>> v.save() 162 163 # The connections argument may be passed to commit, rollback, and the 164 # commit_on_success decorator as a keyword argument, as the first (for 165 # commit and rollback) or second (for the decorator) positional 166 # argument. It may be passed as a ConnectionInfo object, a connection 167 # (DatabaseWrapper) object, a connection name, or a list or dict of 168 # ConnectionInfo objects, connection objects, or connection names. If a 169 # dict is passed, the keys are ignored and the values used as the list 170 # of connections to commit, rollback, etc. 171 172 >>> transaction.commit(connections['_b']) 173 >>> transaction.commit('_b') 174 >>> transaction.commit(connections='_b') 175 >>> transaction.commit(connections=['_b']) 176 >>> transaction.commit(['_a', '_b']) 177 >>> transaction.commit(connections) 178 179 # When the connections argument is omitted entirely, the transaction 180 # command applies to all connections. Here we have committed 181 # connections 'django_test_db_a' and 'django_test_db_b', but not the 182 # default connection, so the new vehicle is lost on rollback. 183 184 >>> transaction.rollback() 185 >>> list(Artist.objects.all()) 186 [<Artist: Paul Klee>, <Artist: Joan Miro>, <Artist: Pablo Picasso>] 187 >>> list(Widget.objects.all()) 188 [<Widget: 100x2r>, <Widget: 99rbln>] 189 >>> list(Vehicle.objects.all()) 190 [<Vehicle: 1966 Chevy Camaro>] 191 >>> transaction.rollback() 192 >>> transaction.managed(False) 193 >>> transaction.leave_transaction_management() 194 195 # Of course, relations and all other normal database operations work 196 # with models that use named connections just the same as with models 197 # that use the default connection. The only caveat is that you can't 198 # use a relation between two models that are stored in different 199 # databases. Note that that doesn't mean that two models using 200 # different connection *names* can't be related; only that in the the 201 # context in which they are used, if you use the relation, the 202 # connections named by the two models must resolve to the same 203 # database. 204 205 >>> a = Artist.objects.get(name="Paul Klee") 206 >>> list(a.opus_set.all()) 207 [] 208 >>> a.opus_set.create(name="Magic Garden", year="1926") 209 <Opus: Magic Garden (1926)> 210 >>> list(a.opus_set.all()) 211 [<Opus: Magic Garden (1926)>] 212 >>> d = DooHickey(name='Thing') 213 >>> d.save() 214 >>> d.widgets.create(code='d101', weight=92) 215 <Widget: d101> 216 >>> list(d.widgets.all()) 217 [<Widget: d101>] 218 >>> w = Widget.objects.get(code='d101') 219 >>> list(w.doohickeys.all()) 220 [<DooHickey: Thing>] 221 """} -
tests/regressiontests/manager_db/tests.py
Property changes on: tests\regressiontests\manager_db ___________________________________________________________________ Name: svn:ignore + *.pyc
1 import unittest 2 from regressiontests.manager_db.models import Insect 3 4 class TestManagerDBAccess(unittest.TestCase): 5 6 def test_db_property(self): 7 m = Insect.objects 8 db = Insect.objects.db 9 assert db 10 assert db.connection 11 assert db.connection.cursor 12 assert db.backend 13 assert db.connection.ops.quote_name 14 assert db.get_creation_module 15 16 if __name__ == '__main__': 17 unittest.main() -
tests/regressiontests/manager_db/models.py
1 from django.db import models 2 3 class Insect(models.Model): 4 common_name = models.CharField(max_length=64) 5 latin_name = models.CharField(max_length=128) -
tests/regressiontests/thread_isolation/tests.py
Property changes on: tests\regressiontests\thread_isolation ___________________________________________________________________ Name: svn:ignore + *.pyc
1 # tests that db settings can be different in different threads 2 # 3 # 4 # What's going on here: 5 # 6 # Simulating multiple web requests in a threaded environment, one in 7 # which settings are different for each request. So we replace 8 # django.conf.settings with a thread local, with different 9 # configurations in each thread, and then fire off three 10 # simultaneous requests (using a condition to sync them up), and 11 # test that each thread sees its own settings and the models in each 12 # thread attempt to connect to the correct database as per their 13 # settings. 14 # 15 16 17 import copy 18 import os 19 import sys 20 import threading 21 import unittest 22 from thread import get_ident 23 24 from django.conf import settings, UserSettingsHolder 25 from django.core.handlers.wsgi import WSGIHandler 26 from django.db import model_connection_name, _default, connection, connections 27 from regressiontests.request_isolation.tests import MockHandler 28 from regressiontests.thread_isolation.models import * 29 30 try: 31 # Only exists in Python 2.4+ 32 from threading import local 33 except ImportError: 34 # Import copy of _thread_local.py from Python 2.4 35 from django.utils._threading_local import local 36 37 # helpers 38 EV = threading.Event() 39 40 class LocalSettings: 41 """Settings holder that allows thread-local overrides of defaults. 42 """ 43 def __init__(self, defaults): 44 self._defaults = defaults 45 self._local = local() 46 47 def __getattr__(self, attr): 48 if attr in ('_defaults', '_local'): 49 return self.__dict__[attr] 50 _local = self.__dict__['_local'] 51 _defaults = self.__dict__['_defaults'] 52 debug("LS get %s (%s)", attr, hasattr(_local, attr)) 53 if not hasattr(_local, attr): 54 # Make sure everything we return is the local version; this 55 # avoids sets to deep datastructures overwriting the defaults 56 setattr(_local, attr, copy.deepcopy(getattr(_defaults, attr))) 57 return getattr(_local, attr) 58 59 def __setattr__(self, attr, val): 60 if attr in ('_defaults', '_local'): 61 self.__dict__[attr] = val 62 else: 63 debug("LS set local %s = %s", attr, val) 64 setattr(self.__dict__['_local'], attr, val) 65 66 def thread_two(func, *arg): 67 def start(): 68 # from django.conf import settings 69 settings.OTHER_DATABASES['_b']['MODELS'] = [] 70 71 debug("t2 ODB: %s", settings.OTHER_DATABASES) 72 debug("t2 waiting") 73 EV.wait(2.0) 74 func(*arg) 75 debug("t2 complete") 76 t2 = threading.Thread(target=start) 77 t2.start() 78 return t2 79 80 def thread_three(func, *arg): 81 def start(): 82 # from django.conf import settings 83 settings.OTHER_DATABASES['_b']['MODELS'] = ['ti.MY'] 84 settings.OTHER_DATABASES['_b'], \ 85 settings.OTHER_DATABASES['_a'] = \ 86 settings.OTHER_DATABASES['_a'], \ 87 settings.OTHER_DATABASES['_b'] 88 89 settings.DATABASE_NAME = \ 90 settings.OTHER_DATABASES['_a']['DATABASE_NAME'] 91 92 debug("t3 ODB: %s", settings.OTHER_DATABASES) 93 debug("3 %s: start: default: %s", get_ident(), settings.DATABASE_NAME) 94 debug("3 %s: start: conn: %s", get_ident(), 95 connection.settings.DATABASE_NAME) 96 97 debug("t3 waiting") 98 EV.wait(2.0) 99 func(*arg) 100 debug("t3 complete") 101 t3 = threading.Thread(target=start) 102 t3.start() 103 return t3 104 105 def debug(*arg): 106 pass 107 ## msg, arg = arg[0], arg[1:] 108 ## print msg % arg 109 110 def start_response(code, headers): 111 debug("start response: %s %s", code, headers) 112 pass 113 114 class TestThreadIsolation(unittest.TestCase): 115 # event used to synchronize threads so we can be sure they are running 116 # together 117 lock = threading.RLock() 118 errors = [] 119 120 def setUp(self): 121 debug("setup") 122 self.settings = settings._target 123 settings._target = UserSettingsHolder(copy.deepcopy(settings._target)) 124 settings.OTHER_DATABASES['_a']['MODELS'] = ['ti.MX'] 125 settings.OTHER_DATABASES['_b']['MODELS'] = ['ti.MY'] 126 127 # normal settings holders aren't thread-safe, so we need to substitute 128 # one that is (and so allows per-thread settings) 129 holder = settings._target 130 settings._target = LocalSettings(holder) 131 132 def teardown(self): 133 debug("teardown") 134 settings._target = self.settings 135 136 def add_thread_error(self, err): 137 self.lock.acquire() 138 try: 139 self.errors.append(err) 140 finally: 141 self.lock.release() 142 143 def thread_errors(self): 144 self.lock.acquire() 145 try: 146 return self.errors[:] 147 finally: 148 self.lock.release() 149 150 def request_one(self, request): 151 """Start out with settings as originally configured""" 152 from django.conf import settings 153 debug("request_one: %s", settings.OTHER_DATABASES) 154 155 self.assertEqual(model_connection_name(MQ), _default) 156 self.assertEqual(model_connection_name(MX), '_a') 157 self.assertEqual( 158 MX._default_manager.db.connection.settings.DATABASE_NAME, 159 settings.OTHER_DATABASES['_a']['DATABASE_NAME']) 160 self.assertEqual(model_connection_name(MY), '_b') 161 self.assertEqual( 162 MY._default_manager.db.connection.settings.DATABASE_NAME, 163 settings.OTHER_DATABASES['_b']['DATABASE_NAME']) 164 self.assert_(MQ._default_manager.db.connection is 165 connections[_default].connection) 166 self.assertEqual( 167 MQ._default_manager.db.connection.settings.DATABASE_NAME, 168 settings.DATABASE_NAME) 169 self.assertEqual(connection.settings.DATABASE_NAME, 170 settings.DATABASE_NAME) 171 172 def request_two(self, request): 173 """Between the first and second requests, settings change to assign 174 model MY to a different connection 175 """ 176 # from django.conf import settings 177 debug("request_two: %s", settings.OTHER_DATABASES) 178 179 try: 180 self.assertEqual(model_connection_name(MQ), _default) 181 self.assertEqual(model_connection_name(MX), '_a') 182 self.assertEqual( 183 MX._default_manager.db.connection.settings.DATABASE_NAME, 184 settings.OTHER_DATABASES['_a']['DATABASE_NAME']) 185 self.assertEqual(model_connection_name(MY), _default) 186 self.assertEqual( 187 MY._default_manager.db.connection.settings.DATABASE_NAME, 188 settings.DATABASE_NAME) 189 self.assert_(MQ._default_manager.db.connection is 190 connections[_default].connection) 191 self.assertEqual( 192 MQ._default_manager.db.connection.settings.DATABASE_NAME, 193 settings.DATABASE_NAME) 194 self.assertEqual(connection.settings.DATABASE_NAME, 195 settings.DATABASE_NAME) 196 except: 197 self.add_thread_error(sys.exc_info()) 198 199 def request_three(self, request): 200 """Between the 2nd and 3rd requests, the settings at the names in 201 OTHER_DATABASES have changed. 202 """ 203 # from django.conf import settings 204 debug("3 %s: %s", get_ident(), settings.OTHER_DATABASES) 205 debug("3 %s: default: %s", get_ident(), settings.DATABASE_NAME) 206 debug("3 %s: conn: %s", get_ident(), 207 connection.settings.DATABASE_NAME) 208 try: 209 self.assertEqual(model_connection_name(MQ), _default) 210 self.assertEqual(model_connection_name(MX), '_b') 211 self.assertEqual( 212 MX._default_manager.db.connection.settings.DATABASE_NAME, 213 settings.OTHER_DATABASES['_b']['DATABASE_NAME']) 214 self.assertEqual(model_connection_name(MY), '_a') 215 self.assertEqual( 216 MY._default_manager.db.connection.settings.DATABASE_NAME, 217 settings.OTHER_DATABASES['_a']['DATABASE_NAME']) 218 self.assert_(MQ._default_manager.db.connection is 219 connections[_default].connection) 220 self.assertEqual( 221 connection.settings.DATABASE_NAME, 222 settings.OTHER_DATABASES['_a']['DATABASE_NAME']) 223 except: 224 self.add_thread_error(sys.exc_info()) 225 226 def test_thread_isolation(self): 227 228 debug("running tests") 229 230 env = os.environ.copy() 231 env['PATH_INFO'] = '/' 232 env['REQUEST_METHOD'] = 'GET' 233 234 t2 = thread_two(MockHandler(self.request_two), env, start_response) 235 t3 = thread_three(MockHandler(self.request_three), env, start_response) 236 237 try: 238 EV.set() 239 MockHandler(self.request_one)(env, start_response) 240 finally: 241 t2.join() 242 t3.join() 243 err = self.thread_errors() 244 if err: 245 import traceback 246 for e in err: 247 traceback.print_exception(*e) 248 raise AssertionError("%s thread%s failed" % 249 (len(err), len(err) > 1 and 's' or 250 '')) 251 -
tests/regressiontests/thread_isolation/models.py
1 from django.db import models 2 3 # models 4 class MQ(models.Model): 5 val = models.CharField(max_length=10) 6 class Meta: 7 app_label = 'ti' 8 9 10 class MX(models.Model): 11 val = models.CharField(max_length=10) 12 class Meta: 13 app_label = 'ti' 14 15 16 class MY(models.Model): 17 val = models.CharField(max_length=10) 18 class Meta: 19 app_label = 'ti' -
tests/regressiontests/request_isolation/tests.py
Property changes on: tests\regressiontests\request_isolation ___________________________________________________________________ Name: svn:ignore + *.pyc
1 # tests that db settings can change between requests 2 import copy 3 import os 4 import unittest 5 from django.conf import settings, UserSettingsHolder 6 from django.core.handlers.wsgi import WSGIHandler 7 from django.db import models, model_connection_name, _default, connection 8 from django.http import HttpResponse 9 from regressiontests.request_isolation.models import * 10 11 12 # helpers 13 class MockHandler(WSGIHandler): 14 15 def __init__(self, test): 16 self.test = test 17 super(MockHandler, self).__init__() 18 19 def get_response(self, request): 20 # debug("mock handler answering %s, %s", path, request) 21 return HttpResponse(self.test(request)) 22 23 24 def debug(*arg): 25 pass 26 # msg, arg = arg[0], arg[1:] 27 # print msg % arg 28 29 30 def start_response(code, headers): 31 debug("start response: %s %s", code, headers) 32 pass 33 34 # tests 35 class TestRequestIsolation(unittest.TestCase): 36 37 def setUp(self): 38 debug("setup") 39 self.settings = settings._target 40 settings._target = UserSettingsHolder(copy.deepcopy(settings._target)) 41 settings.OTHER_DATABASES['_a']['MODELS'] = ['ri.MX'] 42 settings.OTHER_DATABASES['_b']['MODELS'] = ['ri.MY'] 43 44 def tearDown(self): 45 debug("teardown") 46 settings._target = self.settings 47 48 def testRequestIsolation(self): 49 env = os.environ.copy() 50 env['PATH_INFO'] = '/' 51 env['REQUEST_METHOD'] = 'GET' 52 53 def request_one(request): 54 """Start out with settings as originally configured""" 55 self.assertEqual(model_connection_name(MX), '_a') 56 self.assertEqual( 57 MX._default_manager.db.connection.settings.DATABASE_NAME, 58 settings.OTHER_DATABASES['_a']['DATABASE_NAME']) 59 self.assertEqual(model_connection_name(MY), '_b') 60 self.assertEqual( 61 MY._default_manager.db.connection.settings.DATABASE_NAME, 62 settings.OTHER_DATABASES['_b']['DATABASE_NAME']) 63 64 def request_two(request): 65 """Between the first and second requests, settings change to assign 66 model MY to a different connection 67 """ 68 self.assertEqual(model_connection_name(MX), '_a') 69 self.assertEqual( 70 MX._default_manager.db.connection.settings.DATABASE_NAME, 71 settings.OTHER_DATABASES['_a']['DATABASE_NAME']) 72 self.assertEqual(model_connection_name(MY), _default) 73 self.assertEqual( 74 MY._default_manager.db.connection.settings.DATABASE_NAME, 75 settings.DATABASE_NAME) 76 77 def request_three(request): 78 """Between the 2nd and 3rd requests, the settings at the names in 79 OTHER_DATABASES have changed. 80 """ 81 self.assertEqual(model_connection_name(MX), '_b') 82 self.assertEqual( 83 MX._default_manager.db.connection.settings.DATABASE_NAME, 84 settings.OTHER_DATABASES['_b']['DATABASE_NAME']) 85 self.assertEqual(model_connection_name(MY), '_a') 86 self.assertEqual( 87 MY._default_manager.db.connection.settings.DATABASE_NAME, 88 settings.OTHER_DATABASES['_a']['DATABASE_NAME']) 89 90 MockHandler(request_one)(env, start_response) 91 92 settings.OTHER_DATABASES['_b']['MODELS'] = [] 93 MockHandler(request_two)(env, start_response) 94 95 settings.OTHER_DATABASES['_b']['MODELS'] = ['ri.MY'] 96 settings.OTHER_DATABASES['_b'], \ 97 settings.OTHER_DATABASES['_a'] = \ 98 settings.OTHER_DATABASES['_a'], \ 99 settings.OTHER_DATABASES['_b'] 100 MockHandler(request_three)(env, start_response) -
tests/regressiontests/request_isolation/models.py
1 from django.db import models 2 3 # models 4 class MX(models.Model): 5 val = models.CharField(max_length=10) 6 class Meta: 7 app_label = 'ri' 8 9 10 class MY(models.Model): 11 val = models.CharField(max_length=10) 12 class Meta: 13 app_label = 'ri' -
tests/runtests.py
12 12 13 13 14 14 CONTRIB_DIR_NAME = 'django.contrib' 15 TEST_OTHER_DATABASES = { 16 '_a': { 'DATABASE_NAME': 'django_test_a.db', 17 'MODELS': [ 'multiple_databases.Artist', 18 'multiple_databases.Opus' ]}, 19 '_b': { 'DATABASE_NAME': 'django_test_b.db', 20 'MODELS': [ 'multiple_databases.Widget', 21 'multiple_databases.DooHickey' ]} 22 } 15 23 MODEL_TESTS_DIR_NAME = 'modeltests' 16 24 REGRESSION_TESTS_DIR_NAME = 'regressiontests' 17 25 … … 99 107 100 108 # Redirect some settings for the duration of these tests. 101 109 settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS 110 settings.TEST_OTHER_DATABASES = TEST_OTHER_DATABASES 102 111 settings.ROOT_URLCONF = 'urls' 103 112 settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),) 104 113 settings.USE_I18N = True -
docs/multiple_database_support.txt
1 ======================== 2 Using Multiple Databases 3 ======================== 4 5 Standard Django practice is to use a single database connection for 6 all models in all applications. However, Django supports configuring 7 and using multiple database connections on a per-application, per-model 8 or an ad-hoc basis. Using multiple database connections is optional. 9 10 Configuring other database connections 11 ====================================== 12 13 Django's default database connection is configured via the settings 14 DATABASE_ENGINE, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD, 15 DATABASE_HOST, and DATABASE_PORT. Other connections are configured via 16 the OTHER_DATABASES setting. Define OTHER_DATABASES as a dict, with a 17 name for each connection as the key and a dict of settings as the 18 value. In each OTHER_DATABASES entry (called a "named connection"), 19 the keys are the same as the DATABASE_ENGINE, etc, settings used to 20 configure the default connection. All keys are optional; any that are 21 missing in a named connection's settings will inherit their values 22 from the default connection. 23 24 Here's an example:: 25 26 DATABASE_ENGINE = 'postgresql' 27 DATABASE_NAME = 'django_apps' 28 DATABASE_USER = 'default_user' 29 DATABASE_PASSWORD = 'xxx' 30 31 OTHER_DATABASES = { 32 'local': { 'DATABASE_ENGINE': 'sqlite3', 33 'DATABASE_NAME': '/tmp/cache.db' }, 34 'public': { 'DATABASE_HOST': 'public', 35 'DATABASE_USER': 'public_user', 36 'DATABASE_PASSWORD': 'xxx' } 37 'private': { 'DATABASE_HOST': 'private', 38 'DATABASE_USER': 'private_user', 39 'DATABASE_PASSWORD': 'xxx' } 40 } 41 42 In addition to the DATABASE_* settings, each named connection in 43 OTHER_DATABASES may optionally include a MODELS setting. This should 44 be a list of app or app.model names, and is used to configure which 45 models should use this connection instead of the default connection. 46 47 Here's the example above, with ``MODELS``:: 48 49 OTHER_DATABASES = { 50 'local': { 'DATABASE_ENGINE': 'sqlite3', 51 'DATABASE_NAME': '/tmp/cache.db', 52 # A model name: only the model ContentItem 53 # with the app_label myapp will use this connection 54 'MODELS': ['myapp.ContentItem'] }, 55 'public': { 'DATABASE_HOST': 'public', 56 'DATABASE_USER': 'public_user', 57 'DATABASE_PASSWORD': 'xxx', 58 # Two models in myapp will use the connection 59 # named 'public', as will ALL models in 60 # django.contribe.comments 61 'MODELS': ['myapp.Blog','myapp.Article', 62 'django.contrib.comments' ] } 63 # No models or apps are configured to use the private db 64 'private': { 'DATABASE_HOST': 'private', 65 'DATABASE_USER': 'private_user', 66 'DATABASE_PASSWORD': 'xxx' } 67 } 68 69 Accessing a model's connection 70 ============================== 71 72 Each manager has a ``db`` attribute that can be used to access the model's 73 connection. Access the ``db`` attribute of a model's manager to obtain the 74 model's currently configured connection. 75 76 Example:: 77 78 from django.db import models 79 80 class Blog(models.Model) 81 name = models.CharField(maxlength=50) 82 83 class Article(models.Model) 84 blog = models.ForeignKey(Blog) 85 title = models.CharField(maxlength=100) 86 slug = models.SlugField() 87 summary = models.CharField(maxlength=500) 88 body = models.TextField() 89 90 class ContentItem(models.Model) 91 slug = models.SlugField() 92 mimetype = models.CharField(maxlength=50) 93 file = models.FileField() 94 95 # Get a ConnectionInfo instance that describes the connection 96 article_db = Article.objects.db 97 98 # Get a connection and a cursor 99 connection = article_db.connection 100 cursor = connection.cursor() 101 102 # Get the ``quote_name`` function from the backend 103 qn = article_db.backend.quote_name 104 105 Ordinarily you won't have to access a model's connection directly; 106 just use the model and manager normally and they will use the 107 connection configured for the model. 108 109 ConnectionInfo objects 110 ====================== 111 112 FIXME Describe the ConnectionInfo object and each of its attributes. 113 114 115 Accessing connections by name 116 ============================= 117 118 Access named connections directly through 119 ``django.db.connections``. Each entry in ``django.db.connections`` is 120 a ``ConnectionInfo`` instance bound to the settings configured in the 121 OTHER_DATABASES entry under the same key. 122 123 Example:: 124 125 from django.db import connections 126 127 private_db = connections['private'] 128 cursor = private_db.connection.cursor() 129 130 131 Using transactions with other database connections 132 ================================================== 133 134 Transaction managed state applies across all connections 135 commit/rollback apply to all connections by default 136 but you can specify individual connections or lists or dicts of connections 137 138 139 Changing model connections on the fly 140 ===================================== 141 142 Here's an example of primitive mirroring:: 143 144 # Read all articles from the private db 145 # Note that we pull the articles into a list; this is necessary 146 # because query sets are lazy. If we were to change the model's 147 # connection without copying the articles into a local list, we'd 148 # wind up reading from public instead of private. 149 150 Article.objects.db = connections['private'] 151 all_articles = list(Article.objects.all()) 152 153 # Save each article in the public db 154 Article.objects.db = connections['public'] 155 for article in all_articles: 156 article.save() 157 158 Thread and request isolation 159 ============================ 160 161 connections close after each request 162 connection settings are thread-local 163 -
docs/settings.txt
733 733 See `allowed date format strings`_. See also ``DATE_FORMAT``, 734 734 ``DATETIME_FORMAT``, ``TIME_FORMAT`` and ``YEAR_MONTH_FORMAT``. 735 735 736 OTHER_DATABASES 737 --------------- 738 739 Default: ``{}`` 740 741 Other database connections to use in addition to the default connection. See the `multiple database support docs`_. 742 736 743 PREPEND_WWW 737 744 ----------- 738 745