summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorAdrian Holovaty <adrian@holovaty.com>2007-09-15 21:34:09 +0000
committerAdrian Holovaty <adrian@holovaty.com>2007-09-15 21:34:09 +0000
commitbf6a46d8ad11d49990a3878166cce2af2fc6c4fe (patch)
treeb24514e1780e8ec80afb9f295005e196af460f15 /django
parentfb6a0c8ffa1cd74c63aaf4b011665e5952d449e7 (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.mobin35163 -> 35161 bytes
-rw-r--r--django/conf/locale/te/LC_MESSAGES/django.po2
-rw-r--r--django/contrib/admin/media/js/core.js16
-rw-r--r--django/contrib/localflavor/br/forms.py47
-rw-r--r--django/contrib/sites/models.py22
-rw-r--r--django/core/handler.py11
-rw-r--r--django/core/handlers/base.py17
-rw-r--r--django/core/validators.py13
-rw-r--r--django/db/models/base.py10
-rw-r--r--django/http/__init__.py28
-rw-r--r--django/newforms/fields.py23
-rw-r--r--django/newforms/forms.py2
-rw-r--r--django/test/testcases.py8
-rw-r--r--django/views/generic/date_based.py4
-rw-r--r--django/views/i18n.py20
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
index 8823b2015c..e86df1c91c 100644
--- a/django/conf/locale/te/LC_MESSAGES/django.mo
+++ b/django/conf/locale/te/LC_MESSAGES/django.mo
Binary files differ
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 = """