Ticket #4747: multi-db-6110.diff

File multi-db-6110.diff, 188.6 KB (added by ben <ben.fordnz@…>, 8 years ago)

Koens diff against trunk -r6110.

Line 
1=== django/test/utils.py
2==================================================================
3--- django/test/utils.py        (/mirror/django/trunk)  (revision 3932)
4
5+++ django/test/utils.py        (/local/django/multidb) (revision 3932)
6
7@@ -1,6 +1,6 @@
8
9 import sys, time
10 from django.conf import settings
11-from django.db import connection, get_creation_module
12+from django.db import connection, connections, get_creation_module
13 from django.core import mail
14 from django.core.management import call_command
15 from django.dispatch import dispatcher
16@@ -106,6 +106,7 @@
17
18     # in-memory database.
19     if settings.DATABASE_ENGINE == "sqlite3":
20         TEST_DATABASE_NAME = ":memory:"
21+##        TEST_DATABASE_NAME = settings.TEST_DATABASE_NAME
22     else:
23         suffix = {
24             'postgresql': get_postgresql_create_suffix,
25@@ -145,9 +146,9 @@
26
27             else:
28                 print "Tests cancelled."
29                 sys.exit(1)
30-
31-    connection.close()
32+        connection.close()
33     settings.DATABASE_NAME = TEST_DATABASE_NAME
34+    settings.OTHER_DATABASES = settings.TEST_OTHER_DATABASES
35 
36     call_command('syncdb', verbosity=verbosity, interactive=False)
37 
38@@ -161,7 +162,8 @@
39
40 
41     return TEST_DATABASE_NAME
42 
43-def destroy_test_db(old_database_name, verbosity=1):
44+def destroy_test_db(old_database_name, old_databases, verbosity=1):
45+
46     # If the database wants to drop the test DB itself, let it
47     creation_module = get_creation_module()
48     if hasattr(creation_module, "destroy_test_db"):
49@@ -175,10 +177,23 @@
50
51     if verbosity >= 1:
52         print "Destroying test database..."
53     connection.close()
54+    for cnx in connections.keys():
55+        connections[cnx].close()
56+    connections.reset()
57     TEST_DATABASE_NAME = settings.DATABASE_NAME
58+    if verbosity >= 2:
59+        print "Closed connections to %s" % TEST_DATABASE_NAME
60     settings.DATABASE_NAME = old_database_name
61 
62     if settings.DATABASE_ENGINE != "sqlite3":
63+        settings.OTHER_DATABASES = old_databases
64+        for cnx in connections.keys():
65+            try:
66+                connections[cnx].connection.cursor()
67+            except (KeyboardInterrupt, SystemExit):
68+                raise
69+            except:
70+                pass
71         cursor = connection.cursor()
72         _set_autocommit(connection)
73         time.sleep(1) # To avoid "database is being accessed by other users" errors.
74=== django/db/models/base.py
75==================================================================
76--- django/db/models/base.py    (/mirror/django/trunk)  (revision 3932)
77
78+++ django/db/models/base.py    (/local/django/multidb) (revision 3932)
79
80@@ -6,7 +6,7 @@
81
82 from django.db.models.fields.related import OneToOneRel, ManyToOneRel
83 from django.db.models.query import delete_objects
84 from django.db.models.options import Options, AdminOptions
85-from django.db import connection, transaction
86+from django.db import transaction
87 from django.db.models import signals
88 from django.db.models.loading import register_models, get_model
89 from django.dispatch import dispatcher
90@@ -204,6 +204,8 @@
91
92     def save(self, raw=False):
93         dispatcher.send(signal=signals.pre_save, sender=self.__class__, instance=self)
94 
95+        db = self.__class__._default_manager.db
96+        connection = db.connection
97         non_pks = [f for f in self._meta.fields if not f.primary_key]
98         cursor = connection.cursor()
99 
100@@ -222,7 +224,7 @@
101
102                 self._meta.pk.get_db_prep_lookup('exact', pk_val))
103             # If it does already exist, do an UPDATE.
104             if cursor.fetchone():
105-                db_values = [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, False)) for f in non_pks]
106+                db_values = [f.get_db_prep_save(self, raw and getattr(self, f.attname) or f.pre_save(self, False)) for f in non_pks]
107                 if db_values:
108                     cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
109                         (qn(self._meta.db_table),
110@@ -233,11 +235,11 @@
111
112                 record_exists = False
113         if not pk_set or not record_exists:
114             field_names = [qn(f.column) for f in self._meta.fields if not isinstance(f, AutoField)]
115-            db_values = [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)]
116+            db_values = [f.get_db_prep_save(self, raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if not isinstance(f, AutoField)]
117             # If the PK has been manually set, respect that.
118             if pk_set:
119                 field_names += [f.column for f in self._meta.fields if isinstance(f, AutoField)]
120-                db_values += [f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)]
121+                db_values += [f.get_db_prep_save(self, raw and getattr(self, f.attname) or f.pre_save(self, True)) for f in self._meta.fields if isinstance(f, AutoField)]
122             placeholders = ['%s'] * len(field_names)
123             if self._meta.order_with_respect_to:
124                 field_names.append(qn('_order'))
125@@ -256,7 +258,7 @@
126
127                      connection.ops.pk_default_value()))
128             if self._meta.has_auto_field and not pk_set:
129                 setattr(self, self._meta.pk.attname, connection.ops.last_insert_id(cursor, self._meta.db_table, self._meta.pk.column))
130-        transaction.commit_unless_managed()
131+        transaction.commit_unless_managed([connection])
132 
133         # Run any post-save hooks.
134         dispatcher.send(signal=signals.post_save, sender=self.__class__, instance=self)
135@@ -327,6 +329,8 @@
136
137         return force_unicode(dict(field.choices).get(value, value), strings_only=True)
138 
139     def _get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
140+        db = self.__class__._default_manager.db
141+        connection = db.connection
142         qn = connection.ops.quote_name
143         op = is_next and '>' or '<'
144         where = '(%s %s %%s OR (%s = %%s AND %s.%s %s %%s))' % \
145@@ -342,6 +346,8 @@
146
147             raise self.DoesNotExist, "%s matching query does not exist." % self.__class__._meta.object_name
148 
149     def _get_next_or_previous_in_order(self, is_next):
150+        db = self.__class__._default_manager.db
151+        connection = db.connection
152         qn = connection.ops.quote_name
153         cachename = "__%s_order_cache" % is_next
154         if not hasattr(self, cachename):
155@@ -432,6 +438,8 @@
156
157 # ORDERING METHODS #########################
158 
159 def method_set_order(ordered_obj, self, id_list):
160+    db = ordered_obj._default_manager.db
161+    connection = db.connection
162     qn = connection.ops.quote_name
163     cursor = connection.cursor()
164     # Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s"
165@@ -441,9 +449,11 @@
166
167         qn(ordered_obj._meta.pk.column))
168     rel_val = getattr(self, ordered_obj._meta.order_with_respect_to.rel.field_name)
169     cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)])
170-    transaction.commit_unless_managed()
171+    transaction.commit_unless_managed([connection])
172 
173 def method_get_order(ordered_obj, self):
174+    db = ordered_obj._default_manager.db
175+    connection = db.connection
176     qn = connection.ops.quote_name
177     cursor = connection.cursor()
178     # Example: "SELECT id FROM poll_choices WHERE poll_id = %s ORDER BY _order"
179=== django/db/models/manager.py
180==================================================================
181--- django/db/models/manager.py (/mirror/django/trunk)  (revision 3932)
182
183+++ django/db/models/manager.py (/local/django/multidb) (revision 3932)
184
185@@ -1,6 +1,7 @@
186
187-from django.db.models.query import QuerySet, EmptyQuerySet
188+from django.db import ConnectionInfoDescriptor
189+from django.db.models.query import _QuerySet, EmptyQuerySet
190 from django.dispatch import dispatcher
191-from django.db.models import signals
192+from django.db.models import signals, get_apps, get_models
193 from django.db.models.fields import FieldDoesNotExist
194 
195 def ensure_default_manager(sender):
196@@ -13,13 +14,17 @@
197
198         except FieldDoesNotExist:
199             pass
200         cls.add_to_class('objects', Manager())
201+    elif cls._default_manager.model != cls:
202+        # cls is an inherited model; don't want the parent manager
203+        cls.add_to_class('objects', Manager())
204 
205 dispatcher.connect(ensure_default_manager, signal=signals.class_prepared)
206 
207 class Manager(object):
208     # Tracks each time a Manager instance is created. Used to retain order.
209     creation_counter = 0
210-
211+    db = ConnectionInfoDescriptor()
212+   
213     def __init__(self):
214         super(Manager, self).__init__()
215         # Increase the creation counter, and save our local copy.
216@@ -31,9 +36,11 @@
217
218         # TODO: Use weakref because of possible memory leak / circular reference.
219         self.model = model
220         setattr(model, name, ManagerDescriptor(self))
221-        if not hasattr(model, '_default_manager') or self.creation_counter < model._default_manager.creation_counter:
222+        if not hasattr(model, '_default_manager') \
223+            or self.creation_counter < model._default_manager.creation_counter \
224+            or model._default_manager.model != model:
225             model._default_manager = self
226-
227+       
228     #######################
229     # PROXIES TO QUERYSET #
230     #######################
231@@ -45,7 +52,11 @@
232
233         """Returns a new QuerySet object.  Subclasses can override this method
234         to easily customize the behavior of the Manager.
235         """
236-        return QuerySet(self.model)
237+        if self.db.connection.features.uses_custom_queryset:
238+            QS = self.db.connection.ops.query_set_class(_QuerySet)
239+            return QS(self.model)
240+        else:
241+            return _QuerySet(self.model)
242     
243     def none(self):
244         return self.get_empty_query_set()
245@@ -111,3 +122,4 @@
246
247         if instance != None:
248             raise AttributeError, "Manager isn't accessible via %s instances" % type.__name__
249         return self.manager
250+
251=== django/db/models/options.py
252==================================================================
253--- django/db/models/options.py (/mirror/django/trunk)  (revision 3932)
254
255+++ django/db/models/options.py (/local/django/multidb) (revision 3932)
256
257@@ -1,4 +1,5 @@
258
259 from django.conf import settings
260+from django.db import connection_info, connections
261 from django.db.models.related import RelatedObject
262 from django.db.models.fields.related import ManyToManyRel
263 from django.db.models.fields import AutoField, FieldDoesNotExist
264@@ -9,6 +10,7 @@
265
266 from django.utils.encoding import force_unicode, smart_str
267 from bisect import bisect
268 import re
269+import weakref
270 
271 # Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
272 get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', ' \\1', class_name).lower().strip()
273@@ -81,6 +83,9 @@
274
275             self.db_table = "%s_%s" % (self.app_label, self.module_name)
276             self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
277 
278+        # Keep a weakref to my model, for access to managers and such
279+        self._model = weakref.ref(model)
280+
281     def add_field(self, field):
282         # Insert the given field in the order in which it was created, using
283         # the "creation_counter" attribute of the field.
284@@ -120,6 +125,12 @@
285
286                 return f
287         raise FieldDoesNotExist, '%s has no field named %r' % (self.object_name, name)
288 
289+    def get_default_manager(self):
290+        model = self._model()
291+        if model is None:
292+            raise ReferenceError("Model no longer available in %s" % self)
293+        return model._default_manager
294+
295     def get_order_sql(self, table_prefix=''):
296         "Returns the full 'ORDER BY' clause for this object, according to self.ordering."
297         if not self.ordering: return ''
298=== django/db/models/fields/__init__.py
299==================================================================
300--- django/db/models/fields/__init__.py (/mirror/django/trunk)  (revision 3932)
301
302+++ django/db/models/fields/__init__.py (/local/django/multidb) (revision 3932)
303
304@@ -201,7 +201,7 @@
305
306         "Returns field's value just before saving."
307         return getattr(model_instance, self.attname)
308 
309-    def get_db_prep_save(self, value):
310+    def get_db_prep_save(self, model_instance, value):
311         "Returns field's value prepared for saving into a database."
312         return value
313 
314@@ -535,11 +535,11 @@
315
316         else:
317             return self.editable or self.auto_now or self.auto_now_add
318 
319-    def get_db_prep_save(self, value):
320+    def get_db_prep_save(self, model_instance, value):
321         # Casts dates into string format for entry into database.
322         if value is not None:
323             value = value.strftime('%Y-%m-%d')
324-        return Field.get_db_prep_save(self, value)
325+        return Field.get_db_prep_save(self, model_instance, value)
326 
327     def get_manipulator_field_objs(self):
328         return [oldforms.DateField]
329@@ -572,7 +572,17 @@
330
331                 except ValueError:
332                     raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM format.')
333 
334-    def get_db_prep_save(self, value):
335+    def pre_save(self, model_instance, add):
336+        value = super(DateTimeField, self).pre_save(model_instance, add)
337+        if value is not None:
338+            # MySQL will throw a warning if microseconds are given, because it
339+            # doesn't support microseconds.
340+            settings = model_instance._default_manager.db.connection.settings
341+            if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
342+                value = value.replace(microsecond=0)
343+        return value
344+
345+    def get_db_prep_save(self, model_instance, value):
346         # Casts dates into string format for entry into database.
347         if value is not None:
348             # MySQL will throw a warning if microseconds are given, because it
349@@ -580,7 +590,7 @@
350
351             if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
352                 value = value.replace(microsecond=0)
353             value = smart_unicode(value)
354-        return Field.get_db_prep_save(self, value)
355+        return Field.get_db_prep_save(self, model_instance, value)
356 
357     def get_db_prep_lookup(self, lookup_type, value):
358         if lookup_type == 'range':
359@@ -654,10 +664,10 @@
360
361 
362         return u"%.*f" % (self.decimal_places, value)
363 
364-    def get_db_prep_save(self, value):
365+    def get_db_prep_save(self, model_instance, value):
366         if value is not None:
367             value = self._format(value)
368-        return super(DecimalField, self).get_db_prep_save(value)
369+        return super(DecimalField, self).get_db_prep_save(model_instance, value)
370 
371     def get_db_prep_lookup(self, lookup_type, value):
372         if lookup_type == 'range':
373@@ -962,11 +972,12 @@
374
375         else:
376             return super(TimeField, self).pre_save(model_instance, add)
377 
378-    def get_db_prep_save(self, value):
379+    def get_db_prep_save(self, model_instance, value):
380         # Casts dates into string format for entry into database.
381         if value is not None:
382             # MySQL will throw a warning if microseconds are given, because it
383             # doesn't support microseconds.
384+            settings = model_instance._default_manager.db.connection.settings
385             if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
386                 value = value.replace(microsecond=0)
387             if settings.DATABASE_ENGINE == 'oracle':
388@@ -978,7 +989,7 @@
389
390                     value = datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6]))
391             else:
392                 value = smart_unicode(value)
393-        return Field.get_db_prep_save(self, value)
394+        return Field.get_db_prep_save(self, model_instance, value)
395 
396     def get_manipulator_field_objs(self):
397         return [oldforms.TimeField]
398=== django/db/models/fields/related.py
399==================================================================
400--- django/db/models/fields/related.py  (/mirror/django/trunk)  (revision 3932)
401
402+++ django/db/models/fields/related.py  (/local/django/multidb) (revision 3932)
403
404@@ -1,4 +1,4 @@
405
406-from django.db import connection, transaction
407+from django.db import transaction
408 from django.db.models import signals, get_model
409 from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, get_ul_class
410 from django.db.models.related import RelatedObject
411@@ -319,6 +319,7 @@
412
413             # source_col_name: the PK colname in join_table for the source object
414             # target_col_name: the PK colname in join_table for the target object
415             # *objs - objects to add. Either object instances, or primary keys of object instances.
416+            connection = self.model._default_manager.db.connection
417 
418             # If there aren't any objects, there is nothing to do.
419             if objs:
420@@ -343,12 +344,13 @@
421
422                     cursor.execute("INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
423                         (self.join_table, source_col_name, target_col_name),
424                         [self._pk_val, obj_id])
425-                transaction.commit_unless_managed()
426+            transaction.commit_unless_managed(connection)
427 
428         def _remove_items(self, source_col_name, target_col_name, *objs):
429             # source_col_name: the PK colname in join_table for the source object
430             # target_col_name: the PK colname in join_table for the target object
431             # *objs - objects to remove
432+            connection = self.model._default_manager.db.connection
433 
434             # If there aren't any objects, there is nothing to do.
435             if objs:
436@@ -365,15 +367,16 @@
437
438                     (self.join_table, source_col_name,
439                     target_col_name, ",".join(['%s'] * len(old_ids))),
440                     [self._pk_val] + list(old_ids))
441-                transaction.commit_unless_managed()
442+            transaction.commit_unless_managed(connection)
443 
444         def _clear_items(self, source_col_name):
445             # source_col_name: the PK colname in join_table for the source object
446+            connection = self.model._default_manager.db.connection
447             cursor = connection.cursor()
448             cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
449                 (self.join_table, source_col_name),
450                 [self._pk_val])
451-            transaction.commit_unless_managed()
452+            transaction.commit_unless_managed(connection)
453 
454     return ManyRelatedManager
455 
456@@ -397,7 +400,7 @@
457
458         superclass = rel_model._default_manager.__class__
459         RelatedManager = create_many_related_manager(superclass)
460 
461-        qn = connection.ops.quote_name
462+        qn = rel_model._default_manager.db.connection.ops.quote_name
463         manager = RelatedManager(
464             model=rel_model,
465             core_filters={'%s__pk' % self.related.field.name: instance._get_pk_val()},
466@@ -438,7 +441,7 @@
467
468         superclass = rel_model._default_manager.__class__
469         RelatedManager = create_many_related_manager(superclass)
470 
471-        qn = connection.ops.quote_name
472+        qn = rel_model._default_manager.db.connection.ops.quote_name
473         manager = RelatedManager(
474             model=rel_model,
475             core_filters={'%s__pk' % self.field.related_query_name(): instance._get_pk_val()},
476@@ -519,11 +522,11 @@
477
478         else:
479             return [oldforms.IntegerField]
480 
481-    def get_db_prep_save(self, value):
482+    def get_db_prep_save(self, model_instance, value):
483         if value == '' or value == None:
484             return None
485         else:
486-            return self.rel.get_related_field().get_db_prep_save(value)
487+            return self.rel.get_related_field().get_db_prep_save(model_instance, value)
488 
489     def flatten_data(self, follow, obj=None):
490         if not obj:
491=== django/db/models/query.py
492==================================================================
493--- django/db/models/query.py   (/mirror/django/trunk)  (revision 3932)
494
495+++ django/db/models/query.py   (/local/django/multidb) (revision 3932)
496
497@@ -77,11 +77,11 @@
498
499             output.append('%s%s ASC' % (prefix, qn(orderfield2column(f, opts))))
500     return ', '.join(output)
501 
502-def quote_only_if_word(word):
503+def quote_only_if_word(word, qn):
504     if re.search('\W', word): # Don't quote if there are spaces or non-word chars.
505         return word
506     else:
507-        return connection.ops.quote_name(word)
508+        return qn(word)
509 
510 class _QuerySet(object):
511     "Represents a lazy database lookup for a set of objects"
512@@ -184,8 +184,7 @@
513
514         # self._select is a dictionary, and dictionaries' key order is
515         # undefined, so we convert it to a list of tuples.
516         extra_select = self._select.items()
517-
518-        cursor = connection.cursor()
519+        cursor = self.model._default_manager.db.connection.cursor()
520         cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
521 
522         fill_cache = self._select_related
523@@ -219,7 +218,9 @@
524
525         """
526         if self._result_cache is not None:
527             return len(self._result_cache)
528-
529+        #from multi-db
530+        connection = self.model._default_manager.db.connection
531+       
532         counter = self._clone()
533         counter._order_by = ()
534         counter._select_related = False
535@@ -306,6 +307,7 @@
536
537         Returns a dictionary mapping each of the given IDs to the object with
538         that ID.
539         """
540+        connection = self.model._default_manager.db.connection
541         assert self._limit is None and self._offset is None, \
542                 "Cannot use 'limit' or 'offset' with in_bulk"
543         assert isinstance(id_list, (tuple,  list)), "in_bulk() must be provided with a list of IDs."
544@@ -483,12 +485,12 @@
545
546         return self._result_cache
547 
548     def _get_sql_clause(self):
549+        connection = self.model._default_manager.db.connection
550         qn = connection.ops.quote_name
551         opts = self.model._meta
552-
553         # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z.
554         select = ["%s.%s" % (qn(opts.db_table), qn(f.column)) for f in opts.fields]
555-        tables = [quote_only_if_word(t) for t in self._tables]
556+        tables = [quote_only_if_word(t, qn) for t in self._tables]
557         joins = SortedDict()
558         where = self._where[:]
559         params = self._params[:]
560@@ -508,7 +510,7 @@
561
562 
563         # Add any additional SELECTs.
564         if self._select:
565-            select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), qn(s[0])) for s in self._select.items()])
566+            select.extend(['(%s) AS %s' % (quote_only_if_word(s[1], qn), qn(s[0])) for s in self._select.items()])
567 
568         # Start composing the body of the SQL statement.
569         sql = [" FROM", qn(opts.db_table)]
570@@ -565,6 +567,7 @@
571
572         return select, " ".join(sql), params
573 
574 # Use the backend's QuerySet class if it defines one. Otherwise, use _QuerySet.
575+# This is now in manager.py
576 if connection.features.uses_custom_queryset:
577     QuerySet = connection.ops.query_set_class(_QuerySet)
578 else:
579@@ -582,6 +585,9 @@
580
581         except EmptyResultSet:
582             raise StopIteration
583 
584+        #from multi-db
585+        db = self.model._default_manager.db
586+        connection = db.connection
587         qn = connection.ops.quote_name
588 
589         # self._select is a dictionary, and dictionaries' key order is
590@@ -612,7 +618,7 @@
591
592         columns = [f.column for f in fields]
593         select = ['%s.%s' % (qn(self.model._meta.db_table), qn(c)) for c in columns]
594         if extra_select:
595-            select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), qn(s[0])) for s in extra_select])
596+            select.extend(['(%s) AS %s' % (quote_only_if_word(s[1], qn), qn(s[0])) for s in extra_select])
597             field_names.extend([f[0] for f in extra_select])
598 
599         cursor = connection.cursor()
600@@ -638,6 +644,8 @@
601
602         from django.db.backends.util import typecast_timestamp
603         from django.db.models.fields import DateTimeField
604 
605+        db = self.model._default_manager.db
606+        connection = db.connection
607         qn = connection.ops.quote_name
608         self._order_by = () # Clear this because it'll mess things up otherwise.
609         if self._field.null:
610@@ -783,7 +791,8 @@
611
612             return SortedDict(), [], []
613         return joins, where2, params
614 
615-def get_where_clause(lookup_type, table_prefix, field_name, value, db_type):
616+def get_where_clause(opts, lookup_type, table_prefix, field_name, value, db_type):
617+    connection = opts.get_default_manager().db.connection
618     if table_prefix.endswith('.'):
619         table_prefix = connection.ops.quote_name(table_prefix[:-1])+'.'
620     field_name = connection.ops.quote_name(field_name)
621@@ -847,6 +856,7 @@
622
623     Helper function that recursively populates the select, tables and where (in
624     place) for select_related queries.
625     """
626+    connection = opts.get_default_manager().db.connection
627 
628     # If we've got a max_depth set and we've exceeded that depth, bail now.
629     if max_depth and cur_depth > max_depth:
630@@ -950,13 +960,20 @@
631
632     return choices
633 
634 def lookup_inner(path, lookup_type, value, opts, table, column):
635-    qn = connection.ops.quote_name
636     joins, where, params = SortedDict(), [], []
637     current_opts = opts
638     current_table = table
639     current_column = column
640     intermediate_table = None
641     join_required = False
642+    db = current_opts.get_default_manager().db
643+    backend = db.backend
644+    connection = db.connection
645+    qn = connection.ops.quote_name
646+    if hasattr(connection.ops, 'alias'):
647+        al = connection.ops.alias
648+    else:
649+        al = lambda x,y: "%s__%s" % (x,y)
650 
651     name = path.pop(0)
652     # Has the primary key been requested? If so, expand it out
653@@ -969,7 +986,7 @@
654
655         # Does the name belong to a defined many-to-many field?
656         field = find_field(name, current_opts.many_to_many, False)
657         if field:
658-            new_table = current_table + '__' + name
659+            new_table = al(current_table, name)
660             new_opts = field.rel.to._meta
661             new_column = new_opts.pk.column
662 
663@@ -986,7 +1003,7 @@
664
665         # Does the name belong to a reverse defined many-to-many field?
666         field = find_field(name, current_opts.get_all_related_many_to_many_objects(), True)
667         if field:
668-            new_table = current_table + '__' + name
669+            new_table = al(current_table, name)
670             new_opts = field.opts
671             new_column = new_opts.pk.column
672 
673@@ -1003,7 +1020,7 @@
674
675         # Does the name belong to a one-to-many field?
676         field = find_field(name, current_opts.get_all_related_objects(), True)
677         if field:
678-            new_table = table + '__' + name
679+            new_table = al(current_table, name)
680             new_opts = field.opts
681             new_column = field.field.column
682             join_column = opts.pk.column
683@@ -1017,7 +1034,7 @@
684
685         field = find_field(name, current_opts.fields, False)
686         if field:
687             if field.rel: # One-to-One/Many-to-one field
688-                new_table = current_table + '__' + name
689+                new_table = al(current_table, name)
690                 new_opts = field.rel.to._meta
691                 new_column = new_opts.pk.column
692                 join_column = field.column
693@@ -1109,20 +1126,23 @@
694
695             column = field.column
696             db_type = field.db_type()
697 
698-        where.append(get_where_clause(lookup_type, current_table + '.', column, value, db_type))
699+        where.append(get_where_clause(current_opts, lookup_type, current_table + '.', column, value, db_type))
700         params.extend(field.get_db_prep_lookup(lookup_type, value))
701 
702     return joins, where, params
703 
704 def delete_objects(seen_objs):
705     "Iterate through a list of seen classes, and remove any instances that are referred to"
706-    qn = connection.ops.quote_name
707     ordered_classes = seen_objs.keys()
708     ordered_classes.reverse()
709 
710-    cursor = connection.cursor()
711-
712     for cls in ordered_classes:
713+        db = cls._default_manager.db
714+        backend = db.backend
715+        connection = db.connection
716+        cursor = connection.cursor()
717+       qn = connection.ops.quote_name
718+       
719         seen_objs[cls] = seen_objs[cls].items()
720         seen_objs[cls].sort()
721 
722@@ -1161,7 +1181,17 @@
723
724                         pk_list[offset:offset+GET_ITERATOR_CHUNK_SIZE])
725 
726     # Now delete the actual data
727+    dirty_conns = []
728     for cls in ordered_classes:
729+
730+        db = cls._default_manager.db
731+        backend = db.backend
732+        connection = db.connection
733+       qn = connection.ops.quote_name
734+        cursor = connection.cursor()
735+        if connection not in dirty_conns:
736+            dirty_conns.append(connection)
737+           
738         seen_objs[cls].reverse()
739         pk_list = [pk for pk,instance in seen_objs[cls]]
740         for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
741@@ -1180,4 +1210,4 @@
742
743             setattr(instance, cls._meta.pk.attname, None)
744             dispatcher.send(signal=signals.post_delete, sender=cls, instance=instance)
745 
746-    transaction.commit_unless_managed()
747+    transaction.commit_unless_managed(dirty_conns)
748=== django/db/__init__.py
749==================================================================
750--- django/db/__init__.py       (/mirror/django/trunk)  (revision 3932)
751
752+++ django/db/__init__.py       (/local/django/multidb) (revision 3932)
753
754@@ -1,49 +1,382 @@
755
756-from django.conf import settings
757+from django.conf import settings, UserSettingsHolder
758 from django.core import signals
759+from django.core.exceptions import ImproperlyConfigured
760 from django.dispatch import dispatcher
761 
762+try:
763+    # Only exists in Python 2.4+
764+    from threading import local
765+except ImportError:
766+    # Import copy of _thread_local.py from Python 2.4
767+    from django.utils._threading_local import local
768+
769 __all__ = ('backend', 'connection', 'DatabaseError', 'IntegrityError')
770 
771+
772+# singleton to represent the default connection in connections
773+class dummy(object):
774+    def __repr__(self):
775+        return self.__str__()   
776+    def __str__(self):
777+        return '<default>'
778+_default = dummy()
779+del dummy
780+
781+
782+# storage for local default connection
783+_local = local()
784+
785 if not settings.DATABASE_ENGINE:
786     settings.DATABASE_ENGINE = 'dummy'
787+   
788 
789-try:
790-    backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, {}, {}, [''])
791-except ImportError, e:
792-    # The database backend wasn't found. Display a helpful error message
793-    # listing all possible database backends.
794-    from django.core.exceptions import ImproperlyConfigured
795-    import os
796-    backend_dir = os.path.join(__path__[0], 'backends')
797-    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')]
798-    available_backends.sort()
799-    if settings.DATABASE_ENGINE not in available_backends:
800-        raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \
801-            (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends)))
802-    else:
803-        raise # If there's some other error, this must be an error in Django itself.
804+def connect(settings, **kw):
805+    """Connect to the database specified in settings. Returns a
806+    ConnectionInfo on success, raises ImproperlyConfigured if the
807+    settings don't specify a valid database connection.
808+    """
809+    return ConnectionInfo(settings, **kw)
810 
811-get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, {}, {}, [''])
812-get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, {}, {}, [''])
813-runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, {}, {}, ['']).runshell()
814+   
815+class ConnectionInfo(object):
816+    """Encapsulates all information about a connection and the backend
817+    to which it belongs. Provides methods for loading backend
818+    creation, introspection, and shell modules, closing the
819+    connection, and resetting the connection's query log.
820+    """
821+    def __init__(self, settings=None, **kw):
822+        super(ConnectionInfo, self).__init__(**kw)
823+        if settings is None:
824+            from django.conf import settings
825+        if not settings.DATABASE_OPTIONS:
826+            settings.DATABASE_OPTIONS = {}
827+        self.settings = settings
828+        self.backend = self.load_backend()
829+        self.connection = self.backend.DatabaseWrapper(settings)
830+        self.DatabaseError = self.backend.DatabaseError
831 
832-connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS)
833-DatabaseError = backend.DatabaseError
834+        # Register an event that closes the database connection
835+        # when a Django request is finished.
836+        dispatcher.connect(self.close, signal=signals.request_finished)
837+   
838+        # Register an event that resets connection.queries
839+        # when a Django request is started.
840+        dispatcher.connect(self.reset_queries, signal=signals.request_started)
841+       
842+    def __repr__(self):
843+        return "Connection: %r (ENGINE=%s NAME=%s)" \
844+               % (self.connection,
845+                  self.settings.DATABASE_ENGINE,
846+                  self.settings.DATABASE_NAME)
847+
848+    def close(self):
849+        """Close connection"""
850+        self.connection.close()
851+
852+    def get_introspection_module(self):
853+        return __import__('django.db.backends.%s.introspection' %
854+                          self.settings.DATABASE_ENGINE, {}, {}, [''])
855+
856+    def get_creation_module(self):
857+        return __import__('django.db.backends.%s.creation' %
858+                          self.settings.DATABASE_ENGINE, {}, {}, [''])
859+
860+    def load_backend(self):
861+        try:
862+            backend = __import__('django.db.backends.%s.base' %
863+                                 self.settings.DATABASE_ENGINE, {}, {}, [''])
864+        except ImportError, e:
865+            # The database backend wasn't found. Display a helpful error
866+            # message listing all possible database backends.
867+            import os
868+            backend_dir = os.path.join(__path__[0], 'backends')
869+            available_backends = [f for f in os.listdir(backend_dir)
870+                                  if not f.startswith('_')  \
871+                                  and not f.startswith('.') \
872+                                  and not f.endswith('.py') \
873+                                  and not f.endswith('.pyc')]
874+            available_backends.sort()
875+            if self.settings.DATABASE_ENGINE not in available_backends:
876+                raise ImproperlyConfigured, \
877+                      "%r isn't an available database backend. "\
878+                      "Available options are: %s" % \
879+                      (self.settings.DATABASE_ENGINE,
880+                       ", ".join(map(repr, available_backends)))
881+            else:
882+                # If there's some other error, this must be an error
883+                # in Django itself.
884+                raise
885+        return backend
886+
887+    def runshell(self):
888+        __import__('django.db.backends.%s.client' %
889+                   self.settings.DATABASE_ENGINE, {}, {}, ['']
890+                   ).runshell(self.settings)
891+
892+
893+       
894+    def reset_queries(self):
895+        """Reset log of queries executed by connection"""
896+        self.connection.queries = []
897+
898+
899+class LazyConnectionManager(object):
900+    """Manages named connections lazily, instantiating them as
901+    they are requested.
902+    """
903+    def __init__(self):
904+        self.local = local()
905+        self.local.connections = {}
906+
907+        # Reset connections on request finish, to make sure each request can
908+        # load the correct connections for its settings
909+        dispatcher.connect(self.reset, signal=signals.request_finished)
910+       
911+    def __iter__(self):
912+        # Iterates only over *active* connections, not all possible
913+        # connections
914+        return iter(self.local.connections.keys())
915+
916+    def __getattr__(self, attr):
917+        return getattr(self.local.connections, attr)
918+
919+    def __getitem__(self, k):
920+        try:
921+            return self.local.connections[k]
922+        except (AttributeError, KeyError):
923+            return self.connect(k)
924+
925+    def __setitem__(self, k, v):
926+        try:
927+            self.local.connections[k] = v
928+        except AttributeError:
929+            # First access in thread
930+            self.local.connections = {k: v}
931+           
932+    def connect(self, name):
933+        """Return the connection with this name in
934+        settings.OTHER_DATABASES. Creates the connection if it doesn't yet
935+        exist. Reconnects if it does. If the name requested is the default
936+        connection (a singleton defined in django.db), then the default
937+        connection is returned.       
938+        """
939+        try:
940+            cnx = self.local.connections
941+        except AttributeError:
942+            cnx = self.local.connections = {}
943+        if name in cnx:
944+            cnx[name].close()
945+        if name is _default:
946+            cnx[name] = connect(settings)
947+            return cnx[name]
948+        try:
949+            info = settings.OTHER_DATABASES[name]
950+        except KeyError:
951+            raise ImproperlyConfigured, \
952+                  "No database connection '%s' has been configured" % name
953+        except AttributeError:
954+            raise ImproperlyConfigured, \
955+                  "No OTHER_DATABASES in settings."
956+
957+        # In settings it's a dict, but connect() needs an object:
958+        # pass global settings so that the default connection settings
959+        # can be defaults for the named connections.
960+        database = UserSettingsHolder(settings)
961+        for k, v in info.items():
962+            setattr(database, k, v)
963+        cnx[name] = connect(database)
964+        return cnx[name]
965+
966+    def items(self):
967+        # Iterates over *all possible* connections
968+        items = []
969+        for key in self.keys():
970+            items.append((key, self[key]))
971+        return items
972+   
973+    def keys(self):
974+        # Iterates over *all possible* connections
975+        keys = [_default]
976+        try:
977+            keys.extend(settings.OTHER_DATABASES.keys())
978+        except AttributeError:
979+            pass
980+        return keys
981+   
982+    def reset(self):
983+        if not hasattr(self.local, 'connections'):
984+            return
985+        self.local.connections = {}
986+       
987+def model_connection_name(klass):
988+    """Get the connection name that a model is configured to use, with the
989+    current settings.
990+    """
991+    app = klass._meta.app_label
992+    model = klass.__name__
993+    app_model = "%s.%s" % (app, model)
994+
995+    # Quick exit if no OTHER_DATABASES defined
996+    if (not hasattr(settings, 'OTHER_DATABASES')
997+        or not settings.OTHER_DATABASES):
998+        print "No other databases"
999+        return _default
1000+    # Look in MODELS for the best match: app_label.Model. If that isn't
1001+    # found, take just app_label. If nothing is found, use the default
1002+    maybe = None
1003+    for name, db_def in settings.OTHER_DATABASES.items():
1004+        if not 'MODELS' in db_def:
1005+            continue
1006+        mods = db_def['MODELS']
1007+        # Can't get a better match than this
1008+        if app_model in mods:
1009+            return name
1010+        elif app in mods:
1011+            if maybe is not None:
1012+                raise ImproperlyConfigured, \
1013+                    "App %s appears in more than one OTHER_DATABASES " \
1014+                    "setting (%s and %s)" % (maybe, name)
1015+            maybe = name
1016+    if maybe:
1017+        return maybe
1018+    # No named connection for this model; use the default
1019+    return _default
1020+
1021+
1022+class ConnectionInfoDescriptor(object):
1023+    """Descriptor used to access database connection information from a
1024+    manager or other connection holder. Keeps a thread-local cache of
1025+    connections per instance, and always returns the same connection for an
1026+    instance in particular thread during a particular request.
1027+
1028+    Any object that includes a ``model`` attribute that holds a model class
1029+    can use this descriptor to manage connections.
1030+    """
1031+   
1032+    def __init__(self):
1033+        self.local = local()
1034+        self.local.cnx = {}
1035+        dispatcher.connect(self.reset, signal=signals.request_finished)
1036+       
1037+    def __get__(self, instance, type=None):
1038+        if instance is None:
1039+            raise AttributeError, \
1040+                "ConnectionInfo is accessible only through an instance"
1041+        try:
1042+            instance_connection = self.local.cnx.get(instance, None)
1043+        except AttributeError:
1044+            # First access in this thread
1045+            self.local.cnx = {}
1046+            instance_connection = None
1047+        if instance_connection is None:
1048+            instance_connection = self.get_connection(instance)
1049+            self.local.cnx[instance] = instance_connection
1050+        return instance_connection
1051+
1052+    def __set__(self, instance, value):
1053+        try:
1054+            self.local.cnx[instance] = value
1055+        except AttributeError:
1056+            # First access in thread
1057+            self.local.cnx = {instance: value}
1058+
1059+    def __delete__(self, instance):
1060+        try:
1061+            del self.local.cnx[instance]
1062+        except (AttributeError, KeyError):
1063+            # Not stored, no need to reset
1064+            pass
1065+
1066+    def get_connection(self, instance):
1067+        return connections[model_connection_name(instance.model)]
1068+
1069+    def reset(self):
1070+        if not hasattr(self.local, 'cnx'):
1071+            return
1072+        self.local.cnx = {}
1073+
1074+class LocalizingProxy:
1075+    """A lazy-initializing proxy. The proxied object is not
1076+    initialized until the first attempt to access it. This is used to
1077+    attach module-level properties to local storage.
1078+    """
1079+    def __init__(self, name, storage, func, *arg, **kw):
1080+        self.__name = name
1081+        self.__storage = storage
1082+        self.__func = func
1083+        self.__arg = arg
1084+        self.__kw = kw
1085+
1086+        # We need to clear out this thread's storage at the end of each
1087+        # request, in case new settings are loaded with the next
1088+        def reset(stor=storage, name=name):
1089+            if hasattr(stor, name):
1090+                delattr(stor, name)
1091+        dispatcher.connect(reset, signal=signals.request_finished)
1092+       
1093+    def __getattr__(self, attr):
1094+        # Private (__*) attributes are munged
1095+        if attr.startswith('_LocalizingProxy'):
1096+            return self.__dict__[attr]
1097+        try:
1098+            return getattr(getattr(self.__storage, self.__name), attr)
1099+        except AttributeError:
1100+            setattr(self.__storage, self.__name, self.__func(*self.__arg,
1101+                                                             **self.__kw))
1102+            return getattr(getattr(self.__storage, self.__name), attr)
1103+
1104+    def __setattr__(self, attr, val):
1105+        # Private (__*) attributes are munged
1106+        if attr.startswith('_LocalizingProxy'):
1107+            self.__dict__[attr] = val
1108+            return
1109+        try:
1110+            stor = getattr(self.__storage, self.__name)           
1111+        except AttributeError:
1112+            stor =  self.__func(*self.__arg)
1113+            setattr(self.__storage, self.__name, stor)
1114+        setattr(stor, attr, val)
1115+
1116+
1117+# Create a manager for named connections
1118+connections = LazyConnectionManager()
1119+
1120+# Backwards compatibility: establish the default connection and set the
1121+# default connection properties at module level, using the lazy proxy so that
1122+# each thread may have a different default connection, if so configured
1123+connection_info = LocalizingProxy('connection_info', _local,
1124+                                  lambda: connections[_default])
1125+connection = LocalizingProxy('connection', _local,
1126+                             lambda: connections[_default].connection)
1127+backend = LocalizingProxy('backend', _local,
1128+                          lambda: connections[_default].backend)
1129+DatabaseError = LocalizingProxy('DatabaseError', _local,
1130+                                lambda: connections[_default].DatabaseError)
1131+#================================BUG==Might need LocalizingProxy==============
1132 IntegrityError = backend.IntegrityError
1133+get_introspection_module = LocalizingProxy(
1134+    'get_introspection_module', _local,
1135+    lambda: connections[_default].get_introspection_module)
1136+get_creation_module = LocalizingProxy(
1137+    'get_creation_module', _local,
1138+    lambda: connections[_default].get_creation_module)
1139+runshell = LocalizingProxy('runshell', _local,
1140+                           lambda: connections[_default].runshell)
1141 
1142-# Register an event that closes the database connection
1143-# when a Django request is finished.
1144-dispatcher.connect(connection.close, signal=signals.request_finished)
1145 
1146-# Register an event that resets connection.queries
1147-# when a Django request is started.
1148-def reset_queries():
1149-    connection.queries = []
1150-dispatcher.connect(reset_queries, signal=signals.request_started)
1151-
1152-# Register an event that rolls back the connection
1153+# Register an event that rolls back all connections
1154 # when a Django request has an exception.
1155 def _rollback_on_exception():
1156     from django.db import transaction
1157     transaction.rollback_unless_managed()
1158-dispatcher.connect(_rollback_on_exception, signal=signals.got_request_exception)
1159+dispatcher.connect(_rollback_on_exception,
1160+                   signal=signals.got_request_exception)
1161+
1162+def reset_queries():
1163+    connections[_default].reset_queries()
1164+    for c in connections:
1165+        try:
1166+            c.reset_queries()
1167+        except:
1168+            pass
1169+
1170=== django/db/backends/ado_mssql/client.py
1171==================================================================
1172--- django/db/backends/ado_mssql/client.py      (/mirror/django/trunk)  (revision 3932)
1173
1174+++ django/db/backends/ado_mssql/client.py      (/local/django/multidb) (revision 3932)
1175
1176@@ -1,2 +1,2 @@
1177
1178-def runshell():
1179+def runshell(settings):
1180     raise NotImplementedError
1181=== django/db/backends/postgresql/client.py
1182==================================================================
1183--- django/db/backends/postgresql/client.py     (/mirror/django/trunk)  (revision 3932)
1184
1185+++ django/db/backends/postgresql/client.py     (/local/django/multidb) (revision 3932)
1186
1187@@ -1,7 +1,6 @@
1188
1189-from django.conf import settings
1190 import os
1191 
1192-def runshell():
1193+def runshell(settings):
1194     args = ['psql']
1195     if settings.DATABASE_USER:
1196         args += ["-U", settings.DATABASE_USER]
1197=== django/db/backends/postgresql/sql.py
1198==================================================================
1199--- django/db/backends/postgresql/sql.py        (/mirror/django/trunk)  (revision 3932)
1200
1201+++ django/db/backends/postgresql/sql.py        (/local/django/multidb) (revision 3932)
1202
1203@@ -0,0 +1,41 @@
1204
1205+from django.db import models
1206
1207+from django.db.backends.ansi.sql import BoundStatement, SchemaBuilder, \
1208
1209+    default_style
1210
1211+
1212
1213+class PgSchemaBuilder(SchemaBuilder):
1214
1215+    """SchemaBuilder for postgres. Implements an additional method that
1216
1217+    outputs SQL statements to reset the sequence(s) for a model.
1218
1219+    """
1220
1221+    def get_sequence_reset(self, model, style=None):
1222
1223+        """Get sequence reset sql for a model.
1224
1225+        """
1226
1227+        if style is None:
1228
1229+            style=default_style
1230
1231+        for f in model._meta.fields:
1232
1233+            output = []
1234
1235+            db = model._default_manager.db
1236
1237+            connection = db.connection
1238
1239+            qn = db.backend.quote_name
1240
1241+            if isinstance(f, models.AutoField):
1242
1243+                output.append(BoundStatement(
1244
1245+                        "%s setval('%s', (%s max(%s) %s %s));" % \
1246
1247+                        (style.SQL_KEYWORD('SELECT'),
1248
1249+                         style.SQL_FIELD('%s_%s_seq' %
1250
1251+                                         (model._meta.db_table, f.column)),
1252
1253+                         style.SQL_KEYWORD('SELECT'),
1254
1255+                         style.SQL_FIELD(qn(f.column)),
1256
1257+                         style.SQL_KEYWORD('FROM'),
1258
1259+                         style.SQL_TABLE(qn(model._meta.db_table))),
1260
1261+                        connection))
1262
1263+                break # Only one AutoField is allowed per model, so don't bother continuing.
1264
1265+        for f in model._meta.many_to_many:
1266
1267+            output.append(
1268
1269+                BoundStatement("%s setval('%s', (%s max(%s) %s %s));" % \
1270
1271+                               (style.SQL_KEYWORD('SELECT'),
1272
1273+                                style.SQL_FIELD('%s_id_seq' % f.m2m_db_table()),
1274
1275+                                style.SQL_KEYWORD('SELECT'),
1276
1277+                                style.SQL_FIELD(qn('id')),
1278
1279+                                style.SQL_KEYWORD('FROM'),
1280
1281+                                style.SQL_TABLE(f.m2m_db_table())),
1282
1283+                               connection))
1284
1285+        return output
1286
1287=== django/db/backends/sqlite3/base.py
1288==================================================================
1289--- django/db/backends/sqlite3/base.py  (/mirror/django/trunk)  (revision 3932)
1290
1291+++ django/db/backends/sqlite3/base.py  (/local/django/multidb) (revision 3932)
1292
1293@@ -115,7 +115,7 @@
1294
1295         return self.connection.cursor(factory=SQLiteCursorWrapper)
1296 
1297     def close(self):
1298-        from django.conf import settings
1299+        settings = self.settings
1300         # If database is in memory, closing the connection destroys the
1301         # database. To prevent accidental data loss, ignore close requests on
1302         # an in-memory db.
1303=== django/db/backends/sqlite3/client.py
1304==================================================================
1305--- django/db/backends/sqlite3/client.py        (/mirror/django/trunk)  (revision 3932)
1306
1307+++ django/db/backends/sqlite3/client.py        (/local/django/multidb) (revision 3932)
1308
1309@@ -1,6 +1,5 @@
1310
1311-from django.conf import settings
1312 import os
1313 
1314-def runshell():
1315+def runshell(settings):
1316     args = ['', settings.DATABASE_NAME]
1317     os.execvp('sqlite3', args)
1318=== django/db/backends/mysql/client.py
1319==================================================================
1320--- django/db/backends/mysql/client.py  (/mirror/django/trunk)  (revision 3932)
1321
1322+++ django/db/backends/mysql/client.py  (/local/django/multidb) (revision 3932)
1323
1324@@ -1,7 +1,6 @@
1325
1326-from django.conf import settings
1327 import os
1328 
1329-def runshell():
1330+def runshell(settings):
1331     args = ['']
1332     db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME)
1333     user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER)
1334=== django/db/backends/oracle/base.py
1335==================================================================
1336--- django/db/backends/oracle/base.py   (/mirror/django/trunk)  (revision 3932)
1337
1338+++ django/db/backends/oracle/base.py   (/local/django/multidb) (revision 3932)
1339
1340@@ -402,6 +402,7 @@
1341
1342         return self.connection is not None
1343 
1344     def _cursor(self, settings):
1345+        settings = self.settings
1346         if not self._valid_connection():
1347             if len(settings.DATABASE_HOST.strip()) == 0:
1348                 settings.DATABASE_HOST = 'localhost'
1349=== django/db/backends/oracle/client.py
1350==================================================================
1351--- django/db/backends/oracle/client.py (/mirror/django/trunk)  (revision 3932)
1352
1353+++ django/db/backends/oracle/client.py (/local/django/multidb) (revision 3932)
1354
1355@@ -1,7 +1,6 @@
1356
1357-from django.conf import settings
1358 import os
1359 
1360-def runshell():
1361+def runshell(settings):
1362     dsn = settings.DATABASE_USER
1363     if settings.DATABASE_PASSWORD:
1364         dsn += "/%s" % settings.DATABASE_PASSWORD
1365=== django/db/backends/__init__.py
1366==================================================================
1367--- django/db/backends/__init__.py      (/mirror/django/trunk)  (revision 3932)
1368
1369+++ django/db/backends/__init__.py      (/local/django/multidb) (revision 3932)
1370
1371@@ -5,15 +5,16 @@
1372
1373     # Import copy of _thread_local.py from Python 2.4
1374     from django.utils._threading_local import local
1375 
1376-class BaseDatabaseWrapper(local):
1377+class BaseDatabaseWrapper(object):
1378     """
1379     Represents a database connection.
1380     """
1381     ops = None
1382-    def __init__(self, **kwargs):
1383+    def __init__(self, settings):
1384+        self.settings = settings
1385+        self.options = settings.DATABASE_OPTIONS
1386         self.connection = None
1387         self.queries = []
1388-        self.options = kwargs
1389 
1390     def _commit(self):
1391         if self.connection is not None:
1392@@ -29,7 +30,7 @@
1393
1394             self.connection = None
1395 
1396     def cursor(self):
1397-        from django.conf import settings
1398+        settings = self.settings
1399         cursor = self._cursor(settings)
1400         if settings.DEBUG:
1401             return self.make_debug_cursor(cursor)
1402=== django/db/backends/dummy/base.py
1403==================================================================
1404--- django/db/backends/dummy/base.py    (/mirror/django/trunk)  (revision 3932)
1405
1406+++ django/db/backends/dummy/base.py    (/local/django/multidb) (revision 3932)
1407
1408@@ -33,8 +33,5 @@
1409
1410     _commit = complain
1411     _rollback = ignore
1412 
1413-    def __init__(self, **kwargs):
1414-        pass
1415-
1416     def close(self):
1417         pass
1418=== django/db/transaction.py
1419==================================================================
1420--- django/db/transaction.py    (/mirror/django/trunk)  (revision 3932)
1421
1422+++ django/db/transaction.py    (/local/django/multidb) (revision 3932)
1423
1424@@ -16,7 +16,6 @@
1425
1426     import thread
1427 except ImportError:
1428     import dummy_thread as thread
1429-from django.db import connection
1430 from django.conf import settings
1431 
1432 class TransactionManagementError(Exception):
1433@@ -116,48 +115,67 @@
1434
1435     Puts the transaction manager into a manual state: managed transactions have
1436     to be committed explicitly by the user. If you switch off transaction
1437     management and there is a pending commit/rollback, the data will be
1438-    commited.
1439+    commited. Note that managed state applies across all connections.
1440     """
1441     thread_ident = thread.get_ident()
1442     top = state.get(thread_ident, None)
1443     if top:
1444         top[-1] = flag
1445         if not flag and is_dirty():
1446-            connection._commit()
1447+            for cx in all_connections():
1448+                cx._commit()
1449             set_clean()
1450     else:
1451         raise TransactionManagementError("This code isn't under transaction management")
1452 
1453-def commit_unless_managed():
1454+def commit_unless_managed(connections=None):
1455     """
1456     Commits changes if the system is not in managed transaction mode.
1457     """
1458     if not is_managed():
1459-        connection._commit()
1460+        if connections is None:
1461+            connections = all_connections()
1462+        else:
1463+            connections = ensure_connections(connections)
1464+        for cx in connections:
1465+            cx._commit()
1466     else:
1467         set_dirty()
1468 
1469-def rollback_unless_managed():
1470+def rollback_unless_managed(connections=None):
1471     """
1472     Rolls back changes if the system is not in managed transaction mode.
1473     """
1474     if not is_managed():
1475-        connection._rollback()
1476+        if connections is None:
1477+            connections = all_connections()
1478+        for cx in connections:
1479+            cx._rollback()
1480     else:
1481         set_dirty()
1482 
1483-def commit():
1484+def commit(connections=None):
1485     """
1486     Does the commit itself and resets the dirty flag.
1487     """
1488-    connection._commit()
1489+    if connections is None:
1490+        connections = all_connections()
1491+    else:
1492+        connections = ensure_connections(connections)
1493+    for cx in connections:
1494+        cx._commit()
1495     set_clean()
1496 
1497-def rollback():
1498+def rollback(connections=None):
1499     """
1500     This function does the rollback itself and resets the dirty flag.
1501     """
1502-    connection._rollback()
1503+    if connections is None:
1504+        connections = all_connections()
1505+    else:
1506+        connections = ensure_connections(connections)
1507+    for cx in connections:
1508+        cx._rollback()
1509     set_clean()
1510 
1511 ##############
1512@@ -179,7 +197,7 @@
1513
1514             leave_transaction_management()
1515     return _autocommit
1516 
1517-def commit_on_success(func):
1518+def commit_on_success(func, connections=None):
1519     """
1520     This decorator activates commit on response. This way, if the view function
1521     runs successfully, a commit is made; if the viewfunc produces an exception,
1522@@ -198,7 +216,7 @@
1523
1524                 raise
1525             else:
1526                 if is_dirty():
1527-                    commit()
1528+                    commit(connections)
1529             return res
1530         finally:
1531             leave_transaction_management()
1532@@ -220,3 +238,31 @@
1533
1534             leave_transaction_management()
1535 
1536     return _commit_manually
1537+
1538+###########
1539+# HELPERS #
1540+###########
1541+
1542+def all_connections():
1543+    from django.db import connection, connections
1544+    return [connection] + [ c.connection
1545+                               for c in connections.values() ]
1546+
1547+def ensure_connections(val):
1548+    from django.db import connections
1549+    conns = []
1550+    if isinstance(val, basestring):
1551+        val = [val]
1552+    try:
1553+        iter(val)
1554+    except:
1555+        val = [val]
1556+    for cx in val:
1557+        if hasattr(cx, 'cursor'):
1558+            conns.append(cx)
1559+        elif hasattr(cx, 'connection'):
1560+            conns.append(cx.connection)
1561+        elif isinstance(cx, basestring):
1562+            conns.append(connections[cx].connection)
1563+    return conns
1564+       
1565=== django/conf/global_settings.py
1566==================================================================
1567--- django/conf/global_settings.py      (/mirror/django/trunk)  (revision 3932)
1568
1569+++ django/conf/global_settings.py      (/local/django/multidb) (revision 3932)
1570
1571@@ -116,6 +116,9 @@
1572
1573 DATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.
1574 DATABASE_OPTIONS = {}          # Set to empty dictionary for default.
1575 
1576+# Optional named database connections in addition to the default.
1577+OTHER_DATABASES = {}
1578+
1579 # Host for sending e-mail.
1580 EMAIL_HOST = 'localhost'
1581 
1582@@ -339,6 +342,16 @@
1583
1584 # If None, a name of 'test_' + DATABASE_NAME will be assumed
1585 TEST_DATABASE_NAME = None
1586 
1587+# Tuple of other test databases to create. Names in this tuple
1588+# are suffixes that will be appended to TEST_DATABASE_NAME
1589+TEST_DATABASES = []
1590+
1591+# Models to assign to each test database. This must be a list of
1592+# dicts, with each dict key being a name from TEST_DATABASES and value
1593+# a list of models or app_labels that will use that database.
1594+TEST_DATABASE_MODELS = []
1595+
1596+############### FROM TRUNK #############################
1597 # Strings used to set the character set and collation order for the test
1598 # database. These values are passed literally to the server, so they are
1599 # backend-dependent. If None, no special settings are sent (system defaults are
1600=== django/core/context_processors.py
1601==================================================================
1602--- django/core/context_processors.py   (/mirror/django/trunk)  (revision 3932)
1603
1604+++ django/core/context_processors.py   (/local/django/multidb) (revision 3932)
1605
1606@@ -25,8 +25,11 @@
1607
1608     context_extras = {}
1609     if settings.DEBUG and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
1610         context_extras['debug'] = True
1611-        from django.db import connection
1612-        context_extras['sql_queries'] = connection.queries
1613+        from django.db import connections
1614+        sqlq = []
1615+        for c in connections:
1616+            sqlq.extend(connections[c].connection.queries)
1617+        context_extras['sql_queries'] = sqlq
1618     return context_extras
1619 
1620 def i18n(request):
1621=== django/core/management/commands/sqlsequencereset.py
1622==================================================================
1623--- django/core/management/commands/sqlsequencereset.py (/mirror/django/trunk)  (revision 3932)
1624
1625+++ django/core/management/commands/sqlsequencereset.py (/local/django/multidb) (revision 3932)
1626
1627@@ -5,5 +5,8 @@
1628
1629     output_transaction = True
1630 
1631     def handle_app(self, app, **options):
1632-        from django.db import connection, models
1633-        return '\n'.join(connection.ops.sequence_reset_sql(self.style, models.get_models(app)))
1634+        from django.db import connection, models, model_connection_name
1635+        connection_output = {}
1636+        for model in models.get_models(app):
1637+            connection_output.extend(model._default_manager.db.connection.ops.sequence_reset_sql(self.style,[model]))
1638+        return '\n'.join(connection_output)
1639=== django/core/management/commands/syncdb.py
1640==================================================================
1641--- django/core/management/commands/syncdb.py   (/mirror/django/trunk)  (revision 3932)
1642
1643+++ django/core/management/commands/syncdb.py   (/local/django/multidb) (revision 3932)
1644
1645@@ -19,7 +19,8 @@
1646
1647     help = "Create the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
1648 
1649     def handle_noargs(self, **options):
1650-        from django.db import connection, transaction, models
1651+        from django.db import model_connection_name
1652+        from django.db import transaction, models
1653         from django.conf import settings
1654         from django.core.management.sql import table_list, installed_models, sql_model_create, sql_for_pending_references, many_to_many_sql_for_model, custom_sql_for_model, sql_indexes_for_model, emit_post_sync_signal
1655 
1656@@ -36,15 +37,9 @@
1657
1658             except ImportError:
1659                 pass
1660 
1661-        cursor = connection.cursor()
1662-
1663         # Get a list of all existing database tables,
1664         # so we know what needs to be added.
1665         table_list = table_list()
1666-        if connection.features.uses_case_insensitive_names:
1667-            table_name_converter = str.upper
1668-        else:
1669-            table_name_converter = lambda x: x
1670 
1671         # Get a list of already installed *models* so that references work right.
1672         seen_models = installed_models(table_list)
1673@@ -58,7 +53,13 @@
1674
1675             for model in model_list:
1676                 # Create the model's database table, if it doesn't already exist.
1677                 if verbosity >= 2:
1678-                    print "Processing %s.%s model" % (app_name, model._meta.object_name)
1679+                    print "Processing %s.%s model (%s))" % (app_name, model._meta.object_name, model_connection_name(model))
1680+                connection = model._default_manager.db.connection
1681+                cursor = connection.cursor()
1682+                if connection.features.uses_case_insensitive_names:
1683+                    table_name_converter = str.upper
1684+                else:
1685+                    table_name_converter = lambda x: x
1686                 if table_name_converter(model._meta.db_table) in table_list:
1687                     continue
1688                 sql, references = sql_model_create(model, self.style, seen_models)
1689@@ -80,6 +81,8 @@
1690
1691             model_list = models.get_models(app)
1692             for model in model_list:
1693                 if model in created_models:
1694+                    connection = model._default_manager.db.connection
1695+                    cursor = connection.cursor()
1696                     sql = many_to_many_sql_for_model(model, self.style)
1697                     if sql:
1698                         if verbosity >= 2:
1699@@ -99,6 +102,8 @@
1700
1701             app_name = app.__name__.split('.')[-2]
1702             for model in models.get_models(app):
1703                 if model in created_models:
1704+                    connection = model._default_manager.db.connection
1705+                    cursor = connection.cursor()
1706                     custom_sql = custom_sql_for_model(model)
1707                     if custom_sql:
1708                         if verbosity >= 1:
1709@@ -118,6 +123,8 @@
1710
1711             app_name = app.__name__.split('.')[-2]
1712             for model in models.get_models(app):
1713                 if model in created_models:
1714+                    connection = model._default_manager.db.connection
1715+                    cursor = connection.cursor()
1716                     index_sql = sql_indexes_for_model(model, self.style)
1717                     if index_sql:
1718                         if verbosity >= 1:
1719@@ -135,3 +142,4 @@
1720
1721         # Install the 'initial_data' fixture, using format discovery
1722         from django.core.management import call_command
1723         call_command('loaddata', 'initial_data', verbosity=verbosity)
1724+
1725=== django/core/management/validation.py
1726==================================================================
1727--- django/core/management/validation.py        (/mirror/django/trunk)  (revision 3932)
1728
1729+++ django/core/management/validation.py        (/local/django/multidb) (revision 3932)
1730
1731@@ -18,7 +18,7 @@
1732
1733     Returns number of errors.
1734     """
1735     from django.conf import settings
1736-    from django.db import models, connection
1737+    from django.db import models, connections, model_connection_name
1738     from django.db.models.loading import get_app_errors
1739     from django.db.models.fields.related import RelatedObject
1740 
1741@@ -29,6 +29,8 @@
1742
1743 
1744     for cls in models.get_models(app):
1745         opts = cls._meta
1746+        connection_name = model_connection_name(cls)
1747+        connection = connections[connection_name]
1748 
1749         # Do field-specific validation.
1750         for f in opts.fields:
1751@@ -62,7 +64,7 @@
1752
1753 
1754             # Check that max_length <= 255 if using older MySQL versions.
1755             if settings.DATABASE_ENGINE == 'mysql':
1756-                db_version = connection.get_server_version()
1757+                db_version = connection.connection.get_server_version()
1758                 if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.max_length > 255:
1759                     e.add(opts, '"%s": %s cannot have a "max_length" 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]])))
1760 
1761@@ -73,6 +75,11 @@
1762
1763                 if f.rel.to not in models.get_models():
1764                     e.add(opts, "'%s' has relation with model %s, which has not been installed" % (f.name, rel_opts.object_name))
1765 
1766+                #TODO: Fix this to allow relations that span databases by splitting querys up
1767+                rel_connection = model_connection_name(f.rel.to)
1768+                if rel_connection != connection_name:
1769+                    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))
1770+
1771                 rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name()
1772                 rel_query_name = f.related_query_name()
1773                 for r in rel_opts.fields:
1774=== django/core/management/sql.py
1775==================================================================
1776--- django/core/management/sql.py       (/mirror/django/trunk)  (revision 3932)
1777
1778+++ django/core/management/sql.py       (/local/django/multidb) (revision 3932)
1779
1780@@ -9,9 +9,15 @@
1781
1782 
1783 def table_list():
1784     "Returns a list of all table names that exist in the database."
1785-    from django.db import connection, get_introspection_module
1786-    cursor = connection.cursor()
1787-    return get_introspection_module().get_table_list(cursor)
1788+    from django.db import connections
1789+    table_list = []
1790+    for conn in connections:
1791+        try:
1792+            cursor = connections[conn].connection.cursor()
1793+            table_list.extend(connections[conn].get_introspection_module().get_table_list(cursor))
1794+        except:
1795+            pass
1796+    return table_list
1797 
1798 def django_table_list(only_existing=False):
1799     """
1800@@ -38,12 +44,14 @@
1801
1802     all_models = []
1803     for app in models.get_apps():
1804         for model in models.get_models(app):
1805-            all_models.append(model)
1806-    if connection.features.uses_case_insensitive_names:
1807-        converter = lambda x: x.upper()
1808-    else:
1809-        converter = lambda x: x
1810-    return set([m for m in all_models if converter(m._meta.db_table) in map(converter, table_list)])
1811+            connection = model._default_manager.db.connection
1812+            if connection.features.uses_case_insensitive_names:
1813+                converter = lambda x: x.upper()
1814+            else:
1815+                converter = lambda x: x
1816+            if converter(model._meta.db_table) in map(converter, table_list):
1817+                all_models.append(converter(model))
1818+    return set(all_models)
1819 
1820 def sequence_list():
1821     "Returns a list of information about all DB sequences for all models in all apps."
1822@@ -66,7 +74,7 @@
1823
1824 
1825 def sql_create(app, style):
1826     "Returns a list of the CREATE TABLE SQL statements for the given app."
1827-    from django.db import models
1828+    from django.db import models, model_connection_name
1829     from django.conf import settings
1830 
1831     if settings.DATABASE_ENGINE == 'dummy':
1832@@ -81,22 +89,30 @@
1833
1834     # generate invalid SQL (leaving models out of known_models is harmless, so
1835     # we can be conservative).
1836     app_models = models.get_models(app)
1837-    final_output = []
1838+    # final_output = []
1839     known_models = set([model for model in installed_models(table_list()) if model not in app_models])
1840     pending_references = {}
1841 
1842+    connection_output = {}
1843+
1844     for model in app_models:
1845+        connection_name = model_connection_name(model)
1846+        f_output = connection_output.setdefault(connection_name, [])
1847         output, references = sql_model_create(model, style, known_models)
1848-        final_output.extend(output)
1849+        f_output.extend(output)
1850         for refto, refs in references.items():
1851             pending_references.setdefault(refto, []).extend(refs)
1852-        final_output.extend(sql_for_pending_references(model, style, pending_references))
1853+        f_output.extend(sql_for_pending_references(model, style, pending_references))
1854         # Keep track of the fact that we've created the table for this model.
1855         known_models.add(model)
1856 
1857+    final_output = _collate(connection_output)
1858+
1859     # Create the many-to-many join tables.
1860     for model in app_models:
1861-        final_output.extend(many_to_many_sql_for_model(model, style))
1862+        connection_name = model_connection_name(model)
1863+        f_output = connection_output.setdefault(connection_name, [])
1864+        f_output.extend(_get_many_to_many_sql_for_model(model))
1865 
1866     # Handle references to tables that are from other apps
1867     # but don't exist physically.
1868@@ -110,39 +126,45 @@
1869
1870             final_output.append('-- The following references should be added but depend on non-existent tables:')
1871             final_output.extend(alter_sql)
1872 
1873+    # convert Boundstatements into strings
1874+    final_output = map(str, final_output)
1875+
1876     return final_output
1877 
1878 def sql_delete(app, style):
1879     "Returns a list of the DROP TABLE SQL statements for the given app."
1880+    from django.db import model_connection_name
1881     from django.db import connection, models, get_introspection_module
1882     from django.db.backends.util import truncate_name
1883-    introspection = get_introspection_module()
1884 
1885-    # This should work even if a connection isn't available
1886-    try:
1887-        cursor = connection.cursor()
1888-    except:
1889-        cursor = None
1890-
1891-    # Figure out which tables already exist
1892-    if cursor:
1893-        table_names = introspection.get_table_list(cursor)
1894-    else:
1895-        table_names = []
1896-    if connection.features.uses_case_insensitive_names:
1897-        table_name_converter = str.upper
1898-    else:
1899-        table_name_converter = lambda x: x
1900-
1901     output = []
1902-    qn = connection.ops.quote_name
1903-
1904+   
1905     # Output DROP TABLE statements for standard application tables.
1906     to_delete = set()
1907 
1908     references_to_delete = {}
1909+
1910     app_models = models.get_models(app)
1911     for model in app_models:
1912+        connection = model._default_manager.db.connection
1913+        introspection = connection.get_introspection_module()
1914+        # This should work even if a connection isn't available
1915+        try:
1916+            cursor = connection.cursor()
1917+        except:
1918+            cursor = None
1919+        # Figure out which tables already exist
1920+        if cursor:
1921+            table_names = introspection.get_table_list(cursor)
1922+        else:
1923+            table_names = []
1924+        if connection.features.uses_case_insensitive_names:
1925+            table_name_converter = str.upper
1926+        else:
1927+            table_name_converter = lambda x: x
1928+
1929+        qn = connection.ops.quote_name
1930+
1931         if cursor and table_name_converter(model._meta.db_table) in table_names:
1932             # The table exists, so it needs to be dropped
1933             opts = model._meta
1934@@ -153,6 +175,25 @@
1935
1936             to_delete.add(model)
1937 
1938     for model in app_models:
1939+        connection = model._default_manager.db.connection
1940+        introspection = connection.get_introspection_module()
1941+        # This should work even if a connection isn't available
1942+        try:
1943+            cursor = connection.cursor()
1944+        except:
1945+            cursor = None
1946+        # Figure out which tables already exist
1947+        if cursor:
1948+            table_names = introspection.get_table_list(cursor)
1949+        else:
1950+            table_names = []
1951+        if connection.features.uses_case_insensitive_names:
1952+            table_name_converter = str.upper
1953+        else:
1954+            table_name_converter = lambda x: x
1955+
1956+        qn = connection.ops.quote_name
1957+
1958         if cursor and table_name_converter(model._meta.db_table) in table_names:
1959             # Drop the table now
1960             output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'),
1961@@ -177,6 +218,25 @@
1962
1963 
1964     # Output DROP TABLE statements for many-to-many tables.
1965     for model in app_models:
1966+        connection = model._default_manager.db.connection
1967+        introspection = connection.get_introspection_module()
1968+        # This should work even if a connection isn't available
1969+        try:
1970+            cursor = connection.cursor()
1971+        except:
1972+            cursor = None
1973+        # Figure out which tables already exist
1974+        if cursor:
1975+            table_names = introspection.get_table_list(cursor)
1976+        else:
1977+            table_names = []
1978+        if connection.features.uses_case_insensitive_names:
1979+            table_name_converter = str.upper
1980+        else:
1981+            table_name_converter = lambda x: x
1982+
1983+        qn = connection.ops.quote_name
1984+
1985         opts = model._meta
1986         for f in opts.many_to_many:
1987             if cursor and table_name_converter(f.m2m_db_table()) in table_names:
1988@@ -190,9 +250,15 @@
1989
1990 
1991     # Close database connection explicitly, in case this output is being piped
1992     # directly into a database client, to avoid locking issues.
1993-    if cursor:
1994-        cursor.close()
1995-        connection.close()
1996+    for model in app_models:
1997+        connection = model._default_manager.db.connection
1998+        try:
1999+            cursor = connection.cursor()
2000+        except:
2001+            cursor = None
2002+        if cursor:
2003+            cursor.close()
2004+            connection.close()
2005 
2006     return output[::-1] # Reverse it, to deal with table dependencies.
2007 
2008@@ -218,7 +284,8 @@
2009
2010 def sql_custom(app):
2011     "Returns a list of the custom table modifying SQL statements for the given app."
2012     from django.db.models import get_models
2013-    output = []
2014+    from django.db import model_connection_name
2015+    connection_output = []
2016 
2017     app_models = get_models(app)
2018     app_dir = os.path.normpath(os.path.join(os.path.dirname(app.__file__), 'sql'))
2019@@ -226,15 +293,19 @@
2020
2021     for model in app_models:
2022         output.extend(custom_sql_for_model(model))
2023 
2024-    return output
2025+    return _collate(connection_output)
2026 
2027 def sql_indexes(app, style):
2028     "Returns a list of the CREATE INDEX SQL statements for all models in the given app."
2029-    from django.db import models
2030-    output = []
2031-    for model in models.get_models(app):
2032-        output.extend(sql_indexes_for_model(model, style))
2033-    return output
2034+    from django.db import model_connection_name
2035+    from django.db.models import get_models
2036+    connection_output = {}
2037+    for model in get_models(app):
2038+        opts = model._meta
2039+        connection_name = model_connection_name(model)
2040+        output = connection_output.setdefault(connection_name, [])
2041+        output.extend(map(str, get_sql_indexes_for_model(model)))
2042+    return _collate(connection_output)
2043 
2044 def sql_all(app, style):
2045     "Returns a list of CREATE TABLE SQL, initial-data inserts, and CREATE INDEX SQL for the given module."
2046@@ -245,12 +316,13 @@
2047
2048     Returns the SQL required to create a single model, as a tuple of:
2049         (list_of_sql, pending_references_dict)
2050     """
2051-    from django.db import connection, models
2052+    from django.db import models
2053 
2054     opts = model._meta
2055     final_output = []
2056     table_output = []
2057     pending_references = {}
2058+    connection = model._default_manager.db.connection
2059     qn = connection.ops.quote_name
2060     for f in opts.fields:
2061         col_type = f.db_type()
2062@@ -313,10 +385,14 @@
2063
2064     """
2065     Returns any ALTER TABLE statements to add constraints after the fact.
2066     """
2067-    from django.db import connection
2068     from django.db.backends.util import truncate_name
2069 
2070+    connection = model._default_manager.db.connection
2071     qn = connection.ops.quote_name
2072+    if hasattr(connection.ops, 'max_constraint_length'):
2073+        mnl = connection.ops.max_constraint_length
2074+    else:
2075+        mnl = connection.ops.max_name_length
2076     final_output = []
2077     if connection.features.supports_constraints:
2078         opts = model._meta
2079@@ -331,18 +407,19 @@
2080
2081                 # So we are careful with character usage here.
2082                 r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
2083                 final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \
2084-                    (qn(r_table), truncate_name(r_name, connection.ops.max_name_length()),
2085+                    (qn(r_table), truncate_name(r_name, mnl()),
2086                     qn(r_col), qn(table), qn(col),
2087                     connection.ops.deferrable_sql()))
2088             del pending_references[model]
2089     return final_output
2090 
2091 def many_to_many_sql_for_model(model, style):
2092-    from django.db import connection, models
2093+    from django.db import models
2094     from django.contrib.contenttypes import generic
2095 
2096     opts = model._meta
2097     final_output = []
2098+    connection = model._default_manager.db.connection
2099     qn = connection.ops.quote_name
2100     for f in opts.many_to_many:
2101         if not isinstance(f.rel, generic.GenericRel):
2102@@ -454,3 +531,25 @@
2103
2104         dispatcher.send(signal=models.signals.post_syncdb, sender=app,
2105             app=app, created_models=created_models,
2106             verbosity=verbosity, interactive=interactive)
2107+
2108+def _collate(connection_output, reverse=False):
2109+    from django.db import _default
2110+    final_output = []
2111+    if len(connection_output.keys()) == 1:
2112+        # all for the default connection
2113+        for statements in connection_output.values():
2114+            final_output.extend(statements)
2115+            if reverse:
2116+                final_output.reverse()
2117+    else:
2118+        for connection_name, statements in connection_output.items():
2119+            if not statements:
2120+                continue
2121+            final_output.append(' -- The following statements are for connection: %s' % connection_name)
2122+            if reverse:
2123+                statements.reverse()
2124+            final_output.extend(statements)
2125+            final_output.append(' -- END statements for %s\n' %
2126+                                connection_name)
2127+    return map(str, final_output)
2128+
2129=== tests/modeltests/invalid_models/__init__.py
2130==================================================================
2131--- tests/modeltests/invalid_models/__init__.py (/mirror/django/trunk)  (revision 3932)
2132
2133+++ tests/modeltests/invalid_models/__init__.py (/local/django/multidb) (revision 3932)
2134
2135@@ -1 +0,0 @@
2136
2137-
2138=== tests/modeltests/multiple_databases (new directory)
2139==================================================================
2140=== tests/modeltests/multiple_databases/__init__.py
2141==================================================================
2142--- tests/modeltests/multiple_databases/__init__.py     (/mirror/django/trunk)  (revision 3932)
2143
2144+++ tests/modeltests/multiple_databases/__init__.py     (/local/django/multidb) (revision 3932)
2145
2146@@ -0,0 +1 @@
2147
2148+pass
2149
2150=== tests/modeltests/multiple_databases/models.py
2151==================================================================
2152--- tests/modeltests/multiple_databases/models.py       (/mirror/django/trunk)  (revision 3932)
2153
2154+++ tests/modeltests/multiple_databases/models.py       (/local/django/multidb) (revision 3932)
2155
2156@@ -0,0 +1,221 @@
2157
2158+"""
2159
2160+XXX. Using multiple database connections
2161
2162+
2163
2164+Django normally uses only a single database connection. However,
2165
2166+support is available for using any number of different, named
2167
2168+connections. Multiple database support is entirely optional and has
2169
2170+no impact on your application if you don't use it.
2171
2172+
2173
2174+Named connections are defined in your settings module. Create a
2175
2176+`OTHER_DATABASES` variable that is a dict, mapping connection names to their
2177
2178+particulars. The particulars are defined in a dict with the same keys
2179
2180+as the variable names as are used to define the default connection, with one
2181
2182+addition: MODELS.
2183
2184+
2185
2186+The MODELS item in an OTHER_DATABASES entry is a list of the apps and models
2187
2188+that will use that connection.
2189
2190+
2191
2192+Access to named connections is through `django.db.connections`, which
2193
2194+behaves like a dict: you access connections by name. Connections are
2195
2196+established lazily, when accessed.  `django.db.connections[database]`
2197
2198+holds a `ConnectionInfo` instance, with the attributes:
2199
2200+`DatabaseError`, `backend`, `get_introspection_module`,
2201
2202+`get_creation_module`, and `runshell`.
2203
2204+
2205
2206+To access a model's connection, use its manager. The connection is available
2207
2208+at `model._default_manager.db.connection`. To find the backend or other
2209
2210+connection metadata, use `model._meta.db` to access the full ConnectionInfo
2211
2212+with connection metadata.
2213
2214+"""
2215
2216+
2217
2218+from django.db import models
2219
2220+
2221
2222+class Artist(models.Model):
2223
2224+    name = models.CharField(maxlength=100)
2225
2226+    alive = models.BooleanField(default=True)
2227
2228+   
2229
2230+    def __str__(self):
2231
2232+        return self.name
2233
2234+
2235
2236+   
2237
2238+class Opus(models.Model):
2239
2240+    artist = models.ForeignKey(Artist)
2241
2242+    name = models.CharField(maxlength=100)
2243
2244+    year = models.IntegerField()
2245
2246+   
2247
2248+    def __str__(self):
2249
2250+        return "%s (%s)" % (self.name, self.year)
2251
2252+
2253
2254+
2255
2256+class Widget(models.Model):
2257
2258+    code = models.CharField(maxlength=10, unique=True)
2259
2260+    weight = models.IntegerField()
2261
2262+
2263
2264+    def __str__(self):
2265
2266+        return self.code
2267
2268+
2269
2270+
2271
2272+class DooHickey(models.Model):
2273
2274+    name = models.CharField(maxlength=50)
2275
2276+    widgets = models.ManyToManyField(Widget, related_name='doohickeys')
2277
2278+   
2279
2280+    def __str__(self):
2281
2282+        return self.name
2283
2284+
2285
2286+
2287
2288+class Vehicle(models.Model):
2289
2290+    make = models.CharField(maxlength=20)
2291
2292+    model = models.CharField(maxlength=20)
2293
2294+    year = models.IntegerField()
2295
2296+
2297
2298+    def __str__(self):
2299
2300+        return "%d %s %s" % (self.year, self.make, self.model)
2301
2302+
2303
2304+
2305
2306+__test__ = {'API_TESTS': """
2307
2308+
2309
2310+# See what connections are defined. django.db.connections acts like a dict.
2311
2312+>>> from django.db import connection, connections, _default, model_connection_name
2313
2314+>>> from django.conf import settings
2315
2316+
2317
2318+# Connections are referenced by name
2319
2320+>>> connections['_a']
2321
2322+Connection: ...
2323
2324+>>> connections['_b']
2325
2326+Connection: ...
2327
2328+
2329
2330+# Let's see what connections are available. The default connection is always
2331
2332+# included in connections as well, and may be accessed as connections[_default].
2333
2334+
2335
2336+>>> connection_names = connections.keys()
2337
2338+>>> connection_names.sort()
2339
2340+>>> connection_names
2341
2342+[<default>, '_a', '_b']
2343
2344+   
2345
2346+# Invalid connection names raise ImproperlyConfigured
2347
2348+
2349
2350+>>> connections['bad']
2351
2352+Traceback (most recent call last):
2353
2354+ ...
2355
2356+ImproperlyConfigured: No database connection 'bad' has been configured
2357
2358+
2359
2360+# The model_connection_name() function will tell you the name of the
2361
2362+# connection that a model is configured to use.
2363
2364+
2365
2366+>>> model_connection_name(Artist)
2367
2368+'_a'
2369
2370+>>> model_connection_name(Widget)
2371
2372+'_b'
2373
2374+>>> model_connection_name(Vehicle) is _default
2375
2376+True
2377
2378+>>> a = Artist(name="Paul Klee", alive=False)
2379
2380+>>> a.save()
2381
2382+>>> w = Widget(code='100x2r', weight=1000)
2383
2384+>>> w.save()
2385
2386+>>> v = Vehicle(make='Chevy', model='Camaro', year='1966')
2387
2388+>>> v.save()
2389
2390+>>> artists = Artist.objects.all()
2391
2392+>>> list(artists)
2393
2394+[<Artist: Paul Klee>]
2395
2396+
2397
2398+# Models can access their connections through the db property of their
2399
2400+# default manager.
2401
2402+
2403
2404+>>> paul = _[0]
2405
2406+>>> Artist.objects.db
2407
2408+Connection: ... (ENGINE=... NAME=...)
2409
2410+>>> paul._default_manager.db
2411
2412+Connection: ... (ENGINE=... NAME=...)
2413
2414+
2415
2416+# When transactions are not managed, model save will commit only
2417
2418+# for the model's connection.
2419
2420+
2421
2422+>>> from django.db import transaction
2423
2424+>>> transaction.enter_transaction_management()
2425
2426+>>> transaction.managed(False)
2427
2428+>>> a = Artist(name="Joan Miro", alive=False)
2429
2430+>>> w = Widget(code="99rbln", weight=1)
2431
2432+>>> a.save()
2433
2434+
2435
2436+# Only connection '_a' is committed, so if we rollback
2437
2438+# all connections we'll forget the new Widget.
2439
2440+
2441
2442+>>> transaction.rollback()
2443
2444+>>> list(Artist.objects.all())
2445
2446+[<Artist: Paul Klee>, <Artist: Joan Miro>]
2447
2448+>>> list(Widget.objects.all())
2449
2450+[<Widget: 100x2r>]
2451
2452+
2453
2454+# Managed transaction state applies across all connections.
2455
2456+
2457
2458+>>> transaction.managed(True)
2459
2460+
2461
2462+# When managed, just as when using a single connection, updates are
2463
2464+# not committed until a commit is issued.
2465
2466+
2467
2468+>>> a = Artist(name="Pablo Picasso", alive=False)
2469
2470+>>> a.save()
2471
2472+>>> w = Widget(code="99rbln", weight=1)
2473
2474+>>> w.save()
2475
2476+>>> v = Vehicle(make='Pontiac', model='Fiero', year='1987')
2477
2478+>>> v.save()
2479
2480+
2481
2482+# The connections argument may be passed to commit, rollback, and the
2483
2484+# commit_on_success decorator as a keyword argument, as the first (for
2485
2486+# commit and rollback) or second (for the decorator) positional
2487
2488+# argument. It may be passed as a ConnectionInfo object, a connection
2489
2490+# (DatabaseWrapper) object, a connection name, or a list or dict of
2491
2492+# ConnectionInfo objects, connection objects, or connection names. If a
2493
2494+# dict is passed, the keys are ignored and the values used as the list
2495
2496+# of connections to commit, rollback, etc.
2497
2498+
2499
2500+>>> transaction.commit(connections['_b'])
2501
2502+>>> transaction.commit('_b')
2503
2504+>>> transaction.commit(connections='_b')
2505
2506+>>> transaction.commit(connections=['_b'])
2507
2508+>>> transaction.commit(['_a', '_b'])
2509
2510+>>> transaction.commit(connections)
2511
2512+
2513
2514+# When the connections argument is omitted entirely, the transaction
2515
2516+# command applies to all connections. Here we have committed
2517
2518+# connections 'django_test_db_a' and 'django_test_db_b', but not the
2519
2520+# default connection, so the new vehicle is lost on rollback.
2521
2522+
2523
2524+>>> transaction.rollback()
2525
2526+>>> list(Artist.objects.all())
2527
2528+[<Artist: Paul Klee>, <Artist: Joan Miro>, <Artist: Pablo Picasso>]
2529
2530+>>> list(Widget.objects.all())
2531
2532+[<Widget: 100x2r>, <Widget: 99rbln>]
2533
2534+>>> list(Vehicle.objects.all())
2535
2536+[<Vehicle: 1966 Chevy Camaro>]
2537
2538+>>> transaction.rollback()
2539
2540+>>> transaction.managed(False)
2541
2542+>>> transaction.leave_transaction_management()
2543
2544+
2545
2546+# Of course, relations and all other normal database operations work
2547
2548+# with models that use named connections just the same as with models
2549
2550+# that use the default connection. The only caveat is that you can't
2551
2552+# use a relation between two models that are stored in different
2553
2554+# databases. Note that that doesn't mean that two models using
2555
2556+# different connection *names* can't be related; only that in the the
2557
2558+# context in which they are used, if you use the relation, the
2559
2560+# connections named by the two models must resolve to the same
2561
2562+# database.
2563
2564+
2565
2566+>>> a = Artist.objects.get(name="Paul Klee")
2567
2568+>>> list(a.opus_set.all())
2569
2570+[]
2571
2572+>>> a.opus_set.create(name="Magic Garden", year="1926")
2573
2574+<Opus: Magic Garden (1926)>
2575
2576+>>> list(a.opus_set.all())
2577
2578+[<Opus: Magic Garden (1926)>]
2579
2580+>>> d = DooHickey(name='Thing')
2581
2582+>>> d.save()
2583
2584+>>> d.widgets.create(code='d101', weight=92)
2585
2586+<Widget: d101>
2587
2588+>>> list(d.widgets.all())
2589
2590+[<Widget: d101>]
2591
2592+>>> w = Widget.objects.get(code='d101')
2593
2594+>>> list(w.doohickeys.all())
2595
2596+[<DooHickey: Thing>]
2597
2598+"""}
2599
2600
2601Property changes on: tests/modeltests/multiple_databases
2602___________________________________________________________________
2603Name: svn:ignore
2604 +*.pyc
2605 +
2606
2607=== tests/regressiontests/manager_db    (new directory)
2608==================================================================
2609=== tests/regressiontests/manager_db/__init__.py
2610==================================================================
2611=== tests/regressiontests/manager_db/tests.py
2612==================================================================
2613--- tests/regressiontests/manager_db/tests.py   (/mirror/django/trunk)  (revision 3932)
2614
2615+++ tests/regressiontests/manager_db/tests.py   (/local/django/multidb) (revision 3932)
2616
2617@@ -0,0 +1,17 @@
2618
2619+import unittest
2620
2621+from regressiontests.manager_db.models import Insect
2622
2623+
2624
2625+class TestManagerDBAccess(unittest.TestCase):
2626
2627+
2628
2629+    def test_db_property(self):
2630
2631+        m = Insect.objects
2632
2633+        db = Insect.objects.db
2634
2635+        assert db
2636
2637+        assert db.connection
2638
2639+        assert db.connection.cursor
2640
2641+        assert db.backend
2642
2643+        assert db.connection.ops.quote_name
2644
2645+        assert db.get_creation_module
2646
2647+
2648
2649+if __name__ == '__main__':
2650
2651+    unittest.main()
2652
2653=== tests/regressiontests/manager_db/models.py
2654==================================================================
2655--- tests/regressiontests/manager_db/models.py  (/mirror/django/trunk)  (revision 3932)
2656
2657+++ tests/regressiontests/manager_db/models.py  (/local/django/multidb) (revision 3932)
2658
2659@@ -0,0 +1,5 @@
2660
2661+from django.db import models
2662
2663+
2664
2665+class Insect(models.Model):
2666
2667+    common_name = models.CharField(maxlength=64)
2668
2669+    latin_name = models.CharField(maxlength=128)
2670
2671
2672Property changes on: tests/regressiontests/manager_db
2673___________________________________________________________________
2674Name: svn:ignore
2675 +*.pyc
2676 +
2677
2678=== tests/regressiontests/thread_isolation      (new directory)
2679==================================================================
2680=== tests/regressiontests/thread_isolation/__init__.py
2681==================================================================
2682=== tests/regressiontests/thread_isolation/tests.py
2683==================================================================
2684--- tests/regressiontests/thread_isolation/tests.py     (/mirror/django/trunk)  (revision 3932)
2685
2686+++ tests/regressiontests/thread_isolation/tests.py     (/local/django/multidb) (revision 3932)
2687
2688@@ -0,0 +1,251 @@
2689
2690+# tests that db settings can be different in different threads
2691
2692+#
2693
2694+#
2695
2696+#    What's going on here:
2697
2698+#
2699
2700+#    Simulating multiple web requests in a threaded environment, one in
2701
2702+#    which settings are different for each request. So we replace
2703
2704+#    django.conf.settings with a thread local, with different
2705
2706+#    configurations in each thread, and then fire off three
2707
2708+#    simultaneous requests (using a condition to sync them up), and
2709
2710+#    test that each thread sees its own settings and the models in each
2711
2712+#    thread attempt to connect to the correct database as per their
2713
2714+#    settings.
2715
2716+#
2717
2718+
2719
2720+
2721
2722+import copy
2723
2724+import os
2725
2726+import sys
2727
2728+import threading
2729
2730+import unittest
2731
2732+from thread import get_ident
2733
2734+
2735
2736+from django.conf import settings, UserSettingsHolder
2737
2738+from django.core.handlers.wsgi import WSGIHandler
2739
2740+from django.db import model_connection_name, _default, connection, connections
2741
2742+from regressiontests.request_isolation.tests import MockHandler
2743
2744+from regressiontests.thread_isolation.models import *
2745
2746+
2747
2748+try:
2749
2750+    # Only exists in Python 2.4+
2751
2752+    from threading import local
2753
2754+except ImportError:
2755
2756+    # Import copy of _thread_local.py from Python 2.4
2757
2758+    from django.utils._threading_local import local
2759
2760+
2761
2762+# helpers
2763
2764+EV = threading.Event()
2765
2766+
2767
2768+class LocalSettings:
2769
2770+    """Settings holder that allows thread-local overrides of defaults.
2771
2772+    """
2773
2774+    def __init__(self, defaults):
2775
2776+        self._defaults = defaults
2777
2778+        self._local = local()
2779
2780+
2781
2782+    def __getattr__(self, attr):
2783
2784+        if attr in ('_defaults', '_local'):
2785
2786+            return self.__dict__[attr]
2787
2788+        _local = self.__dict__['_local']
2789
2790+        _defaults = self.__dict__['_defaults']
2791
2792+        debug("LS get %s (%s)", attr, hasattr(_local, attr))
2793
2794+        if not hasattr(_local, attr):
2795
2796+            # Make sure everything we return is the local version; this
2797
2798+            # avoids sets to deep datastructures overwriting the defaults
2799
2800+            setattr(_local, attr, copy.deepcopy(getattr(_defaults, attr)))
2801
2802+        return getattr(_local, attr)
2803
2804+
2805
2806+    def __setattr__(self, attr, val):
2807
2808+        if attr in ('_defaults', '_local'):
2809
2810+            self.__dict__[attr] = val
2811
2812+        else:
2813
2814+            debug("LS set local %s = %s", attr, val)
2815
2816+            setattr(self.__dict__['_local'], attr, val)
2817
2818+
2819
2820+def thread_two(func, *arg):
2821
2822+    def start():
2823
2824+        # from django.conf import settings
2825
2826+        settings.OTHER_DATABASES['_b']['MODELS'] = []
2827
2828+
2829
2830+        debug("t2 ODB: %s", settings.OTHER_DATABASES)
2831
2832+        debug("t2 waiting")
2833
2834+        EV.wait(2.0)
2835
2836+        func(*arg)
2837
2838+        debug("t2 complete")
2839
2840+    t2 = threading.Thread(target=start)
2841
2842+    t2.start()
2843
2844+    return t2
2845
2846+
2847
2848+def thread_three(func, *arg):
2849
2850+    def start():
2851
2852+        # from django.conf import settings           
2853
2854+        settings.OTHER_DATABASES['_b']['MODELS'] = ['ti.MY']
2855
2856+        settings.OTHER_DATABASES['_b'], \
2857
2858+            settings.OTHER_DATABASES['_a'] = \
2859
2860+            settings.OTHER_DATABASES['_a'], \
2861
2862+            settings.OTHER_DATABASES['_b']
2863
2864+
2865
2866+        settings.DATABASE_NAME = \
2867
2868+            settings.OTHER_DATABASES['_a']['DATABASE_NAME']
2869
2870+
2871
2872+        debug("t3 ODB: %s", settings.OTHER_DATABASES)
2873
2874+        debug("3 %s: start: default: %s", get_ident(), settings.DATABASE_NAME)
2875
2876+        debug("3 %s: start: conn: %s", get_ident(),
2877
2878+              connection.settings.DATABASE_NAME)
2879
2880+       
2881
2882+        debug("t3 waiting")
2883
2884+        EV.wait(2.0)
2885
2886+        func(*arg)
2887
2888+        debug("t3 complete")
2889
2890+    t3 = threading.Thread(target=start)
2891
2892+    t3.start()
2893
2894+    return t3
2895
2896+
2897
2898+def debug(*arg):
2899
2900+    pass
2901
2902+#    msg, arg = arg[0], arg[1:]
2903
2904+#    print msg % arg
2905
2906+
2907
2908+def start_response(code, headers):
2909
2910+    debug("start response: %s %s", code, headers)
2911
2912+    pass
2913
2914+   
2915
2916+class TestThreadIsolation(unittest.TestCase):
2917
2918+    # event used to synchronize threads so we can be sure they are running
2919
2920+    # together
2921
2922+    lock = threading.RLock()
2923
2924+    errors = []
2925
2926+   
2927
2928+    def setUp(self):
2929
2930+        debug("setup")
2931
2932+        self.settings = settings._target
2933
2934+        settings._target = UserSettingsHolder(copy.deepcopy(settings._target))
2935
2936+        settings.OTHER_DATABASES['_a']['MODELS'] =  ['ti.MX']
2937
2938+        settings.OTHER_DATABASES['_b']['MODELS'] = ['ti.MY']
2939
2940+
2941
2942+        # normal settings holders aren't thread-safe, so we need to substitute
2943
2944+        # one that is (and so allows per-thread settings)
2945
2946+        holder = settings._target
2947
2948+        settings._target = LocalSettings(holder)
2949
2950+
2951
2952+    def teardown(self):
2953
2954+        debug("teardown")
2955
2956+        settings._target = self.settings
2957
2958+
2959
2960+    def add_thread_error(self, err):
2961
2962+        self.lock.acquire()
2963
2964+        try:
2965
2966+            self.errors.append(err)
2967
2968+        finally:
2969
2970+            self.lock.release()
2971
2972+
2973
2974+    def thread_errors(self):
2975
2976+        self.lock.acquire()
2977
2978+        try:
2979
2980+            return self.errors[:]
2981
2982+        finally:
2983
2984+            self.lock.release()
2985
2986+           
2987
2988+    def request_one(self, request):
2989
2990+        """Start out with settings as originally configured"""
2991
2992+        from django.conf import settings
2993
2994+        debug("request_one: %s", settings.OTHER_DATABASES)
2995
2996+
2997
2998+        self.assertEqual(model_connection_name(MQ), _default)
2999
3000+        self.assertEqual(model_connection_name(MX), '_a')
3001
3002+        self.assertEqual(
3003
3004+            MX._default_manager.db.connection.settings.DATABASE_NAME,
3005
3006+            settings.OTHER_DATABASES['_a']['DATABASE_NAME'])
3007
3008+        self.assertEqual(model_connection_name(MY), '_b')
3009
3010+        self.assertEqual(
3011
3012+            MY._default_manager.db.connection.settings.DATABASE_NAME,
3013
3014+            settings.OTHER_DATABASES['_b']['DATABASE_NAME'])
3015
3016+        self.assert_(MQ._default_manager.db.connection is
3017
3018+                     connections[_default].connection)
3019
3020+        self.assertEqual(
3021
3022+            MQ._default_manager.db.connection.settings.DATABASE_NAME,
3023
3024+            settings.DATABASE_NAME)
3025
3026+        self.assertEqual(connection.settings.DATABASE_NAME,
3027
3028+                         settings.DATABASE_NAME)
3029
3030+
3031
3032+    def request_two(self, request):
3033
3034+        """Between the first and second requests, settings change to assign
3035
3036+        model MY to a different connection
3037
3038+        """
3039
3040+        # from django.conf import settings
3041
3042+        debug("request_two: %s", settings.OTHER_DATABASES)
3043
3044+
3045
3046+        try:
3047
3048+            self.assertEqual(model_connection_name(MQ), _default)
3049
3050+            self.assertEqual(model_connection_name(MX), '_a')
3051
3052+            self.assertEqual(
3053
3054+                MX._default_manager.db.connection.settings.DATABASE_NAME,
3055
3056+                settings.OTHER_DATABASES['_a']['DATABASE_NAME'])
3057
3058+            self.assertEqual(model_connection_name(MY), _default)
3059
3060+            self.assertEqual(
3061
3062+                MY._default_manager.db.connection.settings.DATABASE_NAME,
3063
3064+                settings.DATABASE_NAME)
3065
3066+            self.assert_(MQ._default_manager.db.connection is
3067
3068+                         connections[_default].connection)
3069
3070+            self.assertEqual(
3071
3072+                MQ._default_manager.db.connection.settings.DATABASE_NAME,
3073
3074+                settings.DATABASE_NAME)
3075
3076+            self.assertEqual(connection.settings.DATABASE_NAME,
3077
3078+                             settings.DATABASE_NAME)
3079
3080+        except:
3081
3082+            self.add_thread_error(sys.exc_info())
3083
3084+
3085
3086+    def request_three(self, request):
3087
3088+        """Between the 2nd and 3rd requests, the settings at the names in
3089
3090+        OTHER_DATABASES have changed.
3091
3092+        """
3093
3094+        # from django.conf import settings
3095
3096+        debug("3 %s: %s", get_ident(), settings.OTHER_DATABASES)
3097
3098+        debug("3 %s: default: %s", get_ident(), settings.DATABASE_NAME)
3099
3100+        debug("3 %s: conn: %s", get_ident(),
3101
3102+              connection.settings.DATABASE_NAME)
3103
3104+        try:
3105
3106+            self.assertEqual(model_connection_name(MQ), _default)
3107
3108+            self.assertEqual(model_connection_name(MX), '_b')
3109
3110+            self.assertEqual(
3111
3112+                MX._default_manager.db.connection.settings.DATABASE_NAME,
3113
3114+                settings.OTHER_DATABASES['_b']['DATABASE_NAME'])
3115
3116+            self.assertEqual(model_connection_name(MY), '_a')
3117
3118+            self.assertEqual(
3119
3120+                MY._default_manager.db.connection.settings.DATABASE_NAME,
3121
3122+                settings.OTHER_DATABASES['_a']['DATABASE_NAME'])
3123
3124+            self.assert_(MQ._default_manager.db.connection is
3125
3126+                         connections[_default].connection)
3127
3128+            self.assertEqual(
3129
3130+                connection.settings.DATABASE_NAME,
3131
3132+                settings.OTHER_DATABASES['_a']['DATABASE_NAME'])
3133
3134+        except:
3135
3136+            self.add_thread_error(sys.exc_info())
3137
3138+       
3139
3140+    def test_thread_isolation(self):
3141
3142+       
3143
3144+        debug("running tests")
3145
3146+
3147
3148+        env = os.environ.copy()
3149
3150+        env['PATH_INFO'] = '/'
3151
3152+        env['REQUEST_METHOD'] = 'GET'
3153
3154+
3155
3156+        t2 = thread_two(MockHandler(self.request_two), env, start_response)
3157
3158+        t3 = thread_three(MockHandler(self.request_three), env, start_response)
3159
3160+
3161
3162+        try:
3163
3164+            EV.set()
3165
3166+            MockHandler(self.request_one)(env, start_response)
3167
3168+        finally:
3169
3170+            t2.join()
3171
3172+            t3.join()
3173
3174+            err = self.thread_errors()
3175
3176+            if err:
3177
3178+                import traceback
3179
3180+                for e in err:
3181
3182+                    traceback.print_exception(*e)
3183
3184+                    raise AssertionError("%s thread%s failed" %
3185
3186+                                         (len(err), len(err) > 1 and 's' or
3187
3188+                                          ''))
3189
3190+               
3191
3192=== tests/regressiontests/thread_isolation/models.py
3193==================================================================
3194--- tests/regressiontests/thread_isolation/models.py    (/mirror/django/trunk)  (revision 3932)
3195
3196+++ tests/regressiontests/thread_isolation/models.py    (/local/django/multidb) (revision 3932)
3197
3198@@ -0,0 +1,19 @@
3199
3200+from django.db import models
3201
3202+
3203
3204+# models
3205
3206+class MQ(models.Model):
3207
3208+    val = models.CharField(maxlength=10)
3209
3210+    class Meta:
3211
3212+        app_label = 'ti'
3213
3214+
3215
3216+
3217
3218+class MX(models.Model):
3219
3220+    val = models.CharField(maxlength=10)
3221
3222+    class Meta:
3223
3224+        app_label = 'ti'
3225
3226+
3227
3228+       
3229
3230+class MY(models.Model):
3231
3232+    val = models.CharField(maxlength=10)
3233
3234+    class Meta:
3235
3236+        app_label = 'ti'
3237
3238
3239Property changes on: tests/regressiontests/thread_isolation
3240___________________________________________________________________
3241Name: svn:ignore
3242 +*.pyc
3243 +
3244
3245
3246Property changes on: tests/regressiontests/initial_sql_regress/sql
3247___________________________________________________________________
3248Name: svn:ignore
3249 +*.pyc
3250 +
3251
3252=== tests/regressiontests/request_isolation     (new directory)
3253==================================================================
3254=== tests/regressiontests/request_isolation/__init__.py
3255==================================================================
3256=== tests/regressiontests/request_isolation/tests.py
3257==================================================================
3258--- tests/regressiontests/request_isolation/tests.py    (/mirror/django/trunk)  (revision 3932)
3259
3260+++ tests/regressiontests/request_isolation/tests.py    (/local/django/multidb) (revision 3932)
3261
3262@@ -0,0 +1,100 @@
3263
3264+# tests that db settings can change between requests
3265
3266+import copy
3267
3268+import os
3269
3270+import unittest
3271
3272+from django.conf import settings, UserSettingsHolder
3273
3274+from django.core.handlers.wsgi import WSGIHandler
3275
3276+from django.db import models, model_connection_name, _default, connection
3277
3278+from django.http import HttpResponse
3279
3280+from regressiontests.request_isolation.models import *
3281
3282+
3283
3284+
3285
3286+# helpers
3287
3288+class MockHandler(WSGIHandler):
3289
3290+
3291
3292+    def __init__(self, test):
3293
3294+        self.test = test
3295
3296+        super(MockHandler, self).__init__()
3297
3298+       
3299
3300+    def get_response(self, request):
3301
3302+        # debug("mock handler answering %s, %s", path, request)
3303
3304+        return HttpResponse(self.test(request))
3305
3306+
3307
3308+
3309
3310+def debug(*arg):
3311
3312+    pass
3313
3314+    # msg, arg = arg[0], arg[1:]
3315
3316+    # print msg % arg
3317
3318+
3319
3320+
3321
3322+def start_response(code, headers):
3323
3324+    debug("start response: %s %s", code, headers)
3325
3326+    pass
3327
3328+
3329
3330+# tests
3331
3332+class TestRequestIsolation(unittest.TestCase):
3333
3334+
3335
3336+    def setUp(self):
3337
3338+        debug("setup")
3339
3340+        self.settings = settings._target
3341
3342+        settings._target = UserSettingsHolder(copy.deepcopy(settings._target))
3343
3344+        settings.OTHER_DATABASES['_a']['MODELS'] = ['ri.MX']
3345
3346+        settings.OTHER_DATABASES['_b']['MODELS'] = ['ri.MY']
3347
3348+
3349
3350+    def tearDown(self):
3351
3352+        debug("teardown")
3353
3354+        settings._target = self.settings
3355
3356+
3357
3358+    def testRequestIsolation(self):
3359
3360+        env = os.environ.copy()
3361
3362+        env['PATH_INFO'] = '/'
3363
3364+        env['REQUEST_METHOD'] = 'GET'
3365
3366+
3367
3368+        def request_one(request):
3369
3370+            """Start out with settings as originally configured"""
3371
3372+            self.assertEqual(model_connection_name(MX), '_a')
3373
3374+            self.assertEqual(
3375
3376+                MX._default_manager.db.connection.settings.DATABASE_NAME,
3377
3378+                settings.OTHER_DATABASES['_a']['DATABASE_NAME'])
3379
3380+            self.assertEqual(model_connection_name(MY), '_b')
3381
3382+            self.assertEqual(
3383
3384+                MY._default_manager.db.connection.settings.DATABASE_NAME,
3385
3386+                settings.OTHER_DATABASES['_b']['DATABASE_NAME'])
3387
3388+
3389
3390+        def request_two(request):
3391
3392+            """Between the first and second requests, settings change to assign
3393
3394+            model MY to a different connection
3395
3396+            """
3397
3398+            self.assertEqual(model_connection_name(MX), '_a')
3399
3400+            self.assertEqual(
3401
3402+                MX._default_manager.db.connection.settings.DATABASE_NAME,
3403
3404+                settings.OTHER_DATABASES['_a']['DATABASE_NAME'])
3405
3406+            self.assertEqual(model_connection_name(MY), _default)
3407
3408+            self.assertEqual(
3409
3410+                MY._default_manager.db.connection.settings.DATABASE_NAME,
3411
3412+                settings.DATABASE_NAME)
3413
3414+
3415
3416+        def request_three(request):
3417
3418+            """Between the 2nd and 3rd requests, the settings at the names in
3419
3420+            OTHER_DATABASES have changed.
3421
3422+            """
3423
3424+            self.assertEqual(model_connection_name(MX), '_b')
3425
3426+            self.assertEqual(
3427
3428+                MX._default_manager.db.connection.settings.DATABASE_NAME,
3429
3430+                settings.OTHER_DATABASES['_b']['DATABASE_NAME'])
3431
3432+            self.assertEqual(model_connection_name(MY), '_a')
3433
3434+            self.assertEqual(
3435
3436+                MY._default_manager.db.connection.settings.DATABASE_NAME,
3437
3438+                settings.OTHER_DATABASES['_a']['DATABASE_NAME'])
3439
3440+   
3441
3442+        MockHandler(request_one)(env, start_response)
3443
3444+
3445
3446+        settings.OTHER_DATABASES['_b']['MODELS'] = []
3447
3448+        MockHandler(request_two)(env, start_response)
3449
3450+
3451
3452+        settings.OTHER_DATABASES['_b']['MODELS'] = ['ri.MY']
3453
3454+        settings.OTHER_DATABASES['_b'], \
3455
3456+            settings.OTHER_DATABASES['_a'] = \
3457
3458+            settings.OTHER_DATABASES['_a'], \
3459
3460+            settings.OTHER_DATABASES['_b']
3461
3462+        MockHandler(request_three)(env, start_response)
3463
3464=== tests/regressiontests/request_isolation/models.py
3465==================================================================
3466--- tests/regressiontests/request_isolation/models.py   (/mirror/django/trunk)  (revision 3932)
3467
3468+++ tests/regressiontests/request_isolation/models.py   (/local/django/multidb) (revision 3932)
3469
3470@@ -0,0 +1,13 @@
3471
3472+from django.db import models
3473
3474+
3475
3476+# models
3477
3478+class MX(models.Model):
3479
3480+    val = models.CharField(maxlength=10)
3481
3482+    class Meta:
3483
3484+        app_label = 'ri'
3485
3486+
3487
3488+       
3489
3490+class MY(models.Model):
3491
3492+    val = models.CharField(maxlength=10)
3493
3494+    class Meta:
3495
3496+        app_label = 'ri'
3497
3498
3499Property changes on: tests/regressiontests/request_isolation
3500___________________________________________________________________
3501Name: svn:ignore
3502 +*.pyc
3503 +
3504
3505=== tests/runtests.py
3506==================================================================
3507--- tests/runtests.py   (/mirror/django/trunk)  (revision 3932)
3508
3509+++ tests/runtests.py   (/local/django/multidb) (revision 3932)
3510
3511@@ -12,6 +12,14 @@
3512
3513 TEST_TEMPLATE_DIR = 'templates'
3514 
3515 CONTRIB_DIR = os.path.dirname(contrib.__file__)
3516+TEST_OTHER_DATABASES = {
3517+    '_a': { 'DATABASE_NAME': 'django_test_a',
3518+            'MODELS': [ 'multiple_databases.Artist',
3519+            'multiple_databases.Opus' ]},
3520+    '_b': { 'DATABASE_NAME': 'django_test_b',
3521+            'MODELS': [ 'multiple_databases.Widget',
3522+            'multiple_databases.DooHickey' ]}
3523+}
3524 MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME)
3525 REGRESSION_TEST_DIR = os.path.join(os.path.dirname(__file__), REGRESSION_TESTS_DIR_NAME)
3526 
3527@@ -92,6 +100,9 @@
3528
3529     # Redirect some settings for the duration of these tests.
3530     settings.TEST_DATABASE_NAME = TEST_DATABASE_NAME
3531     settings.INSTALLED_APPS = ALWAYS_INSTALLED_APPS
3532+##    settings.TEST_DATABASES = TEST_DATABASES
3533+##    settings.TEST_DATABASE_MODELS = TEST_DATABASE_MODELS
3534+    settings.TEST_OTHER_DATABASES = TEST_OTHER_DATABASES
3535     settings.ROOT_URLCONF = 'urls'
3536     settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), TEST_TEMPLATE_DIR),)
3537     settings.USE_I18N = True
3538@@ -124,6 +135,7 @@
3539
3540                 if mod:
3541                     if model_label not in settings.INSTALLED_APPS:
3542                         settings.INSTALLED_APPS.append(model_label)
3543+                    test_models.append(mod)
3544         except Exception, e:
3545             sys.stderr.write("Error while importing %s:" % model_name + ''.join(traceback.format_exception(*sys.exc_info())[1:]))
3546             continue
3547
3548Property changes on: tests/templates
3549___________________________________________________________________
3550Name: svn:ignore
3551 +*.pyc
3552 +
3553
3554=== docs/settings.txt
3555==================================================================
3556--- docs/settings.txt   (/mirror/django/trunk)  (revision 3932)
3557
3558+++ docs/settings.txt   (/local/django/multidb) (revision 3932)
3559
3560@@ -1,1120 +1,1127 @@
3561
3562-===============
3563-Django settings
3564-===============
3565-
3566-A Django settings file contains all the configuration of your Django
3567-installation. This document explains how settings work and which settings are
3568-available.
3569-
3570-The basics
3571-==========
3572-
3573-A settings file is just a Python module with module-level variables.
3574-
3575-Here are a couple of example settings::
3576-
3577-    DEBUG = False
3578-    DEFAULT_FROM_EMAIL = 'webmaster@example.com'
3579-    TEMPLATE_DIRS = ('/home/templates/mike', '/home/templates/john')
3580-
3581-Because a settings file is a Python module, the following apply:
3582-
3583-    * It doesn't allow for Python syntax errors.
3584-    * It can assign settings dynamically using normal Python syntax.
3585-      For example::
3586-
3587-          MY_SETTING = [str(i) for i in range(30)]
3588-
3589-    * It can import values from other settings files.
3590-
3591-Designating the settings
3592-========================
3593-
3594-When you use Django, you have to tell it which settings you're using. Do this
3595-by using an environment variable, ``DJANGO_SETTINGS_MODULE``.
3596-
3597-The value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax, e.g.
3598-``mysite.settings``. Note that the settings module should be on the
3599-Python `import search path`_.
3600-
3601-.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
3602-
3603-The django-admin.py utility
3604----------------------------
3605-
3606-When using `django-admin.py`_, you can either set the environment variable
3607-once, or explicitly pass in the settings module each time you run the utility.
3608-
3609-Example (Unix Bash shell)::
3610-
3611-    export DJANGO_SETTINGS_MODULE=mysite.settings
3612-    django-admin.py runserver
3613-
3614-Example (Windows shell)::
3615-
3616-    set DJANGO_SETTINGS_MODULE=mysite.settings
3617-    django-admin.py runserver
3618-
3619-Use the ``--settings`` command-line argument to specify the settings manually::
3620-
3621-    django-admin.py runserver --settings=mysite.settings
3622-
3623-.. _django-admin.py: ../django-admin/
3624-
3625-On the server (mod_python)
3626---------------------------
3627-
3628-In your live server environment, you'll need to tell Apache/mod_python which
3629-settings file to use. Do that with ``SetEnv``::
3630-
3631-    <Location "/mysite/">
3632-        SetHandler python-program
3633-        PythonHandler django.core.handlers.modpython
3634-        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
3635-    </Location>
3636-
3637-Read the `Django mod_python documentation`_ for more information.
3638-
3639-.. _Django mod_python documentation: ../modpython/
3640-
3641-Default settings
3642-================
3643-
3644-A Django settings file doesn't have to define any settings if it doesn't need
3645-to. Each setting has a sensible default value. These defaults live in the file
3646-``django/conf/global_settings.py``.
3647-
3648-Here's the algorithm Django uses in compiling settings:
3649-
3650-    * Load settings from ``global_settings.py``.
3651-    * Load settings from the specified settings file, overriding the global
3652-      settings as necessary.
3653-
3654-Note that a settings file should *not* import from ``global_settings``, because
3655-that's redundant.
3656-
3657-Seeing which settings you've changed
3658-------------------------------------
3659-
3660-There's an easy way to view which of your settings deviate from the default
3661-settings. The command ``python manage.py diffsettings`` displays differences
3662-between the current settings file and Django's default settings.
3663-
3664-For more, see the `diffsettings documentation`_.
3665-
3666-.. _diffsettings documentation: ../django-admin/#diffsettings
3667-
3668-Using settings in Python code
3669-=============================
3670-
3671-In your Django apps, use settings by importing the object
3672-``django.conf.settings``. Example::
3673-
3674-    from django.conf import settings
3675-
3676-    if settings.DEBUG:
3677-        # Do something
3678-
3679-Note that ``django.conf.settings`` isn't a module -- it's an object. So
3680-importing individual settings is not possible::
3681-
3682-    from django.conf.settings import DEBUG  # This won't work.
3683-
3684-Also note that your code should *not* import from either ``global_settings`` or
3685-your own settings file. ``django.conf.settings`` abstracts the concepts of
3686-default settings and site-specific settings; it presents a single interface.
3687-It also decouples the code that uses settings from the location of your
3688-settings.
3689-
3690-Altering settings at runtime
3691-============================
3692-
3693-You shouldn't alter settings in your applications at runtime. For example,
3694-don't do this in a view::
3695-
3696-    from django.conf import settings
3697-
3698-    settings.DEBUG = True   # Don't do this!
3699-
3700-The only place you should assign to settings is in a settings file.
3701-
3702-Security
3703-========
3704-
3705-Because a settings file contains sensitive information, such as the database
3706-password, you should make every attempt to limit access to it. For example,
3707-change its file permissions so that only you and your Web server's user can
3708-read it. This is especially important in a shared-hosting environment.
3709-
3710-Available settings
3711-==================
3712-
3713-Here's a full list of all available settings, in alphabetical order, and their
3714-default values.
3715-
3716-ABSOLUTE_URL_OVERRIDES
3717-----------------------
3718-
3719-Default: ``{}`` (Empty dictionary)
3720-
3721-A dictionary mapping ``"app_label.model_name"`` strings to functions that take
3722-a model object and return its URL. This is a way of overriding
3723-``get_absolute_url()`` methods on a per-installation basis. Example::
3724-
3725-    ABSOLUTE_URL_OVERRIDES = {
3726-        'blogs.weblog': lambda o: "/blogs/%s/" % o.slug,
3727-        'news.story': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug),
3728-    }
3729-
3730-Note that the model name used in this setting should be all lower-case, regardless
3731-of the case of the actual model class name.
3732-
3733-ADMIN_FOR
3734----------
3735-
3736-Default: ``()`` (Empty list)
3737-
3738-Used for admin-site settings modules, this should be a tuple of settings
3739-modules (in the format ``'foo.bar.baz'``) for which this site is an admin.
3740-
3741-The admin site uses this in its automatically-introspected documentation of
3742-models, views and template tags.
3743-
3744-ADMIN_MEDIA_PREFIX
3745-------------------
3746-
3747-Default: ``'/media/'``
3748-
3749-The URL prefix for admin media -- CSS, JavaScript and images. Make sure to use
3750-a trailing slash.
3751-
3752-ADMINS
3753-------
3754-
3755-Default: ``()`` (Empty tuple)
3756-
3757-A tuple that lists people who get code error notifications. When
3758-``DEBUG=False`` and a view raises an exception, Django will e-mail these people
3759-with the full exception information. Each member of the tuple should be a tuple
3760-of (Full name, e-mail address). Example::
3761-
3762-    (('John', 'john@example.com'), ('Mary', 'mary@example.com'))
3763-
3764-Note that Django will e-mail *all* of these people whenever an error happens. See the
3765-section on `error reporting via e-mail`_ for more information.
3766-
3767-ALLOWED_INCLUDE_ROOTS
3768----------------------
3769-
3770-Default: ``()`` (Empty tuple)
3771-
3772-A tuple of strings representing allowed prefixes for the ``{% ssi %}`` template
3773-tag. This is a security measure, so that template authors can't access files
3774-that they shouldn't be accessing.
3775-
3776-For example, if ``ALLOWED_INCLUDE_ROOTS`` is ``('/home/html', '/var/www')``,
3777-then ``{% ssi /home/html/foo.txt %}`` would work, but ``{% ssi /etc/passwd %}``
3778-wouldn't.
3779-
3780-APPEND_SLASH
3781-------------
3782-
3783-Default: ``True``
3784-
3785-Whether to append trailing slashes to URLs. This is only used if
3786-``CommonMiddleware`` is installed (see the `middleware docs`_). See also
3787-``PREPEND_WWW``.
3788-
3789-CACHE_BACKEND
3790--------------
3791-
3792-Default: ``'simple://'``
3793-
3794-The cache backend to use. See the `cache docs`_.
3795-
3796-CACHE_MIDDLEWARE_KEY_PREFIX
3797----------------------------
3798-
3799-Default: ``''`` (Empty string)
3800-
3801-The cache key prefix that the cache middleware should use. See the
3802-`cache docs`_.
3803-
3804-CACHE_MIDDLEWARE_SECONDS
3805-------------------------
3806-
3807-Default: ``600``
3808-
3809-The default number of seconds to cache a page when the caching middleware or
3810-``cache_page()`` decorator is used.
3811-
3812-DATABASE_ENGINE
3813----------------
3814-
3815-Default: ``''`` (Empty string)
3816-
3817-The database backend to use. Either ``'postgresql_psycopg2'``,
3818-``'postgresql'``, ``'mysql'``,  ``'mysql_old'``, ``'sqlite3'``,
3819-``'oracle'``, or ``'ado_mssql'``.
3820-
3821-DATABASE_HOST
3822--------------
3823-
3824-Default: ``''`` (Empty string)
3825-
3826-Which host to use when connecting to the database. An empty string means
3827-localhost. Not used with SQLite.
3828-
3829-If this value starts with a forward slash (``'/'``) and you're using MySQL,
3830-MySQL will connect via a Unix socket to the specified socket. For example::
3831-
3832-    DATABASE_HOST = '/var/run/mysql'
3833-
3834-If you're using MySQL and this value *doesn't* start with a forward slash, then
3835-this value is assumed to be the host.
3836-
3837-If you're using PostgreSQL, an empty string means to use a Unix domain socket
3838-for the connection, rather than a network connection to localhost. If you
3839-explictly need to use a TCP/IP connection on the local machine with
3840-PostgreSQL, specify ``localhost`` here.
3841-
3842-DATABASE_NAME
3843--------------
3844-
3845-Default: ``''`` (Empty string)
3846-
3847-The name of the database to use. For SQLite, it's the full path to the database
3848-file.
3849-
3850-DATABASE_OPTIONS
3851-----------------
3852-
3853-Default: ``{}`` (Empty dictionary)
3854-
3855-Extra parameters to use when connecting to the database. Consult backend
3856-module's document for available keywords.
3857-
3858-DATABASE_PASSWORD
3859------------------
3860-
3861-Default: ``''`` (Empty string)
3862-
3863-The password to use when connecting to the database. Not used with SQLite.
3864-
3865-DATABASE_PORT
3866--------------
3867-
3868-Default: ``''`` (Empty string)
3869-
3870-The port to use when connecting to the database. An empty string means the
3871-default port. Not used with SQLite.
3872-
3873-DATABASE_USER
3874--------------
3875-
3876-Default: ``''`` (Empty string)
3877-
3878-The username to use when connecting to the database. Not used with SQLite.
3879-
3880-DATE_FORMAT
3881------------
3882-
3883-Default: ``'N j, Y'`` (e.g. ``Feb. 4, 2003``)
3884-
3885-The default formatting to use for date fields on Django admin change-list
3886-pages -- and, possibly, by other parts of the system. See
3887-`allowed date format strings`_.
3888-
3889-See also DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT.
3890-
3891-.. _allowed date format strings: ../templates/#now
3892-
3893-DATETIME_FORMAT
3894----------------
3895-
3896-Default: ``'N j, Y, P'`` (e.g. ``Feb. 4, 2003, 4 p.m.``)
3897-
3898-The default formatting to use for datetime fields on Django admin change-list
3899-pages -- and, possibly, by other parts of the system. See
3900-`allowed date format strings`_.
3901-
3902-See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT.
3903-
3904-.. _allowed date format strings: ../templates/#now
3905-
3906-DEBUG
3907------
3908-
3909-Default: ``False``
3910-
3911-A boolean that turns on/off debug mode.
3912-
3913-If you define custom settings, django/views/debug.py has a ``HIDDEN_SETTINGS``
3914-regular expression which will hide from the DEBUG view anything that contins
3915-``'SECRET``, ``PASSWORD``, or ``PROFANITIES'``. This allows untrusted users to
3916-be able to give backtraces without seeing sensitive (or offensive) settings.
3917-
3918-Still, note that there are always going to be sections of your debug output that
3919-are inapporpriate for public consumption. File paths, configuration options, and
3920-the like all give attackers extra information about your server. Never deploy a
3921-site with ``DEBUG`` turned on.
3922-
3923-DEFAULT_CHARSET
3924----------------
3925-
3926-Default: ``'utf-8'``
3927-
3928-Default charset to use for all ``HttpResponse`` objects, if a MIME type isn't
3929-manually specified. Used with ``DEFAULT_CONTENT_TYPE`` to construct the
3930-``Content-Type`` header.
3931-
3932-DEFAULT_CONTENT_TYPE
3933---------------------
3934-
3935-Default: ``'text/html'``
3936-
3937-Default content type to use for all ``HttpResponse`` objects, if a MIME type
3938-isn't manually specified. Used with ``DEFAULT_CHARSET`` to construct the
3939-``Content-Type`` header.
3940-
3941-DEFAULT_FROM_EMAIL
3942-------------------
3943-
3944-Default: ``'webmaster@localhost'``
3945-
3946-Default e-mail address to use for various automated correspondence from the
3947-site manager(s).
3948-
3949-DISALLOWED_USER_AGENTS
3950-----------------------
3951-
3952-Default: ``()`` (Empty tuple)
3953-
3954-List of compiled regular expression objects representing User-Agent strings
3955-that are not allowed to visit any page, systemwide. Use this for bad
3956-robots/crawlers.  This is only used if ``CommonMiddleware`` is installed (see
3957-the `middleware docs`_).
3958-
3959-EMAIL_HOST
3960-----------
3961-
3962-Default: ``'localhost'``
3963-
3964-The host to use for sending e-mail.
3965-
3966-See also ``EMAIL_PORT``.
3967-
3968-EMAIL_HOST_PASSWORD
3969--------------------
3970-
3971-Default: ``''`` (Empty string)
3972-
3973-Password to use for the SMTP server defined in ``EMAIL_HOST``. This setting is
3974-used in conjunction with ``EMAIL_HOST_USER`` when authenticating to the SMTP
3975-server. If either of these settings is empty, Django won't attempt
3976-authenticaion.
3977-
3978-See also ``EMAIL_HOST_USER``.
3979-
3980-EMAIL_HOST_USER
3981----------------
3982-
3983-Default: ``''`` (Empty string)
3984-
3985-Username to use for the SMTP server defined in ``EMAIL_HOST``. If empty,
3986-Django won't attempt authentication.
3987-
3988-See also ``EMAIL_HOST_PASSWORD``.
3989-
3990-EMAIL_PORT
3991-----------
3992-
3993-Default: ``25``
3994-
3995-Port to use for the SMTP server defined in ``EMAIL_HOST``.
3996-
3997-EMAIL_SUBJECT_PREFIX
3998---------------------
3999-
4000-Default: ``'[Django] '``
4001-
4002-Subject-line prefix for e-mail messages sent with ``django.core.mail.mail_admins``
4003-or ``django.core.mail.mail_managers``. You'll probably want to include the
4004-trailing space.
4005-
4006-EMAIL_USE_TLS
4007--------------
4008-
4009-**New in Django development version**
4010-
4011-Default: ``False``
4012-
4013-Whether to use a TLS (secure) connection when talking to the SMTP server.
4014-
4015-FILE_CHARSET
4016-------------
4017-
4018-**New in Django development version**
4019-
4020-Default: ``'utf-8'``
4021-
4022-The character encoding used to decode any files read from disk. This includes
4023-template files and initial SQL data files.
4024-
4025-FIXTURE_DIRS
4026--------------
4027-
4028-Default: ``()`` (Empty tuple)
4029-
4030-List of locations of the fixture data files, in search order. Note that
4031-these paths should use Unix-style forward slashes, even on Windows. See
4032-`Testing Django Applications`_.
4033-
4034-.. _Testing Django Applications: ../testing/
4035-
4036-IGNORABLE_404_ENDS
4037-------------------
4038-
4039-Default: ``('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')``
4040-
4041-See also ``IGNORABLE_404_STARTS`` and ``Error reporting via e-mail``.
4042-
4043-IGNORABLE_404_STARTS
4044---------------------
4045-
4046-Default: ``('/cgi-bin/', '/_vti_bin', '/_vti_inf')``
4047-
4048-A tuple of strings that specify beginnings of URLs that should be ignored by
4049-the 404 e-mailer. See ``SEND_BROKEN_LINK_EMAILS``, ``IGNORABLE_404_ENDS`` and
4050-the section on `error reporting via e-mail`_.
4051-
4052-INSTALLED_APPS
4053---------------
4054-
4055-Default: ``()`` (Empty tuple)
4056-
4057-A tuple of strings designating all applications that are enabled in this Django
4058-installation. Each string should be a full Python path to a Python package that
4059-contains a Django application, as created by `django-admin.py startapp`_.
4060-
4061-.. _django-admin.py startapp: ../django-admin/#startapp-appname
4062-
4063-INTERNAL_IPS
4064-------------
4065-
4066-Default: ``()`` (Empty tuple)
4067-
4068-A tuple of IP addresses, as strings, that:
4069-
4070-    * See debug comments, when ``DEBUG`` is ``True``
4071-    * Receive X headers if the ``XViewMiddleware`` is installed (see the
4072-      `middleware docs`_)
4073-
4074-JING_PATH
4075----------
4076-
4077-Default: ``'/usr/bin/jing'``
4078-
4079-Path to the "Jing" executable. Jing is a RELAX NG validator, and Django uses it
4080-to validate each ``XMLField`` in your models.
4081-See http://www.thaiopensource.com/relaxng/jing.html .
4082-
4083-LANGUAGE_CODE
4084--------------
4085-
4086-Default: ``'en-us'``
4087-
4088-A string representing the language code for this installation. This should be
4089-in standard language format. For example, U.S. English is ``"en-us"``. See the
4090-`internationalization docs`_.
4091-
4092-.. _internationalization docs: ../i18n/
4093-
4094-LANGUAGES
4095----------
4096-
4097-Default: A tuple of all available languages. This list is continually growing
4098-and including a copy here would inevitably become rapidly out of date. You can
4099-see the current list of translated languages by looking in
4100-``django/conf/global_settings.py`` (or view the `online source`_).
4101-
4102-.. _online source: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py
4103-
4104-The list is a tuple of two-tuples in the format (language code, language
4105-name) -- for example, ``('ja', 'Japanese')``. This specifies which languages
4106-are available for language selection. See the `internationalization docs`_ for
4107-details.
4108-
4109-Generally, the default value should suffice. Only set this setting if you want
4110-to restrict language selection to a subset of the Django-provided languages.
4111-
4112-If you define a custom ``LANGUAGES`` setting, it's OK to mark the languages as
4113-translation strings (as in the default value displayed above) -- but use a
4114-"dummy" ``gettext()`` function, not the one in ``django.utils.translation``.
4115-You should *never* import ``django.utils.translation`` from within your
4116-settings file, because that module in itself depends on the settings, and that
4117-would cause a circular import.
4118-
4119-The solution is to use a "dummy" ``gettext()`` function. Here's a sample
4120-settings file::
4121-
4122-    gettext = lambda s: s
4123-
4124-    LANGUAGES = (
4125-        ('de', gettext('German')),
4126-        ('en', gettext('English')),
4127-    )
4128-
4129-With this arrangement, ``make-messages.py`` will still find and mark these
4130-strings for translation, but the translation won't happen at runtime -- so
4131-you'll have to remember to wrap the languages in the *real* ``gettext()`` in
4132-any code that uses ``LANGUAGES`` at runtime.
4133-
4134-LOGIN_REDIRECT_URL
4135-------------------
4136-
4137-**New in Django development version**
4138-
4139-Default: ``'/accounts/profile/'``
4140-
4141-The URL where requests are redirected after login when the
4142-``contrib.auth.login`` view gets no ``next`` parameter.
4143-
4144-This is used by the `@login_required`_ decorator, for example.
4145-
4146-LOGIN_URL
4147----------
4148-
4149-**New in Django development version**
4150-
4151-Default: ``'/accounts/login/'``
4152-
4153-The URL where requests are redirected for login, specially when using the
4154-`@login_required`_ decorator.
4155-
4156-LOGOUT_URL
4157-----------
4158-
4159-**New in Django development version**
4160-
4161-Default: ``'/accounts/logout/'``
4162-
4163-LOGIN_URL counterpart.
4164-
4165-MANAGERS
4166---------
4167-
4168-Default: ``()`` (Empty tuple)
4169-
4170-A tuple in the same format as ``ADMINS`` that specifies who should get
4171-broken-link notifications when ``SEND_BROKEN_LINK_EMAILS=True``.
4172-
4173-MEDIA_ROOT
4174-----------
4175-
4176-Default: ``''`` (Empty string)
4177-
4178-Absolute path to the directory that holds media for this installation.
4179-Example: ``"/home/media/media.lawrence.com/"`` See also ``MEDIA_URL``.
4180-
4181-MEDIA_URL
4182----------
4183-
4184-Default: ``''`` (Empty string)
4185-
4186-URL that handles the media served from ``MEDIA_ROOT``.
4187-Example: ``"http://media.lawrence.com"``
4188-
4189-Note that this should have a trailing slash if it has a path component.
4190-
4191-Good: ``"http://www.example.com/static/"``
4192-Bad: ``"http://www.example.com/static"``
4193-
4194-MIDDLEWARE_CLASSES
4195-------------------
4196-
4197-Default::
4198-
4199-    ("django.contrib.sessions.middleware.SessionMiddleware",
4200-     "django.contrib.auth.middleware.AuthenticationMiddleware",
4201-     "django.middleware.common.CommonMiddleware",
4202-     "django.middleware.doc.XViewMiddleware")
4203-
4204-A tuple of middleware classes to use. See the `middleware docs`_.
4205-
4206-MONTH_DAY_FORMAT
4207-----------------
4208-
4209-Default: ``'F j'``
4210-
4211-The default formatting to use for date fields on Django admin change-list
4212-pages -- and, possibly, by other parts of the system -- in cases when only the
4213-month and day are displayed.
4214-
4215-For example, when a Django admin change-list page is being filtered by a date
4216-drilldown, the header for a given day displays the day and month. Different
4217-locales have different formats. For example, U.S. English would say
4218-"January 1," whereas Spanish might say "1 Enero."
4219-
4220-See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
4221-TIME_FORMAT and YEAR_MONTH_FORMAT.
4222-
4223-PREPEND_WWW
4224------------
4225-
4226-Default: ``False``
4227-
4228-Whether to prepend the "www." subdomain to URLs that don't have it. This is
4229-only used if ``CommonMiddleware`` is installed (see the `middleware docs`_).
4230-See also ``APPEND_SLASH``.
4231-
4232-PROFANITIES_LIST
4233-----------------
4234-
4235-A tuple of profanities, as strings, that will trigger a validation error when
4236-the ``hasNoProfanities`` validator is called.
4237-
4238-We don't list the default values here, because that would be profane. To see
4239-the default values, see the file ``django/conf/global_settings.py``.
4240-
4241-ROOT_URLCONF
4242-------------
4243-
4244-Default: Not defined
4245-
4246-A string representing the full Python import path to your root URLconf. For example:
4247-``"mydjangoapps.urls"``. See `How Django processes a request`_.
4248-
4249-.. _How Django processes a request: ../url_dispatch/#how-django-processes-a-request
4250-
4251-SECRET_KEY
4252-----------
4253-
4254-Default: ``''`` (Empty string)
4255-
4256-A secret key for this particular Django installation. Used to provide a seed in
4257-secret-key hashing algorithms. Set this to a random string -- the longer, the
4258-better. ``django-admin.py startproject`` creates one automatically.
4259-
4260-SEND_BROKEN_LINK_EMAILS
4261------------------------
4262-
4263-Default: ``False``
4264-
4265-Whether to send an e-mail to the ``MANAGERS`` each time somebody visits a
4266-Django-powered page that is 404ed with a non-empty referer (i.e., a broken
4267-link). This is only used if ``CommonMiddleware`` is installed (see the
4268-`middleware docs`_). See also ``IGNORABLE_404_STARTS``,
4269-``IGNORABLE_404_ENDS`` and the section on `error reporting via e-mail`_
4270-
4271-SERIALIZATION_MODULES
4272----------------------
4273-
4274-Default: Not defined.
4275-
4276-A dictionary of modules containing serializer definitions (provided as
4277-strings), keyed by a string identifier for that serialization type. For
4278-example, to define a YAML serializer, use::
4279-
4280-    SERIALIZATION_MODULES = { 'yaml' : 'path.to.yaml_serializer' }
4281-
4282-SERVER_EMAIL
4283-------------
4284-
4285-Default: ``'root@localhost'``
4286-
4287-The e-mail address that error messages come from, such as those sent to
4288-``ADMINS`` and ``MANAGERS``.
4289-
4290-SESSION_COOKIE_AGE
4291-------------------
4292-
4293-Default: ``1209600`` (2 weeks, in seconds)
4294-
4295-The age of session cookies, in seconds. See the `session docs`_.
4296-
4297-SESSION_COOKIE_DOMAIN
4298----------------------
4299-
4300-Default: ``None``
4301-
4302-The domain to use for session cookies. Set this to a string such as
4303-``".lawrence.com"`` for cross-domain cookies, or use ``None`` for a standard
4304-domain cookie. See the `session docs`_.
4305-
4306-SESSION_COOKIE_NAME
4307--------------------
4308-
4309-Default: ``'sessionid'``
4310-
4311-The name of the cookie to use for sessions. This can be whatever you want.
4312-See the `session docs`_.
4313-
4314-SESSION_COOKIE_SECURE
4315----------------------
4316-
4317-Default: ``False``
4318-
4319-Whether to use a secure cookie for the session cookie. If this is set to
4320-``True``, the cookie will be marked as "secure," which means browsers may
4321-ensure that the cookie is only sent under an HTTPS connection.
4322-See the `session docs`_.
4323-
4324-SESSION_EXPIRE_AT_BROWSER_CLOSE
4325--------------------------------
4326-
4327-Default: ``False``
4328-
4329-Whether to expire the session when the user closes his or her browser.
4330-See the `session docs`_.
4331-
4332-SESSION_SAVE_EVERY_REQUEST
4333---------------------------
4334-
4335-Default: ``False``
4336-
4337-Whether to save the session data on every request. See the `session docs`_.
4338-
4339-SITE_ID
4340--------
4341-
4342-Default: Not defined
4343-
4344-The ID, as an integer, of the current site in the ``django_site`` database
4345-table. This is used so that application data can hook into specific site(s)
4346-and a single database can manage content for multiple sites.
4347-
4348-See the `site framework docs`_.
4349-
4350-.. _site framework docs: ../sites/
4351-
4352-TEMPLATE_CONTEXT_PROCESSORS
4353----------------------------
4354-
4355-Default::
4356-
4357-    ("django.core.context_processors.auth",
4358-    "django.core.context_processors.debug",
4359-    "django.core.context_processors.i18n",
4360-    "django.core.context_processors.media")
4361-
4362-A tuple of callables that are used to populate the context in ``RequestContext``.
4363-These callables take a request object as their argument and return a dictionary
4364-of items to be merged into the context.
4365-
4366-TEMPLATE_DEBUG
4367---------------
4368-
4369-Default: ``False``
4370-
4371-A boolean that turns on/off template debug mode. If this is ``True``, the fancy
4372-error page will display a detailed report for any ``TemplateSyntaxError``. This
4373-report contains the relevant snippet of the template, with the appropriate line
4374-highlighted.
4375-
4376-Note that Django only displays fancy error pages if ``DEBUG`` is ``True``, so
4377-you'll want to set that to take advantage of this setting.
4378-
4379-See also DEBUG.
4380-
4381-TEMPLATE_DIRS
4382--------------
4383-
4384-Default: ``()`` (Empty tuple)
4385-
4386-List of locations of the template source files, in search order. Note that
4387-these paths should use Unix-style forward slashes, even on Windows.
4388-
4389-See the `template documentation`_.
4390-
4391-TEMPLATE_LOADERS
4392-----------------
4393-
4394-Default: ``('django.template.loaders.filesystem.load_template_source',)``
4395-
4396-A tuple of callables (as strings) that know how to import templates from
4397-various sources. See the `template documentation`_.
4398-
4399-TEMPLATE_STRING_IF_INVALID
4400---------------------------
4401-
4402-Default: ``''`` (Empty string)
4403-
4404-Output, as a string, that the template system should use for invalid (e.g.
4405-misspelled) variables. See `How invalid variables are handled`_.
4406-
4407-.. _How invalid variables are handled: ../templates_python/#how-invalid-variables-are-handled
4408-
4409-TEST_DATABASE_CHARSET
4410----------------------
4411-
4412-**New in Django development version**
4413-
4414-Default: ``None``
4415-
4416-The character set encoding used to create the test database. The value of this
4417-string is passed directly through to the database, so its format is
4418-backend-specific.
4419-
4420-Supported for the PostgreSQL_ (``postgresql``, ``postgresql_psycopg2``) and MySQL_ (``mysql``, ``mysql_old``) backends.
4421-
4422-.. _PostgreSQL: http://www.postgresql.org/docs/8.2/static/multibyte.html
4423-.. _MySQL: http://www.mysql.org/doc/refman/5.0/en/charset-database.html
4424-
4425-TEST_DATABASE_COLLATION
4426-------------------------
4427-
4428-**New in Django development version**
4429-
4430-Default: ``None``
4431-
4432-The collation order to use when creating the test database. This value is
4433-passed directly to the backend, so its format is backend-specific.
4434-
4435-Only supported for ``mysql`` and ``mysql_old`` backends (see `section 10.3.2`_
4436-of the MySQL manual for details).
4437-
4438-.. _section 10.3.2: http://www.mysql.org/doc/refman/5.0/en/charset-database.html
4439-
4440-TEST_DATABASE_NAME
4441-------------------
4442-
4443-Default: ``None``
4444-
4445-The name of database to use when running the test suite. If a value of
4446-``None`` is specified, the test database will use the name ``'test_' + settings.DATABASE_NAME``. See `Testing Django Applications`_.
4447-
4448-.. _Testing Django Applications: ../testing/
4449-
4450-TEST_RUNNER
4451------------
4452-
4453-Default: ``'django.test.simple.run_tests'``
4454-
4455-The name of the method to use for starting the test suite. See
4456-`Testing Django Applications`_.
4457-
4458-.. _Testing Django Applications: ../testing/
4459-
4460-TIME_FORMAT
4461------------
4462-
4463-Default: ``'P'`` (e.g. ``4 p.m.``)
4464-
4465-The default formatting to use for time fields on Django admin change-list
4466-pages -- and, possibly, by other parts of the system. See
4467-`allowed date format strings`_.
4468-
4469-See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and
4470-MONTH_DAY_FORMAT.
4471-
4472-.. _allowed date format strings: ../templates/#now
4473-
4474-TIME_ZONE
4475----------
4476-
4477-Default: ``'America/Chicago'``
4478-
4479-A string representing the time zone for this installation. `See available choices`_.
4480-(Note that list of available choices lists more than one on the same line;
4481-you'll want to use just one of the choices for a given time zone. For instance,
4482-one line says ``'Europe/London GB GB-Eire'``, but you should use the first bit
4483-of that -- ``'Europe/London'`` -- as your ``TIME_ZONE`` setting.)
4484-
4485-Note that this is the time zone to which Django will convert all dates/times --
4486-not necessarily the timezone of the server. For example, one server may serve
4487-multiple Django-powered sites, each with a separate time-zone setting.
4488-
4489-Normally, Django sets the ``os.environ['TZ']`` variable to the time zone you
4490-specify in the  ``TIME_ZONE`` setting. Thus, all your views and models will
4491-automatically operate in the correct time zone. However, if you're using the
4492-manual configuration option (see below), Django will *not* touch the ``TZ``
4493-environment variable, and it'll be up to you to ensure your processes are
4494-running in the correct environment.
4495-
4496-.. note::
4497-    Django cannot reliably use alternate time zones in a Windows environment.
4498-    If you're running Django on Windows, this variable must be set to match the
4499-    system timezone.
4500-
4501-URL_VALIDATOR_USER_AGENT
4502-------------------------
4503-
4504-Default: ``Django/<version> (http://www.djangoproject.com/)``
4505-
4506-The string to use as the ``User-Agent`` header when checking to see if URLs
4507-exist (see the ``verify_exists`` option on URLField_).
4508-
4509-.. _URLField: ../model-api/#urlfield
4510-
4511-USE_ETAGS
4512----------
4513-
4514-Default: ``False``
4515-
4516-A boolean that specifies whether to output the "Etag" header. This saves
4517-bandwidth but slows down performance. This is only used if ``CommonMiddleware``
4518-is installed (see the `middleware docs`_).
4519-
4520-USE_I18N
4521---------
4522-
4523-Default: ``True``
4524-
4525-A boolean that specifies whether Django's internationalization system should be
4526-enabled. This provides an easy way to turn it off, for performance. If this is
4527-set to ``False``, Django will make some optimizations so as not to load the
4528-internationalization machinery.
4529-
4530-YEAR_MONTH_FORMAT
4531------------------
4532-
4533-Default: ``'F Y'``
4534-
4535-The default formatting to use for date fields on Django admin change-list
4536-pages -- and, possibly, by other parts of the system -- in cases when only the
4537-year and month are displayed.
4538-
4539-For example, when a Django admin change-list page is being filtered by a date
4540-drilldown, the header for a given month displays the month and the year.
4541-Different locales have different formats. For example, U.S. English would say
4542-"January 2006," whereas another locale might say "2006/January."
4543-
4544-See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
4545-TIME_FORMAT and MONTH_DAY_FORMAT.
4546-
4547-.. _cache docs: ../cache/
4548-.. _middleware docs: ../middleware/
4549-.. _session docs: ../sessions/
4550-.. _See available choices: http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
4551-.. _template documentation: ../templates_python/
4552-
4553-Creating your own settings
4554-==========================
4555-
4556-There's nothing stopping you from creating your own settings, for your own
4557-Django apps. Just follow these conventions:
4558-
4559-    * Setting names are in all uppercase.
4560-    * For settings that are sequences, use tuples instead of lists. This is
4561-      purely for performance.
4562-    * Don't reinvent an already-existing setting.
4563-
4564-Using settings without setting DJANGO_SETTINGS_MODULE
4565-=====================================================
4566-
4567-In some cases, you might want to bypass the ``DJANGO_SETTINGS_MODULE``
4568-environment variable. For example, if you're using the template system by
4569-itself, you likely don't want to have to set up an environment variable
4570-pointing to a settings module.
4571-
4572-In these cases, you can configure Django's settings manually. Do this by
4573-calling ``django.conf.settings.configure()``.
4574-
4575-Example::
4576-
4577-    from django.conf import settings
4578-
4579-    settings.configure(DEBUG=True, TEMPLATE_DEBUG=True,
4580-        TEMPLATE_DIRS=('/home/web-apps/myapp', '/home/web-apps/base'))
4581-
4582-Pass ``configure()`` as many keyword arguments as you'd like, with each keyword
4583-argument representing a setting and its value. Each argument name should be all
4584-uppercase, with the same name as the settings described above. If a particular
4585-setting is not passed to ``configure()`` and is needed at some later point,
4586-Django will use the default setting value.
4587-
4588-Configuring Django in this fashion is mostly necessary -- and, indeed,
4589-recommended -- when you're using a piece of the framework inside a larger
4590-application.
4591-
4592-Consequently, when configured via ``settings.configure()``, Django will not
4593-make any modifications to the process environment variables. (See the
4594-explanation of ``TIME_ZONE``, above, for why this would normally occur.) It's
4595-assumed that you're already in full control of your environment in these cases.
4596-
4597-Custom default settings
4598------------------------
4599-
4600-If you'd like default values to come from somewhere other than
4601-``django.conf.global_settings``, you can pass in a module or class that
4602-provides the default settings as the ``default_settings`` argument (or as the
4603-first positional argument) in the call to ``configure()``.
4604-
4605-In this example, default settings are taken from ``myapp_defaults``, and the
4606-``DEBUG`` setting is set to ``True``, regardless of its value in
4607-``myapp_defaults``::
4608-
4609-    from django.conf import settings
4610-    from myapp import myapp_defaults
4611-
4612-    settings.configure(default_settings=myapp_defaults, DEBUG=True)
4613-
4614-The following example, which uses ``myapp_defaults`` as a positional argument,
4615-is equivalent::
4616-
4617-    settings.configure(myapp_defaults, DEBUG = True)
4618-
4619-Normally, you will not need to override the defaults in this fashion. The
4620-Django defaults are sufficiently tame that you can safely use them. Be aware
4621-that if you do pass in a new default module, it entirely *replaces* the Django
4622-defaults, so you must specify a value for every possible setting that might be
4623-used in that code you are importing. Check in
4624-``django.conf.settings.global_settings`` for the full list.
4625-
4626-Either configure() or DJANGO_SETTINGS_MODULE is required
4627---------------------------------------------------------
4628-
4629-If you're not setting the ``DJANGO_SETTINGS_MODULE`` environment variable, you
4630-*must* call ``configure()`` at some point before using any code that reads
4631-settings.
4632-
4633-If you don't set ``DJANGO_SETTINGS_MODULE`` and don't call ``configure()``,
4634-Django will raise an ``EnvironmentError`` exception the first time a setting
4635-is accessed.
4636-
4637-If you set ``DJANGO_SETTINGS_MODULE``, access settings values somehow, *then*
4638-call ``configure()``, Django will raise an ``EnvironmentError`` saying settings
4639-have already been configured.
4640-
4641-Also, it's an error to call ``configure()`` more than once, or to call
4642-``configure()`` after any setting has been accessed.
4643-
4644-It boils down to this: Use exactly one of either ``configure()`` or
4645-``DJANGO_SETTINGS_MODULE``. Not both, and not neither.
4646-
4647-.. _@login_required: ../authentication/#the-login-required-decorator
4648-
4649-Error reporting via e-mail
4650-==========================
4651-
4652-Server errors
4653--------------
4654-
4655-When ``DEBUG`` is ``False``, Django will e-mail the users listed in the
4656-``ADMIN`` setting whenever your code raises an unhandled exception and results
4657-in an internal server error (HTTP status code 500). This gives the
4658-administrators immediate notification of any errors.
4659-
4660-To disable this behavior, just remove all entries from the ``ADMINS`` setting.
4661-
4662-404 errors
4663-----------
4664-
4665-When ``DEBUG`` is ``False``, ``SEND_BROKEN_LINK_EMAILS`` is ``True`` and your
4666-``MIDDLEWARE_CLASSES`` setting includes ``CommonMiddleware``, Django will
4667-e-mail the users listed in the ``MANAGERS`` setting whenever your code raises
4668-a 404 and the request has a referer. (It doesn't bother to e-mail for 404s
4669-that don't have a referer.)
4670-
4671-You can tell Django to stop reporting particular 404s by tweaking the
4672-``IGNORABLE_404_ENDS`` and ``IGNORABLE_404_STARTS`` settings. Both should be a
4673-tuple of strings. For example::
4674-
4675-    IGNORABLE_404_ENDS = ('.php', '.cgi')
4676-    IGNORABLE_404_STARTS = ('/phpmyadmin/',)
4677-
4678-In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not*
4679-be reported. Neither will any URL starting with ``/phpmyadmin/``.
4680-
4681-To disable this behavior, just remove all entries from the ``MANAGERS`` setting.
4682+===============
4683
4684+Django settings
4685
4686+===============
4687
4688+
4689
4690+A Django settings file contains all the configuration of your Django
4691
4692+installation. This document explains how settings work and which settings are
4693
4694+available.
4695
4696+
4697
4698+The basics
4699
4700+==========
4701
4702+
4703
4704+A settings file is just a Python module with module-level variables.
4705
4706+
4707
4708+Here are a couple of example settings::
4709
4710+
4711
4712+    DEBUG = False
4713
4714+    DEFAULT_FROM_EMAIL = 'webmaster@example.com'
4715
4716+    TEMPLATE_DIRS = ('/home/templates/mike', '/home/templates/john')
4717
4718+
4719
4720+Because a settings file is a Python module, the following apply:
4721
4722+
4723
4724+    * It doesn't allow for Python syntax errors.
4725
4726+    * It can assign settings dynamically using normal Python syntax.
4727
4728+      For example::
4729
4730+
4731
4732+          MY_SETTING = [str(i) for i in range(30)]
4733
4734+
4735
4736+    * It can import values from other settings files.
4737
4738+
4739
4740+Designating the settings
4741
4742+========================
4743
4744+
4745
4746+When you use Django, you have to tell it which settings you're using. Do this
4747
4748+by using an environment variable, ``DJANGO_SETTINGS_MODULE``.
4749
4750+
4751
4752+The value of ``DJANGO_SETTINGS_MODULE`` should be in Python path syntax, e.g.
4753
4754+``mysite.settings``. Note that the settings module should be on the
4755
4756+Python `import search path`_.
4757
4758+
4759
4760+.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
4761
4762+
4763
4764+The django-admin.py utility
4765
4766+---------------------------
4767
4768+
4769
4770+When using `django-admin.py`_, you can either set the environment variable
4771
4772+once, or explicitly pass in the settings module each time you run the utility.
4773
4774+
4775
4776+Example (Unix Bash shell)::
4777
4778+
4779
4780+    export DJANGO_SETTINGS_MODULE=mysite.settings
4781
4782+    django-admin.py runserver
4783
4784+
4785
4786+Example (Windows shell)::
4787
4788+
4789
4790+    set DJANGO_SETTINGS_MODULE=mysite.settings
4791
4792+    django-admin.py runserver
4793
4794+
4795
4796+Use the ``--settings`` command-line argument to specify the settings manually::
4797
4798+
4799
4800+    django-admin.py runserver --settings=mysite.settings
4801
4802+
4803
4804+.. _django-admin.py: ../django-admin/
4805
4806+
4807
4808+On the server (mod_python)
4809
4810+--------------------------
4811
4812+
4813
4814+In your live server environment, you'll need to tell Apache/mod_python which
4815
4816+settings file to use. Do that with ``SetEnv``::
4817
4818+
4819
4820+    <Location "/mysite/">
4821
4822+        SetHandler python-program
4823
4824+        PythonHandler django.core.handlers.modpython
4825
4826+        SetEnv DJANGO_SETTINGS_MODULE mysite.settings
4827
4828+    </Location>
4829
4830+
4831
4832+Read the `Django mod_python documentation`_ for more information.
4833
4834+
4835
4836+.. _Django mod_python documentation: ../modpython/
4837
4838+
4839
4840+Default settings
4841
4842+================
4843
4844+
4845
4846+A Django settings file doesn't have to define any settings if it doesn't need
4847
4848+to. Each setting has a sensible default value. These defaults live in the file
4849
4850+``django/conf/global_settings.py``.
4851
4852+
4853
4854+Here's the algorithm Django uses in compiling settings:
4855
4856+
4857
4858+    * Load settings from ``global_settings.py``.
4859
4860+    * Load settings from the specified settings file, overriding the global
4861
4862+      settings as necessary.
4863
4864+
4865
4866+Note that a settings file should *not* import from ``global_settings``, because
4867
4868+that's redundant.
4869
4870+
4871
4872+Seeing which settings you've changed
4873
4874+------------------------------------
4875
4876+
4877
4878+There's an easy way to view which of your settings deviate from the default
4879
4880+settings. The command ``python manage.py diffsettings`` displays differences
4881
4882+between the current settings file and Django's default settings.
4883
4884+
4885
4886+For more, see the `diffsettings documentation`_.
4887
4888+
4889
4890+.. _diffsettings documentation: ../django-admin/#diffsettings
4891
4892+
4893
4894+Using settings in Python code
4895
4896+=============================
4897
4898+
4899
4900+In your Django apps, use settings by importing the object
4901
4902+``django.conf.settings``. Example::
4903
4904+
4905
4906+    from django.conf import settings
4907
4908+
4909
4910+    if settings.DEBUG:
4911
4912+        # Do something
4913
4914+
4915
4916+Note that ``django.conf.settings`` isn't a module -- it's an object. So
4917
4918+importing individual settings is not possible::
4919
4920+
4921
4922+    from django.conf.settings import DEBUG  # This won't work.
4923
4924+
4925
4926+Also note that your code should *not* import from either ``global_settings`` or
4927
4928+your own settings file. ``django.conf.settings`` abstracts the concepts of
4929
4930+default settings and site-specific settings; it presents a single interface.
4931
4932+It also decouples the code that uses settings from the location of your
4933
4934+settings.
4935
4936+
4937
4938+Altering settings at runtime
4939
4940+============================
4941
4942+
4943
4944+You shouldn't alter settings in your applications at runtime. For example,
4945
4946+don't do this in a view::
4947
4948+
4949
4950+    from django.conf import settings
4951
4952+
4953
4954+    settings.DEBUG = True   # Don't do this!
4955
4956+
4957
4958+The only place you should assign to settings is in a settings file.
4959
4960+
4961
4962+Security
4963
4964+========
4965
4966+
4967
4968+Because a settings file contains sensitive information, such as the database
4969
4970+password, you should make every attempt to limit access to it. For example,
4971
4972+change its file permissions so that only you and your Web server's user can
4973
4974+read it. This is especially important in a shared-hosting environment.
4975
4976+
4977
4978+Available settings
4979
4980+==================
4981
4982+
4983
4984+Here's a full list of all available settings, in alphabetical order, and their
4985
4986+default values.
4987
4988+
4989
4990+ABSOLUTE_URL_OVERRIDES
4991
4992+----------------------
4993
4994+
4995
4996+Default: ``{}`` (Empty dictionary)
4997
4998+
4999
5000+A dictionary mapping ``"app_label.model_name"`` strings to functions that take
5001
5002+a model object and return its URL. This is a way of overriding
5003
5004+``get_absolute_url()`` methods on a per-installation basis. Example::
5005
5006+
5007
5008+    ABSOLUTE_URL_OVERRIDES = {
5009
5010+        'blogs.weblog': lambda o: "/blogs/%s/" % o.slug,
5011
5012+        'news.story': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug),
5013
5014+    }
5015
5016+
5017
5018+Note that the model name used in this setting should be all lower-case, regardless
5019
5020+of the case of the actual model class name.
5021
5022+
5023
5024+ADMIN_FOR
5025
5026+---------
5027
5028+
5029
5030+Default: ``()`` (Empty list)
5031
5032+
5033
5034+Used for admin-site settings modules, this should be a tuple of settings
5035
5036+modules (in the format ``'foo.bar.baz'``) for which this site is an admin.
5037
5038+
5039
5040+The admin site uses this in its automatically-introspected documentation of
5041
5042+models, views and template tags.
5043
5044+
5045
5046+ADMIN_MEDIA_PREFIX
5047
5048+------------------
5049
5050+
5051
5052+Default: ``'/media/'``
5053
5054+
5055
5056+The URL prefix for admin media -- CSS, JavaScript and images. Make sure to use
5057
5058+a trailing slash.
5059
5060+
5061
5062+ADMINS
5063
5064+------
5065
5066+
5067
5068+Default: ``()`` (Empty tuple)
5069
5070+
5071
5072+A tuple that lists people who get code error notifications. When
5073
5074+``DEBUG=False`` and a view raises an exception, Django will e-mail these people
5075
5076+with the full exception information. Each member of the tuple should be a tuple
5077
5078+of (Full name, e-mail address). Example::
5079
5080+
5081
5082+    (('John', 'john@example.com'), ('Mary', 'mary@example.com'))
5083
5084+
5085
5086+Note that Django will e-mail *all* of these people whenever an error happens. See the
5087
5088+section on `error reporting via e-mail`_ for more information.
5089
5090+
5091
5092+ALLOWED_INCLUDE_ROOTS
5093
5094+---------------------
5095
5096+
5097
5098+Default: ``()`` (Empty tuple)
5099
5100+
5101
5102+A tuple of strings representing allowed prefixes for the ``{% ssi %}`` template
5103
5104+tag. This is a security measure, so that template authors can't access files
5105
5106+that they shouldn't be accessing.
5107
5108+
5109
5110+For example, if ``ALLOWED_INCLUDE_ROOTS`` is ``('/home/html', '/var/www')``,
5111
5112+then ``{% ssi /home/html/foo.txt %}`` would work, but ``{% ssi /etc/passwd %}``
5113
5114+wouldn't.
5115
5116+
5117
5118+APPEND_SLASH
5119
5120+------------
5121
5122+
5123
5124+Default: ``True``
5125
5126+
5127
5128+Whether to append trailing slashes to URLs. This is only used if
5129
5130+``CommonMiddleware`` is installed (see the `middleware docs`_). See also
5131
5132+``PREPEND_WWW``.
5133
5134+
5135
5136+CACHE_BACKEND
5137
5138+-------------
5139
5140+
5141
5142+Default: ``'simple://'``
5143
5144+
5145
5146+The cache backend to use. See the `cache docs`_.
5147
5148+
5149
5150+CACHE_MIDDLEWARE_KEY_PREFIX
5151
5152+---------------------------
5153
5154+
5155
5156+Default: ``''`` (Empty string)
5157
5158+
5159
5160+The cache key prefix that the cache middleware should use. See the
5161
5162+`cache docs`_.
5163
5164+
5165
5166+CACHE_MIDDLEWARE_SECONDS
5167
5168+------------------------
5169
5170+
5171
5172+Default: ``600``
5173
5174+
5175
5176+The default number of seconds to cache a page when the caching middleware or
5177
5178+``cache_page()`` decorator is used.
5179
5180+
5181
5182+DATABASE_ENGINE
5183
5184+---------------
5185
5186+
5187
5188+Default: ``''`` (Empty string)
5189
5190+
5191
5192+The database backend to use. Either ``'postgresql_psycopg2'``,
5193
5194+``'postgresql'``, ``'mysql'``,  ``'mysql_old'``, ``'sqlite3'``,
5195
5196+``'oracle'``, or ``'ado_mssql'``.
5197
5198+
5199
5200+DATABASE_HOST
5201
5202+-------------
5203
5204+
5205
5206+Default: ``''`` (Empty string)
5207
5208+
5209
5210+Which host to use when connecting to the database. An empty string means
5211
5212+localhost. Not used with SQLite.
5213
5214+
5215
5216+If this value starts with a forward slash (``'/'``) and you're using MySQL,
5217
5218+MySQL will connect via a Unix socket to the specified socket. For example::
5219
5220+
5221
5222+    DATABASE_HOST = '/var/run/mysql'
5223
5224+
5225
5226+If you're using MySQL and this value *doesn't* start with a forward slash, then
5227
5228+this value is assumed to be the host.
5229
5230+
5231
5232+If you're using PostgreSQL, an empty string means to use a Unix domain socket
5233
5234+for the connection, rather than a network connection to localhost. If you
5235
5236+explictly need to use a TCP/IP connection on the local machine with
5237
5238+PostgreSQL, specify ``localhost`` here.
5239
5240+
5241
5242+DATABASE_NAME
5243
5244+-------------
5245
5246+
5247
5248+Default: ``''`` (Empty string)
5249
5250+
5251
5252+The name of the database to use. For SQLite, it's the full path to the database
5253
5254+file.
5255
5256+
5257
5258+DATABASE_OPTIONS
5259
5260+----------------
5261
5262+
5263
5264+Default: ``{}`` (Empty dictionary)
5265
5266+
5267
5268+Extra parameters to use when connecting to the database. Consult backend
5269
5270+module's document for available keywords.
5271
5272+
5273
5274+DATABASE_PASSWORD
5275
5276+-----------------
5277
5278+
5279
5280+Default: ``''`` (Empty string)
5281
5282+
5283
5284+The password to use when connecting to the database. Not used with SQLite.
5285
5286+
5287
5288+DATABASE_PORT
5289
5290+-------------
5291
5292+
5293
5294+Default: ``''`` (Empty string)
5295
5296+
5297
5298+The port to use when connecting to the database. An empty string means the
5299
5300+default port. Not used with SQLite.
5301
5302+
5303
5304+DATABASE_USER
5305
5306+-------------
5307
5308+
5309
5310+Default: ``''`` (Empty string)
5311
5312+
5313
5314+The username to use when connecting to the database. Not used with SQLite.
5315
5316+
5317
5318+DATE_FORMAT
5319
5320+-----------
5321
5322+
5323
5324+Default: ``'N j, Y'`` (e.g. ``Feb. 4, 2003``)
5325
5326+
5327
5328+The default formatting to use for date fields on Django admin change-list
5329
5330+pages -- and, possibly, by other parts of the system. See
5331
5332+`allowed date format strings`_.
5333
5334+
5335
5336+See also DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT.
5337
5338+
5339
5340+.. _allowed date format strings: ../templates/#now
5341
5342+
5343
5344+DATETIME_FORMAT
5345
5346+---------------
5347
5348+
5349
5350+Default: ``'N j, Y, P'`` (e.g. ``Feb. 4, 2003, 4 p.m.``)
5351
5352+
5353
5354+The default formatting to use for datetime fields on Django admin change-list
5355
5356+pages -- and, possibly, by other parts of the system. See
5357
5358+`allowed date format strings`_.
5359
5360+
5361
5362+See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT.
5363
5364+
5365
5366+.. _allowed date format strings: ../templates/#now
5367
5368+
5369
5370+DEBUG
5371
5372+-----
5373
5374+
5375
5376+Default: ``False``
5377
5378+
5379
5380+A boolean that turns on/off debug mode.
5381
5382+
5383
5384+If you define custom settings, django/views/debug.py has a ``HIDDEN_SETTINGS``
5385
5386+regular expression which will hide from the DEBUG view anything that contins
5387
5388+``'SECRET``, ``PASSWORD``, or ``PROFANITIES'``. This allows untrusted users to
5389
5390+be able to give backtraces without seeing sensitive (or offensive) settings.
5391
5392+
5393
5394+Still, note that there are always going to be sections of your debug output that
5395
5396+are inapporpriate for public consumption. File paths, configuration options, and
5397
5398+the like all give attackers extra information about your server. Never deploy a
5399
5400+site with ``DEBUG`` turned on.
5401
5402+
5403
5404+DEFAULT_CHARSET
5405
5406+---------------
5407
5408+
5409
5410+Default: ``'utf-8'``
5411
5412+
5413
5414+Default charset to use for all ``HttpResponse`` objects, if a MIME type isn't
5415
5416+manually specified. Used with ``DEFAULT_CONTENT_TYPE`` to construct the
5417
5418+``Content-Type`` header.
5419
5420+
5421
5422+DEFAULT_CONTENT_TYPE
5423
5424+--------------------
5425
5426+
5427
5428+Default: ``'text/html'``
5429
5430+
5431
5432+Default content type to use for all ``HttpResponse`` objects, if a MIME type
5433
5434+isn't manually specified. Used with ``DEFAULT_CHARSET`` to construct the
5435
5436+``Content-Type`` header.
5437
5438+
5439
5440+DEFAULT_FROM_EMAIL
5441
5442+------------------
5443
5444+
5445
5446+Default: ``'webmaster@localhost'``
5447
5448+
5449
5450+Default e-mail address to use for various automated correspondence from the
5451
5452+site manager(s).
5453
5454+
5455
5456+DISALLOWED_USER_AGENTS
5457
5458+----------------------
5459
5460+
5461
5462+Default: ``()`` (Empty tuple)
5463
5464+
5465
5466+List of compiled regular expression objects representing User-Agent strings
5467
5468+that are not allowed to visit any page, systemwide. Use this for bad
5469
5470+robots/crawlers.  This is only used if ``CommonMiddleware`` is installed (see
5471
5472+the `middleware docs`_).
5473
5474+
5475
5476+EMAIL_HOST
5477
5478+----------
5479
5480+
5481
5482+Default: ``'localhost'``
5483
5484+
5485
5486+The host to use for sending e-mail.
5487
5488+
5489
5490+See also ``EMAIL_PORT``.
5491
5492+
5493
5494+EMAIL_HOST_PASSWORD
5495
5496+-------------------
5497
5498+
5499
5500+Default: ``''`` (Empty string)
5501
5502+
5503
5504+Password to use for the SMTP server defined in ``EMAIL_HOST``. This setting is
5505
5506+used in conjunction with ``EMAIL_HOST_USER`` when authenticating to the SMTP
5507
5508+server. If either of these settings is empty, Django won't attempt
5509
5510+authenticaion.
5511
5512+
5513
5514+See also ``EMAIL_HOST_USER``.
5515
5516+
5517
5518+EMAIL_HOST_USER
5519
5520+---------------
5521
5522+
5523
5524+Default: ``''`` (Empty string)
5525
5526+
5527
5528+Username to use for the SMTP server defined in ``EMAIL_HOST``. If empty,
5529
5530+Django won't attempt authentication.
5531
5532+
5533
5534+See also ``EMAIL_HOST_PASSWORD``.
5535
5536+
5537
5538+EMAIL_PORT
5539
5540+----------
5541
5542+
5543
5544+Default: ``25``
5545
5546+
5547
5548+Port to use for the SMTP server defined in ``EMAIL_HOST``.
5549
5550+
5551
5552+EMAIL_SUBJECT_PREFIX
5553
5554+--------------------
5555
5556+
5557
5558+Default: ``'[Django] '``
5559
5560+
5561
5562+Subject-line prefix for e-mail messages sent with ``django.core.mail.mail_admins``
5563
5564+or ``django.core.mail.mail_managers``. You'll probably want to include the
5565
5566+trailing space.
5567
5568+
5569
5570+EMAIL_USE_TLS
5571
5572+-------------
5573
5574+
5575
5576+**New in Django development version**
5577
5578+
5579
5580+Default: ``False``
5581
5582+
5583
5584+Whether to use a TLS (secure) connection when talking to the SMTP server.
5585
5586+
5587
5588+FILE_CHARSET
5589
5590+------------
5591
5592+
5593
5594+**New in Django development version**
5595
5596+
5597
5598+Default: ``'utf-8'``
5599
5600+
5601
5602+The character encoding used to decode any files read from disk. This includes
5603
5604+template files and initial SQL data files.
5605
5606+
5607
5608+FIXTURE_DIRS
5609
5610+-------------
5611
5612+
5613
5614+Default: ``()`` (Empty tuple)
5615
5616+
5617
5618+List of locations of the fixture data files, in search order. Note that
5619
5620+these paths should use Unix-style forward slashes, even on Windows. See
5621
5622+`Testing Django Applications`_.
5623
5624+
5625
5626+.. _Testing Django Applications: ../testing/
5627
5628+
5629
5630+IGNORABLE_404_ENDS
5631
5632+------------------
5633
5634+
5635
5636+Default: ``('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')``
5637
5638+
5639
5640+See also ``IGNORABLE_404_STARTS`` and ``Error reporting via e-mail``.
5641
5642+
5643
5644+IGNORABLE_404_STARTS
5645
5646+--------------------
5647
5648+
5649
5650+Default: ``('/cgi-bin/', '/_vti_bin', '/_vti_inf')``
5651
5652+
5653
5654+A tuple of strings that specify beginnings of URLs that should be ignored by
5655
5656+the 404 e-mailer. See ``SEND_BROKEN_LINK_EMAILS``, ``IGNORABLE_404_ENDS`` and
5657
5658+the section on `error reporting via e-mail`_.
5659
5660+
5661
5662+INSTALLED_APPS
5663
5664+--------------
5665
5666+
5667
5668+Default: ``()`` (Empty tuple)
5669
5670+
5671
5672+A tuple of strings designating all applications that are enabled in this Django
5673
5674+installation. Each string should be a full Python path to a Python package that
5675
5676+contains a Django application, as created by `django-admin.py startapp`_.
5677
5678+
5679
5680+.. _django-admin.py startapp: ../django-admin/#startapp-appname
5681
5682+
5683
5684+INTERNAL_IPS
5685
5686+------------
5687
5688+
5689
5690+Default: ``()`` (Empty tuple)
5691
5692+
5693
5694+A tuple of IP addresses, as strings, that:
5695
5696+
5697
5698+    * See debug comments, when ``DEBUG`` is ``True``
5699
5700+    * Receive X headers if the ``XViewMiddleware`` is installed (see the
5701
5702+      `middleware docs`_)
5703
5704+
5705
5706+JING_PATH
5707
5708+---------
5709
5710+
5711
5712+Default: ``'/usr/bin/jing'``
5713
5714+
5715
5716+Path to the "Jing" executable. Jing is a RELAX NG validator, and Django uses it
5717
5718+to validate each ``XMLField`` in your models.
5719
5720+See http://www.thaiopensource.com/relaxng/jing.html .
5721
5722+
5723
5724+LANGUAGE_CODE
5725
5726+-------------
5727
5728+
5729
5730+Default: ``'en-us'``
5731
5732+
5733
5734+A string representing the language code for this installation. This should be
5735
5736+in standard language format. For example, U.S. English is ``"en-us"``. See the
5737
5738+`internationalization docs`_.
5739
5740+
5741
5742+.. _internationalization docs: ../i18n/
5743
5744+
5745
5746+LANGUAGES
5747
5748+---------
5749
5750+
5751
5752+Default: A tuple of all available languages. This list is continually growing
5753
5754+and including a copy here would inevitably become rapidly out of date. You can
5755
5756+see the current list of translated languages by looking in
5757
5758+``django/conf/global_settings.py`` (or view the `online source`_).
5759
5760+
5761
5762+.. _online source: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py
5763
5764+
5765
5766+The list is a tuple of two-tuples in the format (language code, language
5767
5768+name) -- for example, ``('ja', 'Japanese')``. This specifies which languages
5769
5770+are available for language selection. See the `internationalization docs`_ for
5771
5772+details.
5773
5774+
5775
5776+Generally, the default value should suffice. Only set this setting if you want
5777
5778+to restrict language selection to a subset of the Django-provided languages.
5779
5780+
5781
5782+If you define a custom ``LANGUAGES`` setting, it's OK to mark the languages as
5783
5784+translation strings (as in the default value displayed above) -- but use a
5785
5786+"dummy" ``gettext()`` function, not the one in ``django.utils.translation``.
5787
5788+You should *never* import ``django.utils.translation`` from within your
5789
5790+settings file, because that module in itself depends on the settings, and that
5791
5792+would cause a circular import.
5793
5794+
5795
5796+The solution is to use a "dummy" ``gettext()`` function. Here's a sample
5797
5798+settings file::
5799
5800+
5801
5802+    gettext = lambda s: s
5803
5804+
5805
5806+    LANGUAGES = (
5807
5808+        ('de', gettext('German')),
5809
5810+        ('en', gettext('English')),
5811
5812+    )
5813
5814+
5815
5816+With this arrangement, ``make-messages.py`` will still find and mark these
5817
5818+strings for translation, but the translation won't happen at runtime -- so
5819
5820+you'll have to remember to wrap the languages in the *real* ``gettext()`` in
5821
5822+any code that uses ``LANGUAGES`` at runtime.
5823
5824+
5825
5826+LOGIN_REDIRECT_URL
5827
5828+------------------
5829
5830+
5831
5832+**New in Django development version**
5833
5834+
5835
5836+Default: ``'/accounts/profile/'``
5837
5838+
5839
5840+The URL where requests are redirected after login when the
5841
5842+``contrib.auth.login`` view gets no ``next`` parameter.
5843
5844+
5845
5846+This is used by the `@login_required`_ decorator, for example.
5847
5848+
5849
5850+LOGIN_URL
5851
5852+---------
5853
5854+
5855
5856+**New in Django development version**
5857
5858+
5859
5860+Default: ``'/accounts/login/'``
5861
5862+
5863
5864+The URL where requests are redirected for login, specially when using the
5865
5866+`@login_required`_ decorator.
5867
5868+
5869
5870+LOGOUT_URL
5871
5872+----------
5873
5874+
5875
5876+**New in Django development version**
5877
5878+
5879
5880+Default: ``'/accounts/logout/'``
5881
5882+
5883
5884+LOGIN_URL counterpart.
5885
5886+
5887
5888+MANAGERS
5889
5890+--------
5891
5892+
5893
5894+Default: ``()`` (Empty tuple)
5895
5896+
5897
5898+A tuple in the same format as ``ADMINS`` that specifies who should get
5899
5900+broken-link notifications when ``SEND_BROKEN_LINK_EMAILS=True``.
5901
5902+
5903
5904+MEDIA_ROOT
5905
5906+----------
5907
5908+
5909
5910+Default: ``''`` (Empty string)
5911
5912+
5913
5914+Absolute path to the directory that holds media for this installation.
5915
5916+Example: ``"/home/media/media.lawrence.com/"`` See also ``MEDIA_URL``.
5917
5918+
5919
5920+MEDIA_URL
5921
5922+---------
5923
5924+
5925
5926+Default: ``''`` (Empty string)
5927
5928+
5929
5930+URL that handles the media served from ``MEDIA_ROOT``.
5931
5932+Example: ``"http://media.lawrence.com"``
5933
5934+
5935
5936+Note that this should have a trailing slash if it has a path component.
5937
5938+
5939
5940+Good: ``"http://www.example.com/static/"``
5941
5942+Bad: ``"http://www.example.com/static"``
5943
5944+
5945
5946+MIDDLEWARE_CLASSES
5947
5948+------------------
5949
5950+
5951
5952+Default::
5953
5954+
5955
5956+    ("django.contrib.sessions.middleware.SessionMiddleware",
5957
5958+     "django.contrib.auth.middleware.AuthenticationMiddleware",
5959
5960+     "django.middleware.common.CommonMiddleware",
5961
5962+     "django.middleware.doc.XViewMiddleware")
5963
5964+
5965
5966+A tuple of middleware classes to use. See the `middleware docs`_.
5967
5968+
5969
5970+MONTH_DAY_FORMAT
5971
5972+----------------
5973
5974+
5975
5976+Default: ``'F j'``
5977
5978+
5979
5980+The default formatting to use for date fields on Django admin change-list
5981
5982+pages -- and, possibly, by other parts of the system -- in cases when only the
5983
5984+month and day are displayed.
5985
5986+
5987
5988+For example, when a Django admin change-list page is being filtered by a date
5989
5990+drilldown, the header for a given day displays the day and month. Different
5991
5992+locales have different formats. For example, U.S. English would say
5993
5994+"January 1," whereas Spanish might say "1 Enero."
5995
5996+
5997
5998+See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
5999
6000+TIME_FORMAT and YEAR_MONTH_FORMAT.
6001
6002+
6003
6004+OTHER_DATABASES
6005
6006+---------------
6007
6008+
6009
6010+Default: ``{}``
6011
6012+
6013
6014+Other database connections to use in addition to the default connection. See the `multiple database support docs`_.
6015
6016+
6017
6018+PREPEND_WWW
6019
6020+-----------
6021
6022+
6023
6024+Default: ``False``
6025
6026+
6027
6028+Whether to prepend the "www." subdomain to URLs that don't have it. This is
6029
6030+only used if ``CommonMiddleware`` is installed (see the `middleware docs`_).
6031
6032+See also ``APPEND_SLASH``.
6033
6034+
6035
6036+PROFANITIES_LIST
6037
6038+----------------
6039
6040+
6041
6042+A tuple of profanities, as strings, that will trigger a validation error when
6043
6044+the ``hasNoProfanities`` validator is called.
6045
6046+
6047
6048+We don't list the default values here, because that would be profane. To see
6049
6050+the default values, see the file ``django/conf/global_settings.py``.
6051
6052+
6053
6054+ROOT_URLCONF
6055
6056+------------
6057
6058+
6059
6060+Default: Not defined
6061
6062+
6063
6064+A string representing the full Python import path to your root URLconf. For example:
6065
6066+``"mydjangoapps.urls"``. See `How Django processes a request`_.
6067
6068+
6069
6070+.. _How Django processes a request: ../url_dispatch/#how-django-processes-a-request
6071
6072+
6073
6074+SECRET_KEY
6075
6076+----------
6077
6078+
6079
6080+Default: ``''`` (Empty string)
6081
6082+
6083
6084+A secret key for this particular Django installation. Used to provide a seed in
6085
6086+secret-key hashing algorithms. Set this to a random string -- the longer, the
6087
6088+better. ``django-admin.py startproject`` creates one automatically.
6089
6090+
6091
6092+SEND_BROKEN_LINK_EMAILS
6093
6094+-----------------------
6095
6096+
6097
6098+Default: ``False``
6099
6100+
6101
6102+Whether to send an e-mail to the ``MANAGERS`` each time somebody visits a
6103
6104+Django-powered page that is 404ed with a non-empty referer (i.e., a broken
6105
6106+link). This is only used if ``CommonMiddleware`` is installed (see the
6107
6108+`middleware docs`_). See also ``IGNORABLE_404_STARTS``,
6109
6110+``IGNORABLE_404_ENDS`` and the section on `error reporting via e-mail`_
6111
6112+
6113
6114+SERIALIZATION_MODULES
6115
6116+---------------------
6117
6118+
6119
6120+Default: Not defined.
6121
6122+
6123
6124+A dictionary of modules containing serializer definitions (provided as
6125
6126+strings), keyed by a string identifier for that serialization type. For
6127
6128+example, to define a YAML serializer, use::
6129
6130+
6131
6132+    SERIALIZATION_MODULES = { 'yaml' : 'path.to.yaml_serializer' }
6133
6134+
6135
6136+SERVER_EMAIL
6137
6138+------------
6139
6140+
6141
6142+Default: ``'root@localhost'``
6143
6144+
6145
6146+The e-mail address that error messages come from, such as those sent to
6147
6148+``ADMINS`` and ``MANAGERS``.
6149
6150+
6151
6152+SESSION_COOKIE_AGE
6153
6154+------------------
6155
6156+
6157
6158+Default: ``1209600`` (2 weeks, in seconds)
6159
6160+
6161
6162+The age of session cookies, in seconds. See the `session docs`_.
6163
6164+
6165
6166+SESSION_COOKIE_DOMAIN
6167
6168+---------------------
6169
6170+
6171
6172+Default: ``None``
6173
6174+
6175
6176+The domain to use for session cookies. Set this to a string such as
6177
6178+``".lawrence.com"`` for cross-domain cookies, or use ``None`` for a standard
6179
6180+domain cookie. See the `session docs`_.
6181
6182+
6183
6184+SESSION_COOKIE_NAME
6185
6186+-------------------
6187
6188+
6189
6190+Default: ``'sessionid'``
6191
6192+
6193
6194+The name of the cookie to use for sessions. This can be whatever you want.
6195
6196+See the `session docs`_.
6197
6198+
6199
6200+SESSION_COOKIE_SECURE
6201
6202+---------------------
6203
6204+
6205
6206+Default: ``False``
6207
6208+
6209
6210+Whether to use a secure cookie for the session cookie. If this is set to
6211
6212+``True``, the cookie will be marked as "secure," which means browsers may
6213
6214+ensure that the cookie is only sent under an HTTPS connection.
6215
6216+See the `session docs`_.
6217
6218+
6219
6220+SESSION_EXPIRE_AT_BROWSER_CLOSE
6221
6222+-------------------------------
6223
6224+
6225
6226+Default: ``False``
6227
6228+
6229
6230+Whether to expire the session when the user closes his or her browser.
6231
6232+See the `session docs`_.
6233
6234+
6235
6236+SESSION_SAVE_EVERY_REQUEST
6237
6238+--------------------------
6239
6240+
6241
6242+Default: ``False``
6243
6244+
6245
6246+Whether to save the session data on every request. See the `session docs`_.
6247
6248+
6249
6250+SITE_ID
6251
6252+-------
6253
6254+
6255
6256+Default: Not defined
6257
6258+
6259
6260+The ID, as an integer, of the current site in the ``django_site`` database
6261
6262+table. This is used so that application data can hook into specific site(s)
6263
6264+and a single database can manage content for multiple sites.
6265
6266+
6267
6268+See the `site framework docs`_.
6269
6270+
6271
6272+.. _site framework docs: ../sites/
6273
6274+
6275
6276+TEMPLATE_CONTEXT_PROCESSORS
6277
6278+---------------------------
6279
6280+
6281
6282+Default::
6283
6284+
6285
6286+    ("django.core.context_processors.auth",
6287
6288+    "django.core.context_processors.debug",
6289
6290+    "django.core.context_processors.i18n",
6291
6292+    "django.core.context_processors.media")
6293
6294+
6295
6296+A tuple of callables that are used to populate the context in ``RequestContext``.
6297
6298+These callables take a request object as their argument and return a dictionary
6299
6300+of items to be merged into the context.
6301
6302+
6303
6304+TEMPLATE_DEBUG
6305
6306+--------------
6307
6308+
6309
6310+Default: ``False``
6311
6312+
6313
6314+A boolean that turns on/off template debug mode. If this is ``True``, the fancy
6315
6316+error page will display a detailed report for any ``TemplateSyntaxError``. This
6317
6318+report contains the relevant snippet of the template, with the appropriate line
6319
6320+highlighted.
6321
6322+
6323
6324+Note that Django only displays fancy error pages if ``DEBUG`` is ``True``, so
6325
6326+you'll want to set that to take advantage of this setting.
6327
6328+
6329
6330+See also DEBUG.
6331
6332+
6333
6334+TEMPLATE_DIRS
6335
6336+-------------
6337
6338+
6339
6340+Default: ``()`` (Empty tuple)
6341
6342+
6343
6344+List of locations of the template source files, in search order. Note that
6345
6346+these paths should use Unix-style forward slashes, even on Windows.
6347
6348+
6349
6350+See the `template documentation`_.
6351
6352+
6353
6354+TEMPLATE_LOADERS
6355
6356+----------------
6357
6358+
6359
6360+Default: ``('django.template.loaders.filesystem.load_template_source',)``
6361
6362+
6363
6364+A tuple of callables (as strings) that know how to import templates from
6365
6366+various sources. See the `template documentation`_.
6367
6368+
6369
6370+TEMPLATE_STRING_IF_INVALID
6371
6372+--------------------------
6373
6374+
6375
6376+Default: ``''`` (Empty string)
6377
6378+
6379
6380+Output, as a string, that the template system should use for invalid (e.g.
6381
6382+misspelled) variables. See `How invalid variables are handled`_.
6383
6384+
6385
6386+.. _How invalid variables are handled: ../templates_python/#how-invalid-variables-are-handled
6387
6388+
6389
6390+TEST_DATABASE_CHARSET
6391
6392+---------------------
6393
6394+
6395
6396+**New in Django development version**
6397
6398+
6399
6400+Default: ``None``
6401
6402+
6403
6404+The character set encoding used to create the test database. The value of this
6405
6406+string is passed directly through to the database, so its format is
6407
6408+backend-specific.
6409
6410+
6411
6412+Supported for the PostgreSQL_ (``postgresql``, ``postgresql_psycopg2``) and MySQL_ (``mysql``, ``mysql_old``) backends.
6413
6414+
6415
6416+.. _PostgreSQL: http://www.postgresql.org/docs/8.2/static/multibyte.html
6417
6418+.. _MySQL: http://www.mysql.org/doc/refman/5.0/en/charset-database.html
6419
6420+
6421
6422+TEST_DATABASE_COLLATION
6423
6424+------------------------
6425
6426+
6427
6428+**New in Django development version**
6429
6430+
6431
6432+Default: ``None``
6433
6434+
6435
6436+The collation order to use when creating the test database. This value is
6437
6438+passed directly to the backend, so its format is backend-specific.
6439
6440+
6441
6442+Only supported for ``mysql`` and ``mysql_old`` backends (see `section 10.3.2`_
6443
6444+of the MySQL manual for details).
6445
6446+
6447
6448+.. _section 10.3.2: http://www.mysql.org/doc/refman/5.0/en/charset-database.html
6449
6450+
6451
6452+TEST_DATABASE_NAME
6453
6454+------------------
6455
6456+
6457
6458+Default: ``None``
6459
6460+
6461
6462+The name of database to use when running the test suite. If a value of
6463
6464+``None`` is specified, the test database will use the name ``'test_' + settings.DATABASE_NAME``. See `Testing Django Applications`_.
6465
6466+
6467
6468+.. _Testing Django Applications: ../testing/
6469
6470+
6471
6472+TEST_RUNNER
6473
6474+-----------
6475
6476+
6477
6478+Default: ``'django.test.simple.run_tests'``
6479
6480+
6481
6482+The name of the method to use for starting the test suite. See
6483
6484+`Testing Django Applications`_.
6485
6486+
6487
6488+.. _Testing Django Applications: ../testing/
6489
6490+
6491
6492+TIME_FORMAT
6493
6494+-----------
6495
6496+
6497
6498+Default: ``'P'`` (e.g. ``4 p.m.``)
6499
6500+
6501
6502+The default formatting to use for time fields on Django admin change-list
6503
6504+pages -- and, possibly, by other parts of the system. See
6505
6506+`allowed date format strings`_.
6507
6508+
6509
6510+See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and
6511
6512+MONTH_DAY_FORMAT.
6513
6514+
6515
6516+.. _allowed date format strings: ../templates/#now
6517
6518+
6519
6520+TIME_ZONE
6521
6522+---------
6523
6524+
6525
6526+Default: ``'America/Chicago'``
6527
6528+
6529
6530+A string representing the time zone for this installation. `See available choices`_.
6531
6532+(Note that list of available choices lists more than one on the same line;
6533
6534+you'll want to use just one of the choices for a given time zone. For instance,
6535
6536+one line says ``'Europe/London GB GB-Eire'``, but you should use the first bit
6537
6538+of that -- ``'Europe/London'`` -- as your ``TIME_ZONE`` setting.)
6539
6540+
6541
6542+Note that this is the time zone to which Django will convert all dates/times --
6543
6544+not necessarily the timezone of the server. For example, one server may serve
6545
6546+multiple Django-powered sites, each with a separate time-zone setting.
6547
6548+
6549
6550+Normally, Django sets the ``os.environ['TZ']`` variable to the time zone you
6551
6552+specify in the  ``TIME_ZONE`` setting. Thus, all your views and models will
6553
6554+automatically operate in the correct time zone. However, if you're using the
6555
6556+manual configuration option (see below), Django will *not* touch the ``TZ``
6557
6558+environment variable, and it'll be up to you to ensure your processes are
6559
6560+running in the correct environment.
6561
6562+
6563
6564+.. note::
6565
6566+    Django cannot reliably use alternate time zones in a Windows environment.
6567
6568+    If you're running Django on Windows, this variable must be set to match the
6569
6570+    system timezone.
6571
6572+
6573
6574+URL_VALIDATOR_USER_AGENT
6575
6576+------------------------
6577
6578+
6579
6580+Default: ``Django/<version> (http://www.djangoproject.com/)``
6581
6582+
6583
6584+The string to use as the ``User-Agent`` header when checking to see if URLs
6585
6586+exist (see the ``verify_exists`` option on URLField_).
6587
6588+
6589
6590+.. _URLField: ../model-api/#urlfield
6591
6592+
6593
6594+USE_ETAGS
6595
6596+---------
6597
6598+
6599
6600+Default: ``False``
6601
6602+
6603
6604+A boolean that specifies whether to output the "Etag" header. This saves
6605
6606+bandwidth but slows down performance. This is only used if ``CommonMiddleware``
6607
6608+is installed (see the `middleware docs`_).
6609
6610+
6611
6612+USE_I18N
6613
6614+--------
6615
6616+
6617
6618+Default: ``True``
6619
6620+
6621
6622+A boolean that specifies whether Django's internationalization system should be
6623
6624+enabled. This provides an easy way to turn it off, for performance. If this is
6625
6626+set to ``False``, Django will make some optimizations so as not to load the
6627
6628+internationalization machinery.
6629
6630+
6631
6632+YEAR_MONTH_FORMAT
6633
6634+-----------------
6635
6636+
6637
6638+Default: ``'F Y'``
6639
6640+
6641
6642+The default formatting to use for date fields on Django admin change-list
6643
6644+pages -- and, possibly, by other parts of the system -- in cases when only the
6645
6646+year and month are displayed.
6647
6648+
6649
6650+For example, when a Django admin change-list page is being filtered by a date
6651
6652+drilldown, the header for a given month displays the month and the year.
6653
6654+Different locales have different formats. For example, U.S. English would say
6655
6656+"January 2006," whereas another locale might say "2006/January."
6657
6658+
6659
6660+See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
6661
6662+TIME_FORMAT and MONTH_DAY_FORMAT.
6663
6664+
6665
6666+.. _cache docs: ../cache/
6667
6668+.. _middleware docs: ../middleware/
6669
6670+.. _session docs: ../sessions/
6671
6672+.. _See available choices: http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
6673
6674+.. _template documentation: ../templates_python/
6675
6676+
6677
6678+Creating your own settings
6679
6680+==========================
6681
6682+
6683
6684+There's nothing stopping you from creating your own settings, for your own
6685
6686+Django apps. Just follow these conventions:
6687
6688+
6689
6690+    * Setting names are in all uppercase.
6691
6692+    * For settings that are sequences, use tuples instead of lists. This is
6693
6694+      purely for performance.
6695
6696+    * Don't reinvent an already-existing setting.
6697
6698+
6699
6700+Using settings without setting DJANGO_SETTINGS_MODULE
6701
6702+=====================================================
6703
6704+
6705
6706+In some cases, you might want to bypass the ``DJANGO_SETTINGS_MODULE``
6707
6708+environment variable. For example, if you're using the template system by
6709
6710+itself, you likely don't want to have to set up an environment variable
6711
6712+pointing to a settings module.
6713
6714+
6715
6716+In these cases, you can configure Django's settings manually. Do this by
6717
6718+calling ``django.conf.settings.configure()``.
6719
6720+
6721
6722+Example::
6723
6724+
6725
6726+    from django.conf import settings
6727
6728+
6729
6730+    settings.configure(DEBUG=True, TEMPLATE_DEBUG=True,
6731
6732+        TEMPLATE_DIRS=('/home/web-apps/myapp', '/home/web-apps/base'))
6733
6734+
6735
6736+Pass ``configure()`` as many keyword arguments as you'd like, with each keyword
6737
6738+argument representing a setting and its value. Each argument name should be all
6739
6740+uppercase, with the same name as the settings described above. If a particular
6741
6742+setting is not passed to ``configure()`` and is needed at some later point,
6743
6744+Django will use the default setting value.
6745
6746+
6747
6748+Configuring Django in this fashion is mostly necessary -- and, indeed,
6749
6750+recommended -- when you're using a piece of the framework inside a larger
6751
6752+application.
6753
6754+
6755
6756+Consequently, when configured via ``settings.configure()``, Django will not
6757
6758+make any modifications to the process environment variables. (See the
6759
6760+explanation of ``TIME_ZONE``, above, for why this would normally occur.) It's
6761
6762+assumed that you're already in full control of your environment in these cases.
6763
6764+
6765
6766+Custom default settings
6767
6768+-----------------------
6769
6770+
6771
6772+If you'd like default values to come from somewhere other than
6773
6774+``django.conf.global_settings``, you can pass in a module or class that
6775
6776+provides the default settings as the ``default_settings`` argument (or as the
6777
6778+first positional argument) in the call to ``configure()``.
6779
6780+
6781
6782+In this example, default settings are taken from ``myapp_defaults``, and the
6783
6784+``DEBUG`` setting is set to ``True``, regardless of its value in
6785
6786+``myapp_defaults``::
6787
6788+
6789
6790+    from django.conf import settings
6791
6792+    from myapp import myapp_defaults
6793
6794+
6795
6796+    settings.configure(default_settings=myapp_defaults, DEBUG=True)
6797
6798+
6799
6800+The following example, which uses ``myapp_defaults`` as a positional argument,
6801
6802+is equivalent::
6803
6804+
6805
6806+    settings.configure(myapp_defaults, DEBUG = True)
6807
6808+
6809
6810+Normally, you will not need to override the defaults in this fashion. The
6811
6812+Django defaults are sufficiently tame that you can safely use them. Be aware
6813
6814+that if you do pass in a new default module, it entirely *replaces* the Django
6815
6816+defaults, so you must specify a value for every possible setting that might be
6817
6818+used in that code you are importing. Check in
6819
6820+``django.conf.settings.global_settings`` for the full list.
6821
6822+
6823
6824+Either configure() or DJANGO_SETTINGS_MODULE is required
6825
6826+--------------------------------------------------------
6827
6828+
6829
6830+If you're not setting the ``DJANGO_SETTINGS_MODULE`` environment variable, you
6831
6832+*must* call ``configure()`` at some point before using any code that reads
6833
6834+settings.
6835
6836+
6837
6838+If you don't set ``DJANGO_SETTINGS_MODULE`` and don't call ``configure()``,
6839
6840+Django will raise an ``EnvironmentError`` exception the first time a setting
6841
6842+is accessed.
6843
6844+
6845
6846+If you set ``DJANGO_SETTINGS_MODULE``, access settings values somehow, *then*
6847
6848+call ``configure()``, Django will raise an ``EnvironmentError`` saying settings
6849
6850+have already been configured.
6851
6852+
6853
6854+Also, it's an error to call ``configure()`` more than once, or to call
6855
6856+``configure()`` after any setting has been accessed.
6857
6858+
6859
6860+It boils down to this: Use exactly one of either ``configure()`` or
6861
6862+``DJANGO_SETTINGS_MODULE``. Not both, and not neither.
6863
6864+
6865
6866+.. _@login_required: ../authentication/#the-login-required-decorator
6867
6868+
6869
6870+Error reporting via e-mail
6871
6872+==========================
6873
6874+
6875
6876+Server errors
6877
6878+-------------
6879
6880+
6881
6882+When ``DEBUG`` is ``False``, Django will e-mail the users listed in the
6883
6884+``ADMIN`` setting whenever your code raises an unhandled exception and results
6885
6886+in an internal server error (HTTP status code 500). This gives the
6887
6888+administrators immediate notification of any errors.
6889
6890+
6891
6892+To disable this behavior, just remove all entries from the ``ADMINS`` setting.
6893
6894+
6895
6896+404 errors
6897
6898+----------
6899
6900+
6901
6902+When ``DEBUG`` is ``False``, ``SEND_BROKEN_LINK_EMAILS`` is ``True`` and your
6903
6904+``MIDDLEWARE_CLASSES`` setting includes ``CommonMiddleware``, Django will
6905
6906+e-mail the users listed in the ``MANAGERS`` setting whenever your code raises
6907
6908+a 404 and the request has a referer. (It doesn't bother to e-mail for 404s
6909
6910+that don't have a referer.)
6911
6912+
6913
6914+You can tell Django to stop reporting particular 404s by tweaking the
6915
6916+``IGNORABLE_404_ENDS`` and ``IGNORABLE_404_STARTS`` settings. Both should be a
6917
6918+tuple of strings. For example::
6919
6920+
6921
6922+    IGNORABLE_404_ENDS = ('.php', '.cgi')
6923
6924+    IGNORABLE_404_STARTS = ('/phpmyadmin/',)
6925
6926+
6927
6928+In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not*
6929
6930+be reported. Neither will any URL starting with ``/phpmyadmin/``.
6931
6932+
6933
6934+To disable this behavior, just remove all entries from the ``MANAGERS`` setting.
6935
6936=== docs/multiple_database_support.txt
6937==================================================================
6938--- docs/multiple_database_support.txt  (/mirror/django/trunk)  (revision 3932)
6939
6940+++ docs/multiple_database_support.txt  (/local/django/multidb) (revision 3932)
6941
6942@@ -0,0 +1,163 @@
6943
6944+========================
6945
6946+Using Multiple Databases
6947
6948+========================
6949
6950+
6951
6952+Standard Django practice is to use a single database connection for
6953
6954+all models in all applications. However, Django supports configuring
6955
6956+and using multiple database connections on a per-application, per-model
6957
6958+or an ad-hoc basis. Using multiple database connections is optional.
6959
6960+
6961
6962+Configuring other database connections
6963
6964+======================================
6965
6966+
6967
6968+Django's default database connection is configured via the settings
6969
6970+DATABASE_ENGINE, DATABASE_NAME, DATABASE_USER, DATABASE_PASSWORD,
6971
6972+DATABASE_HOST, and DATABASE_PORT. Other connections are configured via
6973
6974+the OTHER_DATABASES setting. Define OTHER_DATABASES as a dict, with a
6975
6976+name for each connection as the key and a dict of settings as the
6977
6978+value. In each OTHER_DATABASES entry (called a "named connection"),
6979
6980+the keys are the same as the DATABASE_ENGINE, etc, settings used to
6981
6982+configure the default connection. All keys are optional; any that are
6983
6984+missing in a named connection's settings will inherit their values
6985
6986+from the default connection.
6987
6988+
6989
6990+Here's an example::
6991
6992+
6993
6994+    DATABASE_ENGINE = 'postgresql'
6995
6996+    DATABASE_NAME = 'django_apps'
6997
6998+    DATABASE_USER = 'default_user'
6999
7000+    DATABASE_PASSWORD = 'xxx'
7001
7002+       
7003
7004+    OTHER_DATABASES = {
7005
7006+        'local': { 'DATABASE_ENGINE': 'sqlite3',
7007
7008+                   'DATABASE_NAME': '/tmp/cache.db' },
7009
7010+        'public': { 'DATABASE_HOST': 'public',
7011
7012+                    'DATABASE_USER': 'public_user',
7013
7014+                    'DATABASE_PASSWORD': 'xxx' }
7015
7016+        'private': { 'DATABASE_HOST': 'private',
7017
7018+                     'DATABASE_USER': 'private_user',
7019
7020+                     'DATABASE_PASSWORD': 'xxx' }
7021
7022+    }
7023
7024+
7025
7026+In addition to the DATABASE_* settings, each named connection in
7027
7028+OTHER_DATABASES may optionally include a MODELS setting. This should
7029
7030+be a list of app or app.model names, and is used to configure which
7031
7032+models should use this connection instead of the default connection.
7033
7034+
7035
7036+Here's the example above, with ``MODELS``::
7037
7038+
7039
7040+    OTHER_DATABASES = {
7041
7042+        'local': { 'DATABASE_ENGINE': 'sqlite3',
7043
7044+                   'DATABASE_NAME': '/tmp/cache.db',
7045
7046+                   # A model name: only the model ContentItem
7047
7048+                   # with the app_label myapp will use this connection
7049
7050+                   'MODELS': ['myapp.ContentItem'] },
7051
7052+        'public': { 'DATABASE_HOST': 'public',
7053
7054+                    'DATABASE_USER': 'public_user',
7055
7056+                    'DATABASE_PASSWORD': 'xxx',
7057
7058+                   # Two models in myapp will use the connection
7059
7060+                    # named 'public', as will ALL models in
7061
7062+                    # django.contribe.comments
7063
7064+                   'MODELS': ['myapp.Blog','myapp.Article',
7065
7066+                               'django.contrib.comments' ] }
7067
7068+        # No models or apps are configured to use the private db
7069
7070+        'private': { 'DATABASE_HOST': 'private',
7071
7072+                     'DATABASE_USER': 'private_user',
7073
7074+                     'DATABASE_PASSWORD': 'xxx' }
7075
7076+    }
7077
7078+
7079
7080+Accessing a model's connection
7081
7082+==============================
7083
7084+
7085
7086+Each manager has a ``db`` attribute that can be used to access the model's
7087
7088+connection. Access the ``db`` attribute of a model's manager to obtain the
7089
7090+model's currently configured connection.
7091
7092+
7093
7094+Example::
7095
7096+
7097
7098+    from django.db import models
7099
7100+
7101
7102+    class Blog(models.Model)
7103
7104+        name = models.CharField(maxlength=50)
7105
7106+
7107
7108+    class Article(models.Model)
7109
7110+       blog = models.ForeignKey(Blog)
7111
7112+        title = models.CharField(maxlength=100)
7113
7114+        slug = models.SlugField()
7115
7116+        summary = models.CharField(maxlength=500)
7117
7118+        body = models.TextField()
7119
7120+
7121
7122+    class ContentItem(models.Model)
7123
7124+        slug = models.SlugField()
7125
7126+        mimetype = models.CharField(maxlength=50)
7127
7128+       file = models.FileField()
7129
7130+       
7131
7132+    # Get a ConnectionInfo instance that describes the connection
7133
7134+    article_db = Article.objects.db
7135
7136+   
7137
7138+    # Get a connection and a cursor
7139
7140+    connection = article_db.connection
7141
7142+    cursor = connection.cursor()
7143
7144+
7145
7146+    # Get the ``quote_name`` function from the backend
7147
7148+    qn = article_db.backend.quote_name
7149
7150+
7151
7152+Ordinarily you won't have to access a model's connection directly;
7153
7154+just use the model and manager normally and they will use the
7155
7156+connection configured for the model.
7157
7158+
7159
7160+ConnectionInfo objects
7161
7162+======================
7163
7164+
7165
7166+FIXME Describe the ConnectionInfo object and each of its attributes.
7167
7168+
7169
7170+
7171
7172+Accessing connections by name
7173
7174+=============================
7175
7176+
7177
7178+Access named connections directly through
7179
7180+``django.db.connections``. Each entry in ``django.db.connections`` is
7181
7182+a ``ConnectionInfo`` instance bound to the settings configured in the
7183
7184+OTHER_DATABASES entry under the same key.
7185
7186+
7187
7188+Example::
7189
7190+
7191
7192+    from django.db import connections
7193
7194+
7195
7196+    private_db = connections['private']
7197
7198+    cursor = private_db.connection.cursor()
7199
7200+
7201
7202+
7203
7204+Using transactions with other database connections
7205
7206+==================================================
7207
7208+
7209
7210+Transaction managed state applies across all connections
7211
7212+commit/rollback apply to all connections by default
7213
7214+but you can specify individual connections or lists or dicts of connections
7215
7216+
7217
7218+
7219
7220+Changing model connections on the fly
7221
7222+=====================================
7223
7224+
7225
7226+Here's an example of primitive mirroring::
7227
7228+
7229
7230+    # Read all articles from the private db
7231
7232+    # Note that we pull the articles into a list; this is necessary
7233
7234+    # because query sets are lazy. If we were to change the model's
7235
7236+    # connection without copying the articles into a local list, we'd
7237
7238+    # wind up reading from public instead of private.
7239
7240+
7241
7242+    Article.objects.db = connections['private']
7243
7244+    all_articles = list(Article.objects.all())
7245
7246+   
7247
7248+    # Save each article in the public db
7249
7250+    Article.objects.db = connections['public']
7251
7252+    for article in all_articles:
7253
7254+        article.save()
7255
7256+
7257
7258+Thread and request isolation
7259
7260+============================
7261
7262+
7263
7264+connections close after each request
7265
7266+connection settings are thread-local
7267
7268+
7269
7270
7271Property changes on:
7272___________________________________________________________________
7273Name: svk:merge
7274 -bcc190cf-cafb-0310-a4f2-bffc1f526a37:/django/trunk:1054
7275 +bbbf0183-8649-de40-ae96-8c00a8d06f91:/local/django/db2_9:3912
7276 +bcc190cf-cafb-0310-a4f2-bffc1f526a37:/django/trunk:6110
7277
Back to Top