Permalink
Browse files

Applied nonrel changes from latest Bitbucket revision

  • Loading branch information...
1 parent 61a1444 commit 39c56d3528d7171c4aa2360ad30ce999fd69e33b @jonashaag jonashaag committed Nov 29, 2011
Showing with 294 additions and 91 deletions.
  1. +9 −2 .hgignore
  2. +1 −1 django/contrib/admin/sites.py
  3. +1 −1 django/contrib/admin/templates/registration/password_reset_email.html
  4. +2 −2 django/contrib/auth/forms.py
  5. +6 −5 django/contrib/auth/management/__init__.py
  6. +1 −1 django/contrib/auth/models.py
  7. +7 −0 django/contrib/auth/tests/auth_backends.py
  8. +3 −0 django/contrib/auth/tests/forms.py
  9. +1 −1 django/contrib/auth/tests/templates/registration/password_reset_email.html
  10. +2 −2 django/contrib/auth/tests/views.py
  11. +1 −1 django/contrib/auth/urls.py
  12. +6 −6 django/contrib/auth/views.py
  13. +5 −1 django/core/files/uploadhandler.py
  14. +16 −3 django/core/serializers/python.py
  15. +14 −0 django/db/backends/__init__.py
  16. +14 −0 django/db/backends/creation.py
  17. +1 −1 django/db/backends/mysql/base.py
  18. +1 −1 django/db/backends/sqlite3/base.py
  19. +34 −5 django/db/models/base.py
  20. +3 −0 django/db/models/deletion.py
  21. +39 −14 django/db/models/fields/__init__.py
  22. +3 −8 django/db/models/fields/related.py
  23. +8 −6 django/db/models/query.py
  24. +6 −0 django/db/models/sql/compiler.py
  25. +1 −3 django/db/models/sql/query.py
  26. +5 −2 django/http/multipartparser.py
  27. +4 −1 django/test/client.py
  28. +2 −1 django/utils/encoding.py
  29. +12 −0 django/utils/http.py
  30. +9 −1 docs/topics/http/file-uploads.txt
  31. +10 −0 tests/regressiontests/file_uploads/tests.py
  32. +39 −1 tests/regressiontests/file_uploads/uploadhandler.py
  33. +9 −8 tests/regressiontests/file_uploads/urls.py
  34. +7 −1 tests/regressiontests/file_uploads/views.py
  35. +12 −12 tests/regressiontests/formwizard/templates/forms/wizard.html
View
@@ -1,6 +1,13 @@
-syntax:glob
-
+syntax: glob
+*~
+*.tmp
+*.swp
*.egg-info
*.pot
*.py[co]
docs/_build/
+*.orig
+desktop.ini
+nbproject
+tests/django
+build
@@ -231,7 +231,7 @@ def wrapper(*args, **kwargs):
url(r'^jsi18n/$',
wrap(self.i18n_javascript, cacheable=True),
name='jsi18n'),
- url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$',
+ url(r'^r/(?P<content_type_id>[a-z\d]+)/(?P<object_id>.+)/$',
wrap(contenttype_views.shortcut)),
url(r'^(?P<app_label>\w+)/$',
wrap(self.app_index),
@@ -3,7 +3,7 @@
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
-{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
+{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.username }}
@@ -5,7 +5,7 @@
from django.template import Context, loader
from django import forms
from django.utils.translation import ugettext_lazy as _
-from django.utils.http import int_to_base36
+from django.utils.http import urlsafe_base64_encode
class UserCreationForm(forms.ModelForm):
"""
@@ -138,7 +138,7 @@ def save(self, domain_override=None, email_template_name='registration/password_
'email': user.email,
'domain': domain,
'site_name': site_name,
- 'uid': int_to_base36(user.id),
+ 'uid': urlsafe_base64_encode(str(user.id)),
'user': user,
'token': token_generator.make_token(user),
'protocol': use_https and 'https' or 'http',
@@ -35,11 +35,12 @@ def create_permissions(app, created_models, verbosity, **kwargs):
# Find all the Permissions that have a context_type for a model we're
# looking for. We don't need to check for codenames since we already have
# a list of the ones we're going to create.
- all_perms = set(auth_app.Permission.objects.filter(
- content_type__in=ctypes,
- ).values_list(
- "content_type", "codename"
- ))
+ all_perms = set()
+ ctypes_pks = set(ct.pk for ct in ctypes)
+ for ctype, codename in auth_app.Permission.objects.all().values_list(
+ 'content_type', 'codename')[:1000000]:
+ if ctype in ctypes_pks:
+ all_perms.add((ctype, codename))
for ctype, (codename, name) in searched_perms:
# If the permissions exists, move on.
@@ -83,7 +83,7 @@ class Meta:
verbose_name = _('permission')
verbose_name_plural = _('permissions')
unique_together = (('content_type', 'codename'),)
- ordering = ('content_type__app_label', 'content_type__model', 'codename')
+ ordering = ('codename',)
def __unicode__(self):
return u"%s | %s | %s" % (
@@ -4,7 +4,9 @@
from django.contrib.auth.models import User, Group, Permission, AnonymousUser
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ImproperlyConfigured
+from django.db import connection
from django.test import TestCase
+from django.utils import unittest
class BackendTest(TestCase):
@@ -100,6 +102,9 @@ def test_get_all_superuser_permissions(self):
user = User.objects.get(username='test2')
self.assertEqual(len(user.get_all_permissions()), len(Permission.objects.all()))
+BackendTest = unittest.skipIf(not connection.features.supports_joins,
+ 'Requires JOIN support')(BackendTest)
+
class TestObj(object):
pass
@@ -203,6 +208,8 @@ def test_get_group_permissions(self):
self.user3.groups.add(group)
self.assertEqual(self.user3.get_group_permissions(TestObj()), set(['group_perm']))
+RowlevelBackendTest = unittest.skipIf(not connection.features.supports_joins,
+ 'Requires JOIN support')(RowlevelBackendTest)
class AnonymousUserBackend(SimpleRowlevelBackend):
@@ -1,6 +1,8 @@
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm, PasswordChangeForm, SetPasswordForm, UserChangeForm, PasswordResetForm
+from django.db import connection
from django.test import TestCase
+from django.utils import unittest
class UserCreationFormTest(TestCase):
@@ -191,6 +193,7 @@ class UserChangeFormTest(TestCase):
fixtures = ['authtestdata.json']
+ @unittest.skipIf(not connection.features.supports_joins, 'Requires JOIN support')
def test_username_validity(self):
user = User.objects.get(username='testclient')
data = {'username': 'not valid'}
@@ -1 +1 @@
-{{ protocol }}://{{ domain }}/reset/{{ uid }}-{{ token }}/
+{{ protocol }}://{{ domain }}/reset/{{ uid }}/{{ token }}/
@@ -100,13 +100,13 @@ def test_confirm_invalid(self):
def test_confirm_invalid_user(self):
# Ensure that we get a 200 response for a non-existant user, not a 404
- response = self.client.get('/reset/123456-1-1/')
+ response = self.client.get('/reset/123456/1-1/')
self.assertEqual(response.status_code, 200)
self.assertTrue("The password reset link was invalid" in response.content)
def test_confirm_overflow_user(self):
# Ensure that we get a 200 response for a base36 user id that overflows int
- response = self.client.get('/reset/zzzzzzzzzzzzz-1-1/')
+ response = self.client.get('/reset/zzzzzzzzzzzzz/1-1/')
self.assertEqual(response.status_code, 200)
self.assertTrue("The password reset link was invalid" in response.content)
@@ -11,7 +11,7 @@
(r'^password_change/done/$', 'django.contrib.auth.views.password_change_done'),
(r'^password_reset/$', 'django.contrib.auth.views.password_reset'),
(r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done'),
- (r'^reset/(?P<uidb36>[0-9A-Za-z]{1,13})-(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', 'django.contrib.auth.views.password_reset_confirm'),
+ (r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', 'django.contrib.auth.views.password_reset_confirm'),
(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete'),
)
@@ -5,7 +5,7 @@
from django.http import HttpResponseRedirect, QueryDict
from django.shortcuts import render_to_response
from django.template import RequestContext
-from django.utils.http import base36_to_int
+from django.utils.http import urlsafe_base64_decode
from django.utils.translation import ugettext as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
@@ -173,7 +173,7 @@ def password_reset_done(request,
# Doesn't need csrf_protect since no-one can guess the URL
@never_cache
-def password_reset_confirm(request, uidb36=None, token=None,
+def password_reset_confirm(request, uidb64=None, token=None,
template_name='registration/password_reset_confirm.html',
token_generator=default_token_generator,
set_password_form=SetPasswordForm,
@@ -183,13 +183,13 @@ def password_reset_confirm(request, uidb36=None, token=None,
View that checks the hash in a password reset link and presents a
form for entering a new password.
"""
- assert uidb36 is not None and token is not None # checked by URLconf
+ assert uidb64 is not None and token is not None # checked by URLconf
if post_reset_redirect is None:
post_reset_redirect = reverse('django.contrib.auth.views.password_reset_complete')
try:
- uid_int = base36_to_int(uidb36)
- user = User.objects.get(id=uid_int)
- except (ValueError, User.DoesNotExist):
+ uid = urlsafe_base64_decode(str(uidb64))
+ user = User.objects.get(id=uid)
+ except (TypeError, ValueError, User.DoesNotExist):
user = None
if user is not None and token_generator.check_token(user, token):
@@ -84,7 +84,8 @@ def handle_raw_input(self, input_data, META, content_length, boundary, encoding=
"""
pass
- def new_file(self, field_name, file_name, content_type, content_length, charset=None):
+ def new_file(self, field_name, file_name, content_type, content_length,
+ charset=None, content_type_extra=None):
"""
Signal that a new file has been started.
@@ -96,6 +97,9 @@ def new_file(self, field_name, file_name, content_type, content_length, charset=
self.content_type = content_type
self.content_length = content_length
self.charset = charset
+ if content_type_extra is None:
+ content_type_extra = {}
+ self.content_type_extra = content_type_extra
def receive_data_chunk(self, raw_data, start):
"""
@@ -62,10 +62,23 @@ def handle_m2m_field(self, obj, field):
if field.rel.through._meta.auto_created:
if self.use_natural_keys and hasattr(field.rel.to, 'natural_key'):
m2m_value = lambda value: value.natural_key()
+ self._current[field.name] = [m2m_value(related)
+ for related in getattr(obj, field.name).iterator()]
+ elif field.rel.get_related_field().primary_key:
+ m2m_value = lambda value: smart_unicode(
+ getattr(value, related_query.target_field_name + '_id'),
+ strings_only=True)
+ related_query = getattr(obj, field.name)
+ filters = {related_query.source_field_name: obj._get_pk_val()}
+ query = field.rel.through.objects.filter(**filters)
+ self._current[field.name] = sorted((m2m_value(m2m_entity)
+ for m2m_entity in query),
+ reverse=True)
else:
- m2m_value = lambda value: smart_unicode(value._get_pk_val(), strings_only=True)
- self._current[field.name] = [m2m_value(related)
- for related in getattr(obj, field.name).iterator()]
+ m2m_value = lambda value: smart_unicode(value._get_pk_val(),
+ strings_only=True)
+ self._current[field.name] = [m2m_value(related)
+ for related in getattr(obj, field.name).iterator()]
def getvalue(self):
return self.objects
@@ -280,6 +280,11 @@ class BaseDatabaseFeatures(object):
related_fields_match_type = False
allow_sliced_subqueries = True
+ supports_joins = True
+ distinguishes_insert_from_update = True
+ supports_deleting_related_objects = True
+ supports_select_related = True
+
# Does the default test database allow multiple connections?
# Usually an indication that the test database is in-memory
test_db_allows_multiple_connections = True
@@ -668,6 +673,15 @@ def prep_for_like_query(self, x):
# need not necessarily be implemented using "LIKE" in the backend.
prep_for_iexact_query = prep_for_like_query
+ def value_to_db_auto(self, value):
+ """
+ Transform a value to an object compatible with the auto field required
+ by the backend driver for auto columns.
+ """
+ if value is None:
+ return None
+ return int(value)
+
def value_to_db_date(self, value):
"""
Transform a date value to an object compatible with what is expected
@@ -2,6 +2,7 @@
import time
from django.conf import settings
+from django.utils.datastructures import DictWrapper
# The prefix to put on the default database name when creating
# the test database.
@@ -26,6 +27,19 @@ def _digest(self, *args):
"""
return '%x' % (abs(hash(args)) % 4294967296L) # 2**32
+ def db_type(self, field):
+ return self._db_type(field, field.get_internal_type())
+
+ def related_db_type(self, field):
+ return self._db_type(field, field.get_related_internal_type())
+
+ def _db_type(self, field, internal_type):
+ data = DictWrapper(field.__dict__, self.connection.ops.quote_name, "qn_")
+ try:
+ return self.connection.creation.data_types[internal_type] % data
+ except KeyError:
+ return None
+
def sql_create_model(self, model, style, known_models=set()):
"""
Returns the SQL required to create a single model, as a tuple of:
@@ -328,7 +328,7 @@ def _cursor(self):
def _rollback(self):
try:
- BaseDatabaseWrapper._rollback(self)
+ super(DatabaseWrapper, self)._rollback()
except Database.NotSupportedError:
pass
@@ -218,7 +218,7 @@ def close(self):
# database. To prevent accidental data loss, ignore close requests on
# an in-memory db.
if self.settings_dict['NAME'] != ":memory:":
- BaseDatabaseWrapper.close(self)
+ super(DatabaseWrapper, self).close()
FORMAT_QMARK_REGEX = re.compile(r'(?<!%)%s')
Oops, something went wrong.

0 comments on commit 39c56d3

Please sign in to comment.