上传及下载 #2
60
README
60
README
|
@ -1,37 +1,49 @@
|
||||||
Django is a high-level Python Web framework that encourages rapid development
|
Django is a high-level Python Web framework that encourages rapid
|
||||||
and clean, pragmatic design.
|
development and clean, pragmatic design.
|
||||||
|
|
||||||
All documentation is in the "docs" directory and online at
|
|
||||||
http://www.djangoproject.com/documentation/. If you're just getting started,
|
|
||||||
here's how we recommend you read the docs:
|
|
||||||
|
|
||||||
* First, read docs/install.txt for instructions on installing Django.
|
About this version
|
||||||
|
==================
|
||||||
|
|
||||||
* Next, work through the tutorials in order (docs/tutorial01.txt,
|
This is the Django 0.91 "bugfixes" branch, which is intended to
|
||||||
docs/tutorial02.txt, etc.).
|
provide bugfix and patch support for users of Django 0.91 who have not
|
||||||
|
been able to migrate to a more recent version. No new features will be
|
||||||
|
added in this branch, and it is maintained solely as a means of
|
||||||
|
providing support to legacy Django installations.
|
||||||
|
|
||||||
* If you want to set up an actual deployment server, read docs/modpython.txt
|
If you're completely new to Django we highly recommend that you use
|
||||||
for instructions on running Django under mod_python.
|
either the latest stable release or a Subversion checkout from
|
||||||
|
Django's trunk; Django is always evolving, and the latest and greatest
|
||||||
|
features are only available to users of newer versions of the
|
||||||
|
framework.
|
||||||
|
|
||||||
* The rest of the documentation is of the reference-manual variety.
|
|
||||||
Read it -- and the FAQ -- as you run into problems.
|
|
||||||
|
|
||||||
Docs are updated rigorously. If you find any problems in the docs, or think they
|
More information
|
||||||
should be clarified in any way, please take 30 seconds to fill out a ticket
|
================
|
||||||
here:
|
|
||||||
|
|
||||||
http://code.djangoproject.com/newticket
|
The complete history of bugs fixed in this branch can be viewed online
|
||||||
|
at http://code.djangoproject.com/log/django/branches/0.91-bugfixes.
|
||||||
|
|
||||||
To get more help:
|
We also recommend that users of this branch subscribe to the
|
||||||
|
"django-announce" mailing list, a low-traffic, announcements-only list
|
||||||
|
which will send messages whenever an important (i.e.,
|
||||||
|
security-related) bug is fixed. You can subscribe to the list via
|
||||||
|
Google Groups at http://groups.google.com/group/django-announce.
|
||||||
|
|
||||||
* Join the #django channel on irc.freenode.net. Lots of helpful people
|
The documentation for this version of Django has been frozen, and is
|
||||||
hang out there. Read the archives at http://loglibrary.com/179 .
|
available online at http://www.djangoproject.com/documentation/0_91/.
|
||||||
|
|
||||||
* Join the django-users mailing list, or read the archives, at
|
|
||||||
http://groups-beta.google.com/group/django-users.
|
|
||||||
|
|
||||||
To contribute to Django:
|
Submitting bugs
|
||||||
|
===============
|
||||||
|
|
||||||
* Check out http://www.djangoproject.com/community/ for information
|
If you run into a bug in Django 0.91, please search the Django ticket
|
||||||
about getting involved.
|
database to see if the issue has already been reported; if not, please
|
||||||
|
head over to http://code.djangoproject.com/newticket and file a new
|
||||||
|
ticket with as much information about the bug as you can provide.
|
||||||
|
|
||||||
|
If you're running into a bug which has been reported but not fixed,
|
||||||
|
feel free to update the ticket with any additional information you
|
||||||
|
have, and to assign it to 'ubernostrum' (AKA James Bennett, the
|
||||||
|
maintainer of this branch).
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
VERSION = (0, 9, 1, 'SVN')
|
VERSION = (0, 91, 3, 'SVN')
|
||||||
|
|
|
@ -20,7 +20,14 @@ def compile_messages():
|
||||||
if f.endswith('.po'):
|
if f.endswith('.po'):
|
||||||
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
|
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
|
||||||
pf = os.path.splitext(os.path.join(dirpath, f))[0]
|
pf = os.path.splitext(os.path.join(dirpath, f))[0]
|
||||||
cmd = 'msgfmt -o "%s.mo" "%s.po"' % (pf, pf)
|
# Store the names of the .mo and .po files in an environment
|
||||||
|
# variable, rather than doing a string replacement into the
|
||||||
|
# command, so that we can take advantage of shell quoting, to
|
||||||
|
# quote any malicious characters/escaping.
|
||||||
|
# See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
|
||||||
|
os.environ['djangocompilemo'] = pf + '.mo'
|
||||||
|
os.environ['djangocompilepo'] = pf + '.po'
|
||||||
|
cmd = 'msgfmt -o "$djangocompilemo" "$djangocompilepo"'
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,8 +1,35 @@
|
||||||
// Handles related-objects functionality: lookup link for raw_id_admin=True
|
// Handles related-objects functionality: lookup link for raw_id_admin=True
|
||||||
// and Add Another links.
|
// and Add Another links.
|
||||||
|
|
||||||
|
function html_unescape(text) {
|
||||||
|
// Unescape a string that was escaped using django.utils.html.escape.
|
||||||
|
text = text.replace(/</g, '<');
|
||||||
|
text = text.replace(/>/g, '>');
|
||||||
|
text = text.replace(/"/g, '"');
|
||||||
|
text = text.replace(/'/g, "'");
|
||||||
|
text = text.replace(/&/g, '&');
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IE doesn't accept periods or dashes in the window name, but the element IDs
|
||||||
|
// we use to generate popup window names may contain them, therefore we map them
|
||||||
|
// to allowed characters in a reversible way so that we can locate the correct
|
||||||
|
// element when the popup window is dismissed.
|
||||||
|
function id_to_windowname(text) {
|
||||||
|
text = text.replace(/\./g, '__dot__');
|
||||||
|
text = text.replace(/\-/g, '__dash__');
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
function windowname_to_id(text) {
|
||||||
|
text = text.replace(/__dot__/g, '.');
|
||||||
|
text = text.replace(/__dash__/g, '-');
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
function showRelatedObjectLookupPopup(triggeringLink) {
|
function showRelatedObjectLookupPopup(triggeringLink) {
|
||||||
var name = triggeringLink.id.replace(/^lookup_/, '');
|
var name = triggeringLink.id.replace(/^lookup_/, '');
|
||||||
|
name = id_to_windowname(name);
|
||||||
var href;
|
var href;
|
||||||
if (triggeringLink.href.search(/\?/) >= 0) {
|
if (triggeringLink.href.search(/\?/) >= 0) {
|
||||||
href = triggeringLink.href + '&pop=1';
|
href = triggeringLink.href + '&pop=1';
|
||||||
|
@ -15,25 +42,36 @@ function showRelatedObjectLookupPopup(triggeringLink) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismissRelatedLookupPopup(win, chosenId) {
|
function dismissRelatedLookupPopup(win, chosenId) {
|
||||||
var elem = document.getElementById(win.name);
|
var name = windowname_to_id(win.name);
|
||||||
|
var elem = document.getElementById(name);
|
||||||
if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
|
if (elem.className.indexOf('vRawIdAdminField') != -1 && elem.value) {
|
||||||
elem.value += ',' + chosenId;
|
elem.value += ',' + chosenId;
|
||||||
} else {
|
} else {
|
||||||
document.getElementById(win.name).value = chosenId;
|
document.getElementById(name).value = chosenId;
|
||||||
}
|
}
|
||||||
win.close();
|
win.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
function showAddAnotherPopup(triggeringLink) {
|
function showAddAnotherPopup(triggeringLink) {
|
||||||
var name = triggeringLink.id.replace(/^add_/, '');
|
var name = triggeringLink.id.replace(/^add_/, '');
|
||||||
name = name.replace(/\./g, '___');
|
name = id_to_windowname(name);
|
||||||
var win = window.open(triggeringLink.href + '?_popup=1', name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
href = triggeringLink.href
|
||||||
|
if (href.indexOf('?') == -1) {
|
||||||
|
href += '?_popup=1';
|
||||||
|
} else {
|
||||||
|
href += '&_popup=1';
|
||||||
|
}
|
||||||
|
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||||
win.focus();
|
win.focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function dismissAddAnotherPopup(win, newId, newRepr) {
|
function dismissAddAnotherPopup(win, newId, newRepr) {
|
||||||
var name = win.name.replace(/___/g, '.');
|
// newId and newRepr are expected to have previously been escaped by
|
||||||
|
// django.utils.html.escape.
|
||||||
|
newId = html_unescape(newId);
|
||||||
|
newRepr = html_unescape(newRepr);
|
||||||
|
var name = windowname_to_id(win.name);
|
||||||
var elem = document.getElementById(name);
|
var elem = document.getElementById(name);
|
||||||
if (elem) {
|
if (elem) {
|
||||||
if (elem.nodeName == 'SELECT') {
|
if (elem.nodeName == 'SELECT') {
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
<p class="aligned">
|
<p class="aligned">
|
||||||
<label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
|
<label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
|
||||||
<input type="hidden" name="this_is_the_login_form" value="1" />
|
<input type="hidden" name="this_is_the_login_form" value="1" />
|
||||||
<input type="hidden" name="post_data" value="{{ post_data }}" />{% comment %} <span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %}
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="aligned ">
|
<div class="aligned ">
|
||||||
|
|
|
@ -2,43 +2,21 @@ from django.core.extensions import DjangoContext, render_to_response
|
||||||
from django.conf.settings import SECRET_KEY
|
from django.conf.settings import SECRET_KEY
|
||||||
from django.models.auth import users
|
from django.models.auth import users
|
||||||
from django.utils import httpwrappers
|
from django.utils import httpwrappers
|
||||||
|
from django.utils.html import escape
|
||||||
from django.utils.translation import gettext_lazy
|
from django.utils.translation import gettext_lazy
|
||||||
import base64, datetime, md5
|
import base64, datetime
|
||||||
import cPickle as pickle
|
|
||||||
|
|
||||||
ERROR_MESSAGE = gettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
ERROR_MESSAGE = gettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.")
|
||||||
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
LOGIN_FORM_KEY = 'this_is_the_login_form'
|
||||||
|
|
||||||
def _display_login_form(request, error_message=''):
|
def _display_login_form(request, error_message=''):
|
||||||
request.session.set_test_cookie()
|
request.session.set_test_cookie()
|
||||||
if request.POST and request.POST.has_key('post_data'):
|
|
||||||
# User has failed login BUT has previously saved post data.
|
|
||||||
post_data = request.POST['post_data']
|
|
||||||
elif request.POST:
|
|
||||||
# User's session must have expired; save their post data.
|
|
||||||
post_data = _encode_post_data(request.POST)
|
|
||||||
else:
|
|
||||||
post_data = _encode_post_data({})
|
|
||||||
return render_to_response('admin/login', {
|
return render_to_response('admin/login', {
|
||||||
'title': _('Log in'),
|
'title': _('Log in'),
|
||||||
'app_path': request.path,
|
'app_path': escape(request.path),
|
||||||
'post_data': post_data,
|
|
||||||
'error_message': error_message
|
'error_message': error_message
|
||||||
}, context_instance=DjangoContext(request))
|
}, context_instance=DjangoContext(request))
|
||||||
|
|
||||||
def _encode_post_data(post_data):
|
|
||||||
pickled = pickle.dumps(post_data)
|
|
||||||
pickled_md5 = md5.new(pickled + SECRET_KEY).hexdigest()
|
|
||||||
return base64.encodestring(pickled + pickled_md5)
|
|
||||||
|
|
||||||
def _decode_post_data(encoded_data):
|
|
||||||
encoded_data = base64.decodestring(encoded_data)
|
|
||||||
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
|
|
||||||
if md5.new(pickled + SECRET_KEY).hexdigest() != tamper_check:
|
|
||||||
from django.core.exceptions import SuspiciousOperation
|
|
||||||
raise SuspiciousOperation, "User may have tampered with session cookie."
|
|
||||||
return pickle.loads(pickled)
|
|
||||||
|
|
||||||
def staff_member_required(view_func):
|
def staff_member_required(view_func):
|
||||||
"""
|
"""
|
||||||
Decorator for views that checks that the user is logged in and is a staff
|
Decorator for views that checks that the user is logged in and is a staff
|
||||||
|
@ -47,10 +25,6 @@ def staff_member_required(view_func):
|
||||||
def _checklogin(request, *args, **kwargs):
|
def _checklogin(request, *args, **kwargs):
|
||||||
if not request.user.is_anonymous() and request.user.is_staff:
|
if not request.user.is_anonymous() and request.user.is_staff:
|
||||||
# The user is valid. Continue to the admin page.
|
# The user is valid. Continue to the admin page.
|
||||||
if request.POST.has_key('post_data'):
|
|
||||||
# User must have re-authenticated through a different window
|
|
||||||
# or tab.
|
|
||||||
request.POST = _decode_post_data(request.POST['post_data'])
|
|
||||||
return view_func(request, *args, **kwargs)
|
return view_func(request, *args, **kwargs)
|
||||||
|
|
||||||
assert hasattr(request, 'session'), "The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.middleware.sessions.SessionMiddleware'."
|
assert hasattr(request, 'session'), "The Django admin requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.middleware.sessions.SessionMiddleware'."
|
||||||
|
@ -58,7 +32,7 @@ def staff_member_required(view_func):
|
||||||
# If this isn't already the login page, display it.
|
# If this isn't already the login page, display it.
|
||||||
if not request.POST.has_key(LOGIN_FORM_KEY):
|
if not request.POST.has_key(LOGIN_FORM_KEY):
|
||||||
if request.POST:
|
if request.POST:
|
||||||
message = _("Please log in again, because your session has expired. Don't worry: Your submission has been saved.")
|
message = _("Please log in again, because your session has expired.")
|
||||||
else:
|
else:
|
||||||
message = ""
|
message = ""
|
||||||
return _display_login_form(request, message)
|
return _display_login_form(request, message)
|
||||||
|
@ -90,16 +64,7 @@ def staff_member_required(view_func):
|
||||||
request.session[users.SESSION_KEY] = user.id
|
request.session[users.SESSION_KEY] = user.id
|
||||||
user.last_login = datetime.datetime.now()
|
user.last_login = datetime.datetime.now()
|
||||||
user.save()
|
user.save()
|
||||||
if request.POST.has_key('post_data'):
|
return httpwrappers.HttpResponseRedirect(request.path)
|
||||||
post_data = _decode_post_data(request.POST['post_data'])
|
|
||||||
if post_data and not post_data.has_key(LOGIN_FORM_KEY):
|
|
||||||
# overwrite request.POST with the saved post_data, and continue
|
|
||||||
request.POST = post_data
|
|
||||||
request.user = user
|
|
||||||
return view_func(request, *args, **kwargs)
|
|
||||||
else:
|
|
||||||
request.session.delete_test_cookie()
|
|
||||||
return httpwrappers.HttpResponseRedirect(request.path)
|
|
||||||
else:
|
else:
|
||||||
return _display_login_form(request, ERROR_MESSAGE)
|
return _display_login_form(request, ERROR_MESSAGE)
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,16 @@ class ChangeList(object):
|
||||||
self.mod, self.opts = _get_mod_opts(app_label, module_name)
|
self.mod, self.opts = _get_mod_opts(app_label, module_name)
|
||||||
if not request.user.has_perm(app_label + '.' + self.opts.get_change_permission()):
|
if not request.user.has_perm(app_label + '.' + self.opts.get_change_permission()):
|
||||||
raise PermissionDenied
|
raise PermissionDenied
|
||||||
|
|
||||||
self.lookup_mod, self.lookup_opts = self.mod, self.opts
|
lookup_mod, lookup_opts = self.mod, self.opts
|
||||||
|
if self.opts.one_to_one_field:
|
||||||
|
lookup_mod = self.opts.one_to_one_field.rel.to.get_model_module()
|
||||||
|
lookup_opts = lookup_mod.Klass._meta
|
||||||
|
# If lookup_opts doesn't have admin set, give it the default meta.Admin().
|
||||||
|
if not lookup_opts.admin:
|
||||||
|
lookup_opts.admin = meta.Admin()
|
||||||
|
|
||||||
|
self.lookup_mod, self.lookup_opts = lookup_mod, lookup_opts
|
||||||
|
|
||||||
def get_search_parameters(self, request):
|
def get_search_parameters(self, request):
|
||||||
# Get search parameters from the query string.
|
# Get search parameters from the query string.
|
||||||
|
|
|
@ -43,6 +43,6 @@ class LatestCommentsFeed(LatestFreeCommentsFeed):
|
||||||
kwargs = LatestFreeCommentsFeed._get_lookup_kwargs(self)
|
kwargs = LatestFreeCommentsFeed._get_lookup_kwargs(self)
|
||||||
kwargs['is_removed__exact'] = False
|
kwargs['is_removed__exact'] = False
|
||||||
if settings.COMMENTS_BANNED_USERS_GROUP:
|
if settings.COMMENTS_BANNED_USERS_GROUP:
|
||||||
kwargs['where'] = ['user_id NOT IN (SELECT user_id FROM auth_users_group WHERE group_id = %s)']
|
kwargs['where'] = ['user_id NOT IN (SELECT user_id FROM auth_users_groups WHERE group_id = %s)']
|
||||||
kwargs['params'] = [COMMENTS_BANNED_USERS_GROUP]
|
kwargs['params'] = [settings.COMMENTS_BANNED_USERS_GROUP]
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
|
@ -107,7 +107,7 @@ class PublicCommentManipulator(AuthenticationForm):
|
||||||
# send the comment to the managers.
|
# send the comment to the managers.
|
||||||
if self.user_cache.get_comments_comment_count() <= COMMENTS_FIRST_FEW:
|
if self.user_cache.get_comments_comment_count() <= COMMENTS_FIRST_FEW:
|
||||||
message = ngettext('This comment was posted by a user who has posted fewer than %(count)s comment:\n\n%(text)s',
|
message = ngettext('This comment was posted by a user who has posted fewer than %(count)s comment:\n\n%(text)s',
|
||||||
'This comment was posted by a user who has posted fewer than %(count)s comments:\n\n%(text)s') % \
|
'This comment was posted by a user who has posted fewer than %(count)s comments:\n\n%(text)s', COMMENTS_FIRST_FEW) % \
|
||||||
{'count': COMMENTS_FIRST_FEW, 'text': c.get_as_text()}
|
{'count': COMMENTS_FIRST_FEW, 'text': c.get_as_text()}
|
||||||
mail_managers("Comment posted by rookie user", message)
|
mail_managers("Comment posted by rookie user", message)
|
||||||
if COMMENTS_SKETCHY_USERS_GROUP and COMMENTS_SKETCHY_USERS_GROUP in [g.id for g in self.user_cache.get_group_list()]:
|
if COMMENTS_SKETCHY_USERS_GROUP and COMMENTS_SKETCHY_USERS_GROUP in [g.id for g in self.user_cache.get_group_list()]:
|
||||||
|
|
|
@ -16,13 +16,54 @@ except ImportError:
|
||||||
# Import copy of _thread_local.py from python 2.4
|
# Import copy of _thread_local.py from python 2.4
|
||||||
from django.utils._threading_local import local
|
from django.utils._threading_local import local
|
||||||
|
|
||||||
|
def smart_basestring(s, charset):
|
||||||
|
if isinstance(s, unicode):
|
||||||
|
return s.encode(charset)
|
||||||
|
return s
|
||||||
|
|
||||||
|
class UnicodeCursorWrapper(object):
|
||||||
|
"""
|
||||||
|
A thin wrapper around psycopg cursors that allows them to accept Unicode
|
||||||
|
strings as params.
|
||||||
|
|
||||||
|
This is necessary because psycopg doesn't apply any DB quoting to
|
||||||
|
parameters that are Unicode strings. If a param is Unicode, this will
|
||||||
|
convert it to a bytestring using DEFAULT_CHARSET before passing it to
|
||||||
|
psycopg.
|
||||||
|
"""
|
||||||
|
def __init__(self, cursor, charset):
|
||||||
|
self.cursor = cursor
|
||||||
|
self.charset = charset
|
||||||
|
|
||||||
|
def execute(self, sql, params=()):
|
||||||
|
try:
|
||||||
|
params = dict([(k, smart_basestring(v, self.charset)) for (k, v) in params.items()])
|
||||||
|
except AttributeError:
|
||||||
|
params = [smart_basestring(p, self.charset) for p in params]
|
||||||
|
return self.cursor.execute(sql, params)
|
||||||
|
|
||||||
|
def executemany(self, sql, param_list):
|
||||||
|
try:
|
||||||
|
new_param_list = [dict([(k, smart_basestring(v, self.charset)) for (k, v) in params.items()])
|
||||||
|
for params in param_list]
|
||||||
|
except AttributeError:
|
||||||
|
new_param_list = [tuple([smart_basestring(p, self.charset) for p in params])
|
||||||
|
for params in param_list]
|
||||||
|
return self.cursor.executemany(sql, new_param_list)
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
if self.__dict__.has_key(attr):
|
||||||
|
return self.__dict__[attr]
|
||||||
|
else:
|
||||||
|
return getattr(self.cursor, attr)
|
||||||
|
|
||||||
class DatabaseWrapper(local):
|
class DatabaseWrapper(local):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.connection = None
|
self.connection = None
|
||||||
self.queries = []
|
self.queries = []
|
||||||
|
|
||||||
def cursor(self):
|
def cursor(self):
|
||||||
from django.conf.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PORT, DATABASE_PASSWORD, DEBUG, TIME_ZONE
|
from django.conf.settings import DATABASE_USER, DATABASE_NAME, DATABASE_HOST, DATABASE_PORT, DATABASE_PASSWORD, DEBUG, DEFAULT_CHARSET, TIME_ZONE
|
||||||
if self.connection is None:
|
if self.connection is None:
|
||||||
if DATABASE_NAME == '':
|
if DATABASE_NAME == '':
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
@ -40,6 +81,7 @@ class DatabaseWrapper(local):
|
||||||
self.connection.set_isolation_level(1) # make transactions transparent to all cursors
|
self.connection.set_isolation_level(1) # make transactions transparent to all cursors
|
||||||
cursor = self.connection.cursor()
|
cursor = self.connection.cursor()
|
||||||
cursor.execute("SET TIME ZONE %s", [TIME_ZONE])
|
cursor.execute("SET TIME ZONE %s", [TIME_ZONE])
|
||||||
|
cursor = UnicodeCursorWrapper(cursor, DEFAULT_CHARSET)
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
return base.CursorDebugWrapper(cursor, self)
|
return base.CursorDebugWrapper(cursor, self)
|
||||||
return cursor
|
return cursor
|
||||||
|
|
|
@ -325,7 +325,8 @@ class FormField:
|
||||||
|
|
||||||
class TextField(FormField):
|
class TextField(FormField):
|
||||||
input_type = "text"
|
input_type = "text"
|
||||||
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=[], member_name=None):
|
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None, member_name=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
self.length, self.maxlength = length, maxlength
|
self.length, self.maxlength = length, maxlength
|
||||||
self.is_required = is_required
|
self.is_required = is_required
|
||||||
|
@ -362,7 +363,8 @@ class PasswordField(TextField):
|
||||||
input_type = "password"
|
input_type = "password"
|
||||||
|
|
||||||
class LargeTextField(TextField):
|
class LargeTextField(TextField):
|
||||||
def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=[], maxlength=None):
|
def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, maxlength=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
self.rows, self.cols, self.is_required = rows, cols, is_required
|
self.rows, self.cols, self.is_required = rows, cols, is_required
|
||||||
self.validator_list = validator_list[:]
|
self.validator_list = validator_list[:]
|
||||||
|
@ -380,7 +382,8 @@ class LargeTextField(TextField):
|
||||||
self.field_name, self.rows, self.cols, escape(data))
|
self.field_name, self.rows, self.cols, escape(data))
|
||||||
|
|
||||||
class HiddenField(FormField):
|
class HiddenField(FormField):
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name, self.is_required = field_name, is_required
|
self.field_name, self.is_required = field_name, is_required
|
||||||
self.validator_list = validator_list[:]
|
self.validator_list = validator_list[:]
|
||||||
|
|
||||||
|
@ -410,7 +413,8 @@ class CheckboxField(FormField):
|
||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
class SelectField(FormField):
|
class SelectField(FormField):
|
||||||
def __init__(self, field_name, choices=[], size=1, is_required=False, validator_list=[], member_name=None):
|
def __init__(self, field_name, choices=[], size=1, is_required=False, validator_list=None, member_name=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
# choices is a list of (value, human-readable key) tuples because order matters
|
# choices is a list of (value, human-readable key) tuples because order matters
|
||||||
self.choices, self.size, self.is_required = choices, size, is_required
|
self.choices, self.size, self.is_required = choices, size, is_required
|
||||||
|
@ -446,7 +450,8 @@ class NullSelectField(SelectField):
|
||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
class RadioSelectField(FormField):
|
class RadioSelectField(FormField):
|
||||||
def __init__(self, field_name, choices=[], ul_class='', is_required=False, validator_list=[], member_name=None):
|
def __init__(self, field_name, choices=[], ul_class='', is_required=False, validator_list=None, member_name=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
# choices is a list of (value, human-readable key) tuples because order matters
|
# choices is a list of (value, human-readable key) tuples because order matters
|
||||||
self.choices, self.is_required = choices, is_required
|
self.choices, self.is_required = choices, is_required
|
||||||
|
@ -510,7 +515,8 @@ class RadioSelectField(FormField):
|
||||||
|
|
||||||
class NullBooleanField(SelectField):
|
class NullBooleanField(SelectField):
|
||||||
"This SelectField provides 'Yes', 'No' and 'Unknown', mapping results to True, False or None"
|
"This SelectField provides 'Yes', 'No' and 'Unknown', mapping results to True, False or None"
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
SelectField.__init__(self, field_name, choices=[('1', 'Unknown'), ('2', 'Yes'), ('3', 'No')],
|
SelectField.__init__(self, field_name, choices=[('1', 'Unknown'), ('2', 'Yes'), ('3', 'No')],
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
|
||||||
|
@ -563,7 +569,8 @@ class CheckboxSelectMultipleField(SelectMultipleField):
|
||||||
back into the single list that validators, renderers and save() expect.
|
back into the single list that validators, renderers and save() expect.
|
||||||
"""
|
"""
|
||||||
requires_data_list = True
|
requires_data_list = True
|
||||||
def __init__(self, field_name, choices=[], validator_list=[]):
|
def __init__(self, field_name, choices=[], validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list)
|
SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list)
|
||||||
|
|
||||||
def prepare(self, new_data):
|
def prepare(self, new_data):
|
||||||
|
@ -594,7 +601,8 @@ class CheckboxSelectMultipleField(SelectMultipleField):
|
||||||
####################
|
####################
|
||||||
|
|
||||||
class FileUploadField(FormField):
|
class FileUploadField(FormField):
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name, self.is_required = field_name, is_required
|
self.field_name, self.is_required = field_name, is_required
|
||||||
self.validator_list = [self.isNonEmptyFile] + validator_list
|
self.validator_list = [self.isNonEmptyFile] + validator_list
|
||||||
|
|
||||||
|
@ -629,7 +637,8 @@ class ImageUploadField(FileUploadField):
|
||||||
####################
|
####################
|
||||||
|
|
||||||
class IntegerField(TextField):
|
class IntegerField(TextField):
|
||||||
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=[], member_name=None):
|
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None, member_name=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isInteger] + validator_list
|
validator_list = [self.isInteger] + validator_list
|
||||||
if member_name is not None:
|
if member_name is not None:
|
||||||
self.member_name = member_name
|
self.member_name = member_name
|
||||||
|
@ -648,7 +657,8 @@ class IntegerField(TextField):
|
||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
class SmallIntegerField(IntegerField):
|
class SmallIntegerField(IntegerField):
|
||||||
def __init__(self, field_name, length=5, maxlength=5, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=5, maxlength=5, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isSmallInteger] + validator_list
|
validator_list = [self.isSmallInteger] + validator_list
|
||||||
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
||||||
|
|
||||||
|
@ -657,7 +667,8 @@ class SmallIntegerField(IntegerField):
|
||||||
raise validators.CriticalValidationError, _("Enter a whole number between -32,768 and 32,767.")
|
raise validators.CriticalValidationError, _("Enter a whole number between -32,768 and 32,767.")
|
||||||
|
|
||||||
class PositiveIntegerField(IntegerField):
|
class PositiveIntegerField(IntegerField):
|
||||||
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isPositive] + validator_list
|
validator_list = [self.isPositive] + validator_list
|
||||||
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
||||||
|
|
||||||
|
@ -666,7 +677,8 @@ class PositiveIntegerField(IntegerField):
|
||||||
raise validators.CriticalValidationError, _("Enter a positive number.")
|
raise validators.CriticalValidationError, _("Enter a positive number.")
|
||||||
|
|
||||||
class PositiveSmallIntegerField(IntegerField):
|
class PositiveSmallIntegerField(IntegerField):
|
||||||
def __init__(self, field_name, length=5, maxlength=None, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=5, maxlength=None, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isPositiveSmall] + validator_list
|
validator_list = [self.isPositiveSmall] + validator_list
|
||||||
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
IntegerField.__init__(self, field_name, length, maxlength, is_required, validator_list)
|
||||||
|
|
||||||
|
@ -675,7 +687,8 @@ class PositiveSmallIntegerField(IntegerField):
|
||||||
raise validators.CriticalValidationError, _("Enter a whole number between 0 and 32,767.")
|
raise validators.CriticalValidationError, _("Enter a whole number between 0 and 32,767.")
|
||||||
|
|
||||||
class FloatField(TextField):
|
class FloatField(TextField):
|
||||||
def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=[]):
|
def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.max_digits, self.decimal_places = max_digits, decimal_places
|
self.max_digits, self.decimal_places = max_digits, decimal_places
|
||||||
validator_list = [self.isValidFloat] + validator_list
|
validator_list = [self.isValidFloat] + validator_list
|
||||||
TextField.__init__(self, field_name, max_digits+1, max_digits+1, is_required, validator_list)
|
TextField.__init__(self, field_name, max_digits+1, max_digits+1, is_required, validator_list)
|
||||||
|
@ -700,7 +713,8 @@ class FloatField(TextField):
|
||||||
class DatetimeField(TextField):
|
class DatetimeField(TextField):
|
||||||
"""A FormField that automatically converts its data to a datetime.datetime object.
|
"""A FormField that automatically converts its data to a datetime.datetime object.
|
||||||
The data should be in the format YYYY-MM-DD HH:MM:SS."""
|
The data should be in the format YYYY-MM-DD HH:MM:SS."""
|
||||||
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=30, maxlength=None, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
self.length, self.maxlength = length, maxlength
|
self.length, self.maxlength = length, maxlength
|
||||||
self.is_required = is_required
|
self.is_required = is_required
|
||||||
|
@ -723,7 +737,8 @@ class DatetimeField(TextField):
|
||||||
class DateField(TextField):
|
class DateField(TextField):
|
||||||
"""A FormField that automatically converts its data to a datetime.date object.
|
"""A FormField that automatically converts its data to a datetime.date object.
|
||||||
The data should be in the format YYYY-MM-DD."""
|
The data should be in the format YYYY-MM-DD."""
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidDate] + validator_list
|
validator_list = [self.isValidDate] + validator_list
|
||||||
TextField.__init__(self, field_name, length=10, maxlength=10,
|
TextField.__init__(self, field_name, length=10, maxlength=10,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
@ -747,7 +762,8 @@ class DateField(TextField):
|
||||||
class TimeField(TextField):
|
class TimeField(TextField):
|
||||||
"""A FormField that automatically converts its data to a datetime.time object.
|
"""A FormField that automatically converts its data to a datetime.time object.
|
||||||
The data should be in the format HH:MM:SS or HH:MM:SS.mmmmmm."""
|
The data should be in the format HH:MM:SS or HH:MM:SS.mmmmmm."""
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidTime] + validator_list
|
validator_list = [self.isValidTime] + validator_list
|
||||||
TextField.__init__(self, field_name, length=8, maxlength=8,
|
TextField.__init__(self, field_name, length=8, maxlength=8,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
@ -781,7 +797,8 @@ class TimeField(TextField):
|
||||||
|
|
||||||
class EmailField(TextField):
|
class EmailField(TextField):
|
||||||
"A convenience FormField for validating e-mail addresses"
|
"A convenience FormField for validating e-mail addresses"
|
||||||
def __init__(self, field_name, length=50, maxlength=75, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=50, maxlength=75, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidEmail] + validator_list
|
validator_list = [self.isValidEmail] + validator_list
|
||||||
TextField.__init__(self, field_name, length, maxlength=maxlength,
|
TextField.__init__(self, field_name, length, maxlength=maxlength,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
@ -794,7 +811,8 @@ class EmailField(TextField):
|
||||||
|
|
||||||
class URLField(TextField):
|
class URLField(TextField):
|
||||||
"A convenience FormField for validating URLs"
|
"A convenience FormField for validating URLs"
|
||||||
def __init__(self, field_name, length=50, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=50, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidURL] + validator_list
|
validator_list = [self.isValidURL] + validator_list
|
||||||
TextField.__init__(self, field_name, length=length, maxlength=200,
|
TextField.__init__(self, field_name, length=length, maxlength=200,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
@ -806,7 +824,8 @@ class URLField(TextField):
|
||||||
raise validators.CriticalValidationError, e.messages
|
raise validators.CriticalValidationError, e.messages
|
||||||
|
|
||||||
class IPAddressField(TextField):
|
class IPAddressField(TextField):
|
||||||
def __init__(self, field_name, length=15, maxlength=15, is_required=False, validator_list=[]):
|
def __init__(self, field_name, length=15, maxlength=15, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidIPAddress] + validator_list
|
validator_list = [self.isValidIPAddress] + validator_list
|
||||||
TextField.__init__(self, field_name, length=length, maxlength=maxlength,
|
TextField.__init__(self, field_name, length=length, maxlength=maxlength,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
@ -827,7 +846,8 @@ class IPAddressField(TextField):
|
||||||
|
|
||||||
class FilePathField(SelectField):
|
class FilePathField(SelectField):
|
||||||
"A SelectField whose choices are the files in a given directory."
|
"A SelectField whose choices are the files in a given directory."
|
||||||
def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=[]):
|
def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
import os
|
import os
|
||||||
if match is not None:
|
if match is not None:
|
||||||
import re
|
import re
|
||||||
|
@ -850,7 +870,8 @@ class FilePathField(SelectField):
|
||||||
|
|
||||||
class PhoneNumberField(TextField):
|
class PhoneNumberField(TextField):
|
||||||
"A convenience FormField for validating phone numbers (e.g. '630-555-1234')"
|
"A convenience FormField for validating phone numbers (e.g. '630-555-1234')"
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidPhone] + validator_list
|
validator_list = [self.isValidPhone] + validator_list
|
||||||
TextField.__init__(self, field_name, length=12, maxlength=12,
|
TextField.__init__(self, field_name, length=12, maxlength=12,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
@ -863,7 +884,8 @@ class PhoneNumberField(TextField):
|
||||||
|
|
||||||
class USStateField(TextField):
|
class USStateField(TextField):
|
||||||
"A convenience FormField for validating U.S. states (e.g. 'IL')"
|
"A convenience FormField for validating U.S. states (e.g. 'IL')"
|
||||||
def __init__(self, field_name, is_required=False, validator_list=[]):
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isValidUSState] + validator_list
|
validator_list = [self.isValidUSState] + validator_list
|
||||||
TextField.__init__(self, field_name, length=2, maxlength=2,
|
TextField.__init__(self, field_name, length=2, maxlength=2,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
@ -875,15 +897,13 @@ class USStateField(TextField):
|
||||||
raise validators.CriticalValidationError, e.messages
|
raise validators.CriticalValidationError, e.messages
|
||||||
|
|
||||||
def html2python(data):
|
def html2python(data):
|
||||||
if data:
|
return data.upper() # Should always be stored in upper case
|
||||||
return data.upper() # Should always be stored in upper case
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
class CommaSeparatedIntegerField(TextField):
|
class CommaSeparatedIntegerField(TextField):
|
||||||
"A convenience FormField for validating comma-separated integer fields"
|
"A convenience FormField for validating comma-separated integer fields"
|
||||||
def __init__(self, field_name, maxlength=None, is_required=False, validator_list=[]):
|
def __init__(self, field_name, maxlength=None, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
validator_list = [self.isCommaSeparatedIntegerList] + validator_list
|
validator_list = [self.isCommaSeparatedIntegerList] + validator_list
|
||||||
TextField.__init__(self, field_name, length=20, maxlength=maxlength,
|
TextField.__init__(self, field_name, length=20, maxlength=maxlength,
|
||||||
is_required=is_required, validator_list=validator_list)
|
is_required=is_required, validator_list=validator_list)
|
||||||
|
|
|
@ -55,14 +55,14 @@ class BaseHandler:
|
||||||
# Reset query list per request.
|
# Reset query list per request.
|
||||||
db.db.queries = []
|
db.db.queries = []
|
||||||
|
|
||||||
# Apply request middleware
|
|
||||||
for middleware_method in self._request_middleware:
|
|
||||||
response = middleware_method(request)
|
|
||||||
if response:
|
|
||||||
return response
|
|
||||||
|
|
||||||
resolver = urlresolvers.RegexURLResolver(r'^/', ROOT_URLCONF)
|
resolver = urlresolvers.RegexURLResolver(r'^/', ROOT_URLCONF)
|
||||||
try:
|
try:
|
||||||
|
# Apply request middleware
|
||||||
|
for middleware_method in self._request_middleware:
|
||||||
|
response = middleware_method(request)
|
||||||
|
if response:
|
||||||
|
return response
|
||||||
|
|
||||||
callback, callback_args, callback_kwargs = resolver.resolve(path)
|
callback, callback_args, callback_kwargs = resolver.resolve(path)
|
||||||
|
|
||||||
# Apply view middleware
|
# Apply view middleware
|
||||||
|
|
|
@ -13,9 +13,30 @@ class ModPythonRequest(httpwrappers.HttpRequest):
|
||||||
self.path = req.uri
|
self.path = req.uri
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
# Since this is called as part of error handling, we need to be very
|
||||||
|
# robust against potentially malformed input.
|
||||||
|
try:
|
||||||
|
get = pformat(self.GET)
|
||||||
|
except:
|
||||||
|
get = '<could not parse>'
|
||||||
|
try:
|
||||||
|
post = pformat(self.POST)
|
||||||
|
except:
|
||||||
|
post = '<could not parse>'
|
||||||
|
try:
|
||||||
|
cookies = pformat(self.COOKIES)
|
||||||
|
except:
|
||||||
|
cookies = '<could not parse>'
|
||||||
|
try:
|
||||||
|
meta = pformat(self.META)
|
||||||
|
except:
|
||||||
|
meta = '<could not parse>'
|
||||||
|
try:
|
||||||
|
user = self.user
|
||||||
|
except:
|
||||||
|
user = '<could not parse>'
|
||||||
return '<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s,\nuser:%s>' % \
|
return '<ModPythonRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s,\nuser:%s>' % \
|
||||||
(self.path, pformat(self.GET), pformat(self.POST), pformat(self.COOKIES),
|
(self.path, get, post, cookies, meta, user)
|
||||||
pformat(self.META), pformat(self.user))
|
|
||||||
|
|
||||||
def get_full_path(self):
|
def get_full_path(self):
|
||||||
return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '')
|
return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '')
|
||||||
|
@ -141,13 +162,12 @@ class ModPythonHandler(BaseHandler):
|
||||||
try:
|
try:
|
||||||
request = ModPythonRequest(req)
|
request = ModPythonRequest(req)
|
||||||
response = self.get_response(req.uri, request)
|
response = self.get_response(req.uri, request)
|
||||||
|
# Apply response middleware
|
||||||
|
for middleware_method in self._response_middleware:
|
||||||
|
response = middleware_method(request, response)
|
||||||
finally:
|
finally:
|
||||||
db.db.close()
|
db.db.close()
|
||||||
|
|
||||||
# Apply response middleware
|
|
||||||
for middleware_method in self._response_middleware:
|
|
||||||
response = middleware_method(request, response)
|
|
||||||
|
|
||||||
# Convert our custom HttpResponse object back into the mod_python req.
|
# Convert our custom HttpResponse object back into the mod_python req.
|
||||||
populate_apache_request(response, req)
|
populate_apache_request(response, req)
|
||||||
return 0 # mod_python.apache.OK
|
return 0 # mod_python.apache.OK
|
||||||
|
|
|
@ -55,9 +55,30 @@ class WSGIRequest(httpwrappers.HttpRequest):
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
return '<DjangoRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
|
# Since this is called as part of error handling, we need to be very
|
||||||
(pformat(self.GET), pformat(self.POST), pformat(self.COOKIES),
|
# robust against potentially malformed input.
|
||||||
pformat(self.META))
|
try:
|
||||||
|
get = pformat(self.GET)
|
||||||
|
except:
|
||||||
|
get = '<could not parse>'
|
||||||
|
try:
|
||||||
|
post = pformat(self.POST)
|
||||||
|
except:
|
||||||
|
post = '<could not parse>'
|
||||||
|
try:
|
||||||
|
cookies = pformat(self.COOKIES)
|
||||||
|
except:
|
||||||
|
cookies = '<could not parse>'
|
||||||
|
try:
|
||||||
|
meta = pformat(self.META)
|
||||||
|
except:
|
||||||
|
meta = '<could not parse>'
|
||||||
|
try:
|
||||||
|
user = self.user
|
||||||
|
except:
|
||||||
|
user = '<could not parse>'
|
||||||
|
return '<DjangoRequest\npath:%s,\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s,\nuser:%s>' % \
|
||||||
|
(self.path, get, post, cookies, meta, user)
|
||||||
|
|
||||||
def get_full_path(self):
|
def get_full_path(self):
|
||||||
return '%s%s' % (self.path, self.environ['QUERY_STRING'] and ('?' + self.environ['QUERY_STRING']) or '')
|
return '%s%s' % (self.path, self.environ['QUERY_STRING'] and ('?' + self.environ['QUERY_STRING']) or '')
|
||||||
|
@ -157,13 +178,12 @@ class WSGIHandler(BaseHandler):
|
||||||
try:
|
try:
|
||||||
request = WSGIRequest(environ)
|
request = WSGIRequest(environ)
|
||||||
response = self.get_response(request.path, request)
|
response = self.get_response(request.path, request)
|
||||||
|
# Apply response middleware
|
||||||
|
for middleware_method in self._response_middleware:
|
||||||
|
response = middleware_method(request, response)
|
||||||
finally:
|
finally:
|
||||||
db.db.close()
|
db.db.close()
|
||||||
|
|
||||||
# Apply response middleware
|
|
||||||
for middleware_method in self._response_middleware:
|
|
||||||
response = middleware_method(request, response)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
status_text = STATUS_CODE_TEXT[response.status_code]
|
status_text = STATUS_CODE_TEXT[response.status_code]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|
|
@ -151,7 +151,7 @@ class BadKeywordArguments(Exception):
|
||||||
class BoundRelatedObject(object):
|
class BoundRelatedObject(object):
|
||||||
def __init__(self, related_object, field_mapping, original):
|
def __init__(self, related_object, field_mapping, original):
|
||||||
self.relation = related_object
|
self.relation = related_object
|
||||||
self.field_mappings = field_mapping[related_object.opts.module_name]
|
self.field_mappings = field_mapping[related_object.name]
|
||||||
|
|
||||||
def template_name(self):
|
def template_name(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -165,7 +165,7 @@ class RelatedObject(object):
|
||||||
self.opts = opts
|
self.opts = opts
|
||||||
self.field = field
|
self.field = field
|
||||||
self.edit_inline = field.rel.edit_inline
|
self.edit_inline = field.rel.edit_inline
|
||||||
self.name = opts.module_name
|
self.name = '%s_%s' % (opts.app_label, opts.module_name)
|
||||||
self.var_name = opts.object_name.lower()
|
self.var_name = opts.object_name.lower()
|
||||||
|
|
||||||
def flatten_data(self, follow, obj=None):
|
def flatten_data(self, follow, obj=None):
|
||||||
|
@ -1734,7 +1734,7 @@ def manipulator_init(opts, add, change, self, obj_key=None, follow=None):
|
||||||
# Sanity check -- Make sure the "parent" object exists.
|
# Sanity check -- Make sure the "parent" object exists.
|
||||||
# For example, make sure the Place exists for the Restaurant.
|
# For example, make sure the Place exists for the Restaurant.
|
||||||
# Let the ObjectDoesNotExist exception propagate up.
|
# Let the ObjectDoesNotExist exception propagate up.
|
||||||
lookup_kwargs = opts.one_to_one_field.rel.limit_choices_to
|
lookup_kwargs = opts.one_to_one_field.rel.limit_choices_to.copy()
|
||||||
lookup_kwargs['%s__exact' % opts.one_to_one_field.rel.field_name] = obj_key
|
lookup_kwargs['%s__exact' % opts.one_to_one_field.rel.field_name] = obj_key
|
||||||
_ = opts.one_to_one_field.rel.to.get_model_module().get_object(**lookup_kwargs)
|
_ = opts.one_to_one_field.rel.to.get_model_module().get_object(**lookup_kwargs)
|
||||||
params = dict([(f.attname, f.get_default()) for f in opts.fields])
|
params = dict([(f.attname, f.get_default()) for f in opts.fields])
|
||||||
|
|
|
@ -327,18 +327,26 @@ def get_digit(value, arg):
|
||||||
# DATES #
|
# DATES #
|
||||||
###################
|
###################
|
||||||
|
|
||||||
|
EMPTY_DATE_VALUES = (None, '')
|
||||||
|
|
||||||
def date(value, arg=DATE_FORMAT):
|
def date(value, arg=DATE_FORMAT):
|
||||||
"Formats a date according to the given format"
|
"Formats a date according to the given format"
|
||||||
|
if value in EMPTY_DATE_VALUES:
|
||||||
|
return ''
|
||||||
from django.utils.dateformat import format
|
from django.utils.dateformat import format
|
||||||
return format(value, arg)
|
return format(value, arg)
|
||||||
|
|
||||||
def time(value, arg=TIME_FORMAT):
|
def time(value, arg=TIME_FORMAT):
|
||||||
"Formats a time according to the given format"
|
"Formats a time according to the given format"
|
||||||
|
if value in EMPTY_DATE_VALUES:
|
||||||
|
return ''
|
||||||
from django.utils.dateformat import time_format
|
from django.utils.dateformat import time_format
|
||||||
return time_format(value, arg)
|
return time_format(value, arg)
|
||||||
|
|
||||||
def timesince(value):
|
def timesince(value):
|
||||||
'Formats a date as the time since that date (i.e. "4 days, 6 hours")'
|
'Formats a date as the time since that date (i.e. "4 days, 6 hours")'
|
||||||
|
if value in EMPTY_DATE_VALUES:
|
||||||
|
return ''
|
||||||
from django.utils.timesince import timesince
|
from django.utils.timesince import timesince
|
||||||
return timesince(value)
|
return timesince(value)
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
"translation helper functions"
|
"translation helper functions"
|
||||||
|
|
||||||
import os, re, sys
|
import locale
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
import gettext as gettext_module
|
import gettext as gettext_module
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from django.utils.functional import lazy
|
from django.utils.functional import lazy
|
||||||
|
@ -25,15 +28,25 @@ _active = {}
|
||||||
# The default translation is based on the settings file.
|
# The default translation is based on the settings file.
|
||||||
_default = None
|
_default = None
|
||||||
|
|
||||||
# This is a cache for accept-header to translation object mappings to prevent
|
# This is a cache for normalised accept-header languages to prevent multiple
|
||||||
# the accept parser to run multiple times for one user.
|
# file lookups when checking the same locale on repeated requests.
|
||||||
_accepted = {}
|
_accepted = {}
|
||||||
|
|
||||||
def to_locale(language):
|
# Format of Accept-Language header values. From RFC 2616, section 14.4 and 3.9.
|
||||||
|
accept_language_re = re.compile(r'''
|
||||||
|
([A-Za-z]{1,8}(?:-[A-Za-z]{1,8})*|\*) # "en", "en-au", "x-y-z", "*"
|
||||||
|
(?:;q=(0(?:\.\d{,3})?|1(?:.0{,3})?))? # Optional "q=1.00", "q=0.8"
|
||||||
|
(?:\s*,\s*|$) # Multiple accepts per header.
|
||||||
|
''', re.VERBOSE)
|
||||||
|
|
||||||
|
def to_locale(language, to_lower=False):
|
||||||
"Turns a language name (en-us) into a locale name (en_US)."
|
"Turns a language name (en-us) into a locale name (en_US)."
|
||||||
p = language.find('-')
|
p = language.find('-')
|
||||||
if p >= 0:
|
if p >= 0:
|
||||||
return language[:p].lower()+'_'+language[p+1:].upper()
|
if to_lower:
|
||||||
|
return language[:p].lower()+'_'+language[p+1:].lower()
|
||||||
|
else:
|
||||||
|
return language[:p].lower()+'_'+language[p+1:].upper()
|
||||||
else:
|
else:
|
||||||
return language.lower()
|
return language.lower()
|
||||||
|
|
||||||
|
@ -297,46 +310,40 @@ def get_language_from_request(request):
|
||||||
if lang_code in supported and lang_code is not None and check_for_language(lang_code):
|
if lang_code in supported and lang_code is not None and check_for_language(lang_code):
|
||||||
return lang_code
|
return lang_code
|
||||||
|
|
||||||
lang_code = request.COOKIES.get('django_language', None)
|
lang_code = request.COOKIES.get('django_language')
|
||||||
if lang_code in supported and lang_code is not None and check_for_language(lang_code):
|
if lang_code and lang_code in supported and check_for_language(lang_code):
|
||||||
return lang_code
|
return lang_code
|
||||||
|
|
||||||
accept = request.META.get('HTTP_ACCEPT_LANGUAGE', None)
|
accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
|
||||||
if accept is not None:
|
for lang, unused in parse_accept_lang_header(accept):
|
||||||
|
if lang == '*':
|
||||||
|
break
|
||||||
|
|
||||||
t = _accepted.get(accept, None)
|
# We have a very restricted form for our language files (no encoding
|
||||||
if t is not None:
|
# specifier, since they all must be UTF-8 and only one possible
|
||||||
return t
|
# language each time. So we avoid the overhead of gettext.find() and
|
||||||
|
# look up the MO file manually.
|
||||||
|
|
||||||
def _parsed(el):
|
normalized = locale.locale_alias.get(to_locale(lang, True))
|
||||||
p = el.find(';q=')
|
if not normalized:
|
||||||
if p >= 0:
|
continue
|
||||||
lang = el[:p].strip()
|
|
||||||
order = int(float(el[p+3:].strip())*100)
|
|
||||||
else:
|
|
||||||
lang = el
|
|
||||||
order = 100
|
|
||||||
p = lang.find('-')
|
|
||||||
if p >= 0:
|
|
||||||
mainlang = lang[:p]
|
|
||||||
else:
|
|
||||||
mainlang = lang
|
|
||||||
return (lang, mainlang, order)
|
|
||||||
|
|
||||||
langs = [_parsed(el) for el in accept.split(',')]
|
# Remove the default encoding from locale_alias
|
||||||
langs.sort(lambda a,b: -1*cmp(a[2], b[2]))
|
normalized = normalized.split('.')[0]
|
||||||
|
|
||||||
for lang, mainlang, order in langs:
|
if normalized in _accepted:
|
||||||
if lang in supported or mainlang in supported:
|
# We've seen this locale before and have an MO file for it, so no
|
||||||
langfile = gettext_module.find('django', globalpath, [to_locale(lang)])
|
# need to check again.
|
||||||
if langfile:
|
return _accepted[normalized]
|
||||||
# reconstruct the actual language from the language
|
|
||||||
# filename, because otherwise we might incorrectly
|
for lang in (normalized, normalized.split('_')[0]):
|
||||||
# report de_DE if we only have de available, but
|
if lang not in supported:
|
||||||
# did find de_DE because of language normalization
|
continue
|
||||||
lang = langfile[len(globalpath):].split(os.path.sep)[1]
|
langfile = os.path.join(globalpath, lang, 'LC_MESSAGES',
|
||||||
_accepted[accept] = lang
|
'django.mo')
|
||||||
return lang
|
if os.path.exists(langfile):
|
||||||
|
_accepted[normalized] = lang
|
||||||
|
return lang
|
||||||
|
|
||||||
return settings.LANGUAGE_CODE
|
return settings.LANGUAGE_CODE
|
||||||
|
|
||||||
|
@ -457,3 +464,23 @@ def templatize(src):
|
||||||
else:
|
else:
|
||||||
out.write(blankout(t.contents, 'X'))
|
out.write(blankout(t.contents, 'X'))
|
||||||
return out.getvalue()
|
return out.getvalue()
|
||||||
|
|
||||||
|
def parse_accept_lang_header(lang_string):
|
||||||
|
"""
|
||||||
|
Parses the lang_string, which is the body of an HTTP Accept-Language
|
||||||
|
header, and returns a list of (lang, q-value), ordered by 'q' values.
|
||||||
|
|
||||||
|
Any format errors in lang_string results in an empty list being returned.
|
||||||
|
"""
|
||||||
|
result = []
|
||||||
|
pieces = accept_language_re.split(lang_string)
|
||||||
|
if pieces[-1]:
|
||||||
|
return []
|
||||||
|
for i in range(0, len(pieces) - 1, 3):
|
||||||
|
first, lang, priority = pieces[i : i + 3]
|
||||||
|
if first:
|
||||||
|
return []
|
||||||
|
priority = priority and float(priority) or 1.0
|
||||||
|
result.append((lang, priority))
|
||||||
|
result.sort(lambda x, y: -cmp(x[1], y[1]))
|
||||||
|
return result
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -5,7 +5,7 @@ from setuptools import setup, find_packages
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name = "Django",
|
name = "Django",
|
||||||
version = "0.91",
|
version = "0.91.3",
|
||||||
url = 'http://www.djangoproject.com/',
|
url = 'http://www.djangoproject.com/',
|
||||||
author = 'Lawrence Journal-World',
|
author = 'Lawrence Journal-World',
|
||||||
author_email = 'holovaty@gmail.com',
|
author_email = 'holovaty@gmail.com',
|
||||||
|
|
Loading…
Reference in New Issue