Ticket #4747: mdb.patch
File mdb.patch, 203.1 KB (added by , 17 years ago) |
---|
-
django/test/utils.py
=== django/test/utils.py ==================================================================
1 1 import sys, time 2 2 from django.conf import settings 3 from django.db import connection, backend, get_creation_module 3 from django.db import connection, transaction, backend, \ 4 connection_info, connections, get_creation_module 4 5 from django.core import management, mail 5 6 from django.core import management, mail 6 7 from django.dispatch import dispatcher … … 12 13 TEST_DATABASE_PREFIX = 'test_' 13 14 14 15 def instrumented_test_render(self, context): 15 """An instrumented Template render method, providing a signal16 that can be intercepted by the test system Client17 18 16 """ 17 An instrumented Template render method, providing a signal that can be 18 intercepted by the test system Client. 19 """ 19 20 dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context) 20 21 return self.nodelist.render(context) 22 23 def instrumented_test_iter_render(self, context): 24 """ 25 An instrumented Template iter_render method, providing a signal that can be 26 intercepted by the test system Client. 27 """ 28 for chunk in self.nodelist.iter_render(context): 29 yield chunk 30 dispatcher.send(signal=signals.template_rendered, sender=self, template=self, context=context) 21 31 22 32 class TestSMTPConnection(object): 23 33 """A substitute SMTP connection for use during test sessions. … … 45 55 46 56 """ 47 57 Template.original_render = Template.render 58 Template.original_iter_render = Template.iter_render 48 59 Template.render = instrumented_test_render 60 Template.iter_render = instrumented_test_render 49 61 50 62 mail.original_SMTPConnection = mail.SMTPConnection 51 63 mail.SMTPConnection = TestSMTPConnection … … 60 72 61 73 """ 62 74 Template.render = Template.original_render 63 del Template.original_render 75 Template.iter_render = Template.original_iter_render 76 del Template.original_render, Template.original_iter_render 64 77 65 78 mail.SMTPConnection = mail.original_SMTPConnection 66 79 del mail.original_SMTPConnection … … 73 86 connection.connection.autocommit(True) 74 87 elif hasattr(connection.connection, "set_isolation_level"): 75 88 connection.connection.set_isolation_level(0) 76 89 77 90 def get_mysql_create_suffix(): 78 91 suffix = [] 79 92 if settings.TEST_DATABASE_CHARSET: … … 97 110 98 111 if verbosity >= 1: 99 112 print "Creating test database..." 113 100 114 # If we're using SQLite, it's more convenient to test against an 101 115 # in-memory database. 102 116 if settings.DATABASE_ENGINE == "sqlite3": 103 TEST_DATABASE_NAME = ":memory:" 117 TEST_DATABASE_NAME = "/home/ben/test.db" #":memory:" 118 if verbosity >= 2: 119 print "Using in-memory sqlite database for testing" 104 120 else: 105 121 suffix = { 106 122 'postgresql': get_postgresql_create_suffix, … … 112 128 TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME 113 129 else: 114 130 TEST_DATABASE_NAME = TEST_DATABASE_PREFIX + settings.DATABASE_NAME 115 131 132 qn = backend.quote_name 116 133 # Create the test database and connect to it. We need to autocommit 117 134 # if the database supports it because PostgreSQL doesn't allow 118 135 # CREATE/DROP DATABASE statements within transactions. 119 136 cursor = connection.cursor() 120 137 _set_autocommit(connection) 121 138 try: 122 cursor.execute("CREATE DATABASE %s %s" % ( backend.quote_name(TEST_DATABASE_NAME), suffix))139 cursor.execute("CREATE DATABASE %s %s" % (qn(TEST_DATABASE_NAME), suffix)) 123 140 except Exception, e: 124 141 sys.stderr.write("Got an error creating the test database: %s\n" % e) 125 142 if not autoclobber: … … 128 145 try: 129 146 if verbosity >= 1: 130 147 print "Destroying old test database..." 131 cursor.execute("DROP DATABASE %s" % backend.quote_name(TEST_DATABASE_NAME))148 cursor.execute("DROP DATABASE %s" % qn(TEST_DATABASE_NAME)) 132 149 if verbosity >= 1: 133 150 print "Creating test database..." 134 cursor.execute("CREATE DATABASE %s %s" % ( backend.quote_name(TEST_DATABASE_NAME), suffix))151 cursor.execute("CREATE DATABASE %s %s" % (qn(TEST_DATABASE_NAME), suffix)) 135 152 except Exception, e: 136 153 sys.stderr.write("Got an error recreating the test database: %s\n" % e) 137 154 sys.exit(2) … … 148 165 # the side effect of initializing the test database. 149 166 cursor = connection.cursor() 150 167 151 def destroy_test_db(old_database_name, verbosity=1): 168 # Fill OTHER_DATABASES with the TEST_DATABASES settings, 169 # and connect each named connection to the test database. 170 test_databases = {} 171 for db_name in settings.TEST_DATABASES: 172 db_st = {'DATABASE_NAME': TEST_DATABASE_NAME} 173 if db_name in settings.TEST_DATABASE_MODELS: 174 db_st['MODELS'] = settings.TEST_DATABASE_MODELS.get(db_name, []) 175 test_databases[db_name] = db_st 176 settings.OTHER_DATABASES = test_databases 177 178 def destroy_test_db(old_database_name, old_databases, verbosity=1): 152 179 # If the database wants to drop the test DB itself, let it 153 180 creation_module = get_creation_module() 154 181 if hasattr(creation_module, "destroy_test_db"): 155 182 creation_module.destroy_test_db(settings, connection, backend, old_database_name, verbosity) 156 183 return 157 158 184 # Unless we're using SQLite, remove the test database to clean up after 159 185 # ourselves. Connect to the previous database (not the test database) 160 186 # to do so, because it's not allowed to delete a database while being 161 187 # connected to it. 162 188 if verbosity >= 1: 163 189 print "Destroying test database..." 190 164 191 connection.close() 192 for cnx in connections.keys(): 193 connections[cnx].close() 194 connections.reset() 195 165 196 TEST_DATABASE_NAME = settings.DATABASE_NAME 197 if verbosity >= 2: 198 print "Closed connections to %s" % TEST_DATABASE_NAME 166 199 settings.DATABASE_NAME = old_database_name 167 200 168 201 if settings.DATABASE_ENGINE != "sqlite3": 202 settings.OTHER_DATABASES = old_databases 203 for cnx in connections.keys(): 204 try: 205 connections[cnx].connection.cursor() 206 except (KeyboardInterrupt, SystemExit): 207 raise 208 except: 209 pass 169 210 cursor = connection.cursor() 170 211 _set_autocommit(connection) 171 212 time.sleep(1) # To avoid "database is being accessed by other users" errors. -
django/http/__init__.py
=== django/http/__init__.py ==================================================================
224 224 content = ''.join(self._container) 225 225 if isinstance(content, unicode): 226 226 content = content.encode(self._charset) 227 228 # If self._container was an iterator, we have just exhausted it, so we 229 # need to save the results for anything else that needs access 230 if not self._is_string: 231 self._container = [content] 232 self._is_string = True 227 233 return content 228 234 229 235 def _set_content(self, value): … … 233 239 content = property(_get_content, _set_content) 234 240 235 241 def __iter__(self): 236 self._iterator = self._container.__iter__() 237 return self 242 for chunk in self._container: 243 if isinstance(chunk, unicode): 244 chunk = chunk.encode(self._charset) 245 yield chunk 238 246 239 def next(self):240 chunk = self._iterator.next()241 if isinstance(chunk, unicode):242 chunk = chunk.encode(self._charset)243 return chunk244 245 247 def close(self): 246 248 if hasattr(self._container, 'close'): 247 249 self._container.close() -
django/oldforms/__init__.py
=== django/oldforms/__init__.py ==================================================================
309 309 return data 310 310 html2python = staticmethod(html2python) 311 311 312 def iter_render(self, data): 313 # this even needed? 314 return (self.render(data),) 315 312 316 def render(self, data): 313 317 raise NotImplementedError 314 318 -
django/db/models/base.py
=== django/db/models/base.py ==================================================================
6 6 from django.db.models.fields.related import OneToOneRel, ManyToOneRel 7 7 from django.db.models.query import delete_objects 8 8 from django.db.models.options import Options, AdminOptions 9 from django.db import connection, backend,transaction9 from django.db import transaction 10 10 from django.db.models import signals 11 11 from django.db.models.loading import register_models, get_model 12 12 from django.dispatch import dispatcher … … 22 22 "Metaclass for all models" 23 23 def __new__(cls, name, bases, attrs): 24 24 # If this isn't a subclass of Model, don't do anything special. 25 print "\n\n" + "*"*40 26 print "ModelBase Called with name: %s and attrs:" % name 27 print "\n".join(["%s => %s" % (k,v) for k, v in attrs.items()]) 25 28 try: 26 29 if not filter(lambda b: issubclass(b, Model), bases): 27 30 return super(ModelBase, cls).__new__(cls, name, bases, attrs) … … 201 204 def save(self): 202 205 dispatcher.send(signal=signals.pre_save, sender=self.__class__, instance=self) 203 206 207 db = self.__class__._default_manager.db 208 connection = db.connection 209 backend = db.backend 210 qn = backend.quote_name 204 211 non_pks = [f for f in self._meta.fields if not f.primary_key] 205 212 cursor = connection.cursor() 206 213 … … 211 218 if pk_set: 212 219 # Determine whether a record with the primary key already exists. 213 220 cursor.execute("SELECT COUNT(*) FROM %s WHERE %s=%%s" % \ 214 ( backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)),221 (qn(self._meta.db_table), qn(self._meta.pk.column)), 215 222 self._meta.pk.get_db_prep_lookup('exact', pk_val)) 216 223 # If it does already exist, do an UPDATE. 217 224 if cursor.fetchone()[0] > 0: 218 225 db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks] 219 226 if db_values: 220 227 cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \ 221 ( backend.quote_name(self._meta.db_table),222 ','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),223 backend.quote_name(self._meta.pk.column)),228 (qn(self._meta.db_table), 229 ','.join(['%s=%%s' % qn(f.column) for f in non_pks]), 230 qn(self._meta.pk.column)), 224 231 db_values + self._meta.pk.get_db_prep_lookup('exact', pk_val)) 225 232 else: 226 233 record_exists = False 227 234 if not pk_set or not record_exists: 228 field_names = [ backend.quote_name(f.column) for f in self._meta.fields if not isinstance(f, AutoField)]235 field_names = [qn(f.column) for f in self._meta.fields if not isinstance(f, AutoField)] 229 236 db_values = [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)] 230 237 # If the PK has been manually set, respect that. 231 238 if pk_set: … … 233 240 db_values += [f.get_db_prep_save(f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)] 234 241 placeholders = ['%s'] * len(field_names) 235 242 if self._meta.order_with_respect_to: 236 field_names.append( backend.quote_name('_order'))243 field_names.append(qn('_order')) 237 244 # TODO: This assumes the database supports subqueries. 238 245 placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \ 239 ( backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.order_with_respect_to.column)))246 (qn(self._meta.db_table), qn(self._meta.order_with_respect_to.column))) 240 247 db_values.append(getattr(self, self._meta.order_with_respect_to.attname)) 241 248 if db_values: 242 249 cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \ 243 ( backend.quote_name(self._meta.db_table), ','.join(field_names),250 (qn(self._meta.db_table), ','.join(field_names), 244 251 ','.join(placeholders)), db_values) 245 252 else: 246 253 # Create a new record with defaults for everything. 247 254 cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % 248 ( backend.quote_name(self._meta.db_table),249 backend.quote_name(self._meta.pk.column),255 (qn(self._meta.db_table), 256 qn(self._meta.pk.column), 250 257 backend.get_pk_default_value())) 251 258 if self._meta.has_auto_field and not pk_set: 252 259 setattr(self, self._meta.pk.attname, backend.get_last_insert_id(cursor, self._meta.db_table, self._meta.pk.column)) 253 transaction.commit_unless_managed( )260 transaction.commit_unless_managed([connection]) 254 261 255 262 # Run any post-save hooks. 256 263 dispatcher.send(signal=signals.post_save, sender=self.__class__, instance=self) … … 321 328 return dict(field.choices).get(value, value) 322 329 323 330 def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs): 331 qn = self._default_manager.db.backend.quote_name 324 332 op = is_next and '>' or '<' 325 333 where = '(%s %s %%s OR (%s = %%s AND %s.%s %s %%s))' % \ 326 ( backend.quote_name(field.column), op, backend.quote_name(field.column),327 backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column), op)334 (qn(field.column), op, qn(field.column), 335 qn(self._meta.db_table), qn(self._meta.pk.column), op) 328 336 param = str(getattr(self, field.attname)) 329 337 q = self.__class__._default_manager.filter(**kwargs).order_by((not is_next and '-' or '') + field.name, (not is_next and '-' or '') + self._meta.pk.name) 330 338 q._where.append(where) … … 335 343 raise self.DoesNotExist, "%s matching query does not exist." % self.__class__._meta.object_name 336 344 337 345 def _get_next_or_previous_in_order(self, is_next): 346 qn = self._default_manager.db.backend.quote_name 347 338 348 cachename = "__%s_order_cache" % is_next 339 349 if not hasattr(self, cachename): 340 350 op = is_next and '>' or '<' 341 351 order_field = self._meta.order_with_respect_to 342 352 where = ['%s %s (SELECT %s FROM %s WHERE %s=%%s)' % \ 343 ( backend.quote_name('_order'), op, backend.quote_name('_order'),344 backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)),345 '%s=%%s' % backend.quote_name(order_field.column)]353 (qn('_order'), op, qn('_order'), 354 qn(self._meta.db_table), qn(self._meta.pk.column)), 355 '%s=%%s' % qn(order_field.column)] 346 356 params = [self._get_pk_val(), getattr(self, order_field.attname)] 347 357 obj = self._default_manager.order_by('_order').extra(where=where, params=params)[:1].get() 348 358 setattr(self, cachename, obj) … … 424 434 # ORDERING METHODS ######################### 425 435 426 436 def method_set_order(ordered_obj, self, id_list): 437 db = ordered_obj._default_manager.db 438 connection = db.connection 439 qn = db.backend.quote_name 427 440 cursor = connection.cursor() 428 441 # Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s" 429 442 sql = "UPDATE %s SET %s = %%s WHERE %s = %%s AND %s = %%s" % \ 430 ( backend.quote_name(ordered_obj._meta.db_table), backend.quote_name('_order'),431 backend.quote_name(ordered_obj._meta.order_with_respect_to.column),432 backend.quote_name(ordered_obj._meta.pk.column))443 (qn(ordered_obj._meta.db_table), qn('_order'), 444 qn(ordered_obj._meta.order_with_respect_to.column), 445 qn(ordered_obj._meta.pk.column)) 433 446 rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name) 434 447 cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)]) 435 transaction.commit_unless_managed( )448 transaction.commit_unless_managed([connection]) 436 449 437 450 def method_get_order(ordered_obj, self): 451 db = ordered_obj._default_manager.db 452 connection = db.connection 453 qn = db.backend.quote_name 438 454 cursor = connection.cursor() 439 455 # Example: "SELECT id FROM poll_choices WHERE poll_id = %s ORDER BY _order" 440 456 sql = "SELECT %s FROM %s WHERE %s = %%s ORDER BY %s" % \ 441 ( backend.quote_name(ordered_obj._meta.pk.column),442 backend.quote_name(ordered_obj._meta.db_table),443 backend.quote_name(ordered_obj._meta.order_with_respect_to.column),444 backend.quote_name('_order'))457 (qn(ordered_obj._meta.pk.column), 458 qn(ordered_obj._meta.db_table), 459 qn(ordered_obj._meta.order_with_respect_to.column), 460 qn('_order')) 445 461 rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name) 446 462 cursor.execute(sql, [rel_val]) 447 463 return [r[0] for r in cursor.fetchall()] -
django/db/models/manager.py
=== django/db/models/manager.py ==================================================================
1 from django.db import ConnectionInfoDescriptor 1 2 from django.db.models.query import QuerySet, EmptyQuerySet 2 3 from django.dispatch import dispatcher 3 from django.db.models import signals 4 from django.db.models import signals, get_apps, get_models 4 5 from django.db.models.fields import FieldDoesNotExist 5 6 7 try: 8 # Only exists in Python 2.4+ 9 from threading import local 10 except ImportError: 11 # Import copy of _thread_local.py from Python 2.4 12 from django.utils._threading_local import local 13 6 14 # Size of each "chunk" for get_iterator calls. 7 15 # Larger values are slightly faster at the expense of more storage space. 8 16 GET_ITERATOR_CHUNK_SIZE = 100 … … 17 25 except FieldDoesNotExist: 18 26 pass 19 27 cls.add_to_class('objects', Manager()) 20 28 elif cls._default_manager.model != cls: 29 # cls is an inherited model; don't want the parent manager 30 cls.add_to_class('objects', Manager()) 21 31 dispatcher.connect(ensure_default_manager, signal=signals.class_prepared) 22 32 33 34 23 35 class Manager(object): 24 36 # Tracks each time a Manager instance is created. Used to retain order. 25 37 creation_counter = 0 26 38 db = ConnectionInfoDescriptor() 39 27 40 def __init__(self): 28 41 super(Manager, self).__init__() 29 42 # Increase the creation counter, and save our local copy. … … 35 48 # TODO: Use weakref because of possible memory leak / circular reference. 36 49 self.model = model 37 50 setattr(model, name, ManagerDescriptor(self)) 38 if not hasattr(model, '_default_manager') or self.creation_counter < model._default_manager.creation_counter: 51 if not hasattr(model, '_default_manager') \ 52 or self.creation_counter < model._default_manager.creation_counter \ 53 or model._default_manager.model != model: 39 54 model._default_manager = self 40 55 41 56 ####################### 42 57 # PROXIES TO QUERYSET # 43 58 ####################### … … 105 120 def values(self, *args, **kwargs): 106 121 return self.get_query_set().values(*args, **kwargs) 107 122 123 ####################### 124 # SCHEMA MANIPULATION # 125 ####################### 126 127 def install(self, initial_data=False, pending=None): 128 """Install my model's table, indexes and (if requested) initial data. 129 130 Returns a dict of pending statements, keyed by the model that 131 needs to be created before the statements can be executed. 132 (Pending statements are those that could not yet be executed, 133 such as foreign key constraints for tables that don't exist at 134 install time.) 135 """ 136 if pending is None: 137 pending = {} 138 builder = self.db.get_creation_module().builder 139 run, pending = builder.get_create_table(self.model, pending=pending) 140 run += builder.get_create_indexes(self.model) 141 many_many = builder.get_create_many_to_many(self.model) 142 143 for statement in run: 144 statement.execute() 145 for klass, statements in many_many.items(): 146 if klass in builder.models_already_seen: 147 for statement in statements: 148 statement.execute() 149 else: 150 pending.setdefault(klass, []).extend(statements) 151 if initial_data: 152 self.load_initial_data() 153 return pending 154 155 def get_pending(self, rel_class, f): 156 """Get list pending statement relating my model to rel_class via 157 field f 158 """ 159 builder = self.db.get_creation_module().builder 160 return builder.get_ref_sql(self.model, rel_class, f) 161 162 def load_initial_data(self): 163 """Install initial data for model in db, Returns statements executed. 164 """ 165 builder = self.db.get_creation_module().builder 166 statements = builder.get_initialdata(self.model) 167 for statement in statements: 168 statement.execute() 169 return statements 170 171 def get_installed_models(self, table_list): 172 """Get list of models installed, given a list of tables. 173 """ 174 all_models = [] 175 for app in get_apps(): 176 for model in get_models(app): 177 all_models.append(model) 178 return set([m for m in all_models 179 if m._meta.db_table in table_list]) 180 181 def get_table_list(self): 182 """Get list of tables accessible via my model's connection. 183 """ 184 builder = self.db.get_creation_module().builder 185 return builder.get_table_list(self.db) 186 108 187 class ManagerDescriptor(object): 109 188 # This class ensures managers aren't accessible via model instances. 110 189 # For example, Poll.objects works, but poll_obj.objects raises AttributeError. … … 115 194 if instance != None: 116 195 raise AttributeError, "Manager isn't accessible via %s instances" % type.__name__ 117 196 return self.manager 197 -
django/db/models/options.py
=== django/db/models/options.py ==================================================================
1 1 from django.conf import settings 2 from django.db import connection_info, connections 2 3 from django.db.models.related import RelatedObject 3 4 from django.db.models.fields.related import ManyToManyRel 4 5 from django.db.models.fields import AutoField, FieldDoesNotExist … … 7 8 from django.db.models import Manager 8 9 from bisect import bisect 9 10 import re 11 import weakref 10 12 11 13 # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces". 12 14 get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip() … … 79 81 self.db_table = truncate_name(self.db_table, 80 82 backend.get_max_name_length()) 81 83 84 # Keep a weakref to my model, for access to managers and such 85 self._model = weakref.ref(model) 86 82 87 def add_field(self, field): 83 88 # Insert the given field in the order in which it was created, using 84 89 # the "creation_counter" attribute of the field. … … 105 110 return f 106 111 raise FieldDoesNotExist, '%s has no field named %r' % (self.object_name, name) 107 112 113 def get_default_manager(self): 114 model = self._model() 115 if model is None: 116 raise ReferenceError("Model no longer available in %s" % self) 117 return model._default_manager 118 108 119 def get_order_sql(self, table_prefix=''): 109 120 "Returns the full 'ORDER BY' clause for this object, according to self.ordering." 110 121 if not self.ordering: return '' -
django/db/models/loading.py
=== django/db/models/loading.py ==================================================================
12 12 _app_models = {} # Dictionary of models against app label 13 13 # Each value is a dictionary of model name: model class 14 14 # Applabel and Model entry exists in cache when individual model is loaded. 15 _app_model_order = {} # Dictionary of models against app label 16 # Each value is a list of model names, in the order in 17 # which the models were created 15 18 _app_errors = {} # Dictionary of errors that were experienced when loading the INSTALLED_APPS 16 19 # Key is the app_name of the model, value is the exception that was raised 17 20 # during model loading. … … 61 64 get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish. 62 65 return _app_errors 63 66 64 def get_models(app_mod=None ):67 def get_models(app_mod=None, creation_order=False): 65 68 """ 66 69 Given a module containing models, returns a list of the models. Otherwise 67 70 returns a list of all installed models. 68 71 """ 69 72 app_list = get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish. 70 73 if app_mod: 71 return _app_models.get(app_mod.__name__.split('.')[-2], {}).values() 74 app_label = app_mod.__name__.split('.')[-2] 75 app_models = _app_models.get(app_label, {}) 76 if creation_order: 77 return [ app_models[name] 78 for name in _app_model_order.get(app_label, []) ] 79 return app_models.values() 72 80 else: 73 81 model_list = [] 74 82 for app_mod in app_list: -
django/db/models/fields/__init__.py
=== django/db/models/fields/__init__.py ==================================================================
536 536 except ValueError: 537 537 raise validators.ValidationError, gettext('Enter a valid date/time in YYYY-MM-DD HH:MM format.') 538 538 539 def get_db_prep_save(self, value):540 # Casts dates into string format for entry into database.539 def pre_save(self, model_instance, add): 540 value = super(DateField, self).pre_save(model_instance, add) 541 541 if value is not None: 542 542 # MySQL will throw a warning if microseconds are given, because it 543 543 # doesn't support microseconds. 544 settings = model_instance._default_manager.db.connection.settings 544 545 if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 545 546 value = value.replace(microsecond=0) 547 return value 548 549 def get_db_prep_save(self, value): 550 # Casts dates into string format for entry into database. 551 if value is not None: 546 552 value = str(value) 547 553 return Field.get_db_prep_save(self, value) 548 554 … … 909 915 if value is not None: 910 916 # MySQL will throw a warning if microseconds are given, because it 911 917 # doesn't support microseconds. 918 settings = model_instance._default_manager.db.connection.settings 912 919 if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 913 920 value = value.replace(microsecond=0) 914 921 if settings.DATABASE_ENGINE == 'oracle': -
django/db/models/fields/related.py
=== django/db/models/fields/related.py ==================================================================
1 from django.db import backend,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, get_ul_class 4 4 from django.db.models.related import RelatedObject … … 318 318 # source_col_name: the PK colname in join_table for the source object 319 319 # target_col_name: the PK colname in join_table for the target object 320 320 # *objs - objects to add. Either object instances, or primary keys of object instances. 321 from django.db importconnection321 connection = self.model._default_manager.db.connection 322 322 323 323 # If there aren't any objects, there is nothing to do. 324 324 if objs: … … 343 343 cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \ 344 344 (self.join_table, source_col_name, target_col_name), 345 345 [self._pk_val, obj_id]) 346 transaction.commit_unless_managed()346 transaction.commit_unless_managed(connection) 347 347 348 348 def _remove_items(self, source_col_name, target_col_name, *objs): 349 349 # source_col_name: the PK colname in join_table for the source object 350 350 # target_col_name: the PK colname in join_table for the target object 351 351 # *objs - objects to remove 352 from django.db importconnection352 connection = self.model._default_manager.db.connection 353 353 354 354 # If there aren't any objects, there is nothing to do. 355 355 if objs: … … 366 366 (self.join_table, source_col_name, 367 367 target_col_name, ",".join(['%s'] * len(old_ids))), 368 368 [self._pk_val] + list(old_ids)) 369 transaction.commit_unless_managed()369 transaction.commit_unless_managed(connection) 370 370 371 371 def _clear_items(self, source_col_name): 372 372 # source_col_name: the PK colname in join_table for the source object 373 from django.db importconnection373 connection = self.model._default_manager.db.connection 374 374 cursor = connection.cursor() 375 375 cursor.execute("DELETE FROM %s WHERE %s = %%s" % \ 376 376 (self.join_table, source_col_name), 377 377 [self._pk_val]) 378 transaction.commit_unless_managed( )378 transaction.commit_unless_managed(connection) 379 379 380 380 return ManyRelatedManager 381 381 … … 399 399 superclass = rel_model._default_manager.__class__ 400 400 RelatedManager = create_many_related_manager(superclass) 401 401 402 qn = backend.quote_name402 qn = rel_model._default_manager.db.backend.quote_name 403 403 manager = RelatedManager( 404 404 model=rel_model, 405 405 core_filters={'%s__pk' % self.related.field.name: instance._get_pk_val()}, … … 440 440 superclass = rel_model._default_manager.__class__ 441 441 RelatedManager = create_many_related_manager(superclass) 442 442 443 qn = backend.quote_name443 qn = rel_model._default_manager.db.backend.quote_name 444 444 manager = RelatedManager( 445 445 model=rel_model, 446 446 core_filters={'%s__pk' % self.field.related_query_name(): instance._get_pk_val()}, -
django/db/models/query.py
=== django/db/models/query.py ==================================================================
182 182 # self._select is a dictionary, and dictionaries' key order is 183 183 # undefined, so we convert it to a list of tuples. 184 184 extra_select = self._select.items() 185 186 cursor = connection.cursor() 185 cursor = self.model._default_manager.db.connection.cursor() 187 186 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 188 187 189 188 fill_cache = self._select_related … … 217 216 """ 218 217 if self._result_cache is not None: 219 218 return len(self._result_cache) 220 219 #from multi-db 220 db = self.model._default_manager.db 221 backend = db.backend 222 connection = db.connection 223 221 224 counter = self._clone() 222 225 counter._order_by = () 223 226 counter._select_related = False … … 304 307 Returns a dictionary mapping each of the given IDs to the object with 305 308 that ID. 306 309 """ 310 backend = self.model._default_manager.db.backend 307 311 assert self._limit is None and self._offset is None, \ 308 312 "Cannot use 'limit' or 'offset' with in_bulk" 309 313 assert isinstance(id_list, (tuple, list)), "in_bulk() must be provided with a list of IDs." … … 481 485 482 486 def _get_sql_clause(self): 483 487 opts = self.model._meta 484 488 backend = self.model._default_manager.db.backend 489 qn = backend.quote_name 485 490 # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z. 486 select = ["%s.%s" % (backend.quote_name(opts.db_table), backend.quote_name(f.column)) for f in opts.fields] 491 select = ["%s.%s" % (qn(opts.db_table), qn(f.column)) 492 for f in opts.fields] 487 493 tables = [quote_only_if_word(t) for t in self._tables] 488 494 joins = SortedDict() 489 495 where = self._where[:] … … 504 510 505 511 # Add any additional SELECTs. 506 512 if self._select: 507 select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()]) 513 select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), qn(s[0])) 514 for s in self._select.items()]) 508 515 509 516 # Start composing the body of the SQL statement. 510 sql = [" FROM", backend.quote_name(opts.db_table)]517 sql = [" FROM", qn(opts.db_table)] 511 518 512 519 # Compose the join dictionary into SQL describing the joins. 513 520 if joins: … … 540 547 order = "ASC" 541 548 if "." in col_name: 542 549 table_prefix, col_name = col_name.split('.', 1) 543 table_prefix = backend.quote_name(table_prefix) + '.'550 table_prefix = qn(table_prefix) + '.' 544 551 else: 545 552 # Use the database table as a column prefix if it wasn't given, 546 553 # and if the requested column isn't a custom SELECT. 547 554 if "." not in col_name and col_name not in (self._select or ()): 548 table_prefix = backend.quote_name(opts.db_table) + '.'555 table_prefix = qn(opts.db_table) + '.' 549 556 else: 550 557 table_prefix = '' 551 order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order))558 order_by.append('%s%s %s' % (table_prefix, qn(orderfield2column(col_name, opts)), order)) 552 559 if order_by: 553 560 sql.append("ORDER BY " + ", ".join(order_by)) 554 561 … … 597 604 598 605 columns = [f.column for f in fields] 599 606 select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns] 607 608 #from multi-db 609 db = self.model._default_manager.db 610 backend = db.backend 611 qn = backend.quote_name 612 connection = db.connection 613 600 614 # Add any additional SELECTs. 601 615 if self._select: 602 616 select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()]) 603 617 604 618 cursor = connection.cursor() 619 select = ['%s.%s' % (qn(self.model._meta.db_table), qn(c)) 620 for c in columns] 605 621 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 606 622 607 623 has_resolve_columns = hasattr(self, 'resolve_columns') … … 623 639 def iterator(self): 624 640 from django.db.backends.util import typecast_timestamp 625 641 from django.db.models.fields import DateTimeField 642 db = self.model._default_manager.db 643 backend = db.backend 644 qn = backend.quote_name 645 connection = db.connection 646 626 647 self._order_by = () # Clear this because it'll mess things up otherwise. 627 648 if self._field.null: 628 649 self._where.append('%s.%s IS NOT NULL' % \ 629 (backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column))) 650 (qn(self.model._meta.db_table), qn(self._field.column))) 651 630 652 try: 631 653 select, sql, params = self._get_sql_clause() 632 654 except EmptyResultSet: 633 655 raise StopIteration 634 656 635 table_name = backend.quote_name(self.model._meta.db_table)636 field_name = backend.quote_name(self._field.column)657 table_name = qn(self.model._meta.db_table) 658 field_name = qn(self._field.column) 637 659 638 660 if backend.allows_group_by_ordinal: 639 661 group_by = '1' … … 768 790 return SortedDict(), [], [] 769 791 return joins, where2, params 770 792 771 def get_where_clause(lookup_type, table_prefix, field_name, value): 793 def get_where_clause(opts, lookup_type, table_prefix, field_name, value): 794 backend = opts.get_default_manager().db.backend 795 qn = backend.quote_name 796 772 797 if table_prefix.endswith('.'): 773 table_prefix = backend.quote_name(table_prefix[:-1])+'.'774 field_name = backend.quote_name(field_name)798 table_prefix = qn(table_prefix[:-1])+'.' 799 field_name = qn(field_name) 775 800 if type(value) == datetime.datetime and backend.get_datetime_cast_sql(): 776 801 cast_sql = backend.get_datetime_cast_sql() 777 802 else: … … 832 857 Helper function that recursively populates the select, tables and where (in 833 858 place) for select_related queries. 834 859 """ 860 qn = opts.get_default_manager().db.backend.quote_name 835 861 836 862 # If we've got a max_depth set and we've exceeded that depth, bail now. 837 863 if max_depth and cur_depth > max_depth: 838 864 return None 839 865 840 qn = backend.quote_name841 866 for f in opts.fields: 842 867 if f.rel and not f.null: 843 868 db_table = f.rel.to._meta.db_table … … 935 960 return choices 936 961 937 962 def lookup_inner(path, lookup_type, value, opts, table, column): 938 qn = backend.quote_name939 963 joins, where, params = SortedDict(), [], [] 940 964 current_opts = opts 941 965 current_table = table 942 966 current_column = column 943 967 intermediate_table = None 944 968 join_required = False 969 db = current_opts.get_default_manager().db 970 backend = db.backend 971 connection = db.connection 972 qn = backend.quote_name 945 973 946 974 name = path.pop(0) 947 975 # Has the primary key been requested? If so, expand it out … … 1092 1120 # Last query term was a normal field. 1093 1121 column = field.column 1094 1122 1095 where.append(get_where_clause( lookup_type, current_table + '.', column, value))1123 where.append(get_where_clause(current_opts, lookup_type, current_table + '.', column, value)) 1096 1124 params.extend(field.get_db_prep_lookup(lookup_type, value)) 1097 1125 1098 1126 return joins, where, params 1099 1127 1100 1128 def delete_objects(seen_objs): 1101 1129 "Iterate through a list of seen classes, and remove any instances that are referred to" 1102 qn = backend.quote_name1103 1130 ordered_classes = seen_objs.keys() 1104 1131 ordered_classes.reverse() 1105 1132 1106 cursor = connection.cursor()1107 1108 1133 for cls in ordered_classes: 1134 db = cls._default_manager.db 1135 backend = db.backend 1136 connection = db.connection 1137 cursor = connection.cursor() 1138 qn = backend.quote_name 1139 1109 1140 seen_objs[cls] = seen_objs[cls].items() 1110 1141 seen_objs[cls].sort() 1111 1142 … … 1144 1175 pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE]) 1145 1176 1146 1177 # Now delete the actual data 1178 dirty_conns = [] 1147 1179 for cls in ordered_classes: 1180 1181 db = cls._default_manager.db 1182 backend = db.backend 1183 connection = db.connection 1184 qn = backend.quote_name 1185 cursor = connection.cursor() 1186 if connection not in dirty_conns: 1187 dirty_conns.append(connection) 1188 1148 1189 seen_objs[cls].reverse() 1149 1190 pk_list = [pk for pk,instance in seen_objs[cls]] 1150 1191 for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): … … 1163 1204 setattr(instance, cls._meta.pk.attname, None) 1164 1205 dispatcher.send(signal=signals.post_delete, sender=cls, instance=instance) 1165 1206 1166 transaction.commit_unless_managed( )1207 transaction.commit_unless_managed(dirty_conns) -
django/db/__init__.py
=== django/db/__init__.py ==================================================================
1 from django.conf import settings 1 from django.conf import settings, UserSettingsHolder 2 2 from django.core import signals 3 from django.core.exceptions import ImproperlyConfigured 3 4 from django.dispatch import dispatcher 4 5 6 try: 7 # Only exists in Python 2.4+ 8 from threading import local 9 except ImportError: 10 # Import copy of _thread_local.py from Python 2.4 11 from django.utils._threading_local import local 12 5 13 __all__ = ('backend', 'connection', 'DatabaseError', 'IntegrityError') 6 14 15 16 # singleton to represent the default connection in connections 17 class dummy(object): 18 def __repr__(self): 19 return self.__str__() 20 def __str__(self): 21 return '<default>' 22 _default = dummy() 23 del dummy 24 25 26 # storage for local default connection 27 _local = local() 28 29 7 30 if not settings.DATABASE_ENGINE: 8 31 settings.DATABASE_ENGINE = 'dummy' 32 9 33 10 try: 11 backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, {}, {}, ['']) 12 except ImportError, e: 13 # The database backend wasn't found. Display a helpful error message 14 # listing all possible database backends. 15 from django.core.exceptions import ImproperlyConfigured 16 import os 17 backend_dir = os.path.join(__path__[0], 'backends') 18 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')] 19 available_backends.sort() 20 if settings.DATABASE_ENGINE not in available_backends: 21 raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \ 22 (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends))) 23 else: 24 raise # If there's some other error, this must be an error in Django itself. 34 def connect(settings, **kw): 35 """Connect to the database specified in settings. Returns a 36 ConnectionInfo on success, raises ImproperlyConfigured if the 37 settings don't specify a valid database connection. 38 """ 39 return ConnectionInfo(settings, **kw) 25 40 26 get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, {}, {}, ['']) 27 get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, {}, {}, ['']) 28 runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, {}, {}, ['']).runshell() 41 42 class ConnectionInfo(object): 43 """Encapsulates all information about a connection and the backend 44 to which it belongs. Provides methods for loading backend 45 creation, introspection, and shell modules, closing the 46 connection, and resetting the connection's query log. 47 """ 48 def __init__(self, settings=None, **kw): 49 super(ConnectionInfo, self).__init__(**kw) 50 if settings is None: 51 from django.conf import settings 52 if not settings.DATABASE_OPTIONS: 53 settings.DATABASE_OPTIONS = {} 54 self.settings = settings 55 self.backend = self.load_backend() 56 self.connection = self.backend.DatabaseWrapper(settings) 57 self.DatabaseError = self.backend.DatabaseError 29 58 30 connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) 31 DatabaseError = backend.DatabaseError 59 # Register an event that closes the database connection 60 # when a Django request is finished. 61 dispatcher.connect(self.close, signal=signals.request_finished) 62 63 # Register an event that resets connection.queries 64 # when a Django request is started. 65 dispatcher.connect(self.reset_queries, signal=signals.request_started) 66 67 def __repr__(self): 68 return "Connection: %r (ENGINE=%s NAME=%s)" \ 69 % (self.connection, 70 self.settings.DATABASE_ENGINE, 71 self.settings.DATABASE_NAME) 72 73 def close(self): 74 """Close connection""" 75 self.connection.close() 76 77 def get_introspection_module(self): 78 return __import__('django.db.backends.%s.introspection' % 79 self.settings.DATABASE_ENGINE, {}, {}, ['']) 80 81 def get_creation_module(self): 82 return __import__('django.db.backends.%s.creation' % 83 self.settings.DATABASE_ENGINE, {}, {}, ['']) 84 85 def load_backend(self): 86 try: 87 backend = __import__('django.db.backends.%s.base' % 88 self.settings.DATABASE_ENGINE, {}, {}, ['']) 89 except ImportError, e: 90 # The database backend wasn't found. Display a helpful error 91 # message listing all possible database backends. 92 import os 93 backend_dir = os.path.join(__path__[0], 'backends') 94 available_backends = [f for f in os.listdir(backend_dir) 95 if not f.startswith('_') \ 96 and not f.startswith('.') \ 97 and not f.endswith('.py') \ 98 and not f.endswith('.pyc')] 99 available_backends.sort() 100 if self.settings.DATABASE_ENGINE not in available_backends: 101 raise ImproperlyConfigured, \ 102 "%r isn't an available database backend. "\ 103 "Available options are: %s" % \ 104 (self.settings.DATABASE_ENGINE, 105 ", ".join(map(repr, available_backends))) 106 else: 107 # If there's some other error, this must be an error 108 # in Django itself. 109 raise 110 return backend 111 112 def runshell(self): 113 __import__('django.db.backends.%s.client' % 114 self.settings.DATABASE_ENGINE, {}, {}, [''] 115 ).runshell(self.settings) 116 117 118 119 def reset_queries(self): 120 """Reset log of queries executed by connection""" 121 self.connection.queries = [] 122 123 124 class LazyConnectionManager(object): 125 """Manages named connections lazily, instantiating them as 126 they are requested. 127 """ 128 def __init__(self): 129 self.local = local() 130 self.local.connections = {} 131 132 # Reset connections on request finish, to make sure each request can 133 # load the correct connections for its settings 134 dispatcher.connect(self.reset, signal=signals.request_finished) 135 136 def __iter__(self): 137 # Iterates only over *active* connections, not all possible 138 # connections 139 return iter(self.local.connections.keys()) 140 141 def __getattr__(self, attr): 142 return getattr(self.local.connections, attr) 143 144 def __getitem__(self, k): 145 try: 146 return self.local.connections[k] 147 except (AttributeError, KeyError): 148 return self.connect(k) 149 150 def __setitem__(self, k, v): 151 try: 152 self.local.connections[k] = v 153 except AttributeError: 154 # First access in thread 155 self.local.connections = {k: v} 156 157 def connect(self, name): 158 """Return the connection with this name in 159 settings.OTHER_DATABASES. Creates the connection if it doesn't yet 160 exist. Reconnects if it does. If the name requested is the default 161 connection (a singleton defined in django.db), then the default 162 connection is returned. 163 """ 164 try: 165 cnx = self.local.connections 166 except AttributeError: 167 cnx = self.local.connections = {} 168 169 if name in cnx: 170 cnx[name].close() 171 if name is _default: 172 cnx[name] = connect(settings) 173 return cnx[name] 174 try: 175 info = settings.OTHER_DATABASES[name] 176 except KeyError: 177 raise ImproperlyConfigured, \ 178 "No database connection '%s' has been configured" % name 179 except AttributeError: 180 raise ImproperlyConfigured, \ 181 "No OTHER_DATABASES in settings." 182 183 # In settings it's a dict, but connect() needs an object: 184 # pass global settings so that the default connection settings 185 # can be defaults for the named connections. 186 database = UserSettingsHolder(settings) 187 for k, v in info.items(): 188 setattr(database, k, v) 189 cnx[name] = connect(database) 190 return cnx[name] 191 192 def items(self): 193 # Iterates over *all possible* connections 194 items = [] 195 for key in self.keys(): 196 items.append((key, self[key])) 197 return items 198 199 def keys(self): 200 # Iterates over *all possible* connections 201 keys = [_default] 202 try: 203 keys.extend(settings.OTHER_DATABASES.keys()) 204 except AttributeError: 205 pass 206 return keys 207 208 def reset(self): 209 if not hasattr(self.local, 'connections'): 210 return 211 self.local.connections = {} 212 213 def model_connection_name(klass): 214 """Get the connection name that a model is configured to use, with the 215 current settings. 216 """ 217 app = klass._meta.app_label 218 model = klass.__name__ 219 app_model = "%s.%s" % (app, model) 220 221 # Quick exit if no OTHER_DATABASES defined 222 if (not hasattr(settings, 'OTHER_DATABASES') 223 or not settings.OTHER_DATABASES): 224 return _default 225 # Look in MODELS for the best match: app_label.Model. If that isn't 226 # found, take just app_label. If nothing is found, use the default 227 maybe = None 228 for name, db_def in settings.OTHER_DATABASES.items(): 229 if not 'MODELS' in db_def: 230 continue 231 mods = db_def['MODELS'] 232 # Can't get a better match than this 233 if app_model in mods: 234 return name 235 elif app in mods: 236 if maybe is not None: 237 raise ImproperlyConfigured, \ 238 "App %s appears in more than one OTHER_DATABASES " \ 239 "setting (%s and %s)" % (maybe, name) 240 maybe = name 241 if maybe: 242 return maybe 243 # No named connection for this model; use the default 244 return _default 245 246 247 class ConnectionInfoDescriptor(object): 248 """Descriptor used to access database connection information from a 249 manager or other connection holder. Keeps a thread-local cache of 250 connections per instance, and always returns the same connection for an 251 instance in particular thread during a particular request. 252 253 Any object that includes a ``model`` attribute that holds a model class 254 can use this descriptor to manage connections. 255 """ 256 257 def __init__(self): 258 self.local = local() 259 self.local.cnx = {} 260 dispatcher.connect(self.reset, signal=signals.request_finished) 261 262 def __get__(self, instance, type=None): 263 if instance is None: 264 raise AttributeError, \ 265 "ConnectionInfo is accessible only through an instance" 266 try: 267 instance_connection = self.local.cnx.get(instance, None) 268 except AttributeError: 269 # First access in this thread 270 self.local.cnx = {} 271 instance_connection = None 272 if instance_connection is None: 273 instance_connection = self.get_connection(instance) 274 self.local.cnx[instance] = instance_connection 275 return instance_connection 276 277 def __set__(self, instance, value): 278 try: 279 self.local.cnx[instance] = value 280 except AttributeError: 281 # First access in thread 282 self.local.cnx = {instance: value} 283 284 def __delete__(self, instance): 285 try: 286 del self.local.cnx[instance] 287 except (AttributeError, KeyError): 288 # Not stored, no need to reset 289 pass 290 291 def get_connection(self, instance): 292 return connections[model_connection_name(instance.model)] 293 294 def reset(self): 295 if not hasattr(self.local, 'cnx'): 296 return 297 self.local.cnx = {} 298 299 class LocalizingProxy: 300 """A lazy-initializing proxy. The proxied object is not 301 initialized until the first attempt to access it. This is used to 302 attach module-level properties to local storage. 303 """ 304 def __init__(self, name, storage, func, *arg, **kw): 305 self.__name = name 306 self.__storage = storage 307 self.__func = func 308 self.__arg = arg 309 self.__kw = kw 310 311 # We need to clear out this thread's storage at the end of each 312 # request, in case new settings are loaded with the next 313 def reset(stor=storage, name=name): 314 if hasattr(stor, name): 315 delattr(stor, name) 316 dispatcher.connect(reset, signal=signals.request_finished) 317 318 def __getattr__(self, attr): 319 # Private (__*) attributes are munged 320 if attr.startswith('_LocalizingProxy'): 321 return self.__dict__[attr] 322 try: 323 return getattr(getattr(self.__storage, self.__name), attr) 324 except AttributeError: 325 setattr(self.__storage, self.__name, self.__func(*self.__arg, 326 **self.__kw)) 327 return getattr(getattr(self.__storage, self.__name), attr) 328 329 def __setattr__(self, attr, val): 330 # Private (__*) attributes are munged 331 if attr.startswith('_LocalizingProxy'): 332 self.__dict__[attr] = val 333 return 334 try: 335 stor = getattr(self.__storage, self.__name) 336 except AttributeError: 337 stor = self.__func(*self.__arg) 338 setattr(self.__storage, self.__name, stor) 339 setattr(stor, attr, val) 340 341 342 # Create a manager for named connections 343 connections = LazyConnectionManager() 344 345 # Backwards compatibility: establish the default connection and set the 346 # default connection properties at module level, using the lazy proxy so that 347 # each thread may have a different default connection, if so configured 348 connection_info = LocalizingProxy('connection_info', _local, 349 lambda: connections[_default]) 350 connection = LocalizingProxy('connection', _local, 351 lambda: connections[_default].connection) 352 backend = LocalizingProxy('backend', _local, 353 lambda: connections[_default].backend) 354 DatabaseError = LocalizingProxy('DatabaseError', _local, 355 lambda: connections[_default].DatabaseError) 356 #================================BUG==Might need LocalizingProxy============== 32 357 IntegrityError = backend.IntegrityError 358 get_introspection_module = LocalizingProxy( 359 'get_introspection_module', _local, 360 lambda: connections[_default].get_introspection_module) 361 get_creation_module = LocalizingProxy( 362 'get_creation_module', _local, 363 lambda: connections[_default].get_creation_module) 364 runshell = LocalizingProxy('runshell', _local, 365 lambda: connections[_default].runshell) 33 366 34 # Register an event that closes the database connection35 # when a Django request is finished.36 dispatcher.connect(connection.close, signal=signals.request_finished)37 367 38 # Register an event that resets connection.queries 39 # when a Django request is started. 40 def reset_queries(): 41 connection.queries = [] 42 dispatcher.connect(reset_queries, signal=signals.request_started) 43 44 # Register an event that rolls back the connection 368 # Register an event that rolls back all connections 45 369 # when a Django request has an exception. 46 370 def _rollback_on_exception(): 47 371 from django.db import transaction 48 372 transaction.rollback_unless_managed() 49 dispatcher.connect(_rollback_on_exception, signal=signals.got_request_exception) 373 dispatcher.connect(_rollback_on_exception, 374 signal=signals.got_request_exception) 375 376 -
django/db/backends/ado_mssql/base.py
=== django/db/backends/ado_mssql/base.py ==================================================================
48 48 return res 49 49 Database.convertVariantToPython = variantToPython 50 50 51 try: 52 # Only exists in Python 2.4+ 53 from threading import local 54 except ImportError: 55 # Import copy of _thread_local.py from Python 2.4 56 from django.utils._threading_local import local 57 58 class DatabaseWrapper(local): 59 def __init__(self, **kwargs): 51 class DatabaseWrapper(object): 52 def __init__(self, settings): 53 self.settings = settings 54 self.options = settings.DATABASE_OPTIONS 60 55 self.connection = None 61 56 self.queries = [] 62 57 63 58 def cursor(self): 64 from django.conf importsettings59 settings = self.settings 65 60 if self.connection is None: 66 61 if settings.DATABASE_NAME == '' or settings.DATABASE_USER == '': 67 62 from django.core.exceptions import ImproperlyConfigured … … 95 90 needs_datetime_string_cast = True 96 91 needs_upper_for_iops = False 97 92 supports_constraints = True 93 supports_compound_statements = True 98 94 supports_tablespaces = True 99 95 uses_case_insensitive_names = False 100 96 -
django/db/backends/ado_mssql/client.py
=== django/db/backends/ado_mssql/client.py ==================================================================
1 def runshell( ):1 def runshell(settings): 2 2 raise NotImplementedError -
django/db/backends/ado_mssql/creation.py
=== django/db/backends/ado_mssql/creation.py ==================================================================
1 from django.db.backends.ansi import sql 2 builder = sql.SchemaBuilder() 3 1 4 DATA_TYPES = { 2 5 'AutoField': 'int IDENTITY (1, 1)', 3 6 'BooleanField': 'bit', -
django/db/backends/postgresql/base.py
=== django/db/backends/postgresql/base.py ==================================================================
14 14 DatabaseError = Database.DatabaseError 15 15 IntegrityError = Database.IntegrityError 16 16 17 try: 18 # Only exists in Python 2.4+ 19 from threading import local 20 except ImportError: 21 # Import copy of _thread_local.py from Python 2.4 22 from django.utils._threading_local import local 23 17 class DatabaseWrapper(object): 18 def __init__(self, settings): 19 self.settings = settings 24 20 def smart_basestring(s, charset): 25 21 if isinstance(s, unicode): 26 22 return s.encode(charset) … … 55 51 56 52 postgres_version = None 57 53 58 class DatabaseWrapper(local):59 def __init__(self, **kwargs):60 54 self.connection = None 61 55 self.queries = [] 62 self.options = kwargs56 self.options = settings.DATABASE_OPTIONS 63 57 64 58 def cursor(self): 65 from django.conf importsettings59 settings = self.settings 66 60 set_tz = False 67 61 if self.connection is None: 68 62 set_tz = True … … 111 105 needs_datetime_string_cast = True 112 106 needs_upper_for_iops = False 113 107 supports_constraints = True 108 supports_compound_statements = True 114 109 supports_tablespaces = False 115 110 uses_case_insensitive_names = False 116 111 -
django/db/backends/postgresql/client.py
=== django/db/backends/postgresql/client.py ==================================================================
1 from django.conf import settings2 1 import os 3 2 4 def runshell( ):3 def runshell(settings): 5 4 args = ['psql'] 6 5 if settings.DATABASE_USER: 7 6 args += ["-U", settings.DATABASE_USER] -
django/db/backends/postgresql/sql.py
=== django/db/backends/postgresql/sql.py ==================================================================
1 from django.db import models 2 from django.db.backends.ansi.sql import BoundStatement, SchemaBuilder, \ 3 default_style 4 5 class PgSchemaBuilder(SchemaBuilder): 6 """SchemaBuilder for postgres. Implements an additional method that 7 outputs SQL statements to reset the sequence(s) for a model. 8 """ 9 def get_sequence_reset(self, model, style=None): 10 """Get sequence reset sql for a model. 11 """ 12 if style is None: 13 style=default_style 14 for f in model._meta.fields: 15 output = [] 16 db = model._default_manager.db 17 connection = db.connection 18 qn = db.backend.quote_name 19 if isinstance(f, models.AutoField): 20 output.append(BoundStatement( 21 "%s setval('%s', (%s max(%s) %s %s));" % \ 22 (style.SQL_KEYWORD('SELECT'), 23 style.SQL_FIELD('%s_%s_seq' % 24 (model._meta.db_table, f.column)), 25 style.SQL_KEYWORD('SELECT'), 26 style.SQL_FIELD(qn(f.column)), 27 style.SQL_KEYWORD('FROM'), 28 style.SQL_TABLE(qn(model._meta.db_table))), 29 connection)) 30 break # Only one AutoField is allowed per model, so don't bother continuing. 31 for f in model._meta.many_to_many: 32 output.append( 33 BoundStatement("%s setval('%s', (%s max(%s) %s %s));" % \ 34 (style.SQL_KEYWORD('SELECT'), 35 style.SQL_FIELD('%s_id_seq' % f.m2m_db_table()), 36 style.SQL_KEYWORD('SELECT'), 37 style.SQL_FIELD(qn('id')), 38 style.SQL_KEYWORD('FROM'), 39 style.SQL_TABLE(f.m2m_db_table())), 40 connection)) 41 return output -
django/db/backends/postgresql/creation.py
=== django/db/backends/postgresql/creation.py ==================================================================
1 from django.db.backends.postgresql import sql 2 builder = sql.PgSchemaBuilder() 3 1 4 # This dictionary maps Field objects to their associated PostgreSQL column 2 5 # types, as strings. Column-type strings can contain format strings; they'll 3 6 # be interpolated against the values of Field.__dict__ before being output. -
django/db/backends/sqlite3/base.py
=== django/db/backends/sqlite3/base.py ==================================================================
50 50 from django.utils._threading_local import local 51 51 52 52 class DatabaseWrapper(local): 53 def __init__(self, **kwargs): 53 def __init__(self, settings): 54 self.settings = settings 54 55 self.connection = None 55 56 self.queries = [] 56 self.options = kwargs57 self.options = settings.DATABASE_OPTIONS 57 58 58 59 def cursor(self): 59 from django.conf importsettings60 settings = self.settings 60 61 if self.connection is None: 61 62 kwargs = { 62 63 'database': settings.DATABASE_NAME, … … 114 115 needs_datetime_string_cast = True 115 116 needs_upper_for_iops = False 116 117 supports_constraints = False 118 supports_compound_statements = False 117 119 supports_tablespaces = False 118 120 uses_case_insensitive_names = False 119 121 -
django/db/backends/sqlite3/client.py
=== django/db/backends/sqlite3/client.py ==================================================================
1 from django.conf import settings2 1 import os 3 2 4 def runshell( ):3 def runshell(settings): 5 4 args = ['', settings.DATABASE_NAME] 6 5 os.execvp('sqlite3', args) -
django/db/backends/sqlite3/creation.py
=== django/db/backends/sqlite3/creation.py ==================================================================
1 from django.db.backends.ansi import sql 2 builder = sql.SchemaBuilder() 3 1 4 # SQLite doesn't actually support most of these types, but it "does the right 2 5 # thing" given more verbose field definitions, so leave them as is so that 3 6 # schema inspection is more useful. -
django/db/backends/mysql/base.py
=== django/db/backends/mysql/base.py ==================================================================
53 53 # standard util.CursorDebugWrapper can be used. Also, using sql_mode 54 54 # TRADITIONAL will automatically cause most warnings to be treated as errors. 55 55 56 try:57 # Only exists in Python 2.4+58 from threading import local59 except ImportError:60 # Import copy of _thread_local.py from Python 2.461 from django.utils._threading_local import local62 56 63 class DatabaseWrapper(local): 64 def __init__(self, **kwargs): 57 class DatabaseWrapper(object): 58 def __init__(self, settings): 59 self.settings = settings 65 60 self.connection = None 66 61 self.queries = [] 67 62 self.server_version = None 68 self.options = kwargs63 self.options = settings.DATABASE_OPTIONS 69 64 70 65 def _valid_connection(self): 71 66 if self.connection is not None: … … 78 73 return False 79 74 80 75 def cursor(self): 81 from django.conf importsettings76 settings = self.settings 82 77 from warnings import filterwarnings 83 78 if not self._valid_connection(): 84 79 kwargs = { … … 140 135 needs_datetime_string_cast = True # MySQLdb requires a typecast for dates 141 136 needs_upper_for_iops = False 142 137 supports_constraints = True 138 supports_compound_statements = True 143 139 supports_tablespaces = False 144 140 uses_case_insensitive_names = False 145 141 -
django/db/backends/mysql/client.py
=== django/db/backends/mysql/client.py ==================================================================
1 from django.conf import settings2 1 import os 3 2 4 def runshell( ):3 def runshell(settings): 5 4 args = [''] 6 5 db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME) 7 6 user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER) -
django/db/backends/mysql/creation.py
=== django/db/backends/mysql/creation.py ==================================================================
1 from django.db.backends.ansi import sql 2 builder = sql.SchemaBuilder() 3 1 4 # This dictionary maps Field objects to their associated MySQL column 2 5 # types, as strings. Column-type strings can contain format strings; they'll 3 6 # be interpolated against the values of Field.__dict__ before being output. -
django/db/backends/oracle/base.py
=== django/db/backends/oracle/base.py ==================================================================
18 18 DatabaseError = Database.Error 19 19 IntegrityError = Database.IntegrityError 20 20 21 try: 22 # Only exists in Python 2.4+ 23 from threading import local 24 except ImportError: 25 # Import copy of _thread_local.py from Python 2.4 26 from django.utils._threading_local import local 27 28 class DatabaseWrapper(local): 29 def __init__(self, **kwargs): 21 class DatabaseWrapper(object): 22 def __init__(self, settings): 23 self.settings = settings 30 24 self.connection = None 31 25 self.queries = [] 32 self.options = kwargs26 self.options = settings.DATABASE_OPTIONS 33 27 34 28 def _valid_connection(self): 35 29 return self.connection is not None 36 30 37 31 def cursor(self): 32 settings = self.settings 38 33 if not self._valid_connection(): 39 34 if len(settings.DATABASE_HOST.strip()) == 0: 40 35 settings.DATABASE_HOST = 'localhost' … … 73 68 needs_datetime_string_cast = False 74 69 needs_upper_for_iops = True 75 70 supports_constraints = True 71 supports_compound_statements = True 76 72 supports_tablespaces = True 77 73 uses_case_insensitive_names = True 78 74 -
django/db/backends/oracle/client.py
=== django/db/backends/oracle/client.py ==================================================================
1 from django.conf import settings2 1 import os 3 2 4 def runshell( ):3 def runshell(settings): 5 4 dsn = settings.DATABASE_USER 6 5 if settings.DATABASE_PASSWORD: 7 6 dsn += "/%s" % settings.DATABASE_PASSWORD -
django/db/backends/postgresql_psycopg2/base.py
=== django/db/backends/postgresql_psycopg2/base.py ==================================================================
24 24 postgres_version = None 25 25 26 26 class DatabaseWrapper(local): 27 def __init__(self, **kwargs): 27 def __init__(self, settings): 28 self.settings = settings 28 29 self.connection = None 29 30 self.queries = [] 30 self.options = kwargs31 self.options = settings.DATABASE_OPTIONS 31 32 32 33 def cursor(self): 33 from django.conf importsettings34 settings = self.settings 34 35 set_tz = False 35 36 if self.connection is None: 36 37 set_tz = True … … 79 80 needs_datetime_string_cast = False 80 81 needs_upper_for_iops = False 81 82 supports_constraints = True 83 supports_compound_statements = True 82 84 supports_tablespaces = False 83 85 uses_case_insensitive_names = False 84 86 -
django/db/backends/ansi/__init__.py
=== django/db/backends/ansi/__init__.py ==================================================================
1 pass -
django/db/backends/ansi/sql.py
=== django/db/backends/ansi/sql.py ==================================================================
1 """ANSISQL schema manipulation functions and classes 2 """ 3 import os 4 import re 5 from django.db import models 6 from django.contrib.contenttypes import generic 7 8 # For Python 2.3 9 if not hasattr(__builtins__, 'set'): 10 from sets import Set as set 11 12 # default dummy style 13 class dummy: 14 def __getattr__(self, attr): 15 return lambda x: x 16 default_style = dummy() 17 del dummy 18 19 class BoundStatement(object): 20 """Represents an SQL statement that is to be executed, at some point in 21 the future, using a specific database connection. 22 """ 23 def __init__(self, sql, connection): 24 self.sql = sql 25 self.connection = connection 26 27 def execute(self): 28 cursor = self.connection.cursor() 29 cursor.execute(self.sql) 30 31 def __repr__(self): 32 return "BoundStatement(%r)" % self.sql 33 34 def __str__(self): 35 return self.sql 36 37 def __eq__(self, other): 38 return self.sql == other.sql and self.connection == other.connection 39 40 class SchemaBuilder(object): 41 """Basic ANSI SQL schema element builder. Instances of this class may be 42 used to construct SQL expressions that create or drop schema elements such 43 as tables, indexes and (for those backends that support them) foreign key 44 or other constraints. 45 """ 46 def __init__(self): 47 # models that I have created 48 self.models_already_seen = set() 49 # model references, keyed by the referrent model 50 self.references = {} 51 # table cache; set to short-circuit table lookups 52 self.tables = None 53 54 def get_create_table(self, model, style=None, pending=None): 55 """Construct and return the SQL expression(s) needed to create the 56 table for the given model, and any constraints on that 57 table. The return value is a 2-tuple. The first element of the tuple 58 is a list of BoundStatements that may be executed immediately. The 59 second is a dict of BoundStatements representing constraints that 60 can't be executed immediately because (for instance) the referent 61 table does not exist, keyed by the model class they reference. 62 """ 63 if style is None: 64 style = default_style 65 if pending is None: 66 pending = {} 67 self.models_already_seen.add(model) 68 69 opts = model._meta 70 db = model._default_manager.db 71 backend = db.backend 72 quote_name = backend.quote_name 73 data_types = db.get_creation_module().DATA_TYPES 74 table_output = [] 75 76 for f in opts.fields: 77 if isinstance(f, (models.ForeignKey, models.OneToOneField)): 78 rel_field = f.rel.get_related_field() 79 data_type = self.get_rel_data_type(rel_field) 80 else: 81 rel_field = f 82 data_type = f.get_internal_type() 83 col_type = data_types[data_type] 84 if col_type is not None: 85 # Make the definition (e.g. 'foo VARCHAR(30)') for this field. 86 field_output = [style.SQL_FIELD(quote_name(f.column)), 87 style.SQL_COLTYPE(col_type % rel_field.__dict__)] 88 field_output.append(style.SQL_KEYWORD( 89 '%sNULL' % (not f.null and 'NOT ' or ''))) 90 if f.unique: 91 field_output.append(style.SQL_KEYWORD('UNIQUE')) 92 if f.primary_key: 93 field_output.append(style.SQL_KEYWORD('PRIMARY KEY')) 94 if f.rel: 95 if f.rel.to in self.models_already_seen: 96 field_output.append( 97 style.SQL_KEYWORD('REFERENCES') + ' ' + 98 style.SQL_TABLE( 99 quote_name(f.rel.to._meta.db_table)) + ' (' + 100 style.SQL_FIELD( 101 quote_name(f.rel.to._meta.get_field( 102 f.rel.field_name).column)) + ')' 103 ) 104 else: 105 # We haven't yet created the table to which this field 106 # is related, so save it for later. 107 if backend.supports_constraints: 108 pending.setdefault(f.rel.to, []).append((model, f)) 109 table_output.append(' '.join(field_output)) 110 if opts.order_with_respect_to: 111 table_output.append(style.SQL_FIELD(quote_name('_order')) + ' ' + \ 112 style.SQL_COLTYPE(data_types['IntegerField']) + ' ' + \ 113 style.SQL_KEYWORD('NULL')) 114 for field_constraints in opts.unique_together: 115 table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \ 116 ", ".join([quote_name(style.SQL_FIELD( 117 opts.get_field(f).column)) 118 for f in field_constraints])) 119 120 full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + 121 style.SQL_TABLE(quote_name(opts.db_table)) + ' ('] 122 for i, line in enumerate(table_output): # Combine and add commas. 123 full_statement.append(' %s%s' % 124 (line, i < len(table_output)-1 and ',' or '')) 125 full_statement.append(');') 126 create = [BoundStatement('\n'.join(full_statement), db.connection)] 127 128 # Pull out any pending statements for me 129 if pending: 130 if model in pending: 131 for rel_class, f in pending[model]: 132 create.append(self.get_ref_sql(model, rel_class, f, 133 style=style)) 134 # What was pending for me is now no longer pending 135 pending.pop(model) 136 return (create, pending) 137 138 def get_create_indexes(self, model, style=None): 139 """Construct and return SQL statements needed to create the indexes for 140 a model. Returns a list of BoundStatements. 141 """ 142 if style is None: 143 style = default_style 144 db = model._default_manager.db 145 backend = db.backend 146 connection = db.connection 147 output = [] 148 for f in model._meta.fields: 149 if f.db_index: 150 unique = f.unique and 'UNIQUE ' or '' 151 output.append( 152 BoundStatement( 153 ' '.join( 154 [style.SQL_KEYWORD('CREATE %sINDEX' % unique), 155 style.SQL_TABLE('%s_%s' % 156 (model._meta.db_table, f.column)), 157 style.SQL_KEYWORD('ON'), 158 style.SQL_TABLE( 159 backend.quote_name(model._meta.db_table)), 160 "(%s);" % style.SQL_FIELD( 161 backend.quote_name(f.column))]), 162 connection) 163 ) 164 return output 165 166 def get_create_many_to_many(self, model, style=None): 167 """Construct and return SQL statements needed to create the 168 tables and relationships for all many-to-many relations 169 defined in the model. Returns a list of bound statments. Note 170 that these statements should only be executed after all models 171 for an app have been created. 172 """ 173 if style is None: 174 style = default_style 175 db = model._default_manager.db 176 quote_name = db.backend.quote_name 177 connection = db.connection 178 data_types = db.get_creation_module().DATA_TYPES 179 opts = model._meta 180 181 # statements to execute, keyed by the other model 182 output = {} 183 for f in opts.many_to_many: 184 if not isinstance(f.rel, generic.GenericRel): 185 table_output = [ 186 style.SQL_KEYWORD('CREATE TABLE') + ' ' + \ 187 style.SQL_TABLE(quote_name(f.m2m_db_table())) + ' ('] 188 table_output.append(' %s %s %s,' % \ 189 (style.SQL_FIELD(quote_name('id')), 190 style.SQL_COLTYPE(data_types['AutoField']), 191 style.SQL_KEYWORD('NOT NULL PRIMARY KEY'))) 192 table_output.append(' %s %s %s %s (%s),' % \ 193 (style.SQL_FIELD(quote_name(f.m2m_column_name())), 194 style.SQL_COLTYPE(data_types[self.get_rel_data_type(opts.pk)] % opts.pk.__dict__), 195 style.SQL_KEYWORD('NOT NULL REFERENCES'), 196 style.SQL_TABLE(quote_name(opts.db_table)), 197 style.SQL_FIELD(quote_name(opts.pk.column)))) 198 table_output.append(' %s %s %s %s (%s),' % \ 199 (style.SQL_FIELD(quote_name(f.m2m_reverse_name())), 200 style.SQL_COLTYPE(data_types[self.get_rel_data_type(f.rel.to._meta.pk)] % f.rel.to._meta.pk.__dict__), 201 style.SQL_KEYWORD('NOT NULL REFERENCES'), 202 style.SQL_TABLE(quote_name(f.rel.to._meta.db_table)), 203 style.SQL_FIELD(quote_name(f.rel.to._meta.pk.column)))) 204 table_output.append(' %s (%s, %s)' % \ 205 (style.SQL_KEYWORD('UNIQUE'), 206 style.SQL_FIELD(quote_name(f.m2m_column_name())), 207 style.SQL_FIELD(quote_name(f.m2m_reverse_name())))) 208 table_output.append(');') 209 output.setdefault(f.rel.to, []).append( 210 BoundStatement('\n'.join(table_output), connection)) 211 return output 212 213 def get_drop_table(self, model, cascade=False, style=None): 214 """Construct and return the SQL statment(s) needed to drop a model's 215 table. If cascade is true, then output additional statments to drop any 216 many-to-many tables that this table created and any foreign keys that 217 reference this table. 218 """ 219 if style is None: 220 style = default_style 221 opts = model._meta 222 db = model._default_manager.db 223 db_table = opts.db_table 224 backend = db.backend 225 qn = backend.quote_name 226 output = [] 227 output.append(BoundStatement( 228 '%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 229 style.SQL_TABLE(qn(db_table))), 230 db.connection)) 231 232 if cascade: 233 # deal with others that might have a foreign key TO me: alter 234 # their tables to drop the constraint 235 if backend.supports_constraints: 236 references_to_delete = self.get_references() 237 if model in references_to_delete: 238 for rel_class, f in references_to_delete[model]: 239 table = rel_class._meta.db_table 240 if not self.table_exists(db, table): 241 print "NO TABLE %s" % table 242 continue 243 col = f.column 244 r_table = opts.db_table 245 r_col = opts.get_field(f.rel.field_name).column 246 output.append(BoundStatement( 247 '%s %s %s %s;' % 248 (style.SQL_KEYWORD('ALTER TABLE'), 249 style.SQL_TABLE(qn(table)), 250 style.SQL_KEYWORD( 251 backend.get_drop_foreignkey_sql()), 252 style.SQL_FIELD(qn("%s_refs_%s_%x" % 253 (col, r_col, 254 abs(hash((table, r_table))))) 255 )), 256 db.connection)) 257 del references_to_delete[model] 258 # many to many: drop any many-many tables that are my 259 # responsiblity 260 for f in opts.many_to_many: 261 if not isinstance(f.rel, generic.GenericRel): 262 output.append(BoundStatement( 263 '%s %s;' % 264 (style.SQL_KEYWORD('DROP TABLE'), 265 style.SQL_TABLE(qn(f.m2m_db_table()))), 266 db.connection)) 267 return output 268 269 def get_initialdata(self, model): 270 opts = model._meta 271 db = model._default_manager.db 272 settings = db.connection.settings 273 backend = db.backend 274 app_dir = self.get_initialdata_path(model) 275 output = [] 276 277 # Some backends can't execute more than one SQL statement at a time. 278 # We'll split the initial data into individual statements unless 279 # backend.supports_compound_statements. 280 statements = re.compile(r";[ \t]*$", re.M) 281 282 # Find custom SQL, if it's available. 283 sql_files = [os.path.join(app_dir, "%s.%s.sql" % 284 (opts.object_name.lower(), 285 settings.DATABASE_ENGINE)), 286 os.path.join(app_dir, "%s.sql" % 287 opts.object_name.lower())] 288 for sql_file in sql_files: 289 if os.path.exists(sql_file): 290 fp = open(sql_file, 'U') 291 if backend.supports_compound_statements: 292 output.append(BoundStatement(fp.read(), db.connection)) 293 else: 294 for statement in statements.split(fp.read()): 295 # Remove any comments from the file 296 statement = re.sub(r"--.*[\n\Z]", "", statement) 297 if statement.strip(): 298 output.append(BoundStatement(statement + ";", 299 db.connection)) 300 fp.close() 301 return output 302 303 def get_initialdata_path(self, model): 304 """Get the path from which to load sql initial data files for a model. 305 """ 306 return os.path.normpath(os.path.join(os.path.dirname( 307 models.get_app(model._meta.app_label).__file__), 'sql')) 308 309 def get_rel_data_type(self, f): 310 return (f.get_internal_type() in ('AutoField', 'PositiveIntegerField', 311 'PositiveSmallIntegerField')) \ 312 and 'IntegerField' \ 313 or f.get_internal_type() 314 315 def get_ref_sql(self, model, rel_class, f, style=None): 316 """Get sql statement for a reference between model and rel_class on 317 field f. 318 """ 319 if style is None: 320 style = default_style 321 322 db = model._default_manager.db 323 qn = db.backend.quote_name 324 opts = model._meta 325 rel_opts = rel_class._meta 326 table = rel_opts.db_table 327 r_col = f.column 328 r_table = opts.db_table 329 col = opts.get_field(f.rel.field_name).column 330 # For MySQL, r_name must be unique in the first 64 331 # characters. So we are careful with character usage here. 332 r_name = '%s_refs_%s_%x' % (col, r_col, 333 abs(hash((r_table, table)))) 334 sql = style.SQL_KEYWORD('ALTER TABLE') + \ 335 ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \ 336 (qn(table), qn(r_name), 337 qn(r_col), qn(r_table), qn(col)) 338 return BoundStatement(sql, db.connection) 339 340 def get_references(self): 341 """Fill (if needed) and return the reference cache. 342 """ 343 if self.references: 344 return self.references 345 for klass in models.get_models(): 346 for f in klass._meta.fields: 347 if f.rel: 348 self.references.setdefault(f.rel.to, 349 []).append((klass, f)) 350 return self.references 351 352 def get_table_list(self, db): 353 """Get list of tables accessible via db. 354 """ 355 if self.tables is not None: 356 return self.tables 357 cursor = db.connection.cursor() 358 introspection = db.get_introspection_module() 359 return introspection.get_table_list(cursor) 360 361 def table_exists(self, db, table): 362 tables = self.get_table_list(db) 363 return table in tables -
django/db/backends/dummy/base.py
=== django/db/backends/dummy/base.py ==================================================================
22 22 pass 23 23 24 24 class DatabaseWrapper: 25 25 26 cursor = complain 26 27 _commit = complain 27 28 _rollback = ignore 28 29 29 def __init__(self, **kwargs):30 pass30 def __init__(self, settings): 31 self.settings = settings 31 32 32 33 def close(self): 33 34 pass # close() -
django/db/transaction.py
=== django/db/transaction.py ==================================================================
16 16 import thread 17 17 except ImportError: 18 18 import dummy_thread as thread 19 from django .db import connection19 from django import db 20 20 from django.conf import settings 21 21 22 22 class TransactionManagementError(Exception): … … 116 116 Puts the transaction manager into a manual state: managed transactions have 117 117 to be committed explicitly by the user. If you switch off transaction 118 118 management and there is a pending commit/rollback, the data will be 119 commited. 119 commited. Note that managed state applies across all connections. 120 120 """ 121 121 thread_ident = thread.get_ident() 122 122 top = state.get(thread_ident, None) 123 123 if top: 124 124 top[-1] = flag 125 125 if not flag and is_dirty(): 126 connection._commit() 126 for cx in all_connections(): 127 cx._commit() 127 128 set_clean() 128 129 else: 129 130 raise TransactionManagementError("This code isn't under transaction management") 130 131 131 def commit_unless_managed( ):132 def commit_unless_managed(connections=None): 132 133 """ 133 134 Commits changes if the system is not in managed transaction mode. 134 135 """ 135 136 if not is_managed(): 136 connection._commit() 137 if connections is None: 138 connections = all_connections() 139 else: 140 connections = ensure_connections(connections) 141 for cx in connections: 142 cx._commit() 137 143 else: 138 144 set_dirty() 139 145 140 def rollback_unless_managed( ):146 def rollback_unless_managed(connections=None): 141 147 """ 142 148 Rolls back changes if the system is not in managed transaction mode. 143 149 """ 144 150 if not is_managed(): 145 connection._rollback() 151 if connections is None: 152 connections = all_connections() 153 for cx in connections: 154 cx._rollback() 146 155 else: 147 156 set_dirty() 148 157 149 def commit( ):158 def commit(connections=None): 150 159 """ 151 160 Does the commit itself and resets the dirty flag. 152 161 """ 153 connection._commit() 162 if connections is None: 163 connections = all_connections() 164 else: 165 connections = ensure_connections(connections) 166 for cx in connections: 167 cx._commit() 154 168 set_clean() 155 169 156 def rollback( ):170 def rollback(connections=None): 157 171 """ 158 172 This function does the rollback itself and resets the dirty flag. 159 173 """ 160 connection._rollback() 174 if connections is None: 175 connections = all_connections() 176 else: 177 connections = ensure_connections(connections) 178 for cx in connections: 179 cx._rollback() 161 180 set_clean() 162 181 163 182 ############## … … 179 198 leave_transaction_management() 180 199 return _autocommit 181 200 182 def commit_on_success(func ):201 def commit_on_success(func, connections=None): 183 202 """ 184 203 This decorator activates commit on response. This way, if the view function 185 204 runs successfully, a commit is made; if the viewfunc produces an exception, … … 198 217 raise 199 218 else: 200 219 if is_dirty(): 201 commit( )220 commit(connections) 202 221 return res 203 222 finally: 204 223 leave_transaction_management() … … 220 239 leave_transaction_management() 221 240 222 241 return _commit_manually 242 243 ########### 244 # HELPERS # 245 ########### 246 247 def all_connections(): 248 return [db.connection] + [ c.connection 249 for c in db.connections.values() ] 250 251 def ensure_connections(val): 252 connections = [] 253 if isinstance(val, basestring): 254 val = [val] 255 try: 256 iter(val) 257 except: 258 val = [val] 259 for cx in val: 260 if hasattr(cx, 'cursor'): 261 connections.append(cx) 262 elif hasattr(cx, 'connection'): 263 connections.append(cx.connection) 264 elif isinstance(cx, basestring): 265 connections.append(db.connections[cx].connection) 266 return connections 267 -
django/conf/global_settings.py
=== django/conf/global_settings.py ==================================================================
112 112 DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. 113 113 DATABASE_OPTIONS = {} # Set to empty dictionary for default. 114 114 115 # Optional named database connections in addition to the default. 116 OTHER_DATABASES = {} 117 115 118 # Host for sending e-mail. 116 119 EMAIL_HOST = 'localhost' 117 120 … … 334 337 # If None, a name of 'test_' + DATABASE_NAME will be assumed 335 338 TEST_DATABASE_NAME = None 336 339 340 # Tuple of other test databases to create. Names in this tuple 341 # are suffixes that will be appended to TEST_DATABASE_NAME 342 TEST_DATABASES = [] 343 344 # Models to assign to each test database. This must be a list of 345 # dicts, with each dict key being a name from TEST_DATABASES and value 346 # a list of models or app_labels that will use that database. 347 TEST_DATABASE_MODELS = [] 348 349 ############### FROM TRUNK ############################# 337 350 # Strings used to set the character set and collation order for the test 338 351 # database. These values are passed literally to the server, so they are 339 352 # backend-dependent. If None, no special settings are sent (system defaults are -
django/core/servers/basehttp.py
=== django/core/servers/basehttp.py ==================================================================
309 309 """ 310 310 if not self.result_is_file() and not self.sendfile(): 311 311 for data in self.result: 312 self.write(data )312 self.write(data, False) 313 313 self.finish_content() 314 314 self.close() 315 315 … … 377 377 else: 378 378 self._write('Status: %s\r\n' % self.status) 379 379 380 def write(self, data ):380 def write(self, data, flush=True): 381 381 """'write()' callable as specified by PEP 333""" 382 382 383 383 assert type(data) is StringType,"write() argument must be string" … … 394 394 395 395 # XXX check Content-Length and truncate if too many bytes written? 396 396 self._write(data) 397 self._flush() 397 if flush: 398 self._flush() 398 399 399 400 def sendfile(self): 400 401 """Platform-specific file transmission … … 421 422 if not self.headers_sent: 422 423 self.headers['Content-Length'] = "0" 423 424 self.send_headers() 424 else:425 pass # XXX check if content-length was too short?426 425 427 426 def close(self): 428 427 try: -
django/core/management.py
=== django/core/management.py ==================================================================
5 5 from django.core.exceptions import ImproperlyConfigured 6 6 from optparse import OptionParser 7 7 from django.utils import termcolors 8 from django.db import model_connection_name 8 9 import os, re, shutil, sys, textwrap 9 10 10 try: 11 set 12 except NameError: 13 from sets import Set as set # Python 2.3 fallback 11 # For Python 2.3 12 if not hasattr(__builtins__, 'set'): 13 from sets import Set as set 14 14 15 15 16 # For backwards compatibility: get_version() used to be in this module. 16 17 get_version = django.get_version 17 18 … … 103 104 104 105 def get_sql_create(app): 105 106 "Returns a list of the CREATE TABLE SQL statements for the given app." 106 from django.db import get_creation_module, models 107 from django.db import get_creation_module, models, model_connection_name 107 108 108 data_types = get_creation_module().DATA_TYPES 109 # final output will be divided by comments into sections for each 110 # named connection, if there are any named connections 111 connection_output = {} 112 pending = {} 113 final_output = [] 114 115 app_models = models.get_models(app)#, creation_order=True) 116 for model in app_models: 117 opts = model._meta 118 connection_name = model_connection_name(model) 119 output = connection_output.setdefault(connection_name, []) 120 db = model._default_manager.db 121 creation = db.get_creation_module() 122 data_types = creation.DATA_TYPES 123 if not data_types: 124 # This must be the "dummy" database backend, which means the user 125 # hasn't set DATABASE_ENGINE. 109 126 110 if not data_types: 111 # This must be the "dummy" database backend, which means the user 112 # hasn't set DATABASE_ENGINE. 113 sys.stderr.write(style.ERROR("Error: Django doesn't know which syntax to use for your SQL statements,\n" + 114 "because you haven't specified the DATABASE_ENGINE setting.\n" + 115 "Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n")) 116 sys.exit(1) 127 # FIXME diff error message for bad default v bad named 128 sys.stderr.write(style.ERROR("Error: Django doesn't know which syntax to use for your SQL statements,\n" + 129 "because you haven't specified the DATABASE_ENGINE setting.\n" + 130 "Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n")) 131 sys.exit(1) 117 132 118 # Get installed models, so we generate REFERENCES right. 119 # We trim models from the current app so that the sqlreset command does not 120 # generate invalid SQL (leaving models out of known_models is harmless, so 121 # we can be conservative). 122 app_models = models.get_models(app) 123 final_output = [] 124 known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models]) 125 pending_references = {} 133 # Get installed models, so we generate REFERENCES right 134 # We trim models from the current app so that the sqlreset command does 135 # not generate invalid SQL (leaving models out of known_models is 136 # harmless, so we can be conservative). 137 manager = model._default_manager 138 try: 139 tables = manager.get_table_list() 140 except (KeyboardInterrupt, SystemExit): 141 raise 142 except: 143 # Something else went wrong -- maybe the database isn't 144 # running. But we can still generate sql, so use an empty 145 # table list. 146 tables = [] 126 147 127 for model in app_models:128 output, references = _get_sql_model_create(model, known_models)129 final_output.extend(output)130 for refto, refs in references.items():131 pending_references.setdefault(refto,[]).extend(refs)132 final_output.extend(_get_sql_for_pending_references(model, pending_references))133 # Keep track of the fact that we've created the table for this model.134 known_models.add(model)148 installed_models = [ m for m in 149 manager.get_installed_models(tables) 150 if m not in app_models ] 151 models_output = set(installed_models) 152 builder = creation.builder 153 builder.models_already_seen.update(models_output) 154 model_output, pending = builder.get_create_table(model, style, pending) 155 output.extend(model_output) 135 156 136 # Create the many-to-many join tables. 137 for model in app_models: 138 final_output.extend(_get_many_to_many_sql_for_model(model)) 157 # Create the many-to-many join tables. 158 many_many = builder.get_create_many_to_many(model, style) 159 for refmodel, statements in many_many.items(): 160 output.extend(statements) 139 161 162 final_output = _collate(connection_output) 163 140 164 # Handle references to tables that are from other apps 141 165 # but don't exist physically 142 not_installed_models = set(pending _references.keys())166 not_installed_models = set(pending.keys()) 143 167 if not_installed_models: 144 168 alter_sql = [] 145 169 for model in not_installed_models: 146 alter_sql.extend(['-- ' + sql for sql in 147 _get_sql_for_pending_references(model, pending_references)]) 170 builder = model._default_manager.db.get_creation_module().builder 171 172 for rel_class, f in pending[model]: 173 sql = builder.get_ref_sql(model, rel_class, f, style) 174 alter_sql.append('-- '+ str(sql)) 148 175 if alter_sql: 149 final_output.append('-- The following references should be added but depend on non-existent tables:') 176 final_output.append('-- The following references should be added ' 177 'but depend on non-existent tables:') 150 178 final_output.extend(alter_sql) 151 179 # convert BoundStatements into strings 180 final_output = map(str, final_output) 152 181 return final_output 153 182 get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app name(s)." 154 183 get_sql_create.args = APP_ARGS … … 314 343 315 344 def get_sql_delete(app): 316 345 "Returns a list of the DROP TABLE SQL statements for the given app." 346 from django.db import model_connection_name 317 347 from django.db import backend, connection, models, get_introspection_module 318 348 from django.db.backends.util import truncate_name 319 349 introspection = get_introspection_module() 320 321 # This should work even if a connection isn't available 322 try: 323 cursor = connection.cursor() 324 except: 325 cursor = None 326 327 # Figure out which tables already exist 328 if cursor: 329 table_names = introspection.get_table_list(cursor) 330 else: 331 table_names = [] 332 if backend.uses_case_insensitive_names: 333 table_name_converter = str.upper 334 else: 335 table_name_converter = lambda x: x 336 337 output = [] 338 339 # Output DROP TABLE statements for standard application tables. 340 to_delete = set() 341 342 references_to_delete = {} 350 351 connection_output = {} 352 final_output = [] 343 353 app_models = models.get_models(app) 344 354 for model in app_models: 345 if cursor and table_name_converter(model._meta.db_table) in table_names: 346 # The table exists, so it needs to be dropped 347 opts = model._meta 348 for f in opts.fields: 349 if f.rel and f.rel.to not in to_delete: 350 references_to_delete.setdefault(f.rel.to, []).append( (model, f) ) 351 352 to_delete.add(model) 353 354 for model in app_models: 355 if cursor and table_name_converter(model._meta.db_table) in table_names: 356 # Drop the table now 357 output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'), 358 style.SQL_TABLE(backend.quote_name(model._meta.db_table)))) 359 if backend.supports_constraints and model in references_to_delete: 360 for rel_class, f in references_to_delete[model]: 361 table = rel_class._meta.db_table 362 col = f.column 363 r_table = model._meta.db_table 364 r_col = model._meta.get_field(f.rel.field_name).column 365 r_name = '%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table)))) 366 output.append('%s %s %s %s;' % \ 367 (style.SQL_KEYWORD('ALTER TABLE'), 368 style.SQL_TABLE(backend.quote_name(table)), 369 style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()), 370 style.SQL_FIELD(truncate_name(r_name, backend.get_max_name_length())))) 371 del references_to_delete[model] 372 if model._meta.has_auto_field and hasattr(backend, 'get_drop_sequence'): 373 output.append(backend.get_drop_sequence(model._meta.db_table)) 374 375 # Output DROP TABLE statements for many-to-many tables. 376 for model in app_models: 377 opts = model._meta 378 for f in opts.many_to_many: 379 if cursor and table_name_converter(f.m2m_db_table()) in table_names: 380 output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'), 381 style.SQL_TABLE(backend.quote_name(f.m2m_db_table())))) 382 if hasattr(backend, 'get_drop_sequence'): 383 output.append(backend.get_drop_sequence("%s_%s" % (model._meta.db_table, f.column))) 384 385 386 app_label = app_models[0]._meta.app_label 387 388 # Close database connection explicitly, in case this output is being piped 389 # directly into a database client, to avoid locking issues. 390 if cursor: 391 cursor.close() 392 connection.close() 393 394 return output[::-1] # Reverse it, to deal with table dependencies. 355 db = model._default_manager.db 356 connection = db.connection 357 try: 358 cursor = connection.cursor() 359 except: 360 cursor = None 361 #******** Start of conflict section ###### 362 ###** From multi-db 363 builder = db.get_creation_module().builder 364 connection_name = model_connection_name(model) 365 output = connection_output.setdefault(connection_name, []) 366 output.extend(map(str, 367 builder.get_drop_table(model, 368 cascade=True, style=style))) 369 if cursor: 370 # Close database connection explicitly, in case this 371 # output is being piped directly into a database client, 372 # to avoid locking issues. 373 cursor.close() 374 connection.close() 375 376 final_output = _collate(connection_output, reverse=True) 377 return final_output 395 378 get_sql_delete.help_doc = "Prints the DROP TABLE SQL statements for the given app name(s)." 396 379 get_sql_delete.args = APP_ARGS 397 380 … … 439 422 def get_custom_sql(app): 440 423 "Returns a list of the custom table modifying SQL statements for the given app." 441 424 from django.db.models import get_models 442 output = []425 connection_output = {} 443 426 444 427 app_models = get_models(app) 445 428 app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql')) 446 429 447 430 for model in app_models: 448 output.extend(get_custom_sql_for_model(model)) 431 opts = model._meta 432 connection_name = model_connection_name(model) 433 output = connection_output.setdefault(connection_name, []) 434 builder = model._default_manager.db.get_creation_module().builder 435 output.extend(builder.get_initialdata(model)) 449 436 450 return output437 return _collate(connection_output) 451 438 get_custom_sql.help_doc = "Prints the custom table modifying SQL statements for the given app name(s)." 452 439 get_custom_sql.args = APP_ARGS 453 440 … … 458 445 get_sql_initial_data.args = '' 459 446 460 447 def get_sql_sequence_reset(app): 461 "Returns a list of the SQL statements to reset sequences for the given app." 462 from django.db import backend, models 463 return backend.get_sql_sequence_reset(style, models.get_models(app)) 464 get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting sequences for the given app name(s)." 448 "Returns a list of the SQL statements to reset PostgreSQL sequences for the given app." 449 from django.db import model_connection_name 450 from django.db.models import get_models 451 connection_output = {} 452 for model in get_models(app): 453 connection_name = model_connection_name(model) 454 output = connection_output.setdefault(connection_name, []) 455 builder = model._default_manager.db.get_creation_module().builder 456 try: 457 output.extend(builder.get_sequence_reset(model, style)) 458 except AttributeError: 459 sys.stderr.write( 460 "%s is configured to use database engine %s, which does " 461 "not support sequence reset.\n" % 462 (model.__name__, 463 model._default_manager.db.connection.settings.DATABASE_ENGINE)) 464 465 return _collate(connection_output) 466 get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting PostgreSQL sequences for the given app name(s)." 465 467 get_sql_sequence_reset.args = APP_ARGS 466 468 467 469 def get_sql_indexes(app): 468 470 "Returns a list of the CREATE INDEX SQL statements for all models in the given app." 469 from django.db import models 470 output = [] 471 for model in models.get_models(app): 472 output.extend(get_sql_indexes_for_model(model)) 473 return output 471 from django.db import model_connection_name 472 from django.db.models import get_models 473 connection_output = {} 474 for model in get_models(app): 475 opts = model._meta 476 connection_name = model_connection_name(model) 477 output = connection_output.setdefault(connection_name, []) 478 output.extend(map(str, get_sql_indexes_for_model(model))) 479 return _collate(connection_output) 480 474 481 get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)." 475 482 get_sql_indexes.args = APP_ARGS 476 483 … … 503 510 get_sql_all.help_doc = "Prints the CREATE TABLE, initial-data and CREATE INDEX SQL statements for the given model module name(s)." 504 511 get_sql_all.args = APP_ARGS 505 512 513 def _collate(connection_output, reverse=False): 514 from django.db import _default 515 final_output = [] 516 if len(connection_output.keys()) == 1: 517 # all for the default connection 518 for statements in connection_output.values(): 519 final_output.extend(statements) 520 if reverse: 521 final_output.reverse() 522 else: 523 for connection_name, statements in connection_output.items(): 524 if not statements: 525 continue 526 final_output.append(' -- The following statements are for connection: %s' % connection_name) 527 if reverse: 528 statements.reverse() 529 final_output.extend(statements) 530 final_output.append(' -- END statements for %s\n' % 531 connection_name) 532 return map(str, final_output) 533 506 534 def _emit_post_sync_signal(created_models, verbosity, interactive): 507 535 from django.db import models 508 536 from django.dispatch import dispatcher … … 687 715 print '\n'.join(output) 688 716 diffsettings.args = "" 689 717 718 def install(app): 719 "Executes the equivalent of 'get_sql_all' in the current database." 720 # Wrap _install to hide the return value so ./manage.py install 721 # doesn't complain about unprintable output. 722 _install(app) 723 724 def _install(app, commit=True, initial_data=True, pending_allowed=False, 725 pending=None, verbosity=1, signal=True, interactive=True): 726 from django.db import connection, models, transaction 727 import sys 728 729 app_name = app.__name__.split('.')[-2] 730 731 disable_termcolors() 732 733 # First, try validating the models. 734 _check_for_validation_errors(app) 735 736 created_models = [] 737 try: 738 if pending is None: 739 pending = {} 740 for model in models.get_models(app, creation_order=True): 741 if verbosity >= 2: 742 print "Processing %s.%s model" % (app_name, 743 model._meta.object_name) 744 manager = model._default_manager 745 tables = manager.get_table_list() 746 models_installed = manager.get_installed_models(tables) 747 # Don't re-install already-installed models 748 if not model in models_installed: 749 pending = manager.install(initial_data=initial_data, 750 pending=pending) 751 created_models.append(model) 752 753 if pending: 754 models_installed = manager.get_installed_models(tables) 755 756 for model in pending.keys(): 757 manager = model._default_manager 758 if model in models_installed: 759 for rel_class, f in pending[model]: 760 manager.get_pending(rel_class, f).execute() 761 pending.pop(model) 762 elif not pending_allowed: 763 raise Exception("%s is not installed, but it has pending " 764 "references" % model) 765 except Exception, e: 766 import traceback 767 print traceback.format_exception(*sys.exc_info()) 768 sys.stderr.write(style.ERROR("""Error: %s couldn't be installed. Possible reasons: 769 * The database isn't running or isn't configured correctly. 770 * At least one of the database tables already exists. 771 * The SQL was invalid. 772 Hint: Look at the output of 'django-admin.py sqlall %s'. That's the SQL this command wasn't able to run. 773 The full error: """ % (app_name, app_name)) + style.ERROR_OUTPUT(str(e)) + '\n') 774 transaction.rollback_unless_managed() 775 sys.exit(1) 776 if commit: 777 transaction.commit_unless_managed() 778 779 if signal: 780 _post_syncdb(app, created_models=created_models, 781 verbosity=verbosity, interactive=interactive) 782 783 return created_models, pending 784 install.help_doc = "Executes ``sqlall`` for the given app(s) in the current database." 785 install.args = APP_ARGS 786 787 def _post_syncdb(app, created_models, verbosity=1, interactive=True): 788 """Send the post_syncdb signal for an application.""" 789 from django.dispatch import dispatcher 790 from django.db.models import signals 791 792 if verbosity >= 2: 793 print "Sending post-syncdb signal for application", app.__name__.split('.')[-2] 794 dispatcher.send(signal=signals.post_syncdb, sender=app, 795 app=app, created_models=created_models, 796 verbosity=verbosity, interactive=interactive) 797 690 798 def reset(app, interactive=True): 691 799 "Executes the equivalent of 'get_sql_reset' in the current database." 692 800 from django.db import connection, transaction … … 983 1091 Returns number of errors. 984 1092 """ 985 1093 from django.conf import settings 986 from django.db import models, connection1094 from django.db import connections, models, connection, model_connection_name 987 1095 from django.db.models.loading import get_app_errors 988 1096 from django.db.models.fields.related import RelatedObject 989 1097 … … 994 1102 995 1103 for cls in models.get_models(app): 996 1104 opts = cls._meta 997 1105 connection_name = model_connection_name(cls) 1106 connection = connections[connection_name] 1107 998 1108 # Do field-specific validation. 999 1109 for f in opts.fields: 1000 1110 if f.name == 'id' and not f.primary_key and opts.pk.name == 'id': … … 1027 1137 1028 1138 # Check that maxlength <= 255 if using older MySQL versions. 1029 1139 if settings.DATABASE_ENGINE == 'mysql': 1030 db_version = connection. get_server_version()1140 db_version = connection.connection.get_server_version() 1031 1141 if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255: 1032 1142 e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]]))) 1033 1143 … … 1038 1148 if f.rel.to not in models.get_models(): 1039 1149 e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, rel_opts.object_name)) 1040 1150 1151 #TODO: Fix this to allow relations that span databases by splitting querys up 1152 rel_connection = model_connection_name(f.rel.to) 1153 if rel_connection != connection_name: 1154 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)) 1155 1041 1156 rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() 1042 1157 rel_query_name = f.related_query_name() 1043 1158 for r in rel_opts.fields: … … 1546 1661 'createcachetable', 1547 1662 'dbshell', 1548 1663 'diffsettings', 1664 'install', 1549 1665 'reset', 1550 1666 'sqlindexes', 1551 1667 'syncdb', -
django/views/generic/simple.py
Property changes on: django/core/management.py ___________________________________________________________________ Name: svn:eol-style -native === django/views/generic/simple.py ==================================================================
15 15 dictionary[key] = value 16 16 c = RequestContext(request, dictionary) 17 17 t = loader.get_template(template) 18 return HttpResponse(t. render(c), mimetype=mimetype)18 return HttpResponse(t.iter_render(c), mimetype=mimetype) 19 19 20 20 def redirect_to(request, url, **kwargs): 21 21 """ -
django/views/generic/date_based.py
=== django/views/generic/date_based.py ==================================================================
44 44 c[key] = value() 45 45 else: 46 46 c[key] = value 47 return HttpResponse(t. render(c), mimetype=mimetype)47 return HttpResponse(t.iter_render(c), mimetype=mimetype) 48 48 49 49 def archive_year(request, year, queryset, date_field, template_name=None, 50 50 template_loader=loader, extra_context=None, allow_empty=False, … … 92 92 c[key] = value() 93 93 else: 94 94 c[key] = value 95 return HttpResponse(t. render(c), mimetype=mimetype)95 return HttpResponse(t.iter_render(c), mimetype=mimetype) 96 96 97 97 def archive_month(request, year, month, queryset, date_field, 98 98 month_format='%b', template_name=None, template_loader=loader, … … 158 158 c[key] = value() 159 159 else: 160 160 c[key] = value 161 return HttpResponse(t. render(c), mimetype=mimetype)161 return HttpResponse(t.iter_render(c), mimetype=mimetype) 162 162 163 163 def archive_week(request, year, week, queryset, date_field, 164 164 template_name=None, template_loader=loader, … … 206 206 c[key] = value() 207 207 else: 208 208 c[key] = value 209 return HttpResponse(t. render(c), mimetype=mimetype)209 return HttpResponse(t.iter_render(c), mimetype=mimetype) 210 210 211 211 def archive_day(request, year, month, day, queryset, date_field, 212 212 month_format='%b', day_format='%d', template_name=None, … … 270 270 c[key] = value() 271 271 else: 272 272 c[key] = value 273 return HttpResponse(t. render(c), mimetype=mimetype)273 return HttpResponse(t.iter_render(c), mimetype=mimetype) 274 274 275 275 def archive_today(request, **kwargs): 276 276 """ … … 339 339 c[key] = value() 340 340 else: 341 341 c[key] = value 342 response = HttpResponse(t. render(c), mimetype=mimetype)342 response = HttpResponse(t.iter_render(c), mimetype=mimetype) 343 343 populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name)) 344 344 return response -
django/views/generic/list_detail.py
=== django/views/generic/list_detail.py ==================================================================
84 84 model = queryset.model 85 85 template_name = "%s/%s_list.html" % (model._meta.app_label, model._meta.object_name.lower()) 86 86 t = template_loader.get_template(template_name) 87 return HttpResponse(t. render(c), mimetype=mimetype)87 return HttpResponse(t.iter_render(c), mimetype=mimetype) 88 88 89 89 def object_detail(request, queryset, object_id=None, slug=None, 90 90 slug_field=None, template_name=None, template_name_field=None, … … 126 126 c[key] = value() 127 127 else: 128 128 c[key] = value 129 response = HttpResponse(t. render(c), mimetype=mimetype)129 response = HttpResponse(t.iter_render(c), mimetype=mimetype) 130 130 populate_xheaders(request, response, model, getattr(obj, obj._meta.pk.name)) 131 131 return response -
django/views/generic/create_update.py
=== django/views/generic/create_update.py ==================================================================
68 68 c[key] = value() 69 69 else: 70 70 c[key] = value 71 return HttpResponse(t. render(c))71 return HttpResponse(t.iter_render(c)) 72 72 73 73 def update_object(request, model, object_id=None, slug=None, 74 74 slug_field=None, template_name=None, template_loader=loader, … … 141 141 c[key] = value() 142 142 else: 143 143 c[key] = value 144 response = HttpResponse(t. render(c))144 response = HttpResponse(t.iter_render(c)) 145 145 populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname)) 146 146 return response 147 147 … … 195 195 c[key] = value() 196 196 else: 197 197 c[key] = value 198 response = HttpResponse(t. render(c))198 response = HttpResponse(t.iter_render(c)) 199 199 populate_xheaders(request, response, model, getattr(object, object._meta.pk.attname)) 200 200 return response -
django/views/debug.py
=== django/views/debug.py ==================================================================
137 137 'template_does_not_exist': template_does_not_exist, 138 138 'loader_debug_info': loader_debug_info, 139 139 }) 140 return HttpResponseServerError(t. render(c), mimetype='text/html')140 return HttpResponseServerError(t.iter_render(c), mimetype='text/html') 141 141 142 142 def technical_404_response(request, exception): 143 143 "Create a technical 404 error response. The exception should be the Http404." … … 160 160 'request_protocol': request.is_secure() and "https" or "http", 161 161 'settings': get_safe_settings(), 162 162 }) 163 return HttpResponseNotFound(t. render(c), mimetype='text/html')163 return HttpResponseNotFound(t.iter_render(c), mimetype='text/html') 164 164 165 165 def empty_urlconf(request): 166 166 "Create an empty URLconf 404 error response." … … 168 168 c = Context({ 169 169 'project_name': settings.SETTINGS_MODULE.split('.')[0] 170 170 }) 171 return HttpResponseNotFound(t. render(c), mimetype='text/html')171 return HttpResponseNotFound(t.iter_render(c), mimetype='text/html') 172 172 173 173 def _get_lines_from_file(filename, lineno, context_lines, loader=None, module_name=None): 174 174 """ -
django/views/defaults.py
=== django/views/defaults.py ==================================================================
76 76 The path of the requested URL (e.g., '/app/pages/bad_page/') 77 77 """ 78 78 t = loader.get_template(template_name) # You need to create a 404.html template. 79 return http.HttpResponseNotFound(t. render(RequestContext(request, {'request_path': request.path})))79 return http.HttpResponseNotFound(t.iter_render(RequestContext(request, {'request_path': request.path}))) 80 80 81 81 def server_error(request, template_name='500.html'): 82 82 """ … … 86 86 Context: None 87 87 """ 88 88 t = loader.get_template(template_name) # You need to create a 500.html template. 89 return http.HttpResponseServerError(t. render(Context({})))89 return http.HttpResponseServerError(t.iter_render(Context({}))) -
django/views/static.py
=== django/views/static.py ==================================================================
92 92 'directory' : path + '/', 93 93 'file_list' : files, 94 94 }) 95 return HttpResponse(t. render(c))95 return HttpResponse(t.iter_render(c)) 96 96 97 97 def was_modified_since(header=None, mtime=0, size=0): 98 98 """ -
django/shortcuts/__init__.py
=== django/shortcuts/__init__.py ==================================================================
7 7 from django.db.models.manager import Manager 8 8 9 9 def render_to_response(*args, **kwargs): 10 return HttpResponse(loader.render_to_ string(*args, **kwargs))10 return HttpResponse(loader.render_to_iter(*args, **kwargs)) 11 11 load_and_render = render_to_response # For backwards compatibility. 12 12 13 13 def get_object_or_404(klass, *args, **kwargs): -
django/contrib/comments/templatetags/comments.py
=== django/contrib/comments/templatetags/comments.py ==================================================================
24 24 self.photo_options, self.rating_options = photo_options, rating_options 25 25 self.is_public = is_public 26 26 27 def render(self, context):27 def iter_render(self, context): 28 28 from django.conf import settings 29 29 from django.utils.text import normalize_newlines 30 30 import base64 … … 33 33 try: 34 34 self.obj_id = template.resolve_variable(self.obj_id_lookup_var, context) 35 35 except template.VariableDoesNotExist: 36 return ''36 return 37 37 # Validate that this object ID is valid for this content-type. 38 38 # We only have to do this validation if obj_id_lookup_var is provided, 39 39 # because do_comment_form() validates hard-coded object IDs. … … 67 67 context['hash'] = Comment.objects.get_security_hash(context['options'], context['photo_options'], context['rating_options'], context['target']) 68 68 context['logout_url'] = settings.LOGOUT_URL 69 69 default_form = loader.get_template(COMMENT_FORM) 70 output = default_form.render(context) 70 for chunk in default_form.iter_render(context): 71 yield chunk 71 72 context.pop() 72 return output73 73 74 74 class CommentCountNode(template.Node): 75 75 def __init__(self, package, module, context_var_name, obj_id, var_name, free): … … 77 77 self.context_var_name, self.obj_id = context_var_name, obj_id 78 78 self.var_name, self.free = var_name, free 79 79 80 def render(self, context):80 def iter_render(self, context): 81 81 from django.conf import settings 82 82 manager = self.free and FreeComment.objects or Comment.objects 83 83 if self.context_var_name is not None: … … 86 86 content_type__app_label__exact=self.package, 87 87 content_type__model__exact=self.module, site__id__exact=settings.SITE_ID).count() 88 88 context[self.var_name] = comment_count 89 return ''89 return () 90 90 91 91 class CommentListNode(template.Node): 92 92 def __init__(self, package, module, context_var_name, obj_id, var_name, free, ordering, extra_kwargs=None): … … 96 96 self.ordering = ordering 97 97 self.extra_kwargs = extra_kwargs or {} 98 98 99 def render(self, context):99 def iter_render(self, context): 100 100 from django.conf import settings 101 101 get_list_function = self.free and FreeComment.objects.filter or Comment.objects.get_list_with_karma 102 102 if self.context_var_name is not None: 103 103 try: 104 104 self.obj_id = template.resolve_variable(self.context_var_name, context) 105 105 except template.VariableDoesNotExist: 106 return ''106 return () 107 107 kwargs = { 108 108 'object_id__exact': self.obj_id, 109 109 'content_type__app_label__exact': self.package, … … 127 127 comment_list = [c for c in comment_list if not c.is_hidden or (user_id == c.user_id)] 128 128 129 129 context[self.var_name] = comment_list 130 return ''130 return () 131 131 132 132 class DoCommentForm: 133 133 """ -
django/contrib/admin/templatetags/admin_modify.py
=== django/contrib/admin/templatetags/admin_modify.py ==================================================================
94 94 return cls.nodelists[klass] 95 95 get_nodelist = classmethod(get_nodelist) 96 96 97 def render(self, context):97 def iter_render(self, context): 98 98 bound_field = template.resolve_variable(self.bound_field_var, context) 99 99 100 100 context.push() 101 101 context['bound_field'] = bound_field 102 102 103 output = self.get_nodelist(bound_field.field.__class__).render(context) 103 for chunk in self.get_nodelist(bound_field.field.__class__).iter_render(context): 104 yield chunk 104 105 context.pop() 105 return output106 106 107 107 class FieldWrapper(object): 108 108 def __init__(self, field ): … … 157 157 def __init__(self, rel_var): 158 158 self.rel_var = rel_var 159 159 160 def render(self, context):160 def iter_render(self, context): 161 161 relation = template.resolve_variable(self.rel_var, context) 162 162 context.push() 163 163 if relation.field.rel.edit_inline == models.TABULAR: … … 169 169 original = context.get('original', None) 170 170 bound_related_object = relation.bind(context['form'], original, bound_related_object_class) 171 171 context['bound_related_object'] = bound_related_object 172 t = loader.get_template(bound_related_object.template_name())173 output = t.render(context)172 for chunk in loader.get_template(bound_related_object.template_name()).iter_render(context): 173 yield chunk 174 174 context.pop() 175 return output176 175 177 176 def output_all(form_fields): 178 177 return ''.join([str(f) for f in form_fields]) -
django/contrib/admin/templatetags/log.py
=== django/contrib/admin/templatetags/log.py ==================================================================
10 10 def __repr__(self): 11 11 return "<GetAdminLog Node>" 12 12 13 def render(self, context):13 def iter_render(self, context): 14 14 if self.user is None: 15 15 context[self.varname] = LogEntry.objects.all().select_related()[:self.limit] 16 16 else: 17 17 if not self.user.isdigit(): 18 18 self.user = context[self.user].id 19 19 context[self.varname] = LogEntry.objects.filter(user__id__exact=self.user).select_related()[:self.limit] 20 return ''20 return () 21 21 22 22 class DoGetAdminLog: 23 23 """ -
django/contrib/admin/templatetags/adminapplist.py
=== django/contrib/admin/templatetags/adminapplist.py ==================================================================
7 7 def __init__(self, varname): 8 8 self.varname = varname 9 9 10 def render(self, context):10 def iter_render(self, context): 11 11 from django.db import models 12 12 from django.utils.text import capfirst 13 13 app_list = [] … … 54 54 'models': model_list, 55 55 }) 56 56 context[self.varname] = app_list 57 return ''57 return () 58 58 59 59 def get_admin_app_list(parser, token): 60 60 """ -
django/template/__init__.py
=== django/template/__init__.py ==================================================================
55 55 '\n<html>\n\n</html>\n' 56 56 """ 57 57 import re 58 import types 58 59 from inspect import getargspec 59 60 from django.conf import settings 60 61 from django.template.context import Context, RequestContext, ContextPopException … … 167 168 for subnode in node: 168 169 yield subnode 169 170 170 def render(self, context):171 def iter_render(self, context): 171 172 "Display stage -- can be called many times" 172 return self.nodelist. render(context)173 return self.nodelist.iter_render(context) 173 174 175 def render(self, context): 176 return ''.join(self.iter_render(context)) 177 174 178 def compile_string(template_string, origin): 175 179 "Compiles template_string into NodeList ready for rendering" 176 180 lexer = lexer_factory(template_string, origin) … … 695 699 del bits[0] 696 700 return current 697 701 702 class NodeBase(type): 703 def __new__(cls, name, bases, attrs): 704 """ 705 Ensures that either a 'render' or 'render_iter' method is defined on 706 any Node sub-class. This avoids potential infinite loops at runtime. 707 """ 708 if not (isinstance(attrs.get('render'), types.FunctionType) or 709 isinstance(attrs.get('iter_render'), types.FunctionType)): 710 raise TypeError('Unable to create Node subclass without either "render" or "iter_render" method.') 711 return type.__new__(cls, name, bases, attrs) 712 698 713 class Node(object): 714 __metaclass__ = NodeBase 715 716 def iter_render(self, context): 717 return (self.render(context),) 718 699 719 def render(self, context): 700 720 "Return the node rendered as a string" 701 pass721 return ''.join(self.iter_render(context)) 702 722 703 723 def __iter__(self): 704 724 yield self … … 714 734 715 735 class NodeList(list): 716 736 def render(self, context): 717 bits = [] 737 return ''.join(self.iter_render(context)) 738 739 def iter_render(self, context): 718 740 for node in self: 719 if isinstance(node, Node): 720 bits.append(self.render_node(node, context)) 721 else: 722 bits.append(node) 723 return ''.join(bits) 741 for chunk in node.iter_render(context): 742 yield chunk 724 743 725 744 def get_nodes_by_type(self, nodetype): 726 745 "Return a list of all nodes of the given type" … … 729 748 nodes.extend(node.get_nodes_by_type(nodetype)) 730 749 return nodes 731 750 732 def render_node(self, node, context):733 return(node.render(context))734 735 751 class DebugNodeList(NodeList): 736 def render_node(self, node, context): 737 try: 738 result = node.render(context) 739 except TemplateSyntaxError, e: 740 if not hasattr(e, 'source'): 741 e.source = node.source 742 raise 743 except Exception, e: 744 from sys import exc_info 745 wrapped = TemplateSyntaxError('Caught an exception while rendering: %s' % e) 746 wrapped.source = node.source 747 wrapped.exc_info = exc_info() 748 raise wrapped 749 return result 752 def iter_render(self, context): 753 for node in self: 754 if not isinstance(node, Node): 755 yield node 756 continue 757 try: 758 for chunk in node.iter_render(context): 759 yield chunk 760 except TemplateSyntaxError, e: 761 if not hasattr(e, 'source'): 762 e.source = node.source 763 raise 764 except Exception, e: 765 from sys import exc_info 766 wrapped = TemplateSyntaxError('Caught an exception while rendering: %s' % e) 767 wrapped.source = node.source 768 wrapped.exc_info = exc_info() 769 raise wrapped 750 770 751 771 class TextNode(Node): 752 772 def __init__(self, s): … … 755 775 def __repr__(self): 756 776 return "<Text Node: '%s'>" % self.s[:25] 757 777 778 def iter_render(self, context): 779 return (self.s,) 780 758 781 def render(self, context): 759 782 return self.s 760 783 … … 778 801 else: 779 802 return output 780 803 804 def iter_render(self, context): 805 return (self.render(context),) 806 781 807 def render(self, context): 782 808 output = self.filter_expression.resolve(context) 783 809 return self.encode_output(output) … … 866 892 def __init__(self, vars_to_resolve): 867 893 self.vars_to_resolve = vars_to_resolve 868 894 895 #def iter_render(self, context): 896 # return (self.render(context),) 897 869 898 def render(self, context): 870 899 resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] 871 900 return func(*resolved_vars) … … 888 917 def __init__(self, vars_to_resolve): 889 918 self.vars_to_resolve = vars_to_resolve 890 919 891 def render(self, context):920 def iter_render(self, context): 892 921 resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] 893 922 if takes_context: 894 923 args = [context] + resolved_vars … … 904 933 else: 905 934 t = get_template(file_name) 906 935 self.nodelist = t.nodelist 907 return self.nodelist. render(context_class(dict))936 return self.nodelist.iter_render(context_class(dict)) 908 937 909 938 compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, InclusionNode) 910 939 compile_func.__doc__ = func.__doc__ -
django/template/defaulttags.py
=== django/template/defaulttags.py ==================================================================
16 16 register = Library() 17 17 18 18 class CommentNode(Node): 19 def render(self, context):20 return ''19 def iter_render(self, context): 20 return () 21 21 22 22 class CycleNode(Node): 23 23 def __init__(self, cyclevars, variable_name=None): … … 26 26 self.counter = -1 27 27 self.variable_name = variable_name 28 28 29 def iter_render(self, context): 30 return (self.render(context),) 31 29 32 def render(self, context): 30 33 self.counter += 1 31 34 value = self.cyclevars[self.counter % self.cyclevars_len] … … 34 37 return value 35 38 36 39 class DebugNode(Node): 37 def render(self, context):40 def iter_render(self, context): 38 41 from pprint import pformat 39 output = [pformat(val) for val in context]40 output.append('\n\n')41 output.append(pformat(sys.modules))42 return ''.join(output)42 for val in context: 43 yield pformat(val) 44 yield "\n\n" 45 yield pformat(sys.modules) 43 46 44 47 class FilterNode(Node): 45 48 def __init__(self, filter_expr, nodelist): 46 49 self.filter_expr, self.nodelist = filter_expr, nodelist 47 50 48 def render(self, context):51 def iter_render(self, context): 49 52 output = self.nodelist.render(context) 50 53 # apply filters 51 54 context.update({'var': output}) 52 55 filtered = self.filter_expr.resolve(context) 53 56 context.pop() 54 return filtered57 return (filtered,) 55 58 56 59 class FirstOfNode(Node): 57 60 def __init__(self, vars): 58 61 self.vars = vars 59 62 63 def iter_render(self, context): 64 return (self.render(context),) 65 60 66 def render(self, context): 61 67 for var in self.vars: 62 68 try: … … 92 98 nodes.extend(self.nodelist_loop.get_nodes_by_type(nodetype)) 93 99 return nodes 94 100 95 def render(self, context): 96 nodelist = NodeList() 101 def iter_render(self, context): 97 102 if 'forloop' in context: 98 103 parentloop = context['forloop'] 99 104 else: … … 101 106 context.push() 102 107 try: 103 108 values = self.sequence.resolve(context, True) 109 if values is None: 110 values = () 111 elif not hasattr(values, '__len__'): 112 values = list(values) 104 113 except VariableDoesNotExist: 105 values = [] 106 if values is None: 107 values = [] 108 if not hasattr(values, '__len__'): 109 values = list(values) 114 values = () 110 115 len_values = len(values) 111 116 if self.reversed: 112 117 values = reversed(values) … … 125 130 'parentloop': parentloop, 126 131 } 127 132 if unpack: 128 # If there are multiple loop variables, unpack the item into them. 133 # If there are multiple loop variables, unpack the item into 134 # them. 129 135 context.update(dict(zip(self.loopvars, item))) 130 136 else: 131 137 context[self.loopvars[0]] = item 138 139 # We inline this to avoid the overhead since ForNode is pretty 140 # common. 132 141 for node in self.nodelist_loop: 133 nodelist.append(node.render(context)) 142 for chunk in node.iter_render(context): 143 yield chunk 134 144 if unpack: 135 145 # The loop variables were pushed on to the context so pop them 136 146 # off again. This is necessary because the tag lets the length … … 139 149 # context. 140 150 context.pop() 141 151 context.pop() 142 return nodelist.render(context)143 152 144 153 class IfChangedNode(Node): 145 154 def __init__(self, nodelist, *varlist): … … 147 156 self._last_seen = None 148 157 self._varlist = varlist 149 158 150 def render(self, context):159 def iter_render(self, context): 151 160 if 'forloop' in context and context['forloop']['first']: 152 161 self._last_seen = None 153 162 try: … … 165 174 self._last_seen = compare_to 166 175 context.push() 167 176 context['ifchanged'] = {'firstloop': firstloop} 168 content = self.nodelist.render(context) 177 for chunk in self.nodelist.iter_render(context): 178 yield chunk 169 179 context.pop() 170 return content171 else:172 return ''173 180 174 181 class IfEqualNode(Node): 175 182 def __init__(self, var1, var2, nodelist_true, nodelist_false, negate): … … 180 187 def __repr__(self): 181 188 return "<IfEqualNode>" 182 189 183 def render(self, context):190 def iter_render(self, context): 184 191 try: 185 192 val1 = resolve_variable(self.var1, context) 186 193 except VariableDoesNotExist: … … 190 197 except VariableDoesNotExist: 191 198 val2 = None 192 199 if (self.negate and val1 != val2) or (not self.negate and val1 == val2): 193 return self.nodelist_true. render(context)194 return self.nodelist_false. render(context)200 return self.nodelist_true.iter_render(context) 201 return self.nodelist_false.iter_render(context) 195 202 196 203 class IfNode(Node): 197 204 def __init__(self, bool_exprs, nodelist_true, nodelist_false, link_type): … … 216 223 nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) 217 224 return nodes 218 225 219 def render(self, context):226 def iter_render(self, context): 220 227 if self.link_type == IfNode.LinkTypes.or_: 221 228 for ifnot, bool_expr in self.bool_exprs: 222 229 try: … … 224 231 except VariableDoesNotExist: 225 232 value = None 226 233 if (value and not ifnot) or (ifnot and not value): 227 return self.nodelist_true. render(context)228 return self.nodelist_false. render(context)234 return self.nodelist_true.iter_render(context) 235 return self.nodelist_false.iter_render(context) 229 236 else: 230 237 for ifnot, bool_expr in self.bool_exprs: 231 238 try: … … 233 240 except VariableDoesNotExist: 234 241 value = None 235 242 if not ((value and not ifnot) or (ifnot and not value)): 236 return self.nodelist_false. render(context)237 return self.nodelist_true. render(context)243 return self.nodelist_false.iter_render(context) 244 return self.nodelist_true.iter_render(context) 238 245 239 246 class LinkTypes: 240 247 and_ = 0, … … 245 252 self.target, self.expression = target, expression 246 253 self.var_name = var_name 247 254 248 def render(self, context):255 def iter_render(self, context): 249 256 obj_list = self.target.resolve(context, True) 250 257 if obj_list == None: # target_var wasn't found in context; fail silently 251 258 context[self.var_name] = [] 252 return ''259 return () 253 260 # List of dictionaries in the format 254 261 # {'grouper': 'key', 'list': [list of contents]}. 255 262 context[self.var_name] = [{'grouper':key, 'list':list(val)} for key, val in 256 263 groupby(obj_list, lambda v, f=self.expression.resolve: f(v, True))] 257 return ''264 return () 258 265 259 266 def include_is_allowed(filepath): 260 267 for root in settings.ALLOWED_INCLUDE_ROOTS: … … 266 273 def __init__(self, filepath, parsed): 267 274 self.filepath, self.parsed = filepath, parsed 268 275 269 def render(self, context):276 def iter_render(self, context): 270 277 if not include_is_allowed(self.filepath): 271 278 if settings.DEBUG: 272 return "[Didn't have permission to include file]"279 return ("[Didn't have permission to include file]",) 273 280 else: 274 281 return '' # Fail silently for invalid includes. 275 282 try: … … 280 287 output = '' 281 288 if self.parsed: 282 289 try: 283 t = Template(output, name=self.filepath) 284 return t.render(context) 290 return Template(output, name=self.filepath).iter_render(context) 285 291 except TemplateSyntaxError, e: 286 292 if settings.DEBUG: 287 293 return "[Included template had syntax error: %s]" % e 288 294 else: 289 295 return '' # Fail silently for invalid included templates. 290 return output296 return (output,) 291 297 292 298 class LoadNode(Node): 293 def render(self, context):294 return ''299 def iter_render(self, context): 300 return () 295 301 296 302 class NowNode(Node): 297 303 def __init__(self, format_string): 298 304 self.format_string = format_string 299 305 306 def iter_render(self, context): 307 return (self.render(context),) 308 300 309 def render(self, context): 301 310 from datetime import datetime 302 311 from django.utils.dateformat import DateFormat … … 325 334 def __init__(self, tagtype): 326 335 self.tagtype = tagtype 327 336 337 def iter_render(self, context): 338 return (self.render(context),) 339 328 340 def render(self, context): 329 341 return self.mapping.get(self.tagtype, '') 330 342 … … 334 346 self.args = args 335 347 self.kwargs = kwargs 336 348 337 def render(self, context):349 def iter_render(self, context): 338 350 from django.core.urlresolvers import reverse, NoReverseMatch 339 351 args = [arg.resolve(context) for arg in self.args] 340 352 kwargs = dict([(k, v.resolve(context)) for k, v in self.kwargs.items()]) 341 353 try: 342 return reverse(self.view_name, args=args, kwargs=kwargs)354 return (reverse(self.view_name, args=args, kwargs=kwargs),) 343 355 except NoReverseMatch: 344 356 try: 345 357 project_name = settings.SETTINGS_MODULE.split('.')[0] 346 358 return reverse(project_name + '.' + self.view_name, args=args, kwargs=kwargs) 347 359 except NoReverseMatch: 348 return ''360 return () 349 361 350 362 class WidthRatioNode(Node): 351 363 def __init__(self, val_expr, max_expr, max_width): … … 353 365 self.max_expr = max_expr 354 366 self.max_width = max_width 355 367 368 def iter_render(self, context): 369 return (self.render(context),) 370 356 371 def render(self, context): 357 372 try: 358 373 value = self.val_expr.resolve(context) … … 376 391 def __repr__(self): 377 392 return "<WithNode>" 378 393 379 def render(self, context):394 def iter_render(self, context): 380 395 val = self.var.resolve(context) 381 396 context.push() 382 397 context[self.name] = val 383 output = self.nodelist.render(context) 398 for chunk in self.nodelist.iter_render(context): 399 yield chunk 384 400 context.pop() 385 return output386 401 387 402 #@register.tag 388 403 def comment(parser, token): -
django/template/loader_tags.py
=== django/template/loader_tags.py ==================================================================
15 15 def __repr__(self): 16 16 return "<Block Node: %s. Contents: %r>" % (self.name, self.nodelist) 17 17 18 def render(self, context):18 def iter_render(self, context): 19 19 context.push() 20 20 # Save context in case of block.super(). 21 21 self.context = context 22 22 context['block'] = self 23 result = self.nodelist.render(context) 23 for chunk in self.nodelist.iter_render(context): 24 yield chunk 24 25 context.pop() 25 return result26 26 27 27 def super(self): 28 28 if self.parent: … … 57 57 except TemplateDoesNotExist: 58 58 raise TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent 59 59 else: 60 return get_template_from_string(source, origin , parent)60 return get_template_from_string(source, origin) 61 61 62 def render(self, context):62 def iter_render(self, context): 63 63 compiled_parent = self.get_parent(context) 64 64 parent_is_child = isinstance(compiled_parent.nodelist[0], ExtendsNode) 65 65 parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)]) … … 79 79 parent_block.parent = block_node.parent 80 80 parent_block.add_parent(parent_block.nodelist) 81 81 parent_block.nodelist = block_node.nodelist 82 return compiled_parent. render(context)82 return compiled_parent.iter_render(context) 83 83 84 84 class ConstantIncludeNode(Node): 85 85 def __init__(self, template_path): … … 91 91 raise 92 92 self.template = None 93 93 94 def render(self, context):94 def iter_render(self, context): 95 95 if self.template: 96 return self.template.render(context) 97 else: 98 return '' 96 return self.template.iter_render(context) 97 return () 99 98 100 99 class IncludeNode(Node): 101 100 def __init__(self, template_name): 102 101 self.template_name = template_name 103 102 104 def render(self, context):103 def iter_render(self, context): 105 104 try: 106 105 template_name = resolve_variable(self.template_name, context) 107 106 t = get_template(template_name) 108 return t. render(context)107 return t.iter_render(context) 109 108 except TemplateSyntaxError, e: 110 109 if settings.TEMPLATE_DEBUG: 111 110 raise 112 return ''111 return () 113 112 except: 114 return ''# Fail silently for invalid included templates.113 return () # Fail silently for invalid included templates. 115 114 116 115 def do_block(parser, token): 117 116 """ -
django/template/loader.py
=== django/template/loader.py ==================================================================
76 76 Returns a compiled Template object for the given template name, 77 77 handling template inheritance recursively. 78 78 """ 79 source, origin = find_template_source(template_name) 80 template = get_template_from_string(source, origin, template_name) 81 return template 79 return get_template_from_string(*find_template_source(template_name)) 82 80 83 def get_template_from_string(source, origin=None , name=None):81 def get_template_from_string(source, origin=None): 84 82 """ 85 83 Returns a compiled Template object for the given template code, 86 84 handling template inheritance recursively. 87 85 """ 88 return Template(source, origin , name)86 return Template(source, origin) 89 87 90 def render_to_string(template_name, dictionary=None, context_instance=None):88 def _render_setup(template_name, dictionary=None, context_instance=None): 91 89 """ 92 Loads the given template_name and renders it with the given dictionary as 93 context. The template_name may be a string to load a single template using 94 get_template, or it may be a tuple to use select_template to find one of 95 the templates in the list. Returns a string. 90 Common setup code for render_to_string and render_to_iter. 96 91 """ 97 dictionary = dictionary or {} 92 if dictionary is None: 93 dictionary = {} 98 94 if isinstance(template_name, (list, tuple)): 99 95 t = select_template(template_name) 100 96 else: … … 103 99 context_instance.update(dictionary) 104 100 else: 105 101 context_instance = Context(dictionary) 106 return t .render(context_instance)102 return t, context_instance 107 103 104 def render_to_string(template_name, dictionary=None, context_instance=None): 105 """ 106 Loads the given template_name and renders it with the given dictionary as 107 context. The template_name may be a string to load a single template using 108 get_template, or it may be a tuple to use select_template to find one of 109 the templates in the list. Returns a string. 110 """ 111 t, c = _render_setup(template_name, dictionary=dictionary, context_instance=context_instance) 112 return t.render(c) 113 114 def render_to_iter(template_name, dictionary=None, context_instance=None): 115 """ 116 Loads the given template_name and renders it with the given dictionary as 117 context. The template_name may be a string to load a single template using 118 get_template, or it may be a tuple to use select_template to find one of 119 the templates in the list. Returns a string. 120 """ 121 t, c = _render_setup(template_name, dictionary=dictionary, context_instance=context_instance) 122 return t.iter_render(c) 123 124 108 125 def select_template(template_name_list): 109 126 "Given a list of template names, returns the first that can be loaded." 110 127 for template_name in template_name_list: -
tests/modeltests/multiple_databases/__init__.py
=== tests/modeltests/multiple_databases/__init__.py ==================================================================
1 pass -
tests/modeltests/multiple_databases/models.py
=== 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(maxlength=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(maxlength=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(maxlength=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(maxlength=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(maxlength=20) 68 model = models.CharField(maxlength=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/modeltests/multiple_databases ___________________________________________________________________ Name: svn:ignore +*.pyc + === tests/regressiontests/manager_db/__init__.py ================================================================== === tests/regressiontests/manager_db/tests.py ==================================================================
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.backend.quote_name 14 assert db.get_creation_module 15 16 if __name__ == '__main__': 17 unittest.main() -
tests/regressiontests/manager_db/models.py
=== tests/regressiontests/manager_db/models.py ==================================================================
1 from django.db import models 2 3 class Insect(models.Model): 4 common_name = models.CharField(maxlength=64) 5 latin_name = models.CharField(maxlength=128) -
tests/regressiontests/thread_isolation/tests.py
Property changes on: tests/regressiontests/manager_db ___________________________________________________________________ Name: svn:ignore +*.pyc + === tests/regressiontests/thread_isolation/__init__.py ================================================================== === tests/regressiontests/thread_isolation/tests.py ==================================================================
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
=== tests/regressiontests/thread_isolation/models.py ==================================================================
1 from django.db import models 2 3 # models 4 class MQ(models.Model): 5 val = models.CharField(maxlength=10) 6 class Meta: 7 app_label = 'ti' 8 9 10 class MX(models.Model): 11 val = models.CharField(maxlength=10) 12 class Meta: 13 app_label = 'ti' 14 15 16 class MY(models.Model): 17 val = models.CharField(maxlength=10) 18 class Meta: 19 app_label = 'ti' -
tests/regressiontests/ansi_sql/sql/car.sql
Property changes on: tests/regressiontests/thread_isolation ___________________________________________________________________ Name: svn:ignore +*.pyc + Property changes on: tests/regressiontests/initial_sql_regress/sql ___________________________________________________________________ Name: svn:ignore +*.pyc + === tests/regressiontests/ansi_sql/sql/car.sql ==================================================================
1 insert into ansi_sql_car (make, model, year, condition) 2 values ('Chevy', 'Impala', 1966, 'mint'); -
tests/regressiontests/ansi_sql/models.py
Property changes on: tests/regressiontests/ansi_sql/sql ___________________________________________________________________ Name: svn:ignore +*.pyc + === tests/regressiontests/ansi_sql/__init__.py ================================================================== === tests/regressiontests/ansi_sql/models.py ==================================================================
1 """ 2 >>> from django.db.backends.ansi import sql 3 4 # so we can test with a predicatable constraint setting 5 >>> real_cnst = Mod._default_manager.db.backend.supports_constraints 6 >>> Mod._default_manager.db.backend.supports_constraints = True 7 8 # generate create sql 9 >>> builder = sql.SchemaBuilder() 10 >>> builder.get_create_table(Car) 11 ([BoundStatement('CREATE TABLE "ansi_sql_car" (...);')], {}) 12 >>> builder.models_already_seen 13 Set([<class 'regressiontests.ansi_sql.models.Car'>]) 14 >>> builder.models_already_seen = set() 15 16 # test that styles are used 17 >>> builder.get_create_table(Car, style=mockstyle()) 18 ([BoundStatement('SQL_KEYWORD(CREATE TABLE) SQL_TABLE("ansi_sql_car") (...SQL_FIELD("id")...);')], {}) 19 20 # test pending relationships 21 >>> builder.models_already_seen = set() 22 >>> builder.get_create_table(Mod) 23 ([BoundStatement('CREATE TABLE "ansi_sql_mod" (..."car_id" integer NOT NULL,...);')], {<class 'regressiontests.ansi_sql.models.Car'>: [(<class 'regressiontests.ansi_sql.models.Mod'>, <django.db.models.fields.related.ForeignKey...>)]}) 24 >>> builder.models_already_seen = set() 25 >>> builder.get_create_table(Car) 26 ([BoundStatement('CREATE TABLE "ansi_sql_car" (...);')], {}) 27 >>> builder.get_create_table(Mod) 28 ([BoundStatement('CREATE TABLE "ansi_sql_mod" (..."car_id" integer NOT NULL REFERENCES "ansi_sql_car" ("id"),...);')], {}) 29 30 # test many-many 31 >>> builder.get_create_table(Collector) 32 ([BoundStatement('CREATE TABLE "ansi_sql_collector" (...);')], {}) 33 >>> builder.get_create_many_to_many(Collector) 34 {<class 'regressiontests.ansi_sql.models.Car'>: [BoundStatement('CREATE TABLE "ansi_sql_collector_cars" (...);')]} 35 36 # test indexes 37 >>> builder.get_create_indexes(Car) 38 [] 39 >>> builder.get_create_indexes(Mod) 40 [BoundStatement('CREATE INDEX ... ON "ansi_sql_mod" ("car_id");'), BoundStatement('CREATE INDEX ... ON "ansi_sql_mod" ("part");')] 41 >>> builder.get_create_indexes(Collector) 42 [] 43 44 # test initial data 45 # patch builder so that it looks for initial data where we want it to 46 # >>> builder.get_initialdata_path = othertests_sql 47 >>> builder.get_initialdata(Car) 48 [BoundStatement("insert into ansi_sql_car (...)...values (...);...")] 49 50 # test drop 51 >>> builder.get_drop_table(Mod) 52 [BoundStatement('DROP TABLE "ansi_sql_mod";')] 53 >>> builder.get_drop_table(Mod, cascade=True) 54 [BoundStatement('DROP TABLE "ansi_sql_mod";')] 55 >>> builder.get_drop_table(Car) 56 [BoundStatement('DROP TABLE "ansi_sql_car";')] 57 58 # drop with cascade 59 >>> builder.tables = ['ansi_sql_car', 'ansi_sql_mod', 'ansi_sql_collector'] 60 >>> Mod._default_manager.db.backend.supports_constraints = False 61 >>> Mod._default_manager.db.backend.supports_constraints 62 False 63 >>> Car._default_manager.db.backend.supports_constraints 64 False 65 >>> builder.get_drop_table(Car, cascade=True) 66 [BoundStatement('DROP TABLE "ansi_sql_car";')] 67 >>> Mod._default_manager.db.backend.supports_constraints = True 68 >>> Mod._default_manager.db.backend.supports_constraints 69 True 70 >>> Car._default_manager.db.backend.supports_constraints 71 True 72 >>> builder.get_drop_table(Car, cascade=True) 73 [BoundStatement('DROP TABLE "ansi_sql_car";'), BoundStatement('ALTER TABLE "ansi_sql_mod" ...')] 74 >>> builder.get_drop_table(Collector) 75 [BoundStatement('DROP TABLE "ansi_sql_collector";')] 76 >>> builder.get_drop_table(Collector, cascade=True) 77 [BoundStatement('DROP TABLE "ansi_sql_collector";'), BoundStatement('DROP TABLE "ansi_sql_collector_cars";')] 78 >>> Mod._default_manager.db.backend.supports_constraints = real_cnst 79 80 """ 81 #import os 82 #import sys 83 #from django.conf import settings 84 #from django.core.management import install 85 from django.db import models 86 #from django.db.models import loading 87 88 89 # For Python 2.3 90 if not hasattr(__builtins__, 'set'): 91 from sets import Set as set 92 93 94 # test models 95 class Car(models.Model): 96 make = models.CharField(maxlength=32) 97 model = models.CharField(maxlength=32) 98 year = models.IntegerField() 99 condition = models.CharField(maxlength=32) 100 101 102 class Collector(models.Model): 103 name = models.CharField(maxlength=32) 104 cars = models.ManyToManyField(Car) 105 106 107 class Mod(models.Model): 108 car = models.ForeignKey(Car) 109 part = models.CharField(maxlength=32, db_index=True) 110 description = models.TextField() 111 112 113 class mockstyle: 114 """mock style that wraps text in STYLE(text), for testing""" 115 def __getattr__(self, attr): 116 if attr in ('ERROR', 'ERROR_OUTPUT', 'SQL_FIELD', 'SQL_COLTYPE', 117 'SQL_KEYWORD', 'SQL_TABLE'): 118 return lambda text: "%s(%s)" % (attr, text) 119 120 121 # def othertests_sql(mod): 122 # """Look in othertests/sql for sql initialdata""" 123 # return os.path.normpath(os.path.join(os.path.dirname(__file__), 'sql')) 124 125 126 # # install my models and force myself into the registry of apps and models 127 # # (without this, references and such to/from the models installed here 128 # # won't be picked up in get_models(), since get_models() looks only at 129 # # models from apps in INSTALLED_APPS, and the model and app lookup rules 130 # # enforce a module structure that this test file can't follow) 131 # Car.objects.install() 132 # Collector.objects.install() 133 # Mod.objects.install() 134 # loading.get_apps() 135 # loading._app_list.append(sys.modules[__name__]) 136 137 # # model lookup only works for pk.models, so fake up my module name 138 # __name__ = 'othertests.ansi_sql.models' -
tests/regressiontests/request_isolation/tests.py
Property changes on: tests/regressiontests/ansi_sql ___________________________________________________________________ Name: svn:ignore +*.pyc + === tests/regressiontests/request_isolation/__init__.py ================================================================== === tests/regressiontests/request_isolation/tests.py ==================================================================
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
=== tests/regressiontests/request_isolation/models.py ==================================================================
1 from django.db import models 2 3 # models 4 class MX(models.Model): 5 val = models.CharField(maxlength=10) 6 class Meta: 7 app_label = 'ri' 8 9 10 class MY(models.Model): 11 val = models.CharField(maxlength=10) 12 class Meta: 13 app_label = 'ri' -
tests/regressiontests/manager_schema_manipulation/tests.py
Property changes on: tests/regressiontests/request_isolation ___________________________________________________________________ Name: svn:ignore +*.pyc + === tests/regressiontests/manager_schema_manipulation/__init__.py ================================================================== === tests/regressiontests/manager_schema_manipulation/tests.py ==================================================================
1 """ 2 # Django uses a model's default manager to perform schema 3 # manipulations such as creating or dropping the model's table. 4 5 >>> from django.db import models 6 >>> from django.conf import settings 7 >>> import copy 8 9 # save copy of settings so we can restore it later 10 >>> odb = copy.deepcopy(settings.OTHER_DATABASES) 11 >>> settings.OTHER_DATABASES['django_msm_test_db_a'] = { 'MODELS': ['msm.PA', 'msm.P', 'msm.PC']} 12 >>> settings.OTHER_DATABASES['django_msm_test_db_b'] = {'MODELS': ['msm.QA', 'msm.QB', 'msm.QC', 'msm.QD']} 13 14 # default connection 15 >>> class DA(models.Model): 16 ... name = models.CharField(maxlength=20) 17 ... 18 ... def __str__(self): 19 ... return self.name 20 21 # connection a 22 >>> class PA(models.Model): 23 ... name = models.CharField(maxlength=20) 24 ... # This creates a cycle in the dependency graph 25 ... c = models.ForeignKey('PC', null=True) 26 ... 27 ... def __str__(self): 28 ... return self.name 29 ... 30 ... class Meta: 31 ... app_label = 'msm' 32 33 >>> class PB(models.Model): 34 ... name = models.CharField(maxlength=20) 35 ... a = models.ForeignKey(PA) 36 ... 37 ... def __str__(self): 38 ... return self.name 39 ... 40 ... class Meta: 41 ... app_label = 'msm' 42 43 >>> class PC(models.Model): 44 ... name = models.CharField(maxlength=20) 45 ... b = models.ForeignKey(PB) 46 ... 47 ... def __str__(self): 48 ... return self.name 49 ... 50 ... class Meta: 51 ... app_label = 'msm' 52 53 # connection b 54 >>> class QA(models.Model): 55 ... name = models.CharField(maxlength=20) 56 ... 57 ... def __str__(self): 58 ... return self.name 59 ... 60 ... class Meta: 61 ... app_label = 'msm' 62 63 >>> class QB(models.Model): 64 ... name = models.CharField(maxlength=20) 65 ... a = models.ForeignKey(QA) 66 ... 67 ... def __str__(self): 68 ... return self.name 69 ... 70 ... class Meta: 71 ... app_label = 'msm' 72 73 # many-many 74 >>> class QC(models.Model): 75 ... name = models.CharField(maxlength=20) 76 ... 77 ... def __str__(self): 78 ... return self.name 79 ... 80 ... class Meta: 81 ... app_label = 'msm' 82 83 >>> class QD(models.Model): 84 ... name = models.CharField(maxlength=20) 85 ... qcs = models.ManyToManyField(QC) 86 ... 87 ... def __str__(self): 88 ... return self.name 89 ... 90 ... class Meta: 91 ... app_label = 'msm' 92 93 # Using the manager, models can be installed individually, whether they 94 # use the default connection or a named connection. 95 96 >>> DA.objects.install() 97 {} 98 >>> QA.objects.install() 99 {} 100 >>> QB.objects.install() 101 {} 102 >>> DA.objects.all() 103 [] 104 >>> list(QA.objects.all()) 105 [] 106 >>> list(QB.objects.all()) 107 [] 108 >>> QA(name="something").save() 109 >>> QA.objects.all() 110 [<QA: something>] 111 112 # The `install()` method returns a tuple, the first element of which is a 113 # list of statements that were executed, and the second, pending 114 # statements that could not be executed because (for instance) they are 115 # meant to establish foreign key relationships to tables that don't 116 # exist. These are bound to the model's connection and should 117 # be executed after all models in the app have been installed. The pending 118 # statments are returned as a dict keyed by the model which must be installed 119 # before the pending statements can be installed. 120 121 # NOTE: pretend db supports constraints for this test 122 >>> real_cnst = PA._default_manager.db.backend.supports_constraints 123 >>> PA._default_manager.db.backend.supports_constraints = True 124 >>> result = PA.objects.install() 125 >>> result 126 {<class 'regressiontests.manager_schema_manipulation.tests.PC'>: [(<class 'regressiontests.manager_schema_manipulation.tests.PA'>, <django.db.models.fields.related.ForeignKey ...>)]} 127 128 # NOTE: restore real constraint flag 129 >>> PA._default_manager.db.backend.supports_constraints = real_cnst 130 131 # Models with many-many relationships may also have pending statement 132 # lists. Like other pending statements, these should be executed after 133 # all models in the app have been installed. If the related table's model 134 # has already been created, then there will be no pending list. 135 136 >>> QC.objects.install() 137 {} 138 >>> QD.objects.install() 139 {} 140 141 # Finally, restore the original settings 142 >>> settings.OTHER_DATABASES = odb 143 """ -
tests/runtests.py
=== tests/regressiontests/manager_schema_manipulation/models.py ================================================================== Property changes on: tests/regressiontests/manager_schema_manipulation ___________________________________________________________________ Name: svn:ignore +*.pyc + === tests/runtests.py ==================================================================
12 12 TEST_TEMPLATE_DIR = 'templates' 13 13 14 14 CONTRIB_DIR = os.path.dirname(contrib.__file__) 15 16 TEST_DATABASES = ('_a', '_b') 17 18 TEST_DATABASE_MODELS = { 19 '_a': [ 'multiple_databases.Artist', 20 'multiple_databases.Opus' ], 21 '_b': [ 'multiple_databases.Widget', 22 'multiple_databases.DooHickey' ] 23 } 24 25 15 26 MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME) 16 27 REGRESSION_TEST_DIR = os.path.join(os.path.dirname(__file__), REGRESSION_TESTS_DIR_NAME) 17 28 … … 86 97 # Redirect some settings for the duration of these tests. 87 98 settings.TEST_DATABASE_NAME = TEST_DATABASE_NAME 88 99 settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS 100 settings.TEST_DATABASES = TEST_DATABASES 101 settings.TEST_DATABASE_MODELS = TEST_DATABASE_MODELS 89 102 settings.ROOT_URLCONF = 'urls' 90 103 settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),) 91 104 settings.USE_I18N = True -
docs/settings.txt
Property changes on: tests/templates ___________________________________________________________________ Name: svn:ignore +*.pyc + === docs/settings.txt ==================================================================
640 640 See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT, 641 641 TIME_FORMAT and YEAR_MONTH_FORMAT. 642 642 643 OTHER_DATABASES 644 --------------- 645 646 Default: ``{}`` 647 648 Other database connections to use in addition to the default connection. See the `multiple database support docs`_. 649 643 650 PREPEND_WWW 644 651 ----------- 645 652 … … 966 973 967 974 .. _cache docs: ../cache/ 968 975 .. _middleware docs: ../middleware/ 976 .. _multiple database support docs: ../multiple_database_support/ 969 977 .. _session docs: ../sessions/ 970 978 .. _See available choices: http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE 971 979 .. _template documentation: ../templates_python/ -
docs/multiple_database_support.txt
=== 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/templates_python.txt
=== docs/templates_python.txt ==================================================================
219 219 220 220 While ``TEMPLATE_STRING_IF_INVALID`` can be a useful debugging tool, 221 221 it is a bad idea to turn it on as a 'development default'. 222 222 223 223 Many templates, including those in the Admin site, rely upon the 224 224 silence of the template system when a non-existent variable is 225 225 encountered. If you assign a value other than ``''`` to 226 226 ``TEMPLATE_STRING_IF_INVALID``, you will experience rendering 227 227 problems with these templates and sites. 228 228 229 229 Generally, ``TEMPLATE_STRING_IF_INVALID`` should only be enabled 230 230 in order to debug a specific template problem, then cleared 231 231 once debugging is complete. … … 693 693 694 694 When Django compiles a template, it splits the raw template text into 695 695 ''nodes''. Each node is an instance of ``django.template.Node`` and has 696 a ``render()`` method. A compiled template is, simply, a list of ``Node`` 697 objects. When you call ``render()`` on a compiled template object, the template 698 calls ``render()`` on each ``Node`` in its node list, with the given context. 699 The results are all concatenated together to form the output of the template. 696 either a ``render()`` or ``iter_render()`` method. A compiled template is, 697 simply, a list of ``Node`` objects. When you call ``render()`` on a compiled 698 template object, the template calls ``render()`` on each ``Node`` in its node 699 list, with the given context. The results are all concatenated together to 700 form the output of the template. 700 701 701 702 Thus, to define a custom template tag, you specify how the raw template tag is 702 703 converted into a ``Node`` (the compilation function), and what the node's 703 ``render()`` method does.704 ``render()`` or ``iter_render()`` method does. 704 705 705 706 Writing the compilation function 706 707 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ … … 770 771 ~~~~~~~~~~~~~~~~~~~~ 771 772 772 773 The second step in writing custom tags is to define a ``Node`` subclass that 773 has a ``render()`` method. 774 has a ``render()`` method (we will discuss the ``iter_render()`` alternative 775 in `Improving rendering speed`_, below). 774 776 775 777 Continuing the above example, we need to define ``CurrentTimeNode``:: 776 778 … … 874 876 def __init__(self, date_to_be_formatted, format_string): 875 877 self.date_to_be_formatted = date_to_be_formatted 876 878 self.format_string = format_string 877 879 878 880 def render(self, context): 879 881 try: 880 882 actual_date = resolve_variable(self.date_to_be_formatted, context) … … 1175 1177 1176 1178 .. _configuration: 1177 1179 1180 Improving rendering speed 1181 ~~~~~~~~~~~~~~~~~~~~~~~~~ 1182 1183 For most practical purposes, the ``render()`` method on a ``Node`` will be 1184 sufficient and the simplest way to implement a new tag. However, if your 1185 template tag is expected to produce large strings via ``render()``, you can 1186 speed up the rendering process (and reduce memory usage) using iterative 1187 rendering via the ``iter_render()`` method. 1188 1189 The ``iter_render()`` method should either be an iterator that yields string 1190 chunks, one at a time, or a method that returns a sequence of string chunks. 1191 The template renderer will join the successive chunks together when creating 1192 the final output. The improvement over the ``render()`` method here is that 1193 you do not need to create one large string containing all the output of the 1194 ``Node``, instead you can produce the output in smaller chunks. 1195 1196 By way of example, here's a trivial ``Node`` subclass that simply returns the 1197 contents of a file it is given:: 1198 1199 class FileNode(Node): 1200 def __init__(self, filename): 1201 self.filename = filename 1202 1203 def iter_render(self): 1204 for line in file(self.filename): 1205 yield line 1206 1207 For very large files, the full file contents will never be read entirely into 1208 memory when this tag is used, which is a useful optimisation. 1209 1210 If you define an ``iter_render()`` method on your ``Node`` subclass, you do 1211 not need to define a ``render()`` method. The reverse is true as well: the 1212 default ``Node.iter_render()`` method will call your ``render()`` method if 1213 necessary. A useful side-effect of this is that you can develop a new tag 1214 using ``render()`` and producing all the output at once, which is easy to 1215 debug. Then you can rewrite the method as an iterator, rename it to 1216 ``iter_render()`` and everything will still work. 1217 1218 It is compulsory, however, to define *either* ``render()`` or ``iter_render()`` 1219 in your subclass. If you omit them both, a ``TypeError`` will be raised when 1220 the code is imported. 1221 1178 1222 Configuring the template system in standalone mode 1179 1223 ================================================== 1180 1224 … … 1206 1250 1207 1251 .. _settings file: ../settings/#using-settings-without-the-django-settings-module-environment-variable 1208 1252 .. _settings documentation: ../settings/ 1253