Permalink
Browse files

Fixed #1142 -- Added multiple database support.

This monster of a patch is the result of Alex Gaynor's 2009 Google Summer of Code project.
Congratulations to Alex for a job well done.

Big thanks also go to:
 * Justin Bronn for keeping GIS in line with the changes,
 * Karen Tracey and Jani Tiainen for their help testing Oracle support
 * Brett Hoerner, Jon Loyens, and Craig Kimmerer for their feedback.
 * Malcolm Treddinick for his guidance during the GSoC submission process.
 * Simon Willison for driving the original design process
 * Cal Henderson for complaining about ponies he wanted.

... and everyone else too numerous to mention that helped to bring this feature into fruition.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@11952 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 7ef212a commit ff60c5f9de3e8690d1e86f3e9e3f7248a15397c8 @freakboy3742 freakboy3742 committed Dec 22, 2009
Showing with 7,874 additions and 5,682 deletions.
  1. +3 −0 django/conf/global_settings.py
  2. +10 −6 django/conf/project_template/settings.py
  3. +21 −10 django/contrib/admin/options.py
  4. +5 −4 django/contrib/admin/widgets.py
  5. +5 −9 django/contrib/auth/models.py
  6. +10 −8 django/contrib/comments/forms.py
  7. +4 −4 django/contrib/comments/models.py
  8. +2 −2 django/contrib/comments/views/comments.py
  9. +11 −11 django/contrib/contenttypes/generic.py
  10. +5 −4 django/contrib/contenttypes/management.py
  11. +10 −10 django/contrib/contenttypes/models.py
  12. +0 −20 django/contrib/gis/db/backend/__init__.py
  13. +0 −26 django/contrib/gis/db/backend/base.py
  14. +0 −13 django/contrib/gis/db/backend/mysql/__init__.py
  15. +0 −5 django/contrib/gis/db/backend/mysql/creation.py
  16. +0 −53 django/contrib/gis/db/backend/mysql/field.py
  17. +0 −59 django/contrib/gis/db/backend/mysql/query.py
  18. +0 −35 django/contrib/gis/db/backend/oracle/__init__.py
  19. +0 −5 django/contrib/gis/db/backend/oracle/adaptor.py
  20. +0 −5 django/contrib/gis/db/backend/oracle/creation.py
  21. +0 −102 django/contrib/gis/db/backend/oracle/field.py
  22. +0 −154 django/contrib/gis/db/backend/oracle/query.py
  23. +0 −51 django/contrib/gis/db/backend/postgis/__init__.py
  24. +0 −231 django/contrib/gis/db/backend/postgis/creation.py
  25. +0 −95 django/contrib/gis/db/backend/postgis/field.py
  26. +0 −54 django/contrib/gis/db/backend/postgis/management.py
  27. +0 −313 django/contrib/gis/db/backend/postgis/query.py
  28. +0 −60 django/contrib/gis/db/backend/spatialite/__init__.py
  29. +0 −61 django/contrib/gis/db/backend/spatialite/creation.py
  30. +0 −82 django/contrib/gis/db/backend/spatialite/field.py
  31. +0 −160 django/contrib/gis/db/backend/spatialite/query.py
  32. 0 django/contrib/gis/db/backends/__init__.py
  33. +1 −1 django/contrib/gis/db/{backend/adaptor.py → backends/adapter.py}
  34. +327 −0 django/contrib/gis/db/backends/base.py
  35. 0 django/contrib/gis/db/backends/mysql/__init__.py
  36. +11 −0 django/contrib/gis/db/backends/mysql/base.py
  37. +18 −0 django/contrib/gis/db/backends/mysql/creation.py
  38. +64 −0 django/contrib/gis/db/backends/mysql/operations.py
  39. 0 django/contrib/gis/db/backends/oracle/__init__.py
  40. +5 −0 django/contrib/gis/db/backends/oracle/adapter.py
  41. +10 −0 django/contrib/gis/db/backends/oracle/base.py
  42. +44 −0 django/contrib/gis/db/backends/oracle/compiler.py
  43. +42 −0 django/contrib/gis/db/backends/oracle/creation.py
  44. +9 −4 django/contrib/gis/db/{backend → backends}/oracle/models.py
  45. +289 −0 django/contrib/gis/db/backends/oracle/operations.py
  46. 0 django/contrib/gis/db/backends/postgis/__init__.py
  47. +3 −4 django/contrib/gis/db/{backend/postgis/adaptor.py → backends/postgis/adapter.py}
  48. +10 −0 django/contrib/gis/db/backends/postgis/base.py
  49. +60 −0 django/contrib/gis/db/backends/postgis/creation.py
  50. +3 −2 django/contrib/gis/db/{backend → backends}/postgis/models.py
  51. +570 −0 django/contrib/gis/db/backends/postgis/operations.py
  52. 0 django/contrib/gis/db/backends/spatialite/__init__.py
  53. +2 −2 django/contrib/gis/db/{backend/spatialite/adaptor.py → backends/spatialite/adapter.py}
  54. +73 −0 django/contrib/gis/db/backends/spatialite/base.py
  55. +5 −0 django/contrib/gis/db/backends/spatialite/client.py
  56. +97 −0 django/contrib/gis/db/backends/spatialite/creation.py
  57. +4 −3 django/contrib/gis/db/{backend → backends}/spatialite/models.py
  58. +329 −0 django/contrib/gis/db/backends/spatialite/operations.py
  59. +24 −23 django/contrib/gis/db/{backend → backends}/util.py
  60. +5 −22 django/contrib/gis/db/models/aggregates.py
  61. +130 −101 django/contrib/gis/db/models/{fields/__init__.py → fields.py}
  62. +1 −5 django/contrib/gis/db/models/manager.py
  63. +86 −65 django/contrib/gis/db/models/query.py
  64. +30 −95 django/contrib/gis/db/models/sql/aggregates.py
  65. +276 −0 django/contrib/gis/db/models/sql/compiler.py
  66. +1 −3 django/contrib/gis/db/models/sql/conversion.py
  67. +39 −286 django/contrib/gis/db/models/sql/query.py
  68. +0 −39 django/contrib/gis/db/models/sql/subqueries.py
  69. +37 −84 django/contrib/gis/db/models/sql/where.py
  70. 0 django/contrib/gis/geometry/__init__.py
  71. +21 −0 django/contrib/gis/geometry/backend/__init__.py
  72. +3 −0 django/contrib/gis/geometry/backend/geos.py
  73. +0 −233 django/contrib/gis/models.py
  74. +13 −11 django/contrib/gis/sitemaps/views.py
  75. +12 −74 django/contrib/gis/tests/__init__.py
  76. +7 −7 django/contrib/gis/tests/distapp/tests.py
  77. +97 −0 django/contrib/gis/tests/geoapp/fixtures/initial_data.json
  78. +0 −8 django/contrib/gis/tests/geoapp/sql/city.mysql.sql
  79. +0 −8 django/contrib/gis/tests/geoapp/sql/city.oracle.sql
  80. +0 −8 django/contrib/gis/tests/geoapp/sql/city.postgresql_psycopg2.sql
  81. +0 −8 django/contrib/gis/tests/geoapp/sql/city.sqlite3.sql
  82. +0 −1 django/contrib/gis/tests/geoapp/sql/co.wkt
  83. +0 −4 django/contrib/gis/tests/geoapp/sql/country.mysql.sql
  84. +0 −4 django/contrib/gis/tests/geoapp/sql/country.postgresql_psycopg2.sql
  85. +0 −4 django/contrib/gis/tests/geoapp/sql/country.sqlite3.sql
  86. +0 −1 django/contrib/gis/tests/geoapp/sql/ks.wkt
  87. +0 −1 django/contrib/gis/tests/geoapp/sql/nz.wkt
  88. +0 −5 django/contrib/gis/tests/geoapp/sql/state.mysql.sql
  89. +0 −5 django/contrib/gis/tests/geoapp/sql/state.postgresql_psycopg2.sql
  90. +0 −5 django/contrib/gis/tests/geoapp/sql/state.sqlite3.sql
  91. +0 −1 django/contrib/gis/tests/geoapp/sql/tx.wkt
  92. +0 −1 django/contrib/gis/tests/geoapp/test_regress.py
  93. +120 −142 django/contrib/gis/tests/geoapp/tests.py
  94. +0 −186 django/contrib/gis/tests/geoapp/tests_mysql.py
  95. +15 −11 django/contrib/gis/tests/layermap/tests.py
  96. +0 −1 django/contrib/gis/tests/layermap/tests_mysql.py
  97. +11 −11 django/contrib/gis/tests/relatedapp/tests.py
  98. +0 −1 django/contrib/gis/tests/relatedapp/tests_mysql.py
  99. +10 −8 django/contrib/gis/tests/test_spatialrefsys.py
  100. +9 −7 django/contrib/gis/tests/utils.py
  101. +72 −165 django/contrib/gis/utils/layermapping.py
  102. +2 −2 django/contrib/localflavor/us/models.py
  103. +8 −3 django/contrib/sessions/backends/db.py
  104. +2 −2 django/contrib/sites/management.py
  105. +14 −3 django/core/management/commands/createcachetable.py
  106. +15 −5 django/core/management/commands/dbshell.py
  107. +10 −4 django/core/management/commands/dumpdata.py
  108. +26 −17 django/core/management/commands/flush.py
  109. +13 −4 django/core/management/commands/inspectdb.py
  110. +88 −74 django/core/management/commands/loaddata.py
  111. +12 −7 django/core/management/commands/reset.py
  112. +11 −2 django/core/management/commands/sql.py
  113. +11 −2 django/core/management/commands/sqlall.py
  114. +11 −2 django/core/management/commands/sqlclear.py
  115. +11 −2 django/core/management/commands/sqlcustom.py
  116. +11 −2 django/core/management/commands/sqlflush.py
  117. +12 −2 django/core/management/commands/sqlindexes.py
  118. +12 −2 django/core/management/commands/sqlreset.py
  119. +12 −1 django/core/management/commands/sqlsequencereset.py
  120. +29 −21 django/core/management/commands/syncdb.py
  121. +28 −32 django/core/management/sql.py
  122. +7 −7 django/core/serializers/__init__.py
  123. +4 −3 django/core/serializers/base.py
  124. +1 −1 django/core/serializers/json.py
  125. +4 −3 django/core/serializers/python.py
  126. +2 −6 django/core/serializers/pyyaml.py
  127. +4 −3 django/core/serializers/xml_serializer.py
  128. +66 −47 django/db/__init__.py
  129. +32 −28 django/db/backends/__init__.py
  130. +15 −19 django/db/backends/creation.py
  131. +2 −2 django/db/backends/dummy/base.py
  132. +14 −14 django/db/backends/mysql/base.py
  133. +6 −6 django/db/backends/mysql/client.py
  134. +8 −10 django/db/backends/mysql/creation.py
  135. +1 −3 django/db/backends/mysql/validation.py
  136. +60 −16 django/db/backends/oracle/base.py
  137. +66 −0 django/db/backends/oracle/compiler.py
  138. +64 −65 django/db/backends/oracle/creation.py
  139. +0 −150 django/db/backends/oracle/query.py
  140. +15 −15 django/db/backends/postgresql/base.py
  141. +7 −7 django/db/backends/postgresql/client.py
  142. +3 −4 django/db/backends/postgresql/creation.py
  143. +4 −3 django/db/backends/postgresql/operations.py
  144. +15 −17 django/db/backends/postgresql_psycopg2/base.py
  145. +6 −10 django/db/backends/sqlite3/base.py
  146. +1 −1 django/db/backends/sqlite3/client.py
  147. +5 −6 django/db/backends/sqlite3/creation.py
  148. +0 −3 django/db/models/aggregates.py
  149. +49 −28 django/db/models/base.py
  150. +4 −4 django/db/models/expressions.py
  151. +97 −37 django/db/models/fields/__init__.py
  152. +3 −3 django/db/models/fields/files.py
  153. +54 −33 django/db/models/fields/related.py
  154. +69 −3 django/db/models/fields/subclassing.py
  155. +22 −4 django/db/models/manager.py
  156. +110 −49 django/db/models/query.py
  157. +2 −2 django/db/models/query_utils.py
  158. +3 −2 django/db/models/related.py
  159. +3 −6 django/db/models/sql/aggregates.py
  160. +921 −0 django/db/models/sql/compiler.py
  161. +4 −8 django/db/models/sql/datastructures.py
  162. +9 −13 django/db/models/sql/expressions.py
  163. +44 −724 django/db/models/sql/query.py
  164. +41 −228 django/db/models/sql/subqueries.py
  165. +46 −31 django/db/models/sql/where.py
  166. +159 −93 django/db/transaction.py
  167. +82 −0 django/db/utils.py
  168. +4 −1 django/forms/models.py
  169. +8 −4 django/test/simple.py
  170. +61 −19 django/test/testcases.py
  171. +0 −1 django/test/utils.py
  172. +20 −0 django/utils/itercompat.py
  173. +1 −1 django/views/debug.py
  174. +93 −36 docs/howto/custom-model-fields.txt
  175. +20 −16 docs/howto/initial-data.txt
  176. +10 −9 docs/howto/legacy-databases.txt
  177. +2 −1 docs/index.txt
  178. +36 −10 docs/internals/contributing.txt
  179. +13 −1 docs/internals/deprecation.txt
  180. +31 −25 docs/intro/tutorial01.txt
  181. +2 −2 docs/man/django-admin.1
  182. +61 −46 docs/ref/databases.txt
  183. +148 −19 docs/ref/django-admin.txt
  184. +3 −3 docs/ref/models/options.txt
  185. +18 −0 docs/ref/models/querysets.txt
  186. +218 −78 docs/ref/settings.txt
  187. +15 −15 docs/releases/0.96.txt
  188. +151 −0 docs/releases/1.2.txt
  189. +1 −0 docs/topics/db/index.txt
  190. +265 −0 docs/topics/db/multi-db.txt
  191. +1 −1 docs/topics/db/sql.txt
  192. +25 −5 docs/topics/db/transactions.txt
  193. +20 −8 docs/topics/http/sessions.txt
  194. +76 −38 docs/topics/testing.txt
  195. +3 −3 tests/modeltests/basic/models.py
  196. +2 −2 tests/modeltests/custom_pk/models.py
  197. +2 −2 tests/modeltests/delete/models.py
  198. +10 −0 tests/modeltests/fixtures/fixtures/db_fixture_1.default.json
  199. BIN tests/modeltests/fixtures/fixtures/db_fixture_2.default.json.gz
  200. +10 −0 tests/modeltests/fixtures/fixtures/db_fixture_3.nosuchdb.json
  201. +38 −2 tests/modeltests/fixtures/models.py
  202. +5 −3 tests/modeltests/lookup/models.py
  203. +1 −1 tests/modeltests/many_to_one/models.py
  204. +3 −2 tests/modeltests/proxy_models/models.py
  205. +2 −2 tests/modeltests/raw_query/tests.py
  206. +9 −9 tests/modeltests/serializers/models.py
  207. +2 −2 tests/modeltests/transactions/models.py
  208. +19 −20 tests/regressiontests/admin_scripts/tests.py
  209. +8 −9 tests/regressiontests/aggregation_regress/models.py
  210. +5 −5 tests/regressiontests/backends/tests.py
  211. +5 −5 tests/regressiontests/datatypes/models.py
  212. +8 −4 tests/regressiontests/defer_regress/models.py
  213. +9 −0 tests/regressiontests/defer_regress/tests.py
  214. +9 −8 tests/regressiontests/delete_regress/models.py
  215. +2 −2 tests/regressiontests/expressions_regress/models.py
  216. +5 −3 tests/regressiontests/extra_regress/models.py
  217. +3 −2 tests/regressiontests/fixtures_regress/models.py
  218. +0 −1 tests/regressiontests/generic_inline_admin/tests.py
  219. +2 −2 tests/regressiontests/introspection/tests.py
  220. +10 −8 tests/regressiontests/model_fields/tests.py
  221. +2 −1 tests/regressiontests/model_inheritance_regress/models.py
  222. +4 −3 tests/regressiontests/model_regress/models.py
  223. 0 tests/regressiontests/multiple_database/__init__.py
  224. +10 −0 tests/regressiontests/multiple_database/fixtures/multidb-common.json
  225. +26 −0 tests/regressiontests/multiple_database/fixtures/multidb.default.json
  226. +26 −0 tests/regressiontests/multiple_database/fixtures/multidb.other.json
  227. +49 −0 tests/regressiontests/multiple_database/models.py
  228. +705 −0 tests/regressiontests/multiple_database/tests.py
  229. +11 −10 tests/regressiontests/queries/models.py
  230. +13 −13 tests/regressiontests/serializers_regress/tests.py
  231. +0 −1 tests/runtests.py
@@ -131,6 +131,9 @@
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
DATABASE_OPTIONS = {} # Set to empty dictionary for default.
+DATABASES = {
+}
+
# The email backend to use. For possible shortcuts see django.core.mail.
# The default is to use the SMTP backend.
# Third-party backends can be specified by providing a Python path
@@ -9,12 +9,16 @@
MANAGERS = ADMINS
-DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
-DATABASE_NAME = '' # Or path to database file if using sqlite3.
-DATABASE_USER = '' # Not used with sqlite3.
-DATABASE_PASSWORD = '' # Not used with sqlite3.
-DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
-DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': '', # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
@@ -141,8 +141,9 @@ def formfield_for_foreignkey(self, db_field, request=None, **kwargs):
"""
Get a form Field for a ForeignKey.
"""
+ db = kwargs.get('using')
if db_field.name in self.raw_id_fields:
- kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel)
+ kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel, using=db)
elif db_field.name in self.radio_fields:
kwargs['widget'] = widgets.AdminRadioSelect(attrs={
'class': get_ul_class(self.radio_fields[db_field.name]),
@@ -159,9 +160,10 @@ def formfield_for_manytomany(self, db_field, request=None, **kwargs):
# a field in admin.
if not db_field.rel.through._meta.auto_created:
return None
+ db = kwargs.get('using')
if db_field.name in self.raw_id_fields:
- kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel)
+ kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel, using=db)
kwargs['help_text'] = ''
elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)):
kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical))
@@ -739,15 +741,15 @@ def add_view(self, request, form_url='', extra_context=None):
form_validated = False
new_object = self.model()
prefixes = {}
- for FormSet in self.get_formsets(request):
+ for FormSet, inline in zip(self.get_formsets(request), self.inline_instances):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1:
prefix = "%s-%s" % (prefix, prefixes[prefix])
formset = FormSet(data=request.POST, files=request.FILES,
instance=new_object,
save_as_new=request.POST.has_key("_saveasnew"),
- prefix=prefix)
+ prefix=prefix, queryset=inline.queryset(request))
formsets.append(formset)
if all_valid(formsets) and form_validated:
self.save_model(request, new_object, form, change=False)
@@ -770,12 +772,14 @@ def add_view(self, request, form_url='', extra_context=None):
initial[k] = initial[k].split(",")
form = ModelForm(initial=initial)
prefixes = {}
- for FormSet in self.get_formsets(request):
+ for FormSet, inline in zip(self.get_formsets(request),
+ self.inline_instances):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1:
prefix = "%s-%s" % (prefix, prefixes[prefix])
- formset = FormSet(instance=self.model(), prefix=prefix)
+ formset = FormSet(instance=self.model(), prefix=prefix,
+ queryset=inline.queryset(request))
formsets.append(formset)
adminForm = helpers.AdminForm(form, list(self.get_fieldsets(request)), self.prepopulated_fields)
@@ -837,13 +841,16 @@ def change_view(self, request, object_id, extra_context=None):
form_validated = False
new_object = obj
prefixes = {}
- for FormSet in self.get_formsets(request, new_object):
+ for FormSet, inline in zip(self.get_formsets(request, new_object),
+ self.inline_instances):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1:
prefix = "%s-%s" % (prefix, prefixes[prefix])
formset = FormSet(request.POST, request.FILES,
- instance=new_object, prefix=prefix)
+ instance=new_object, prefix=prefix,
+ queryset=inline.queryset(request))
+
formsets.append(formset)
if all_valid(formsets) and form_validated:
@@ -859,12 +866,13 @@ def change_view(self, request, object_id, extra_context=None):
else:
form = ModelForm(instance=obj)
prefixes = {}
- for FormSet in self.get_formsets(request, obj):
+ for FormSet, inline in zip(self.get_formsets(request, obj), self.inline_instances):
prefix = FormSet.get_default_prefix()
prefixes[prefix] = prefixes.get(prefix, 0) + 1
if prefixes[prefix] != 1:
prefix = "%s-%s" % (prefix, prefixes[prefix])
- formset = FormSet(instance=obj, prefix=prefix)
+ formset = FormSet(instance=obj, prefix=prefix,
+ queryset=inline.queryset(request))
formsets.append(formset)
adminForm = helpers.AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields)
@@ -1187,6 +1195,9 @@ def get_fieldsets(self, request, obj=None):
form = self.get_formset(request).form
return [(None, {'fields': form.base_fields.keys()})]
+ def queryset(self, request):
+ return self.model._default_manager.all()
+
class StackedInline(InlineModelAdmin):
template = 'admin/edit_inline/stacked.html'
@@ -102,8 +102,9 @@ class ForeignKeyRawIdWidget(forms.TextInput):
A Widget for displaying ForeignKeys in the "raw_id" interface rather than
in a <select> box.
"""
- def __init__(self, rel, attrs=None):
+ def __init__(self, rel, attrs=None, using=None):
self.rel = rel
+ self.db = using
super(ForeignKeyRawIdWidget, self).__init__(attrs)
def render(self, name, value, attrs=None):
@@ -148,16 +149,16 @@ def url_parameters(self):
def label_for_value(self, value):
key = self.rel.get_related_field().name
- obj = self.rel.to._default_manager.get(**{key: value})
+ obj = self.rel.to._default_manager.using(self.db).get(**{key: value})
return '&nbsp;<strong>%s</strong>' % escape(truncate_words(obj, 14))
class ManyToManyRawIdWidget(ForeignKeyRawIdWidget):
"""
A Widget for displaying ManyToMany ids in the "raw_id" interface rather than
in a <select multiple> box.
"""
- def __init__(self, rel, attrs=None):
- super(ManyToManyRawIdWidget, self).__init__(rel, attrs)
+ def __init__(self, rel, attrs=None, using=None):
+ super(ManyToManyRawIdWidget, self).__init__(rel, attrs, using=None)
def render(self, name, value, attrs=None):
attrs['class'] = 'vManyToManyRawIdAdminField'
@@ -3,19 +3,15 @@
from django.contrib import auth
from django.core.exceptions import ImproperlyConfigured
-from django.db import models
+from django.db import models, DEFAULT_DB_ALIAS
from django.db.models.manager import EmptyManager
from django.contrib.contenttypes.models import ContentType
from django.utils.encoding import smart_str
from django.utils.hashcompat import md5_constructor, sha_constructor
from django.utils.translation import ugettext_lazy as _
-UNUSABLE_PASSWORD = '!' # This will never be a valid hash
-try:
- set
-except NameError:
- from sets import Set as set # Python 2.3 fallback
+UNUSABLE_PASSWORD = '!' # This will never be a valid hash
def get_hexdigest(algorithm, salt, raw_password):
"""
@@ -114,15 +110,15 @@ def create_user(self, username, email, password=None):
user.set_password(password)
else:
user.set_unusable_password()
- user.save()
+ user.save(using=self.db)
return user
def create_superuser(self, username, email, password):
u = self.create_user(username, email, password)
u.is_staff = True
u.is_active = True
u.is_superuser = True
- u.save()
+ u.save(using=self.db)
return u
def make_random_password(self, length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789'):
@@ -319,7 +315,7 @@ def get_profile(self):
try:
app_label, model_name = settings.AUTH_PROFILE_MODULE.split('.')
model = models.get_model(app_label, model_name)
- self._profile_cache = model._default_manager.get(user__id__exact=self.id)
+ self._profile_cache = model._default_manager.using(self._state.db).get(user__id__exact=self.id)
self._profile_cache.user = self
except (ImportError, ImproperlyConfigured):
raise SiteProfileNotAvailable
@@ -28,7 +28,7 @@ def __init__(self, target_object, data=None, initial=None):
initial = {}
initial.update(self.generate_security_data())
super(CommentSecurityForm, self).__init__(data=data, initial=initial)
-
+
def security_errors(self):
"""Return just those errors associated with security"""
errors = ErrorDict()
@@ -107,21 +107,21 @@ def get_comment_object(self):
"""
if not self.is_valid():
raise ValueError("get_comment_object may only be called on valid forms")
-
+
CommentModel = self.get_comment_model()
new = CommentModel(**self.get_comment_create_data())
new = self.check_for_duplicate_comment(new)
-
+
return new
-
+
def get_comment_model(self):
"""
Get the comment model to create with this form. Subclasses in custom
comment apps should override this, get_comment_create_data, and perhaps
check_for_duplicate_comment to provide custom comment models.
"""
return Comment
-
+
def get_comment_create_data(self):
"""
Returns the dict of data to be used to create a comment. Subclasses in
@@ -140,13 +140,15 @@ def get_comment_create_data(self):
is_public = True,
is_removed = False,
)
-
+
def check_for_duplicate_comment(self, new):
"""
Check that a submitted comment isn't a duplicate. This might be caused
by someone posting a comment twice. If it is a dup, silently return the *previous* comment.
"""
- possible_duplicates = self.get_comment_model()._default_manager.filter(
+ possible_duplicates = self.get_comment_model()._default_manager.using(
+ self.target_object._state.db
+ ).filter(
content_type = new.content_type,
object_pk = new.object_pk,
user_name = new.user_name,
@@ -156,7 +158,7 @@ def check_for_duplicate_comment(self, new):
for old in possible_duplicates:
if old.submit_date.date() == new.submit_date.date() and old.comment == new.comment:
return old
-
+
return new
def clean_comment(self):
@@ -79,10 +79,10 @@ class Meta:
def __unicode__(self):
return "%s: %s..." % (self.name, self.comment[:50])
- def save(self, force_insert=False, force_update=False):
+ def save(self, *args, **kwargs):
if self.submit_date is None:
self.submit_date = datetime.datetime.now()
- super(Comment, self).save(force_insert, force_update)
+ super(Comment, self).save(*args, **kwargs)
def _get_userinfo(self):
"""
@@ -185,7 +185,7 @@ def __unicode__(self):
return "%s flag of comment ID %s by %s" % \
(self.flag, self.comment_id, self.user.username)
- def save(self, force_insert=False, force_update=False):
+ def save(self, *args, **kwargs):
if self.flag_date is None:
self.flag_date = datetime.datetime.now()
- super(CommentFlag, self).save(force_insert, force_update)
+ super(CommentFlag, self).save(*args, **kwargs)
@@ -25,7 +25,7 @@ def __init__(self, why):
@csrf_protect
@require_POST
-def post_comment(request, next=None):
+def post_comment(request, next=None, using=None):
"""
Post a comment.
@@ -50,7 +50,7 @@ def post_comment(request, next=None):
return CommentPostBadRequest("Missing content_type or object_pk field.")
try:
model = models.get_model(*ctype.split(".", 1))
- target = model._default_manager.get(pk=object_pk)
+ target = model._default_manager.using(using).get(pk=object_pk)
except TypeError:
return CommentPostBadRequest(
"Invalid content_type value: %r" % escape(ctype))
Oops, something went wrong. Retry.

0 comments on commit ff60c5f

Please sign in to comment.