Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of github.com:django/django into schema-alteration

Conflicts:
	django/db/backends/postgresql_psycopg2/base.py
  • Loading branch information...
commit 4a2e80fff44d0eb1856b593ac5f31ab1492b3e45 2 parents 959a3f9 + ab6cd1c
Andrew Godwin andrewgodwin authored
Showing with 3,184 additions and 2,078 deletions.
  1. +1 −1  AUTHORS
  2. +6 −2 django/conf/__init__.py
  3. +3 −2 django/conf/urls/__init__.py
  4. +7 −8 django/contrib/admin/helpers.py
  5. +1 −2  django/contrib/admin/models.py
  6. +4 −5 django/contrib/admin/options.py
  7. +2 −1  django/contrib/admin/sites.py
  8. +2 −1  django/contrib/admin/static/admin/css/widgets.css
  9. +1 −2  django/contrib/admin/templates/admin/auth/user/change_password.html
  10. +2 −3 django/contrib/admin/templates/admin/change_form.html
  11. +1 −2  django/contrib/admin/templates/admin/change_list.html
  12. +1 −1  django/contrib/admin/templates/admin/delete_confirmation.html
  13. +1 −1  django/contrib/admin/templates/admin/edit_inline/stacked.html
  14. +1 −1  django/contrib/admin/templates/admin/edit_inline/tabular.html
  15. +1 −1  django/contrib/admin/templates/admin/object_history.html
  16. +24 −18 django/contrib/admin/templatetags/admin_list.py
  17. +1 −1  django/contrib/admin/templatetags/admin_modify.py
  18. +7 −1 django/contrib/admin/templatetags/admin_urls.py
  19. +10 −10 django/contrib/admin/util.py
  20. +10 −8 django/contrib/admin/widgets.py
  21. +1 −1  django/contrib/admindocs/templates/admin_doc/bookmarklets.html
  22. +1 −1  django/contrib/admindocs/views.py
  23. +1 −1  django/contrib/auth/admin.py
  24. +6 −4 django/contrib/auth/decorators.py
  25. +17 −7 django/contrib/auth/forms.py
  26. +8 −9 django/contrib/auth/models.py
  27. +3 −3 django/contrib/auth/tests/basic.py
  28. +1 −2  django/contrib/auth/tests/management.py
  29. +13 −23 django/contrib/auth/tests/models.py
  30. +5 −5 django/contrib/auth/tests/views.py
  31. +3 −2 django/contrib/auth/tokens.py
  32. +8 −5 django/contrib/auth/views.py
  33. +3 −3 django/contrib/comments/views/moderation.py
  34. +7 −3 django/contrib/comments/views/utils.py
  35. +4 −5 django/contrib/contenttypes/tests.py
  36. +7 −8 django/contrib/databrowse/datastructures.py
  37. +6 −5 django/contrib/databrowse/plugins/calendars.py
  38. +9 −8 django/contrib/databrowse/plugins/fieldchoices.py
  39. +6 −2 django/contrib/databrowse/plugins/objects.py
  40. +1 −1  django/contrib/flatpages/views.py
  41. +2 −1  django/contrib/formtools/utils.py
  42. +6 −4 django/contrib/formtools/wizard/views.py
  43. +3 −2 django/contrib/gis/admin/widgets.py
  44. +4 −3 django/contrib/gis/db/backends/base.py
  45. +3 −2 django/contrib/gis/db/backends/oracle/operations.py
  46. +3 −2 django/contrib/gis/db/backends/postgis/operations.py
  47. +2 −1  django/contrib/gis/db/backends/spatialite/introspection.py
  48. +3 −2 django/contrib/gis/db/backends/spatialite/operations.py
  49. +4 −2 django/contrib/gis/db/backends/util.py
  50. +2 −1  django/contrib/gis/db/models/fields.py
  51. +2 −1  django/contrib/gis/db/models/proxy.py
  52. +9 −6 django/contrib/gis/db/models/query.py
  53. +1 −1  django/contrib/gis/db/models/sql/compiler.py
  54. +12 −6 django/contrib/gis/forms/fields.py
  55. +2 −2 django/contrib/gis/gdal/__init__.py
  56. +2 −1  django/contrib/gis/gdal/base.py
  57. +7 −4 django/contrib/gis/gdal/datasource.py
  58. +6 −4 django/contrib/gis/gdal/driver.py
  59. +10 −7 django/contrib/gis/gdal/feature.py
  60. +14 −21 django/contrib/gis/gdal/geometries.py
  61. +5 −3 django/contrib/gis/gdal/geomtype.py
  62. +11 −8 django/contrib/gis/gdal/layer.py
  63. +11 −17 django/contrib/gis/gdal/libgdal.py
  64. +10 −9 django/contrib/gis/gdal/prototypes/errcheck.py
  65. +5 −10 django/contrib/gis/gdal/prototypes/geom.py
  66. +17 −15 django/contrib/gis/gdal/srs.py
  67. +2 −6 django/contrib/gis/gdal/tests/test_geom.py
  68. +4 −2 django/contrib/gis/geoip/base.py
  69. +3 −1 django/contrib/gis/geoip/tests.py
  70. +0 −1  django/contrib/gis/geos/base.py
  71. +5 −4 django/contrib/gis/geos/collections.py
  72. +1 −0  django/contrib/gis/geos/coordseq.py
  73. +3 −1 django/contrib/gis/geos/factory.py
  74. +10 −9 django/contrib/gis/geos/geometry.py
  75. +2 −1  django/contrib/gis/geos/linestring.py
  76. +5 −3 django/contrib/gis/geos/mutable_list.py
  77. +4 −2 django/contrib/gis/geos/point.py
  78. +3 −1 django/contrib/gis/geos/polygon.py
  79. +5 −3 django/contrib/gis/geos/prototypes/io.py
  80. +1 −0  django/contrib/gis/geos/prototypes/misc.py
  81. +7 −4 django/contrib/gis/geos/tests/test_geos.py
  82. +6 −5 django/contrib/gis/geos/tests/test_io.py
  83. +2 −1  django/contrib/gis/geos/tests/test_mutable_list.py
  84. +11 −8 django/contrib/gis/maps/google/gmap.py
  85. +6 −5 django/contrib/gis/maps/google/overlays.py
  86. +11 −10 django/contrib/gis/maps/google/zoom.py
  87. +3 −2 django/contrib/gis/measure.py
  88. +2 −1  django/contrib/gis/tests/geoapp/tests.py
  89. +17 −0 django/contrib/gis/tests/test_geoforms.py
  90. +6 −5 django/contrib/gis/utils/layermapping.py
  91. +3 −2 django/contrib/gis/utils/ogrinspect.py
  92. +5 −3 django/contrib/gis/utils/wkt.py
  93. +8 −4 django/contrib/humanize/templatetags/humanize.py
  94. +47 −31 django/contrib/humanize/tests.py
  95. +11 −1 django/contrib/localflavor/ar/forms.py
  96. +7 −4 django/contrib/localflavor/fr/forms.py
  97. +5 −4 django/contrib/localflavor/mx/forms.py
  98. +3 −2 django/contrib/localflavor/se/utils.py
  99. +3 −3 django/contrib/localflavor/tr/forms.py
  100. +5 −5 django/contrib/messages/tests/base.py
  101. +1 −1  django/contrib/messages/tests/cookie.py
  102. +1 −1  django/contrib/sessions/backends/base.py
  103. +1 −0  django/contrib/sessions/backends/cache.py
  104. +1 −1  django/contrib/sessions/backends/signed_cookies.py
  105. +9 −7 django/contrib/sessions/middleware.py
  106. +16 −0 django/contrib/sessions/tests.py
  107. +7 −3 django/contrib/sitemaps/__init__.py
  108. +2 −0  django/contrib/sitemaps/tests/generic.py
  109. +7 −3 django/contrib/staticfiles/handlers.py
  110. +22 −10 django/contrib/staticfiles/storage.py
  111. +27 −3 django/contrib/staticfiles/templatetags/staticfiles.py
  112. +5 −2 django/contrib/staticfiles/views.py
  113. +5 −6 django/contrib/syndication/views.py
  114. +4 −1 django/core/cache/__init__.py
  115. +4 −12 django/core/cache/backends/db.py
  116. +1 −1  django/core/cache/backends/filebased.py
  117. +1 −1  django/core/cache/backends/locmem.py
  118. +3 −1 django/core/cache/backends/memcached.py
  119. +5 −2 django/core/files/storage.py
  120. +2 −1  django/core/handlers/base.py
  121. +1 −4 django/core/handlers/wsgi.py
  122. +13 −15 django/core/mail/backends/console.py
  123. +2 −1  django/core/mail/backends/filebased.py
  124. +1 −4 django/core/mail/backends/smtp.py
  125. +5 −4 django/core/mail/message.py
  126. +1 −1  django/core/management/__init__.py
  127. +2 −2 django/core/management/commands/dumpdata.py
  128. +3 −1 django/core/management/commands/flush.py
  129. +2 −1  django/core/management/commands/inspectdb.py
  130. +44 −23 django/core/management/commands/makemessages.py
  131. +17 −7 django/core/management/commands/shell.py
  132. +20 −14 django/core/management/sql.py
  133. +6 −4 django/core/management/templates.py
  134. +6 −5 django/core/management/validation.py
  135. +2 −1  django/core/serializers/base.py
  136. +4 −4 django/core/serializers/json.py
  137. +4 −2 django/core/serializers/pyyaml.py
  138. +9 −6 django/core/servers/basehttp.py
  139. +11 −4 django/core/urlresolvers.py
  140. +8 −4 django/core/validators.py
  141. +74 −29 django/db/backends/__init__.py
  142. +1 −1  django/db/backends/creation.py
  143. +29 −25 django/db/backends/mysql/base.py
  144. +47 −27 django/db/backends/oracle/base.py
  145. +10 −7 django/db/backends/postgresql_psycopg2/base.py
  146. +19 −15 django/db/backends/postgresql_psycopg2/operations.py
  147. +18 −8 django/db/backends/sqlite3/base.py
  148. +0 −2  django/db/models/__init__.py
  149. +69 −49 django/db/models/base.py
  150. +4 −3 django/db/models/fields/__init__.py
  151. +8 −3 django/db/models/fields/files.py
  152. +11 −10 django/db/models/fields/related.py
  153. +11 −6 django/db/models/loading.py
  154. +4 −3 django/db/models/options.py
  155. +30 −11 django/db/models/query.py
  156. +11 −2 django/db/models/query_utils.py
  157. +6 −3 django/db/models/sql/compiler.py
  158. +0 −3  django/db/models/sql/datastructures.py
  159. +18 −7 django/db/models/sql/query.py
  160. +2 −0  django/db/models/sql/subqueries.py
  161. +50 −33 django/db/models/sql/where.py
  162. +2 −1  django/db/utils.py
  163. +34 −34 django/dispatch/dispatcher.py
  164. +2 −1  django/forms/extras/widgets.py
  165. +12 −8 django/forms/fields.py
  166. +11 −9 django/forms/forms.py
  167. +5 −3 django/forms/formsets.py
  168. +7 −5 django/forms/models.py
  169. +14 −7 django/forms/util.py
  170. +40 −31 django/forms/widgets.py
  171. +49 −54 django/http/__init__.py
  172. +2 −1  django/http/multipartparser.py
  173. +1 −1  django/shortcuts/__init__.py
  174. +5 −9 django/template/base.py
  175. +21 −14 django/template/defaultfilters.py
  176. +8 −11 django/template/defaulttags.py
  177. +2 −1  django/template/loader.py
  178. +9 −8 django/template/response.py
  179. +2 −1  django/templatetags/i18n.py
  180. +64 −5 django/templatetags/static.py
  181. +2 −1  django/templatetags/tz.py
  182. +15 −13 django/test/_doctest.py
  183. +10 −6 django/test/client.py
  184. +14 −14 django/test/html.py
  185. +12 −0 django/test/signals.py
  186. +2 −2 django/test/simple.py
  187. +57 −22 django/test/testcases.py
  188. +2 −1  django/test/utils.py
  189. +3 −1 django/utils/archive.py
  190. +1 −1  django/utils/autoreload.py
  191. +1 −1  django/utils/baseconv.py
  192. +3 −1 django/utils/checksums.py
  193. +4 −3 django/utils/crypto.py
  194. +2 −2 django/utils/daemonize.py
  195. +97 −89 django/utils/datastructures.py
  196. +3 −2 django/utils/dateformat.py
  197. +3 −1 django/utils/dictconfig.py
  198. +37 −24 django/utils/encoding.py
  199. +7 −4 django/utils/feedgenerator.py
  200. +6 −5 django/utils/formats.py
  201. +6 −5 django/utils/functional.py
  202. +56 −21 django/utils/html.py
  203. +14 −10 django/utils/html_parser.py
  204. +19 −12 django/utils/http.py
  205. +1 −1  django/utils/importlib.py
  206. +1 −0  django/utils/ipv6.py
  207. +3 −3 django/utils/itercompat.py
  208. +3 −2 django/utils/numberformat.py
  209. +0 −109 django/utils/py3.py
  210. +3 −1 django/utils/regex_helper.py
  211. +17 −16 django/utils/safestring.py
  212. +367 −0 django/utils/six.py
  213. +15 −14 django/utils/text.py
  214. +3 −2 django/utils/timezone.py
  215. +8 −7 django/utils/translation/__init__.py
  216. +1 −1  django/utils/translation/trans_real.py
  217. +1 −1  django/views/csrf.py
  218. +7 −6 django/views/debug.py
  219. +3 −3 django/views/defaults.py
  220. +1 −1  django/views/generic/detail.py
  221. +4 −3 django/views/i18n.py
  222. +7 −4 django/views/static.py
  223. +1 −0  docs/conf.py
  224. +3 −3 docs/faq/install.txt
  225. +4 −7 docs/faq/models.txt
  226. +1 −1  docs/howto/custom-management-commands.txt
  227. +6 −2 docs/howto/custom-model-fields.txt
  228. +1 −1  docs/howto/deployment/wsgi/uwsgi.txt
  229. +6 −6 docs/howto/initial-data.txt
  230. +1 −1  docs/howto/jython.txt
  231. +26 −11 docs/internals/committers.txt
  232. +3 −3 docs/internals/contributing/localizing.txt
  233. +1 −1  docs/internals/contributing/writing-code/unit-tests.txt
  234. +1 −1  docs/internals/contributing/writing-documentation.txt
  235. +7 −0 docs/internals/deprecation.txt
  236. BIN  docs/intro/_images/admin12t.png
  237. +1 −1  docs/intro/install.txt
  238. +21 −2 docs/intro/tutorial02.txt
  239. +3 −3 docs/intro/whatsnext.txt
  240. +9 −9 docs/ref/class-based-views/generic-display.txt
  241. +18 −17 docs/ref/contrib/admin/index.txt
  242. +1 −1  docs/ref/contrib/comments/index.txt
  243. +2 −3 docs/ref/contrib/formtools/form-wizard.txt
  244. +6 −53 docs/ref/contrib/gis/deployment.txt
  245. +1 −1  docs/ref/contrib/gis/gdal.txt
  246. +3 −3 docs/ref/contrib/gis/geoquerysets.txt
  247. +2 −2 docs/ref/contrib/gis/geos.txt
  248. +15 −76 docs/ref/contrib/gis/install.txt
  249. +2 −2 docs/ref/contrib/gis/model-api.txt
  250. +4 −5 docs/ref/contrib/gis/sitemaps.txt
  251. +1 −1  docs/ref/contrib/gis/tutorial.txt
  252. +3 −3 docs/ref/contrib/localflavor.txt
  253. +5 −2 docs/ref/contrib/messages.txt
  254. +1 −1  docs/ref/contrib/sitemaps.txt
  255. +11 −0 docs/ref/contrib/staticfiles.txt
  256. +5 −3 docs/ref/databases.txt
  257. +23 −3 docs/ref/django-admin.txt
  258. +5 −1 docs/ref/forms/fields.txt
  259. +1 −1  docs/ref/forms/widgets.txt
  260. +11 −11 docs/ref/models/fields.txt
  261. +35 −1 docs/ref/models/instances.txt
  262. +2 −2 docs/ref/models/options.txt
  263. +14 −33 docs/ref/models/querysets.txt
  264. +11 −12 docs/ref/request-response.txt
  265. +1 −1  docs/ref/settings.txt
  266. +17 −6 docs/ref/templates/api.txt
  267. +17 −6 docs/ref/templates/builtins.txt
  268. +68 −3 docs/ref/utils.txt
  269. +1 −1  docs/releases/1.0-beta-2.txt
  270. +2 −2 docs/releases/1.0.1.txt
  271. +1 −1  docs/releases/1.0.txt
  272. +2 −2 docs/releases/1.1.txt
  273. +1 −1  docs/releases/1.3.txt
  274. +10 −2 docs/releases/1.4.txt
  275. +84 −4 docs/releases/1.5.txt
  276. +5 −5 docs/topics/class-based-views/generic-display.txt
  277. +2 −2 docs/topics/class-based-views/index.txt
  278. +2 −1  docs/topics/db/models.txt
  279. +7 −0 docs/topics/db/transactions.txt
  280. +1 −1  docs/topics/email.txt
  281. +23 −0 docs/topics/files.txt
  282. +3 −0  docs/topics/forms/index.txt
  283. +2 −1  docs/topics/forms/modelforms.txt
  284. +2 −1  docs/topics/http/middleware.txt
  285. +4 −1 docs/topics/http/sessions.txt
  286. +2 −2 docs/topics/http/shortcuts.txt
  287. +2 −2 docs/topics/http/urls.txt
  288. +1 −1  docs/topics/i18n/timezones.txt
  289. +5 −5 docs/topics/i18n/translation.txt
  290. +3 −3 docs/topics/install.txt
  291. +2 −2 docs/topics/logging.txt
  292. +84 −199 docs/topics/python3.txt
  293. +11 −4 docs/topics/signals.txt
  294. +105 −38 docs/topics/testing.txt
  295. +20 −0 tests/modeltests/aggregation/tests.py
  296. +13 −11 tests/modeltests/basic/tests.py
  297. +5 −4 tests/modeltests/custom_columns/tests.py
  298. +2 −1  tests/modeltests/custom_managers/tests.py
  299. +3 −2 tests/modeltests/custom_pk/fields.py
  300. +8 −7 tests/modeltests/custom_pk/tests.py
Sorry, we could not display the entire diff because too many files (406) changed.
2  AUTHORS
View
@@ -30,6 +30,7 @@ The PRIMARY AUTHORS are (and/or have been):
* Aymeric Augustin
* Claude Paroz
* Anssi Kääriäinen
+ * Florian Apolloner
More information on the main contributors to Django can be found in
docs/internals/committers.txt.
@@ -61,7 +62,6 @@ answer newbie questions, and generally made Django that much better:
andy@jadedplanet.net
Fabrice Aneche <akh@nobugware.com>
ant9000@netwise.it
- Florian Apolloner <florian@apolloner.eu>
arien <regexbot@gmail.com>
David Ascher <http://ascher.ca/>
atlithorn <atlithorn@gmail.com>
8 django/conf/__init__.py
View
@@ -15,6 +15,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.utils.functional import LazyObject, empty
from django.utils import importlib
+from django.utils import six
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
@@ -73,7 +74,7 @@ def __setattr__(self, name, value):
elif name == "ADMIN_MEDIA_PREFIX":
warnings.warn("The ADMIN_MEDIA_PREFIX setting has been removed; "
"use STATIC_URL instead.", DeprecationWarning)
- elif name == "ALLOWED_INCLUDE_ROOTS" and isinstance(value, basestring):
+ elif name == "ALLOWED_INCLUDE_ROOTS" and isinstance(value, six.string_types):
raise ValueError("The ALLOWED_INCLUDE_ROOTS setting must be set "
"to a tuple, not a string.")
object.__setattr__(self, name, value)
@@ -102,7 +103,10 @@ def __init__(self, settings_module):
if setting == setting.upper():
setting_value = getattr(mod, setting)
if setting in tuple_settings and \
- isinstance(setting_value, basestring):
+ isinstance(setting_value, six.string_types):
+ warnings.warn("The %s setting must be a tuple. Please fix your "
+ "settings, as auto-correction is now deprecated." % setting,
+ PendingDeprecationWarning)
setting_value = (setting_value,) # In case the user forgot the comma.
setattr(self, setting, setting_value)
5 django/conf/urls/__init__.py
View
@@ -2,6 +2,7 @@
RegexURLResolver, LocaleRegexURLResolver)
from django.core.exceptions import ImproperlyConfigured
from django.utils.importlib import import_module
+from django.utils import six
__all__ = ['handler403', 'handler404', 'handler500', 'include', 'patterns', 'url']
@@ -20,7 +21,7 @@ def include(arg, namespace=None, app_name=None):
# No namespace hint - use manually provided namespace
urlconf_module = arg
- if isinstance(urlconf_module, basestring):
+ if isinstance(urlconf_module, six.string_types):
urlconf_module = import_module(urlconf_module)
patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
@@ -52,7 +53,7 @@ def url(regex, view, kwargs=None, name=None, prefix=''):
urlconf_module, app_name, namespace = view
return RegexURLResolver(regex, urlconf_module, kwargs, app_name=app_name, namespace=namespace)
else:
- if isinstance(view, basestring):
+ if isinstance(view, six.string_types):
if not view:
raise ImproperlyConfigured('Empty URL pattern view name not permitted (for pattern %r)' % regex)
if prefix:
15 django/contrib/admin/helpers.py
View
@@ -10,8 +10,9 @@
from django.forms.util import flatatt
from django.template.defaultfilters import capfirst
from django.utils.encoding import force_unicode, smart_unicode
-from django.utils.html import escape, conditional_escape
+from django.utils.html import conditional_escape, format_html
from django.utils.safestring import mark_safe
+from django.utils import six
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
@@ -49,7 +50,7 @@ def first_field(self):
try:
fieldset_name, fieldset_options = self.fieldsets[0]
field_name = fieldset_options['fields'][0]
- if not isinstance(field_name, basestring):
+ if not isinstance(field_name, six.string_types):
field_name = field_name[0]
return self.form[field_name]
except (KeyError, IndexError):
@@ -163,11 +164,9 @@ def label_tag(self):
if not self.is_first:
attrs["class"] = "inline"
label = self.field['label']
- contents = capfirst(force_unicode(escape(label))) + ":"
- return mark_safe('<label%(attrs)s>%(contents)s</label>' % {
- "attrs": flatatt(attrs),
- "contents": contents,
- })
+ return format_html('<label{0}>{1}:</label>',
+ flatatt(attrs),
+ capfirst(force_unicode(label)))
def contents(self):
from django.contrib.admin.templatetags.admin_list import _boolean_icon
@@ -190,7 +189,7 @@ def contents(self):
if value is None:
result_repr = EMPTY_CHANGELIST_VALUE
elif isinstance(f.rel, ManyToManyRel):
- result_repr = ", ".join(map(unicode, value.all()))
+ result_repr = ", ".join(map(six.text_type, value.all()))
else:
result_repr = display_for_field(value, f)
return conditional_escape(result_repr)
3  django/contrib/admin/models.py
View
@@ -6,7 +6,6 @@
from django.contrib.admin.util import quote
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
-from django.utils.safestring import mark_safe
ADDITION = 1
CHANGE = 2
@@ -66,5 +65,5 @@ def get_admin_url(self):
This is relative to the Django admin index page.
"""
if self.content_type and self.object_id:
- return mark_safe("%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, quote(self.object_id)))
+ return "%s/%s/%s/" % (self.content_type.app_label, self.content_type.model, quote(self.object_id))
return None
9 django/contrib/admin/options.py
View
@@ -24,6 +24,7 @@
from django.utils.datastructures import SortedDict
from django.utils.html import escape, escapejs
from django.utils.safestring import mark_safe
+from django.utils import six
from django.utils.text import capfirst, get_text_list
from django.utils.translation import ugettext as _
from django.utils.translation import ungettext
@@ -57,9 +58,8 @@ class IncorrectLookupParameters(Exception):
csrf_protect_m = method_decorator(csrf_protect)
-class BaseModelAdmin(object):
+class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
"""Functionality common to both ModelAdmin and InlineAdmin."""
- __metaclass__ = forms.MediaDefiningClass
raw_id_fields = ()
fields = None
@@ -745,7 +745,7 @@ def render_change_form(self, request, context, add=False, change=False, form_url
'has_file_field': True, # FIXME - this should check if form or formsets have a FileField,
'has_absolute_url': hasattr(self.model, 'get_absolute_url'),
'ordered_objects': ordered_objects,
- 'form_url': mark_safe(form_url),
+ 'form_url': form_url,
'opts': opts,
'content_type_id': ContentType.objects.get_for_model(self.model).id,
'save_as': self.save_as,
@@ -998,7 +998,6 @@ def add_view(self, request, form_url='', extra_context=None):
'title': _('Add %s') % force_unicode(opts.verbose_name),
'adminform': adminForm,
'is_popup': "_popup" in request.REQUEST,
- 'show_delete': False,
'media': media,
'inline_admin_formsets': inline_admin_formsets,
'errors': helpers.AdminErrorList(form, formsets),
@@ -1321,7 +1320,7 @@ def history_view(self, request, object_id, extra_context=None):
opts = model._meta
app_label = opts.app_label
action_list = LogEntry.objects.filter(
- object_id = object_id,
+ object_id = unquote(object_id),
content_type__id__exact = ContentType.objects.get_for_model(model).id
).select_related().order_by('action_time')
# If no history was found, see whether this object even exists.
3  django/contrib/admin/sites.py
View
@@ -231,7 +231,8 @@ def wrapper(*args, **kwargs):
wrap(self.i18n_javascript, cacheable=True),
name='jsi18n'),
url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$',
- wrap(contenttype_views.shortcut)),
+ wrap(contenttype_views.shortcut),
+ name='view_on_site'),
url(r'^(?P<app_label>\w+)/$',
wrap(self.app_index),
name='app_list')
3  django/contrib/admin/static/admin/css/widgets.css
View
@@ -41,7 +41,8 @@
text-align: left;
}
-.selector .selector-filter label {
+.selector .selector-filter label,
+.inline-group .aligned .selector .selector-filter label {
width: 16px;
padding: 2px;
}
3  django/contrib/admin/templates/admin/auth/user/change_password.html
View
@@ -3,8 +3,7 @@
{% load admin_urls %}
{% block extrahead %}{{ block.super }}
-{% url 'admin:jsi18n' as jsi18nurl %}
-<script type="text/javascript" src="{{ jsi18nurl|default:"../../../../jsi18n/" }}"></script>
+<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
{% endblock %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />{% endblock %}
{% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %}
5 django/contrib/admin/templates/admin/change_form.html
View
@@ -3,8 +3,7 @@
{% load admin_urls %}
{% block extrahead %}{{ block.super }}
-{% url 'admin:jsi18n' as jsi18nurl %}
-<script type="text/javascript" src="{{ jsi18nurl|default:"../../../jsi18n/" }}"></script>
+<script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
{{ media }}
{% endblock %}
@@ -31,7 +30,7 @@
<ul class="object-tools">
{% block object-tools-items %}
<li><a href="history/" class="historylink">{% trans "History" %}</a></li>
- {% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ original.pk }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
+ {% if has_absolute_url %}<li><a href="{% url 'admin:view_on_site' content_type_id original.pk %}" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
{% endblock %}
</ul>
{% endif %}{% endif %}
3  django/contrib/admin/templates/admin/change_list.html
View
@@ -9,8 +9,7 @@
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />
{% endif %}
{% if cl.formset or action_form %}
- {% url 'admin:jsi18n' as jsi18nurl %}
- <script type="text/javascript" src="{{ jsi18nurl|default:'../../jsi18n/' }}"></script>
+ <script type="text/javascript" src="{% url 'admin:jsi18n' %}"></script>
{% endif %}
{{ media.css }}
{% if not actions_on_top and not actions_on_bottom %}
2  django/contrib/admin/templates/admin/delete_confirmation.html
View
@@ -7,7 +7,7 @@
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=opts.app_label %}">{{ app_label|capfirst }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ opts.verbose_name_plural|capfirst|escape }}</a>
-&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}{{ object.pk }}">{{ object|truncatewords:"18" }}</a>
+&rsaquo; <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
&rsaquo; {% trans 'Delete' %}
</div>
{% endblock %}
2  django/contrib/admin/templates/admin/edit_inline/stacked.html
View
@@ -6,7 +6,7 @@
{% for inline_admin_form in inline_admin_formset %}<div class="inline-related{% if forloop.last %} empty-form last-related{% endif %}" id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
<h3><b>{{ inline_admin_formset.opts.verbose_name|title }}:</b>&nbsp;<span class="inline_label">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% else %}#{{ forloop.counter }}{% endif %}</span>
- {% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.pk }}/">{% trans "View on site" %}</a>{% endif %}
+ {% if inline_admin_form.show_url %}<a href="{% url 'admin:view_on_site' inline_admin_form.original_content_type_id inline_admin_form.original.pk %}">{% trans "View on site" %}</a>{% endif %}
{% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
</h3>
{% if inline_admin_form.form.non_field_errors %}{{ inline_admin_form.form.non_field_errors }}{% endif %}
2  django/contrib/admin/templates/admin/edit_inline/tabular.html
View
@@ -27,7 +27,7 @@
<td class="original">
{% if inline_admin_form.original or inline_admin_form.show_url %}<p>
{% if inline_admin_form.original %} {{ inline_admin_form.original }}{% endif %}
- {% if inline_admin_form.show_url %}<a href="../../../r/{{ inline_admin_form.original_content_type_id }}/{{ inline_admin_form.original.pk }}/">{% trans "View on site" %}</a>{% endif %}
+ {% if inline_admin_form.show_url %}<a href="{% url 'admin:view_on_site' inline_admin_form.original_content_type_id inline_admin_form.original.pk %}">{% trans "View on site" %}</a>{% endif %}
</p>{% endif %}
{% if inline_admin_form.has_auto_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{{ inline_admin_form.fk_field.field }}
2  django/contrib/admin/templates/admin/object_history.html
View
@@ -7,7 +7,7 @@
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label=app_label %}">{{ app_label|capfirst|escape }}</a>
&rsaquo; <a href="{% url opts|admin_urlname:'changelist' %}">{{ module_name }}</a>
-&rsaquo; <a href="{% url opts|admin_urlname:'change' object.pk %}">{{ object|truncatewords:"18" }}</a>
+&rsaquo; <a href="{% url opts|admin_urlname:'change' object.pk|admin_urlquote %}">{{ object|truncatewords:"18" }}</a>
&rsaquo; {% trans 'History' %}
</div>
{% endblock %}
42 django/contrib/admin/templatetags/admin_list.py
View
@@ -10,7 +10,7 @@
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils import formats
-from django.utils.html import escape, conditional_escape
+from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.utils.text import capfirst
from django.utils.translation import ugettext as _
@@ -31,9 +31,12 @@ def paginator_number(cl,i):
if i == DOT:
return '... '
elif i == cl.page_num:
- return mark_safe('<span class="this-page">%d</span> ' % (i+1))
+ return format_html('<span class="this-page">{0}</span> ', i+1)
else:
- return mark_safe('<a href="%s"%s>%d</a> ' % (escape(cl.get_query_string({PAGE_VAR: i})), (i == cl.paginator.num_pages-1 and ' class="end"' or ''), i+1))
+ return format_html('<a href="{0}"{1}>{2}</a> ',
+ cl.get_query_string({PAGE_VAR: i}),
+ mark_safe(' class="end"' if i == cl.paginator.num_pages-1 else ''),
+ i+1)
@register.inclusion_tag('admin/pagination.html')
def pagination(cl):
@@ -159,13 +162,14 @@ def result_headers(cl):
"url_primary": cl.get_query_string({ORDER_VAR: '.'.join(o_list_primary)}),
"url_remove": cl.get_query_string({ORDER_VAR: '.'.join(o_list_remove)}),
"url_toggle": cl.get_query_string({ORDER_VAR: '.'.join(o_list_toggle)}),
- "class_attrib": mark_safe(th_classes and ' class="%s"' % ' '.join(th_classes) or '')
+ "class_attrib": format_html(' class="{0}"', ' '.join(th_classes))
+ if th_classes else '',
}
def _boolean_icon(field_val):
icon_url = static('admin/img/icon-%s.gif' %
{True: 'yes', False: 'no', None: 'unknown'}[field_val])
- return mark_safe('<img src="%s" alt="%s" />' % (icon_url, field_val))
+ return format_html('<img src="{0}" alt="{1}" />', icon_url, field_val)
def items_for_result(cl, result, form):
"""
@@ -182,7 +186,7 @@ def items_for_result(cl, result, form):
else:
if f is None:
if field_name == 'action_checkbox':
- row_class = ' class="action-checkbox"'
+ row_class = mark_safe(' class="action-checkbox"')
allow_tags = getattr(attr, 'allow_tags', False)
boolean = getattr(attr, 'boolean', False)
if boolean:
@@ -190,23 +194,21 @@ def items_for_result(cl, result, form):
result_repr = display_for_value(value, boolean)
# Strip HTML tags in the resulting text, except if the
# function has an "allow_tags" attribute set to True.
- if not allow_tags:
- result_repr = escape(result_repr)
- else:
+ if allow_tags:
result_repr = mark_safe(result_repr)
if isinstance(value, (datetime.date, datetime.time)):
- row_class = ' class="nowrap"'
+ row_class = mark_safe(' class="nowrap"')
else:
if isinstance(f.rel, models.ManyToOneRel):
field_val = getattr(result, f.name)
if field_val is None:
result_repr = EMPTY_CHANGELIST_VALUE
else:
- result_repr = escape(field_val)
+ result_repr = field_val
else:
result_repr = display_for_field(value, f)
if isinstance(f, (models.DateField, models.TimeField, models.ForeignKey)):
- row_class = ' class="nowrap"'
+ row_class = mark_safe(' class="nowrap"')
if force_unicode(result_repr) == '':
result_repr = mark_safe('&nbsp;')
# If list_display_links not defined, add the link tag to the first field
@@ -222,8 +224,14 @@ def items_for_result(cl, result, form):
attr = pk
value = result.serializable_value(attr)
result_id = repr(force_unicode(value))[1:]
- yield mark_safe('<%s%s><a href="%s"%s>%s</a></%s>' % \
- (table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), conditional_escape(result_repr), table_tag))
+ yield format_html('<{0}{1}><a href="{2}"{3}>{4}</a></{5}>',
+ table_tag,
+ row_class,
+ url,
+ format_html(' onclick="opener.dismissRelatedLookupPopup(window, {0}); return false;"', result_id)
+ if cl.is_popup else '',
+ result_repr,
+ table_tag)
else:
# By default the fields come from ModelAdmin.list_editable, but if we pull
# the fields out of the form instead of list_editable custom admins
@@ -233,11 +241,9 @@ def items_for_result(cl, result, form):
form[cl.model._meta.pk.name].is_hidden)):
bf = form[field_name]
result_repr = mark_safe(force_unicode(bf.errors) + force_unicode(bf))
- else:
- result_repr = conditional_escape(result_repr)
- yield mark_safe('<td%s>%s</td>' % (row_class, result_repr))
+ yield format_html('<td{0}>{1}</td>', row_class, result_repr)
if form and not form[cl.model._meta.pk.name].is_hidden:
- yield mark_safe('<td>%s</td>' % force_unicode(form[cl.model._meta.pk.name]))
+ yield format_html('<td>{0}</td>', force_unicode(form[cl.model._meta.pk.name]))
class ResultList(list):
# Wrapper class used to return items in a list_editable
2  django/contrib/admin/templatetags/admin_modify.py
View
@@ -32,7 +32,7 @@ def submit_row(context):
'onclick_attrib': (opts.get_ordered_objects() and change
and 'onclick="submitOrderForm();"' or ''),
'show_delete_link': (not is_popup and context['has_delete_permission']
- and (change or context['show_delete'])),
+ and change and context.get('show_delete', True)),
'show_save_as_new': not is_popup and change and save_as,
'show_save_and_add_another': context['has_add_permission'] and
not is_popup and (not save_as or context['add']),
8 django/contrib/admin/templatetags/admin_urls.py
View
@@ -1,8 +1,14 @@
-from django.core.urlresolvers import reverse, NoReverseMatch
+from django.core.urlresolvers import reverse
from django import template
+from django.contrib.admin.util import quote
register = template.Library()
@register.filter
def admin_urlname(value, arg):
return 'admin:%s_%s_%s' % (value.app_label, value.module_name, arg)
+
+
+@register.filter
+def admin_urlquote(value):
+ return quote(value)
20 django/contrib/admin/util.py
View
@@ -9,11 +9,11 @@
from django.db.models.related import RelatedObject
from django.forms.forms import pretty_name
from django.utils import formats
-from django.utils.html import escape
-from django.utils.safestring import mark_safe
+from django.utils.html import format_html
from django.utils.text import capfirst
from django.utils import timezone
from django.utils.encoding import force_unicode, smart_unicode, smart_str
+from django.utils import six
from django.utils.translation import ungettext
from django.core.urlresolvers import reverse
@@ -52,7 +52,7 @@ def quote(s):
quoting is slightly different so that it doesn't get automatically
unquoted by the Web browser.
"""
- if not isinstance(s, basestring):
+ if not isinstance(s, six.string_types):
return s
res = list(s)
for i in range(len(res)):
@@ -124,10 +124,10 @@ def format_callback(obj):
if not user.has_perm(p):
perms_needed.add(opts.verbose_name)
# Display a link to the admin page.
- return mark_safe('%s: <a href="%s">%s</a>' %
- (escape(capfirst(opts.verbose_name)),
- admin_url,
- escape(obj)))
+ return format_html('{0}: <a href="{1}">{2}</a>',
+ capfirst(opts.verbose_name),
+ admin_url,
+ obj)
else:
# Don't display link to edit, because it either has no
# admin or is edited inline.
@@ -275,10 +275,10 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
except models.FieldDoesNotExist:
if name == "__unicode__":
label = force_unicode(model._meta.verbose_name)
- attr = unicode
+ attr = six.text_type
elif name == "__str__":
label = smart_str(model._meta.verbose_name)
- attr = str
+ attr = bytes
else:
if callable(name):
attr = name
@@ -350,7 +350,7 @@ def display_for_value(value, boolean=False):
return formats.localize(timezone.template_localtime(value))
elif isinstance(value, (datetime.date, datetime.time)):
return formats.localize(value)
- elif isinstance(value, (decimal.Decimal, float, int, long)):
+ elif isinstance(value, six.integer_types + (decimal.Decimal, float)):
return formats.number_format(value)
else:
return smart_unicode(value)
18 django/contrib/admin/widgets.py
View
@@ -10,11 +10,12 @@
from django.core.urlresolvers import reverse
from django.forms.widgets import RadioFieldRenderer
from django.forms.util import flatatt
-from django.utils.html import escape
+from django.utils.html import escape, format_html, format_html_join
from django.utils.text import Truncator
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
from django.utils.encoding import force_unicode
+from django.utils import six
class FilteredSelectMultiple(forms.SelectMultiple):
@@ -85,16 +86,17 @@ def __init__(self, attrs=None):
forms.MultiWidget.__init__(self, widgets, attrs)
def format_output(self, rendered_widgets):
- return mark_safe('<p class="datetime">%s %s<br />%s %s</p>' % \
- (_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]))
+ return format_html('<p class="datetime">{0} {1}<br />{2} {3}</p>',
+ _('Date:'), rendered_widgets[0],
+ _('Time:'), rendered_widgets[1])
class AdminRadioFieldRenderer(RadioFieldRenderer):
def render(self):
"""Outputs a <ul> for this set of radio fields."""
- return mark_safe('<ul%s>\n%s\n</ul>' % (
- flatatt(self.attrs),
- '\n'.join(['<li>%s</li>' % force_unicode(w) for w in self]))
- )
+ return format_html('<ul{0}>\n{1}\n</ul>',
+ flatatt(self.attrs),
+ format_html_join('\n', '<li>{0}</li>',
+ ((force_unicode(w),) for w in self)))
class AdminRadioSelect(forms.RadioSelect):
renderer = AdminRadioFieldRenderer
@@ -120,7 +122,7 @@ def url_params_from_lookup_dict(lookups):
# See django.db.fields.BooleanField.get_prep_lookup
v = ('0', '1')[v]
else:
- v = unicode(v)
+ v = six.text_type(v)
items.append((k, v))
params.update(dict(items))
return params
2  django/contrib/admindocs/templates/admin_doc/bookmarklets.html
View
@@ -22,7 +22,7 @@
{% endblocktrans %}
<div id="content-main">
- <h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('HEAD',location.href,false);x.send(null);try{view=x.getResponseHeader('x-view');}catch(e){alert('No view found for this page');return;}if(view=='undefined'){alert('No view found for this page');}document.location='{{ admin_url }}doc/views/'+view+'/';})()">{% trans "Documentation for this page" %}</a></h3>
+ <h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('HEAD',location.href,false);x.send(null);try{view=x.getResponseHeader('x-view');}catch(e){alert('No view found for this page');return;}if(view=='undefined'){alert('No view found for this page');}document.location='{{ admin_url|escapejs }}doc/views/'+view+'/';})()">{% trans "Documentation for this page" %}</a></h3>
<p>{% trans "Jumps you from any page to the documentation for the view that generates that page." %}</p>
<h3><a href="javascript:(function(){if(typeof ActiveXObject!='undefined'){x=new ActiveXObject('Microsoft.XMLHTTP')}else if(typeof XMLHttpRequest!='undefined'){x=new XMLHttpRequest()}else{return;}x.open('GET',location.href,false);x.send(null);try{type=x.getResponseHeader('x-object-type');id=x.getResponseHeader('x-object-id');}catch(e){type='(none)';id='(none)';}d=document;b=d.body;e=d.createElement('div');e.id='xxxhhh';s=e.style;s.position='absolute';s.left='10px';s.top='10px';s.font='10px monospace';s.border='1px black solid';s.padding='4px';s.backgroundColor='#eee';e.appendChild(d.createTextNode('Type: '+type));e.appendChild(d.createElement('br'));e.appendChild(d.createTextNode('ID: '+id));e.appendChild(d.createElement('br'));l=d.createElement('a');l.href='#';l.onclick=function(){b.removeChild(e);};l.appendChild(d.createTextNode('[close]'));l.style.textDecoration='none';e.appendChild(l);b.appendChild(e);})();">{% trans "Show object ID" %}</a></h3>
2  django/contrib/admindocs/views.py
View
@@ -37,7 +37,7 @@ def bookmarklets(request):
admin_root = urlresolvers.reverse('admin:index')
return render_to_response('admin_doc/bookmarklets.html', {
'root_path': admin_root,
- 'admin_url': mark_safe("%s://%s%s" % (request.is_secure() and 'https' or 'http', request.get_host(), admin_root)),
+ 'admin_url': "%s://%s%s" % (request.is_secure() and 'https' or 'http', request.get_host(), admin_root),
}, context_instance=RequestContext(request))
@staff_member_required
2  django/contrib/auth/admin.py
View
@@ -134,7 +134,7 @@ def user_change_password(self, request, id, form_url=''):
context = {
'title': _('Change password: %s') % escape(user.username),
'adminForm': adminForm,
- 'form_url': mark_safe(form_url),
+ 'form_url': form_url,
'form': form,
'is_popup': '_popup' in request.REQUEST,
'add': True,
10 django/contrib/auth/decorators.py
View
@@ -1,4 +1,7 @@
-import urlparse
+try:
+ from urllib.parse import urlparse
+except ImportError: # Python 2
+ from urlparse import urlparse
from functools import wraps
from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME
@@ -21,9 +24,8 @@ def _wrapped_view(request, *args, **kwargs):
path = request.build_absolute_uri()
# If the login url is the same scheme and net location then just
# use the path as the "next" url.
- login_scheme, login_netloc = urlparse.urlparse(login_url or
- settings.LOGIN_URL)[:2]
- current_scheme, current_netloc = urlparse.urlparse(path)[:2]
+ login_scheme, login_netloc = urlparse(login_url or settings.LOGIN_URL)[:2]
+ current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
24 django/contrib/auth/forms.py
View
@@ -1,6 +1,10 @@
+from __future__ import unicode_literals
+
from django import forms
from django.forms.util import flatatt
from django.template import loader
+from django.utils.datastructures import SortedDict
+from django.utils.html import format_html, format_html_join
from django.utils.http import int_to_base36
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext, ugettext_lazy as _
@@ -11,6 +15,7 @@
from django.contrib.auth.tokens import default_token_generator
from django.contrib.sites.models import get_current_site
+
UNMASKED_DIGITS_TO_SHOW = 6
mask_password = lambda p: "%s%s" % (p[:UNMASKED_DIGITS_TO_SHOW], "*" * max(len(p) - UNMASKED_DIGITS_TO_SHOW, 0))
@@ -28,13 +33,15 @@ def render(self, name, value, attrs):
try:
hasher = identify_hasher(encoded)
except ValueError:
- summary = "<strong>Invalid password format or unknown hashing algorithm.</strong>"
+ summary = mark_safe("<strong>Invalid password format or unknown hashing algorithm.</strong>")
else:
- summary = ""
- for key, value in hasher.safe_summary(encoded).iteritems():
- summary += "<strong>%(key)s</strong>: %(value)s " % {"key": ugettext(key), "value": value}
+ summary = format_html_join('',
+ "<strong>{0}</strong>: {1} ",
+ ((ugettext(key), value)
+ for key, value in hasher.safe_summary(encoded).items())
+ )
- return mark_safe("<div%(attrs)s>%(summary)s</div>" % {"attrs": flatatt(final_attrs), "summary": summary})
+ return format_html("<div{0}>{1}</div>", flatatt(final_attrs), summary)
class ReadOnlyPasswordHashField(forms.Field):
@@ -288,8 +295,11 @@ def clean_old_password(self):
raise forms.ValidationError(
self.error_messages['password_incorrect'])
return old_password
-PasswordChangeForm.base_fields.keyOrder = ['old_password', 'new_password1',
- 'new_password2']
+
+PasswordChangeForm.base_fields = SortedDict([
+ (k, PasswordChangeForm.base_fields[k])
+ for k in ['old_password', 'new_password1', 'new_password2']
+])
class AdminPasswordChangeForm(forms.Form):
17 django/contrib/auth/models.py
View
@@ -1,13 +1,12 @@
from __future__ import unicode_literals
-import urllib
-
from django.core.exceptions import ImproperlyConfigured
from django.core.mail import send_mail
from django.db import models
from django.db.models.manager import EmptyManager
from django.utils.crypto import get_random_string
-from django.utils.encoding import smart_str
+from django.utils.http import urlquote
+from django.utils import six
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
@@ -79,9 +78,9 @@ class Meta:
def __unicode__(self):
return "%s | %s | %s" % (
- unicode(self.content_type.app_label),
- unicode(self.content_type),
- unicode(self.name))
+ six.text_type(self.content_type.app_label),
+ six.text_type(self.content_type),
+ six.text_type(self.name))
def natural_key(self):
return (self.codename,) + self.content_type.natural_key()
@@ -267,7 +266,7 @@ def natural_key(self):
return (self.username,)
def get_absolute_url(self):
- return "/users/%s/" % urllib.quote(smart_str(self.username))
+ return "/users/%s/" % urlquote(self.username)
def is_anonymous(self):
"""
@@ -300,7 +299,7 @@ def check_password(self, raw_password):
"""
def setter(raw_password):
self.set_password(raw_password)
- self.save()
+ self.save(update_fields=["password"])
return check_password(raw_password, self.password, setter)
def set_unusable_password(self):
@@ -421,7 +420,7 @@ def __unicode__(self):
return 'AnonymousUser'
def __str__(self):
- return unicode(self).encode('utf-8')
+ return six.text_type(self).encode('utf-8')
def __eq__(self, other):
return isinstance(other, self.__class__)
6 django/contrib/auth/tests/basic.py
View
@@ -1,8 +1,8 @@
-from django.test import TestCase
-from django.utils.unittest import skipUnless
from django.contrib.auth.models import User, AnonymousUser
from django.core.management import call_command
-from StringIO import StringIO
+from django.test import TestCase
+from django.utils.six import StringIO
+from django.utils.unittest import skipUnless
try:
import crypt as crypt_module
3  django/contrib/auth/tests/management.py
View
@@ -1,11 +1,10 @@
from __future__ import unicode_literals
-from StringIO import StringIO
-
from django.contrib.auth import models, management
from django.contrib.auth.management.commands import changepassword
from django.core.management.base import CommandError
from django.test import TestCase
+from django.utils.six import StringIO
class GetDefaultUsernameTestCase(TestCase):
36 django/contrib/auth/tests/models.py
View
@@ -5,39 +5,29 @@
SiteProfileNotAvailable, UserManager)
-@override_settings(USE_TZ=False)
+@override_settings(USE_TZ=False, AUTH_PROFILE_MODULE='')
class ProfileTestCase(TestCase):
- fixtures = ['authtestdata.json']
-
- def setUp(self):
- """Backs up the AUTH_PROFILE_MODULE"""
- self.old_AUTH_PROFILE_MODULE = getattr(settings,
- 'AUTH_PROFILE_MODULE', None)
-
- def tearDown(self):
- """Restores the AUTH_PROFILE_MODULE -- if it was not set it is deleted,
- otherwise the old value is restored"""
- if self.old_AUTH_PROFILE_MODULE is None and \
- hasattr(settings, 'AUTH_PROFILE_MODULE'):
- del settings.AUTH_PROFILE_MODULE
-
- if self.old_AUTH_PROFILE_MODULE is not None:
- settings.AUTH_PROFILE_MODULE = self.old_AUTH_PROFILE_MODULE
def test_site_profile_not_available(self):
+ user = User.objects.create(username='testclient')
+
# calling get_profile without AUTH_PROFILE_MODULE set
- if hasattr(settings, 'AUTH_PROFILE_MODULE'):
- del settings.AUTH_PROFILE_MODULE
- user = User.objects.get(username='testclient')
- self.assertRaises(SiteProfileNotAvailable, user.get_profile)
+ del settings.AUTH_PROFILE_MODULE
+ with self.assertRaisesRegexp(SiteProfileNotAvailable,
+ "You need to set AUTH_PROFILE_MODULE in your project"):
+ user.get_profile()
# Bad syntax in AUTH_PROFILE_MODULE:
settings.AUTH_PROFILE_MODULE = 'foobar'
- self.assertRaises(SiteProfileNotAvailable, user.get_profile)
+ with self.assertRaisesRegexp(SiteProfileNotAvailable,
+ "app_label and model_name should be separated by a dot"):
+ user.get_profile()
# module that doesn't exist
settings.AUTH_PROFILE_MODULE = 'foo.bar'
- self.assertRaises(SiteProfileNotAvailable, user.get_profile)
+ with self.assertRaisesRegexp(SiteProfileNotAvailable,
+ "Unable to load the profile model"):
+ user.get_profile()
@override_settings(USE_TZ=False)
10 django/contrib/auth/tests/views.py
View
@@ -1,6 +1,5 @@
import os
import re
-import urllib
from django.conf import settings
from django.contrib.sites.models import Site, RequestSite
@@ -10,6 +9,7 @@
from django.http import QueryDict
from django.utils.encoding import force_unicode
from django.utils.html import escape
+from django.utils.http import urlquote
from django.test import TestCase
from django.test.utils import override_settings
@@ -256,7 +256,7 @@ def test_security_check(self, password='password'):
nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
'url': login_url,
'next': REDIRECT_FIELD_NAME,
- 'bad_url': urllib.quote(bad_url),
+ 'bad_url': urlquote(bad_url),
}
response = self.client.post(nasty_url, {
'username': 'testclient',
@@ -277,7 +277,7 @@ def test_security_check(self, password='password'):
safe_url = '%(url)s?%(next)s=%(good_url)s' % {
'url': login_url,
'next': REDIRECT_FIELD_NAME,
- 'good_url': urllib.quote(good_url),
+ 'good_url': urlquote(good_url),
}
response = self.client.post(safe_url, {
'username': 'testclient',
@@ -412,7 +412,7 @@ def test_security_check(self, password='password'):
nasty_url = '%(url)s?%(next)s=%(bad_url)s' % {
'url': logout_url,
'next': REDIRECT_FIELD_NAME,
- 'bad_url': urllib.quote(bad_url),
+ 'bad_url': urlquote(bad_url),
}
self.login()
response = self.client.get(nasty_url)
@@ -432,7 +432,7 @@ def test_security_check(self, password='password'):
safe_url = '%(url)s?%(next)s=%(good_url)s' % {
'url': logout_url,
'next': REDIRECT_FIELD_NAME,
- 'good_url': urllib.quote(good_url),
+ 'good_url': urlquote(good_url),
}
self.login()
response = self.client.get(safe_url)
5 django/contrib/auth/tokens.py
View
@@ -2,6 +2,7 @@
from django.conf import settings
from django.utils.http import int_to_base36, base36_to_int
from django.utils.crypto import constant_time_compare, salted_hmac
+from django.utils import six
class PasswordResetTokenGenerator(object):
"""
@@ -56,8 +57,8 @@ def _make_token_with_timestamp(self, user, timestamp):
# Ensure results are consistent across DB backends
login_timestamp = user.last_login.replace(microsecond=0, tzinfo=None)
- value = (unicode(user.id) + user.password +
- unicode(login_timestamp) + unicode(timestamp))
+ value = (six.text_type(user.id) + user.password +
+ six.text_type(login_timestamp) + six.text_type(timestamp))
hash = salted_hmac(key_salt, value).hexdigest()[::2]
return "%s-%s" % (ts_b36, hash)
13 django/contrib/auth/views.py
View
@@ -1,4 +1,7 @@
-import urlparse
+try:
+ from urllib.parse import urlparse, urlunparse
+except ImportError: # Python 2
+ from urlparse import urlparse, urlunparse
from django.conf import settings
from django.core.urlresolvers import reverse
@@ -34,7 +37,7 @@ def login(request, template_name='registration/login.html',
if request.method == "POST":
form = authentication_form(data=request.POST)
if form.is_valid():
- netloc = urlparse.urlparse(redirect_to)[1]
+ netloc = urlparse(redirect_to)[1]
# Use default setting if redirect_to is empty
if not redirect_to:
@@ -80,7 +83,7 @@ def logout(request, next_page=None,
auth_logout(request)
redirect_to = request.REQUEST.get(redirect_field_name, '')
if redirect_to:
- netloc = urlparse.urlparse(redirect_to)[1]
+ netloc = urlparse(redirect_to)[1]
# Security check -- don't allow redirection to a different host.
if not (netloc and netloc != request.get_host()):
return HttpResponseRedirect(redirect_to)
@@ -116,13 +119,13 @@ def redirect_to_login(next, login_url=None,
if not login_url:
login_url = settings.LOGIN_URL
- login_url_parts = list(urlparse.urlparse(login_url))
+ login_url_parts = list(urlparse(login_url))
if redirect_field_name:
querystring = QueryDict(login_url_parts[4], mutable=True)
querystring[redirect_field_name] = next
login_url_parts[4] = querystring.urlencode(safe='/')
- return HttpResponseRedirect(urlparse.urlunparse(login_url_parts))
+ return HttpResponseRedirect(urlunparse(login_url_parts))
# 4 views for password reset:
# - password_reset sends the mail
6 django/contrib/comments/views/moderation.py
View
@@ -17,7 +17,7 @@ def flag(request, comment_id, next=None):
"""
Flags a comment. Confirmation on GET, action on POST.
- Templates: `comments/flag.html`,
+ Templates: :template:`comments/flag.html`,
Context:
comment
the flagged `comments.comment` object
@@ -43,7 +43,7 @@ def delete(request, comment_id, next=None):
Deletes a comment. Confirmation on GET, action on POST. Requires the "can
moderate comments" permission.
- Templates: `comments/delete.html`,
+ Templates: :template:`comments/delete.html`,
Context:
comment
the flagged `comments.comment` object
@@ -70,7 +70,7 @@ def approve(request, comment_id, next=None):
Approve a comment (that is, mark it as public and non-removed). Confirmation
on GET, action on POST. Requires the "can moderate comments" permission.
- Templates: `comments/approve.html`,
+ Templates: :template:`comments/approve.html`,
Context:
comment
the `comments.comment` object for approval
10 django/contrib/comments/views/utils.py
View
@@ -2,8 +2,12 @@
A few bits of helper functions for comment views.
"""
-import urllib
import textwrap
+try:
+ from urllib.parse import urlencode
+except ImportError: # Python 2
+ from urllib import urlencode
+
from django.http import HttpResponseRedirect
from django.core import urlresolvers
from django.shortcuts import render_to_response
@@ -33,7 +37,7 @@ def next_redirect(data, default, default_view, **get_kwargs):
anchor = ''
joiner = ('?' in next) and '&' or '?'
- next += joiner + urllib.urlencode(get_kwargs) + anchor
+ next += joiner + urlencode(get_kwargs) + anchor
return HttpResponseRedirect(next)
def confirmation_view(template, doc="Display a confirmation view."):
@@ -56,7 +60,7 @@ def confirmed(request):
confirmed.__doc__ = textwrap.dedent("""\
%s
- Templates: `%s``
+ Templates: :template:`%s``
Context:
comment
The posted comment
9 django/contrib/contenttypes/tests.py
View
@@ -1,14 +1,13 @@
from __future__ import unicode_literals
-import urllib
-
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.views import shortcut
from django.contrib.sites.models import Site
from django.http import HttpRequest, Http404
from django.test import TestCase
-from django.utils.encoding import smart_str
+from django.utils.http import urlquote
+from django.utils import six
class ConcreteModel(models.Model):
@@ -35,7 +34,7 @@ class FooWithUrl(FooWithoutUrl):
"""
def get_absolute_url(self):
- return "/users/%s/" % urllib.quote(smart_str(self.name))
+ return "/users/%s/" % urlquote(self.name)
class FooWithBrokenAbsoluteUrl(FooWithoutUrl):
"""
@@ -271,4 +270,4 @@ def test_missing_model(self):
app_label = 'contenttypes',
model = 'OldModel',
)
- self.assertEqual(unicode(ct), 'Old model')
+ self.assertEqual(six.text_type(ct), 'Old model')
15 django/contrib/databrowse/datastructures.py
View
@@ -8,7 +8,6 @@
from django.utils import formats
from django.utils.text import capfirst
from django.utils.encoding import smart_unicode, smart_str, iri_to_uri
-from django.utils.safestring import mark_safe
from django.db.models.query import QuerySet
EMPTY_VALUE = '(None)'
@@ -30,7 +29,7 @@ def model_databrowse(self):
return self.site.registry[self.model]
def url(self):
- return mark_safe('%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name))
+ return '%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name)
def objects(self, **kwargs):
return self.get_query_set().filter(**kwargs)
@@ -70,9 +69,9 @@ def choices(self):
def url(self):
if self.field.choices:
- return mark_safe('%s%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name))
+ return '%s%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name)
elif self.field.rel:
- return mark_safe('%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name))
+ return '%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name)
class EasyChoice(object):
def __init__(self, easy_model, field, value, label):
@@ -83,7 +82,7 @@ def __repr__(self):
return smart_str('<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name))
def url(self):
- return mark_safe('%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, iri_to_uri(self.value)))
+ return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, iri_to_uri(self.value))
class EasyInstance(object):
def __init__(self, easy_model, instance):
@@ -105,7 +104,7 @@ def pk(self):
return self.instance._get_pk_val()
def url(self):
- return mark_safe('%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk())))
+ return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, iri_to_uri(self.pk()))
def fields(self):
"""
@@ -187,14 +186,14 @@ def urls(self):
for value in self.values():
if value is None:
continue
- url = mark_safe('%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, iri_to_uri(value._get_pk_val())))
+ url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, iri_to_uri(value._get_pk_val()))
lst.append((smart_unicode(value), url))
else:
lst = [(value, None) for value in self.values()]
elif self.field.choices:
lst = []
for value in self.values():
- url = mark_safe('%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, iri_to_uri(self.raw_value)))
+ url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, iri_to_uri(self.raw_value))
lst.append((value, url))
elif isinstance(self.field, models.URLField):
val = self.values()[0]
11 django/contrib/databrowse/plugins/calendars.py
View
@@ -5,9 +5,9 @@
from django.contrib.databrowse.datastructures import EasyModel
from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response
+from django.utils.html import format_html, format_html_join
from django.utils.text import capfirst
from django.utils.encoding import force_unicode
-from django.utils.safestring import mark_safe
from django.views.generic import dates
from django.utils import datetime_safe
@@ -64,18 +64,19 @@ def model_index_html(self, request, model, site):
fields = self.field_dict(model)
if not fields:
return ''
- return mark_safe('<p class="filter"><strong>View calendar by:</strong> %s</p>' % \
- ', '.join(['<a href="calendars/%s/">%s</a>' % (f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values()]))
+ return format_html('<p class="filter"><strong>View calendar by:</strong> {0}</p>',
+ format_html_join(', ', '<a href="calendars/{0}/">{1}</a>',
+ ((f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values())))
def urls(self, plugin_name, easy_instance_field):
if isinstance(easy_instance_field.field, models.DateField):
d = easy_instance_field.raw_value
- return [mark_safe('%s%s/%s/%s/%s/%s/' % (
+ return ['%s%s/%s/%s/%s/%s/' % (
easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name,
str(d.year),
datetime_safe.new_date(d).strftime('%b').lower(),
- d.day))]
+ d.day)]
def model_view(self, request, model_databrowse, url):
self.model, self.site = model_databrowse.model, model_databrowse.site
17 django/contrib/databrowse/plugins/fieldchoices.py
View
@@ -5,10 +5,11 @@
from django.contrib.databrowse.datastructures import EasyModel
from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response
+from django.utils.html import format_html, format_html_join
+from django.utils.http import urlquote
from django.utils.text import capfirst
-from django.utils.encoding import smart_str, force_unicode
-from django.utils.safestring import mark_safe
-import urllib
+from django.utils.encoding import force_unicode
+
class FieldChoicePlugin(DatabrowsePlugin):
def __init__(self, field_filter=None):
@@ -32,16 +33,16 @@ def model_index_html(self, request, model, site):
fields = self.field_dict(model)
if not fields:
return ''
- return mark_safe('<p class="filter"><strong>View by:</strong> %s</p>' % \
- ', '.join(['<a href="fields/%s/">%s</a>' % (f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values()]))
+ return format_html('<p class="filter"><strong>View by:</strong> {0}</p>',
+ format_html_join(', ', '<a href="fields/{0}/">{1}</a>',
+ ((f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values())))
def urls(self, plugin_name, easy_instance_field):
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
- field_value = smart_str(easy_instance_field.raw_value)
- return [mark_safe('%s%s/%s/%s/' % (
+ return ['%s%s/%s/%s/' % (
easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name,
- urllib.quote(field_value, safe='')))]
+ urlquote(easy_instance_field.raw_value, safe=''))]
def model_view(self, request, model_databrowse, url):
self.model, self.site = model_databrowse.model, model_databrowse.site
8 django/contrib/databrowse/plugins/objects.py
View
@@ -1,14 +1,18 @@
+try:
+ from urllib.parse import urljoin
+except ImportError: # Python 2
+ from urlparse import urljoin
+
from django import http
from django.contrib.databrowse.datastructures import EasyModel
from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response
-import urlparse
class ObjectDetailPlugin(DatabrowsePlugin):
def model_view(self, request, model_databrowse, url):
# If the object ID wasn't provided, redirect to the model page, which is one level up.
if url is None:
- return http.HttpResponseRedirect(urlparse.urljoin(request.path, '../'))
+ return http.HttpResponseRedirect(urljoin(request.path, '../'))
easy_model = EasyModel(model_databrowse.site, model_databrowse.model)
obj = easy_model.object_by_pk(url)
return render_to_response('databrowse/object_detail.html', {'object': obj, 'root_url': model_databrowse.site.root_url})
2  django/contrib/flatpages/views.py
View
@@ -23,7 +23,7 @@ def flatpage(request, url):
Models: `flatpages.flatpages`
Templates: Uses the template defined by the ``template_name`` field,
- or `flatpages/default.html` if template_name is not defined.
+ or :template:`flatpages/default.html` if template_name is not defined.
Context:
flatpage
`flatpages.flatpages` object
3  django/contrib/formtools/utils.py
View
@@ -2,6 +2,7 @@
import pickle
from django.utils.crypto import salted_hmac
+from django.utils import six
def form_hmac(form):
@@ -16,7 +17,7 @@ def form_hmac(form):
value = bf.data or ''
else:
value = bf.field.clean(bf.data) or ''
- if isinstance(value, basestring):
+ if isinstance(value, six.string_types):
value = value.strip()
data.append((bf.name, value))
10 django/contrib/formtools/wizard/views.py
View
@@ -7,6 +7,7 @@
from django.views.generic import TemplateView
from django.utils.datastructures import SortedDict
from django.utils.decorators import classonlymethod
+from django.utils import six
from django.contrib.formtools.wizard.storage import get_storage
from django.contrib.formtools.wizard.storage.exceptions import NoFileStorageConfigured
@@ -133,8 +134,9 @@ def get_initkwargs(cls, form_list, initial_dict=None,
The key should be equal to the `step_name` in the `form_list` (or
the str of the zero based counter - if no step_names added in the
`form_list`)
- * `instance_dict` - contains a dictionary of instance objects. This
- is only used when `ModelForm`s are used. The key should be equal to
+ * `instance_dict` - contains a dictionary whose values are model
+ instances if the step is based on a ``ModelForm`` and querysets if
+ the step is based on a ``ModelFormSet``. The key should be equal to
the `step_name` in the `form_list`. Same rules as for `initial_dict`
apply.
* `condition_dict` - contains a dictionary of boolean values or
@@ -156,10 +158,10 @@ def get_initkwargs(cls, form_list, initial_dict=None,
if isinstance(form, (list, tuple)):
# if the element is a tuple, add the tuple to the new created
# sorted dictionary.
- init_form_list[unicode(form[0])] = form[1]
+ init_form_list[six.text_type(form[0])] = form[1]
else:
# if not, add the form with a zero based counter as unicode
- init_form_list[unicode(i)] = form
+ init_form_list[six.text_type(i)] = form
# walk through the new created list of forms
for form in init_form_list.itervalues():
5 django/contrib/gis/admin/widgets.py
View
@@ -1,6 +1,7 @@
from django.forms.widgets import Textarea
from django.template import loader, Context
from django.templatetags.static import static
+from django.utils import six
from django.utils import translation
from django.contrib.gis.gdal import OGRException
@@ -25,7 +26,7 @@ def render(self, name, value, attrs=None):
# If a string reaches here (via a validation error on another
# field) then just reconstruct the Geometry.
- if isinstance(value, basestring):
+ if isinstance(value, six.string_types):
try:
value = GEOSGeometry(value)
except (GEOSException, ValueError):
@@ -109,7 +110,7 @@ def _has_changed(self, initial, data):
""" Compare geographic value of data with its initial value. """
# Ensure we are dealing with a geographic object
- if isinstance(initial, basestring):
+ if isinstance(initial, six.string_types):
try:
initial = GEOSGeometry(initial)
except (GEOSException, ValueError):
7 django/contrib/gis/db/backends/base.py
View
@@ -4,6 +4,7 @@
"""
import re
from django.contrib.gis import gdal
+from django.utils import six
class BaseSpatialOperations(object):
"""
@@ -88,7 +89,7 @@ def convert_geom(self, geom_val, geom_field):
# For quoting column values, rather than columns.
def geo_quote_name(self, name):
- if isinstance(name, unicode):
+ if isinstance(name, six.text_type):
name = name.encode('ascii')
return "'%s'" % name
@@ -330,6 +331,6 @@ def __unicode__(self):
it will be 'pretty' OGC WKT.
"""
try:
- return unicode(self.srs)
+ return six.text_type(self.srs)
except:
- return unicode(self.wkt)
+ return six.text_type(self.wkt)
5 django/contrib/gis/db/backends/oracle/operations.py
View
@@ -16,6 +16,7 @@
from django.contrib.gis.db.backends.util import SpatialFunction
from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.measure import Distance
+from django.utils import six
class SDOOperation(SpatialFunction):
"Base class for SDO* Oracle operations."
@@ -65,7 +66,7 @@ def __init__(self, mask):
super(SDORelate, self).__init__(self.relate_func, mask=mask)
# Valid distance types and substitutions
-dtypes = (Decimal, Distance, float, int, long)
+dtypes = (Decimal, Distance, float) + six.integer_types
class OracleOperations(DatabaseOperations, BaseSpatialOperations):
compiler_module = "django.contrib.gis.db.backends.oracle.compiler"
@@ -120,7 +121,7 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
'exact' : SDOOperation('SDO_EQUAL'),
'overlaps' : SDOOperation('SDO_OVERLAPS'),
'same_as' : SDOOperation('SDO_EQUAL'),
- 'relate' : (SDORelate, basestring), # Oracle uses a different syntax, e.g., 'mask=inside+touch'
+ 'relate' : (SDORelate, six.string_types), # Oracle uses a different syntax, e.g., 'mask=inside+touch'
'touches' : SDOOperation('SDO_TOUCH'),
'within' : SDOOperation('SDO_INSIDE'),
}
5 django/contrib/gis/db/backends/postgis/operations.py
View
@@ -10,6 +10,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.db.backends.postgresql_psycopg2.base import DatabaseOperations
from django.db.utils import DatabaseError
+from django.utils import six
#### Classes used in constructing PostGIS spatial SQL ####
class PostGISOperator(SpatialOperation):
@@ -161,11 +162,11 @@ def __init__(self, connection):
'overlaps' : PostGISFunction(prefix, 'Overlaps'),
'contains' : PostGISFunction(prefix, 'Contains'),
'intersects' : PostGISFunction(prefix, 'Intersects'),
- 'relate' : (PostGISRelate, basestring),
+ 'relate' : (PostGISRelate, six.string_types),
}
# Valid distance types and substitutions
- dtypes = (Decimal, Distance, float, int, long)
+ dtypes = (Decimal, Distance, float) + six.integer_types
def get_dist_ops(operator):
"Returns operations for both regular and spherical distances."
return {'cartesian' : PostGISDistance(prefix, operator),
3  django/contrib/gis/db/backends/spatialite/introspection.py
View
@@ -1,5 +1,6 @@
from django.contrib.gis.gdal import OGRGeomType
from django.db.backends.sqlite3.introspection import DatabaseIntrospection, FlexibleFieldLookupDict
+from django.utils import six
class GeoFlexibleFieldLookupDict(FlexibleFieldLookupDict):
"""
@@ -43,7 +44,7 @@ def get_geometry_type(self, table_name, geo_col):
field_params = {}
if srid != 4326:
field_params['srid'] = srid
- if isinstance(dim, basestring) and 'Z' in dim:
+ if isinstance(dim, six.string_types) and 'Z' in dim:
field_params['dim'] = 3
finally:
cursor.close()
5 django/contrib/gis/db/backends/spatialite/operations.py
View
@@ -9,6 +9,7 @@
from django.core.exceptions import ImproperlyConfigured
from django.db.backends.sqlite3.base import DatabaseOperations
from django.db.utils import DatabaseError
+from django.utils import six
class SpatiaLiteOperator(SpatialOperation):
"For SpatiaLite operators (e.g. `&&`, `~`)."
@@ -42,7 +43,7 @@ def __init__(self, pattern):
super(SpatiaLiteRelate, self).__init__('Relate')
# Valid distance types and substitutions
-dtypes = (Decimal, Distance, float, int, long)
+dtypes = (Decimal, Distance, float) + six.integer_types
def get_dist_ops(operator):
"Returns operations for regular distances; spherical distances are not currently supported."
return (SpatiaLiteDistance(operator),)
@@ -89,7 +90,7 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
'overlaps' : SpatiaLiteFunction('Overlaps'),
'contains' : SpatiaLiteFunction('Contains'),
'intersects' : SpatiaLiteFunction('Intersects'),
- 'relate' : (SpatiaLiteRelate, basestring),
+ 'relate' : (SpatiaLiteRelate, six.string_types),
# Returns true if B's bounding box completely contains A's bounding box.
'contained' : SpatiaLiteFunction('MbrWithin'),
# Returns true if A's bounding box completely contains B's bounding box.
6 django/contrib/gis/db/backends/util.py
View
@@ -3,14 +3,16 @@
backends.
"""
+from django.utils import six
+
def gqn(val):
"""
The geographic quote name function; used for quoting tables and
geometries (they use single rather than the double quotes of the
backend quotename function).
"""
- if isinstance(val, basestring):
- if isinstance(val, unicode): val = val.encode('ascii')
+ if isinstance(val, six.string_types):
+ if isinstance(val, six.text_type): val = val.encode('ascii')
return "'%s'" % val
else:
return str(val)
3  django/contrib/gis/db/models/fields.py
View
@@ -4,6 +4,7 @@
from django.contrib.gis import forms
from django.contrib.gis.db.models.proxy import GeometryProxy
from django.contrib.gis.geometry.backend import Geometry, GeometryException
+from django.utils import six
# Local cache of the spatial_ref_sys table, which holds SRID data for each
# spatial database alias. This cache exists so that the database isn't queried
@@ -159,7 +160,7 @@ def get_prep_value(self, value):
# from the given string input.
if isinstance(geom, Geometry):
pass