diff options
| author | Adrian Holovaty <adrian@holovaty.com> | 2007-09-15 21:34:09 +0000 |
|---|---|---|
| committer | Adrian Holovaty <adrian@holovaty.com> | 2007-09-15 21:34:09 +0000 |
| commit | bf6a46d8ad11d49990a3878166cce2af2fc6c4fe (patch) | |
| tree | b24514e1780e8ec80afb9f295005e196af460f15 /django | |
| parent | fb6a0c8ffa1cd74c63aaf4b011665e5952d449e7 (diff) | |
queryset-refactor: Merged to [6190]
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6334 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django')
| -rw-r--r-- | django/conf/locale/te/LC_MESSAGES/django.mo | bin | 35163 -> 35161 bytes | |||
| -rw-r--r-- | django/conf/locale/te/LC_MESSAGES/django.po | 2 | ||||
| -rw-r--r-- | django/contrib/admin/media/js/core.js | 16 | ||||
| -rw-r--r-- | django/contrib/localflavor/br/forms.py | 47 | ||||
| -rw-r--r-- | django/contrib/sites/models.py | 22 | ||||
| -rw-r--r-- | django/core/handler.py | 11 | ||||
| -rw-r--r-- | django/core/handlers/base.py | 17 | ||||
| -rw-r--r-- | django/core/validators.py | 13 | ||||
| -rw-r--r-- | django/db/models/base.py | 10 | ||||
| -rw-r--r-- | django/http/__init__.py | 28 | ||||
| -rw-r--r-- | django/newforms/fields.py | 23 | ||||
| -rw-r--r-- | django/newforms/forms.py | 2 | ||||
| -rw-r--r-- | django/test/testcases.py | 8 | ||||
| -rw-r--r-- | django/views/generic/date_based.py | 4 | ||||
| -rw-r--r-- | django/views/i18n.py | 20 |
15 files changed, 168 insertions, 55 deletions
diff --git a/django/conf/locale/te/LC_MESSAGES/django.mo b/django/conf/locale/te/LC_MESSAGES/django.mo Binary files differindex 8823b2015c..e86df1c91c 100644 --- a/django/conf/locale/te/LC_MESSAGES/django.mo +++ b/django/conf/locale/te/LC_MESSAGES/django.mo diff --git a/django/conf/locale/te/LC_MESSAGES/django.po b/django/conf/locale/te/LC_MESSAGES/django.po index 248baf2249..e0c600ba3e 100644 --- a/django/conf/locale/te/LC_MESSAGES/django.po +++ b/django/conf/locale/te/LC_MESSAGES/django.po @@ -14,7 +14,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" -"Plural-Forms: nplurals=2; nplurals=n>1;" +"Plural-Forms: nplurals=2; plural=n>1;" #: contrib/comments/models.py:67 contrib/comments/models.py:166 msgid "object ID" diff --git a/django/contrib/admin/media/js/core.js b/django/contrib/admin/media/js/core.js index a17ac8a4d2..c8d0db6a8d 100644 --- a/django/contrib/admin/media/js/core.js +++ b/django/contrib/admin/media/js/core.js @@ -1,5 +1,9 @@ // Core javascript helper functions +// basic browser identification & version +var isOpera = (navigator.userAgent.indexOf("Opera")>=0) && parseFloat(navigator.appVersion); +var isIE = ((document.all) && (!isOpera)) && parseFloat(navigator.appVersion.split("MSIE ")[1].split(";")[0]); + // Cross-browser event handlers. function addEvent(obj, evType, fn) { if (obj.addEventListener) { @@ -71,9 +75,13 @@ function findPosX(obj) { var curleft = 0; if (obj.offsetParent) { while (obj.offsetParent) { - curleft += obj.offsetLeft; + curleft += obj.offsetLeft - ((isOpera) ? 0 : obj.scrollLeft); obj = obj.offsetParent; } + // IE offsetParent does not include the top-level + if (isIE && obj.parentElement){ + curleft += obj.offsetLeft - obj.scrollLeft; + } } else if (obj.x) { curleft += obj.x; } @@ -84,9 +92,13 @@ function findPosY(obj) { var curtop = 0; if (obj.offsetParent) { while (obj.offsetParent) { - curtop += obj.offsetTop; + curtop += obj.offsetTop - ((isOpera) ? 0 : obj.scrollTop); obj = obj.offsetParent; } + // IE offsetParent does not include the top-level + if (isIE && obj.parentElement){ + curtop += obj.offsetTop - obj.scrollTop; + } } else if (obj.y) { curtop += obj.y; } diff --git a/django/contrib/localflavor/br/forms.py b/django/contrib/localflavor/br/forms.py index c7082c0f9e..58bf795292 100644 --- a/django/contrib/localflavor/br/forms.py +++ b/django/contrib/localflavor/br/forms.py @@ -6,16 +6,21 @@ BR-specific Form helpers from django.newforms import ValidationError from django.newforms.fields import Field, RegexField, CharField, Select, EMPTY_VALUES from django.utils.encoding import smart_unicode -from django.utils.translation import ugettext +from django.utils.translation import ugettext as _ import re +try: + set +except NameError: + from sets import Set as set # For Python 2.3 + phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$') class BRZipCodeField(RegexField): def __init__(self, *args, **kwargs): super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$', max_length=None, min_length=None, - error_message=ugettext('Enter a zip code in the format XXXXX-XXX.'), + error_message=_('Enter a zip code in the format XXXXX-XXX.'), *args, **kwargs) class BRPhoneNumberField(Field): @@ -27,7 +32,7 @@ class BRPhoneNumberField(Field): m = phone_digits_re.search(value) if m: return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) - raise ValidationError(ugettext('Phone numbers must be in XX-XXXX-XXXX format.')) + raise ValidationError(_('Phone numbers must be in XX-XXXX-XXXX format.')) class BRStateSelect(Select): """ @@ -38,6 +43,32 @@ class BRStateSelect(Select): from br_states import STATE_CHOICES super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES) +class BRStateChoiceField(Field): + """ + A choice field that uses a list of Brazilian states as its choices. + """ + widget = Select + + def __init__(self, required=True, widget=None, label=None, + initial=None, help_text=None): + super(BRStateChoiceField, self).__init__(required, widget, label, + initial, help_text) + from br_states import STATE_CHOICES + self.widget.choices = STATE_CHOICES + + def clean(self, value): + value = super(BRStateChoiceField, self).clean(value) + if value in EMPTY_VALUES: + value = u'' + value = smart_unicode(value) + if value == u'': + return value + valid_values = set([smart_unicode(k) for k, v in self.widget.choices]) + if value not in valid_values: + raise ValidationError(_(u'Select a valid brazilian state.' + u' That state is not one' + u' of the available states.')) + return value def DV_maker(v): if v >= 2: @@ -69,9 +100,9 @@ class BRCPFField(CharField): try: int(value) except ValueError: - raise ValidationError(ugettext("This field requires only numbers.")) + raise ValidationError(_("This field requires only numbers.")) if len(value) != 11: - raise ValidationError(ugettext("This field requires at most 11 digits or 14 characters.")) + raise ValidationError(_("This field requires at most 11 digits or 14 characters.")) orig_dv = value[-2:] new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))]) @@ -81,7 +112,7 @@ class BRCPFField(CharField): new_2dv = DV_maker(new_2dv % 11) value = value[:-1] + str(new_2dv) if value[-2:] != orig_dv: - raise ValidationError(ugettext("Invalid CPF number.")) + raise ValidationError(_("Invalid CPF number.")) return orig_value @@ -103,7 +134,7 @@ class BRCNPJField(Field): raise ValidationError("This field requires only numbers.") if len(value) != 14: raise ValidationError( - ugettext("This field requires at least 14 digits")) + _("This field requires at least 14 digits")) orig_dv = value[-2:] new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))]) @@ -113,7 +144,7 @@ class BRCNPJField(Field): new_2dv = DV_maker(new_2dv % 11) value = value[:-1] + str(new_2dv) if value[-2:] != orig_dv: - raise ValidationError(ugettext("Invalid CNPJ number.")) + raise ValidationError(_("Invalid CNPJ number.")) return orig_value diff --git a/django/contrib/sites/models.py b/django/contrib/sites/models.py index 921cf4ff4d..253a2722b6 100644 --- a/django/contrib/sites/models.py +++ b/django/contrib/sites/models.py @@ -1,15 +1,33 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ +from django.http import get_host + +SITE_CACHE = {} class SiteManager(models.Manager): def get_current(self): + """ + Returns the current ``Site`` based on the SITE_ID in the + project's settings. The ``Site`` object is cached the first + time it's retrieved from the database. + """ from django.conf import settings try: sid = settings.SITE_ID except AttributeError: from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured("You're using the Django \"sites framework\" without having set the SITE_ID setting. Create a site in your database and set the SITE_ID setting to fix this error.") - return self.get(pk=sid) + try: + current_site = SITE_CACHE[sid] + except KeyError: + current_site = self.get(pk=sid) + SITE_CACHE[sid] = current_site + return current_site + + def clear_cache(self): + """Clears the ``Site`` object cache.""" + global SITE_CACHE + SITE_CACHE = {} class Site(models.Model): domain = models.CharField(_('domain name'), max_length=100) @@ -36,7 +54,7 @@ class RequestSite(object): The save() and delete() methods raise NotImplementedError. """ def __init__(self, request): - self.domain = self.name = request.META['SERVER_NAME'] + self.domain = self.name = get_host(request) def __unicode__(self): return self.domain diff --git a/django/core/handler.py b/django/core/handler.py deleted file mode 100644 index 039406722b..0000000000 --- a/django/core/handler.py +++ /dev/null @@ -1,11 +0,0 @@ -# This module is DEPRECATED! -# -# You should no longer be pointing your mod_python configuration -# at "django.core.handler". -# -# Use "django.core.handlers.modpython" instead. - -from django.core.handlers.modpython import ModPythonHandler - -def handler(req): - return ModPythonHandler()(req) diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py index ca48b301d4..768fc14b00 100644 --- a/django/core/handlers/base.py +++ b/django/core/handlers/base.py @@ -50,6 +50,10 @@ class BaseHandler(object): def get_response(self, request): "Returns an HttpResponse object for the given HttpRequest" + response = self._real_get_response(request) + return fix_location_header(request, response) + + def _real_get_response(self, request): from django.core import exceptions, urlresolvers from django.core.mail import mail_admins from django.conf import settings @@ -129,3 +133,16 @@ class BaseHandler(object): "Helper function to return the traceback as a string" import traceback return '\n'.join(traceback.format_exception(*(exc_info or sys.exc_info()))) + +def fix_location_header(request, response): + """ + Ensure that we always use an absolute URI in any location header in the + response. This is required by RFC 2616, section 14.30. + + Code constructing response objects is free to insert relative paths and + this function converts them to absolute paths. + """ + if 'Location' in response.headers and http.get_host(request): + response['Location'] = request.build_absolute_uri(response['Location']) + return response + diff --git a/django/core/validators.py b/django/core/validators.py index fd28ba4ef8..7611aef921 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -181,10 +181,15 @@ def isValidImage(field_data, all_data): except TypeError: raise ValidationError, _("No file was submitted. Check the encoding type on the form.") try: - Image.open(StringIO(content)) - except (IOError, OverflowError): # Python Imaging Library doesn't recognize it as an image - # OverflowError is due to a bug in PIL with Python 2.4+ which can cause - # it to gag on OLE files. + # load() is the only method that can spot a truncated JPEG, + # but it cannot be called sanely after verify() + trial_image = Image.open(StringIO(content)) + trial_image.load() + # verify() is the only method that can spot a corrupt PNG, + # but it must be called immediately after the constructor + trial_image = Image.open(StringIO(content)) + trial_image.verify() + except Exception: # Python Imaging Library doesn't recognize it as an image raise ValidationError, _("Upload a valid image. The file you uploaded was either not an image or a corrupted image.") def isValidImageURL(field_data, all_data): diff --git a/django/db/models/base.py b/django/db/models/base.py index 9bbac65385..beb413fc4c 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -241,10 +241,12 @@ class Model(object): placeholders = ['%s'] * len(field_names) if self._meta.order_with_respect_to: field_names.append(qn('_order')) - # TODO: This assumes the database supports subqueries. - placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \ - (qn(self._meta.db_table), qn(self._meta.order_with_respect_to.column))) - db_values.append(getattr(self, self._meta.order_with_respect_to.attname)) + placeholders.append('%s') + subsel = 'SELECT COUNT(*) FROM %s WHERE %s = %%s' % ( + qn(self._meta.db_table), + qn(self._meta.order_with_respect_to.column)) + cursor.execute(subsel, (getattr(self, self._meta.order_with_respect_to.attname),)) + db_values.append(cursor.fetchone()[0]) if db_values: cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \ (qn(self._meta.db_table), ','.join(field_names), diff --git a/django/http/__init__.py b/django/http/__init__.py index 20818f138b..2b68a6243a 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -2,6 +2,7 @@ import os from Cookie import SimpleCookie from pprint import pformat from urllib import urlencode +from urlparse import urljoin from django.utils.datastructures import MultiValueDict, FileDict from django.utils.encoding import smart_str, iri_to_uri, force_unicode @@ -42,10 +43,24 @@ class HttpRequest(object): return key in self.GET or key in self.POST __contains__ = has_key - + def get_full_path(self): return '' + def build_absolute_uri(self, location=None): + """ + Builds an absolute URI from the location and the variables available in + this request. If no location is specified, the absolute URI is built on + ``request.get_full_path()``. + """ + if not location: + location = self.get_full_path() + if not ':' in location: + current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http', + get_host(self), self.path) + location = urljoin(current_uri, location) + return location + def is_secure(self): return os.environ.get("HTTPS") == "on" @@ -364,9 +379,16 @@ class HttpResponseServerError(HttpResponse): def get_host(request): "Gets the HTTP host from the environment or request headers." + # We try three options, in order of decreasing preference. host = request.META.get('HTTP_X_FORWARDED_HOST', '') - if not host: - host = request.META.get('HTTP_HOST', '') + if 'HTTP_HOST' in request.META: + host = request.META['HTTP_HOST'] + else: + # Reconstruct the host using the algorithm from PEP 333. + host = request.META['SERVER_NAME'] + server_port = request.META['SERVER_PORT'] + if server_port != (request.is_secure() and 443 or 80): + host = '%s:%s' % (host, server_port) return host # It's neither necessary nor appropriate to use diff --git a/django/newforms/fields.py b/django/newforms/fields.py index fc816a842b..d83cb6cde2 100644 --- a/django/newforms/fields.py +++ b/django/newforms/fields.py @@ -2,6 +2,7 @@ Field classes """ +import copy import datetime import re import time @@ -100,6 +101,12 @@ class Field(object): """ return {} + def __deepcopy__(self, memo): + result = copy.copy(self) + memo[id(self)] = result + result.widget = copy.deepcopy(self.widget, memo) + return result + class CharField(Field): def __init__(self, max_length=None, min_length=None, *args, **kwargs): self.max_length, self.min_length = max_length, min_length @@ -386,10 +393,15 @@ class ImageField(FileField): from PIL import Image from cStringIO import StringIO try: - Image.open(StringIO(f.content)) - except (IOError, OverflowError): # Python Imaging Library doesn't recognize it as an image - # OverflowError is due to a bug in PIL with Python 2.4+ which can cause - # it to gag on OLE files. + # load() is the only method that can spot a truncated JPEG, + # but it cannot be called sanely after verify() + trial_image = Image.open(StringIO(f.content)) + trial_image.load() + # verify() is the only method that can spot a corrupt PNG, + # but it must be called immediately after the constructor + trial_image = Image.open(StringIO(f.content)) + trial_image.verify() + except Exception: # Python Imaging Library doesn't recognize it as an image raise ValidationError(ugettext(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image.")) return f @@ -409,6 +421,9 @@ class URLField(RegexField): self.user_agent = validator_user_agent def clean(self, value): + # If no URL scheme given, assume http:// + if value and '://' not in value: + value = u'http://%s' % value value = super(URLField, self).clean(value) if value == u'': return value diff --git a/django/newforms/forms.py b/django/newforms/forms.py index 5baf0a079b..ab8729be65 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -31,7 +31,7 @@ class SortedDictFromList(SortedDict): dict.__init__(self, dict(data)) def copy(self): - return SortedDictFromList([(k, copy.copy(v)) for k, v in self.items()]) + return SortedDictFromList([(k, copy.deepcopy(v)) for k, v in self.items()]) class DeclarativeFieldsMetaclass(type): """ diff --git a/django/test/testcases.py b/django/test/testcases.py index baa6e7bb19..6b7714ec7b 100644 --- a/django/test/testcases.py +++ b/django/test/testcases.py @@ -84,12 +84,8 @@ class TestCase(unittest.TestCase): self.assertEqual(response.status_code, status_code, ("Response didn't redirect as expected: Response code was %d" " (expected %d)" % (response.status_code, status_code))) - scheme, netloc, path, query, fragment = urlsplit(response['Location']) - url = path - if query: - url += '?' + query - if fragment: - url += '#' + fragment + url = response['Location'] + scheme, netloc, path, query, fragment = urlsplit(url) self.assertEqual(url, expected_url, "Response redirected to '%s', expected '%s'" % (url, expected_url)) diff --git a/django/views/generic/date_based.py b/django/views/generic/date_based.py index 1a8c4c611a..e6a75e63aa 100644 --- a/django/views/generic/date_based.py +++ b/django/views/generic/date_based.py @@ -10,7 +10,7 @@ from django.http import Http404, HttpResponse def archive_index(request, queryset, date_field, num_latest=15, template_name=None, template_loader=loader, extra_context=None, allow_empty=False, context_processors=None, - mimetype=None, allow_future=False): + mimetype=None, allow_future=False, template_object_name='latest'): """ Generic top-level archive of date-based objects. @@ -39,7 +39,7 @@ def archive_index(request, queryset, date_field, num_latest=15, t = template_loader.get_template(template_name) c = RequestContext(request, { 'date_list' : date_list, - 'latest' : latest, + template_object_name : latest, }, context_processors) for key, value in extra_context.items(): if callable(value): diff --git a/django/views/i18n.py b/django/views/i18n.py index 320caf37d7..5b50f75d23 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -9,20 +9,26 @@ def set_language(request): """ Redirect to a given url while setting the chosen language in the session or cookie. The url and the language code need to be - specified in the GET parameters. + specified in the request parameters. + + Since this view changes how the user will see the rest of the site, it must + only be accessed as a POST request. If called as a GET request, it will + redirect to the page in the request (the 'next' parameter) without changing + any state. """ - lang_code = request.GET.get('language', None) next = request.GET.get('next', None) if not next: next = request.META.get('HTTP_REFERER', None) if not next: next = '/' response = http.HttpResponseRedirect(next) - if lang_code and check_for_language(lang_code): - if hasattr(request, 'session'): - request.session['django_language'] = lang_code - else: - response.set_cookie('django_language', lang_code) + if request.method == 'POST': + lang_code = request.POST.get('language', None) + if lang_code and check_for_language(lang_code): + if hasattr(request, 'session'): + request.session['django_language'] = lang_code + else: + response.set_cookie('django_language', lang_code) return response NullSource = """ |
