Ticket #4747: multi-db-6110.patch

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

Koen patch against trunk -r6110. Renamed extension to patch so you can see it in the html interface.

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