From 84eb80bbd79af35293797fd77766513b28c8a7da Mon Sep 17 00:00:00 2001 From: Georg Bauer Date: Fri, 25 Nov 2005 00:20:13 +0000 Subject: [PATCH 01/13] and another little fix to the email sending stuff on password_reset - using Context works much better after importing it git-svn-id: http://code.djangoproject.com/svn/django/trunk@1409 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/views/registration/passwords.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django/views/registration/passwords.py b/django/views/registration/passwords.py index 0dde5f7b6d..65bacafd98 100644 --- a/django/views/registration/passwords.py +++ b/django/views/registration/passwords.py @@ -1,6 +1,6 @@ from django.core import formfields, validators from django.core.extensions import DjangoContext, render_to_response -from django.core.template import loader +from django.core.template import Context, loader from django.models.auth import users from django.views.decorators.auth import login_required from django.utils.httpwrappers import HttpResponseRedirect From c5e5c0fc3573f050d2db08517f88db2e16379455 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 00:54:40 +0000 Subject: [PATCH 02/13] Fixed #625 -- Added template-tag decorators simple_tag and inclusion_tag. Taken from new-admin. Thanks, rjwittams git-svn-id: http://code.djangoproject.com/svn/django/trunk@1410 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/template/decorators.py | 67 ++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 django/core/template/decorators.py diff --git a/django/core/template/decorators.py b/django/core/template/decorators.py new file mode 100644 index 0000000000..2a61a600ec --- /dev/null +++ b/django/core/template/decorators.py @@ -0,0 +1,67 @@ +from django.core.template import Context, Node, TemplateSyntaxError, register_tag, resolve_variable +from django.core.template_loader import get_template +from django.utils.functional import curry +from inspect import getargspec + +def generic_tag_compiler(params, defaults, name, node_class, parser, token): + "Returns a template.Node subclass." + bits = token.contents.split()[1:] + bmax = len(params) + def_len = defaults and len(defaults) or 0 + bmin = bmax - def_len + if(len(bits) < bmin or len(bits) > bmax): + if bmin == bmax: + message = "%s takes %s arguments" % (name, bmin) + else: + message = "%s takes between %s and %s arguments" % (name, bmin, bmax) + raise TemplateSyntaxError, message + return node_class(bits) + +def simple_tag(func): + (params, xx, xxx, defaults) = getargspec(func) + + class SimpleNode(Node): + def __init__(self, vars_to_resolve): + self.vars_to_resolve = vars_to_resolve + + def render(self, context): + resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] + return func(*resolved_vars) + + compile_func = curry(generic_tag_compiler, params, defaults, func.__name__, SimpleNode) + compile_func.__doc__ = func.__doc__ + register_tag(func.__name__, compile_func) + return func + +def inclusion_tag(file_name, context_class=Context, takes_context=False): + def dec(func): + (params, xx, xxx, defaults) = getargspec(func) + if takes_context: + if params[0] == 'context': + params = params[1:] + else: + raise TemplateSyntaxError, "Any tag function decorated with takes_context=True must have a first argument of 'context'" + + class InclusionNode(Node): + def __init__(self, vars_to_resolve): + self.vars_to_resolve = vars_to_resolve + + def render(self, context): + resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve] + if takes_context: + args = [context] + resolved_vars + else: + args = resolved_vars + + dict = func(*args) + + if not getattr(self, 'nodelist', False): + t = get_template(file_name) + self.nodelist = t.nodelist + return self.nodelist.render(context_class(dict)) + + compile_func = curry(generic_tag_compiler, params, defaults, func.__name__, InclusionNode) + compile_func.__doc__ = func.__doc__ + register_tag(func.__name__, compile_func) + return func + return dec From 16da4e69c40d5926087c87c6084c375860c108f6 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 01:00:52 +0000 Subject: [PATCH 03/13] Converted django.contrib.admin.templatetags.adminmedia to use simple_tag decorator git-svn-id: http://code.djangoproject.com/svn/django/trunk@1411 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- .../contrib/admin/templatetags/adminmedia.py | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/django/contrib/admin/templatetags/adminmedia.py b/django/contrib/admin/templatetags/adminmedia.py index 2b18252d7d..3a822ed9b0 100644 --- a/django/contrib/admin/templatetags/adminmedia.py +++ b/django/contrib/admin/templatetags/adminmedia.py @@ -1,17 +1,9 @@ -from django.core import template +from django.core.template.decorators import simple_tag -class AdminMediaPrefixNode(template.Node): - def render(self, context): - try: - from django.conf.settings import ADMIN_MEDIA_PREFIX - except ImportError: - return '' - return ADMIN_MEDIA_PREFIX - -def admin_media_prefix(parser, token): - """ - {% admin_media_prefix %} - """ - return AdminMediaPrefixNode() - -template.register_tag('admin_media_prefix', admin_media_prefix) +def admin_media_prefix(): + try: + from django.conf.settings import ADMIN_MEDIA_PREFIX + except ImportError: + return '' + return ADMIN_MEDIA_PREFIX +admin_media_prefix = simple_tag(admin_media_prefix) From f57e22495fb336b864c9af81bbea5e16687da086 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 01:03:58 +0000 Subject: [PATCH 04/13] Tiny formatting changes to templatetags/i18n.py git-svn-id: http://code.djangoproject.com/svn/django/trunk@1412 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/templatetags/i18n.py | 29 +++++++---------------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/django/templatetags/i18n.py b/django/templatetags/i18n.py index bf752ed598..e6ef3b062e 100644 --- a/django/templatetags/i18n.py +++ b/django/templatetags/i18n.py @@ -1,15 +1,10 @@ -"Default tags used by the template system, available to all templates." - from django.core.template import Node, NodeList, Template, Context, resolve_variable, resolve_variable_with_filters, registered_filters from django.core.template import TemplateSyntaxError, register_tag, TokenParser from django.core.template import TOKEN_BLOCK, TOKEN_TEXT, TOKEN_VAR from django.utils import translation - -import sys -import re +import re, sys class GetAvailableLanguagesNode(Node): - def __init__(self, variable): self.variable = variable @@ -19,7 +14,6 @@ class GetAvailableLanguagesNode(Node): return '' class GetCurrentLanguageNode(Node): - def __init__(self, variable): self.variable = variable @@ -28,7 +22,6 @@ class GetCurrentLanguageNode(Node): return '' class TranslateNode(Node): - def __init__(self, value, noop): self.value = value self.noop = noop @@ -41,7 +34,6 @@ class TranslateNode(Node): return translation.gettext(value) class BlockTranslateNode(Node): - def __init__(self, extra_context, singular, plural=None, countervar=None, counter=None): self.extra_context = extra_context self.singular = singular @@ -78,7 +70,7 @@ def do_get_available_languages(parser, token): This will store a list of available languages in the context. - Usage is as follows:: + Usage:: {% get_available_languages as languages %} {% for language in languages %} @@ -89,7 +81,6 @@ def do_get_available_languages(parser, token): your setting file (or the default settings) and put it into the named variable. """ - args = token.contents.split() if len(args) != 3 or args[1] != 'as': raise TemplateSyntaxError, "'get_available_languages' requires 'as variable' (got %r)" % args @@ -97,10 +88,9 @@ def do_get_available_languages(parser, token): def do_get_current_language(parser, token): """ - This will store the current language in - the context. + This will store the current language in the context. - Usage is as follows:: + Usage:: {% get_current_language as language %} @@ -108,7 +98,6 @@ def do_get_current_language(parser, token): put it's value into the ``language`` context variable. """ - args = token.contents.split() if len(args) != 3 or args[1] != 'as': raise TemplateSyntaxError, "'get_available_languages' requires 'as variable' (got %r)" % args @@ -119,7 +108,7 @@ def do_translate(parser, token): This will mark a string for translation and will translate the string for the current language. - Usage is like this:: + Usage:: {% trans "this is a test" %} @@ -144,9 +133,7 @@ def do_translate(parser, token): the variable ``variable``. Make sure that the string in there is something that is in the .po file. """ - class TranslateParser(TokenParser): - def top(self): value = self.value() if self.more(): @@ -157,7 +144,6 @@ def do_translate(parser, token): else: noop = False return (value, noop) - (value, noop) = TranslateParser(token.contents).top() return TranslateNode(value, noop) @@ -165,13 +151,13 @@ def do_block_translate(parser, token): """ This will translate a block of text with parameters. - Format is like this:: + Usage:: {% blocktrans with foo|filter as bar and baz|filter as boo %} This is {{ bar }} and {{ boo }}. {% endblocktrans %} - Additionally this supports pluralization:: + Additionally, this supports pluralization:: {% blocktrans count var|length as count %} There is {{ count }} object. @@ -231,4 +217,3 @@ register_tag('get_available_languages', do_get_available_languages) register_tag('get_current_language', do_get_current_language) register_tag('trans', do_translate) register_tag('blocktrans', do_block_translate) - From 473eabc4471df57e9bd534999a26d50aa42482c5 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 01:54:17 +0000 Subject: [PATCH 05/13] Negligible spacing change in tests/othertests/templates.py git-svn-id: http://code.djangoproject.com/svn/django/trunk@1416 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- tests/othertests/templates.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/othertests/templates.py b/tests/othertests/templates.py index 60d3627708..c1dbdde64f 100644 --- a/tests/othertests/templates.py +++ b/tests/othertests/templates.py @@ -244,7 +244,8 @@ TEMPLATE_TESTS = { are you gentlemen. - """ ), + """), + # simple translation of a string delimited by ' 'i18n01': ("{% load i18n %}{% trans 'xxxyyyxxx' %}", {}, "xxxyyyxxx"), From baba996254ecfe0ba2fa49e5d8b6b177b20869fe Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 02:18:37 +0000 Subject: [PATCH 06/13] Added translation strings to django/contrib/admin/views/decorators.py. Taken from new-admin git-svn-id: http://code.djangoproject.com/svn/django/trunk@1418 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/admin/views/decorators.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/django/contrib/admin/views/decorators.py b/django/contrib/admin/views/decorators.py index 44e1234ce4..852057bf53 100644 --- a/django/contrib/admin/views/decorators.py +++ b/django/contrib/admin/views/decorators.py @@ -19,7 +19,7 @@ def _display_login_form(request, error_message=''): else: post_data = _encode_post_data({}) return render_to_response('admin/login', { - 'title': 'Log in', + 'title': _('Log in'), 'app_path': request.path, 'post_data': post_data, 'error_message': error_message @@ -53,15 +53,14 @@ def staff_member_required(view_func): # If this isn't already the login page, display it. if not request.POST.has_key(LOGIN_FORM_KEY): 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. Don't worry: Your submission has been saved.") else: message = "" return _display_login_form(request, message) # Check that the user accepts cookies. if not request.session.test_cookie_worked(): - message = "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again." + message = _("Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again.") return _display_login_form(request, message) # Check the password. @@ -75,9 +74,9 @@ def staff_member_required(view_func): try: user = users.get_object(email__exact=username) except users.UserDoesNotExist: - message = "Usernames cannot contain the '@' character." + message = _("Usernames cannot contain the '@' character.") else: - message = "Your e-mail address is not your username. Try '%s' instead." % user.username + message = _("Your e-mail address is not your username. Try '%s' instead.") % user.username return _display_login_form(request, message) # The user data is correct; log in the user in and continue. From c60e323e5d320bfdefaf89592feb681b32b384fa Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 02:26:08 +0000 Subject: [PATCH 07/13] new-admin and trunk: Normalized spacing differences in bin/validate.py between trunk and new-admin git-svn-id: http://code.djangoproject.com/svn/django/trunk@1420 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/bin/validate.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/django/bin/validate.py b/django/bin/validate.py index f0c37d01cb..220c173edc 100644 --- a/django/bin/validate.py +++ b/django/bin/validate.py @@ -13,19 +13,27 @@ def validate_class(klass): # Fields. for f in opts.fields: if isinstance(f, meta.ManyToManyField): - assert isinstance(f.rel, meta.ManyToMany), "ManyToManyField %s should have 'rel' set to a ManyToMany instance." % f.name + assert isinstance(f.rel, meta.ManyToMany), \ + "ManyToManyField %s should have 'rel' set to a ManyToMany instance." % f.name # Inline related objects. for rel_opts, rel_field in opts.get_inline_related_objects(): - assert len([f for f in rel_opts.fields if f.core]) > 0, "At least one field in %s should have core=True, because it's being edited inline by %s." % (rel_opts.object_name, opts.object_name) + assert len([f for f in rel_opts.fields if f.core]) > 0, \ + "At least one field in %s should have core=True, because it's being edited inline by %s." % \ + (rel_opts.object_name, opts.object_name) # All related objects. related_apps_seen = [] for rel_opts, rel_field in opts.get_all_related_objects(): if rel_opts in related_apps_seen: - assert rel_field.rel.related_name is not None, "Relationship in field %s.%s needs to set 'related_name' because more than one %s object is referenced in %s." % (rel_opts.object_name, rel_field.name, opts.object_name, rel_opts.object_name) + assert rel_field.rel.related_name is not None, \ + "Relationship in field %s.%s needs to set 'related_name' because more than one" \ + " %s object is referenced in %s." % \ + (rel_opts.object_name, rel_field.name, opts.object_name, rel_opts.object_name) related_apps_seen.append(rel_opts) # Etc. if opts.admin is not None: - assert opts.admin.ordering or opts.ordering, "%s needs to set 'ordering' on either its 'admin' or its model, because it has 'admin' set." % opts.object_name + assert opts.admin.ordering or opts.ordering, \ + "%s needs to set 'ordering' on either its 'admin' or its model," \ + " because it has 'admin' set." % opts.object_name if __name__ == "__main__": import sys From 9898c4ae02e455896c6e53a10891dc1b3a334a80 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 02:32:37 +0000 Subject: [PATCH 08/13] Added translation strings to core/formfields.py. Taken from new-admin. git-svn-id: http://code.djangoproject.com/svn/django/trunk@1422 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/formfields.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/django/core/formfields.py b/django/core/formfields.py index fae239987a..78fd044815 100644 --- a/django/core/formfields.py +++ b/django/core/formfields.py @@ -2,6 +2,7 @@ from django.core import validators from django.core.exceptions import PermissionDenied from django.utils.html import escape from django.conf.settings import DEFAULT_CHARSET +from django.utils.translation import gettext_lazy, ngettext FORM_FIELD_ID_PREFIX = 'id_' @@ -23,7 +24,7 @@ class Manipulator: for field in self.fields: if field.field_name == field_name: return field - raise KeyError, "Field %s not found" % field_name + raise KeyError, "Field %s not found\n%s" % (field_name, repr(self.fields)) def __delitem__(self, field_name): "Deletes the field with the given field name; raises KeyError on failure" @@ -55,7 +56,7 @@ class Manipulator: errors = {} for field in self.fields: if field.is_required and not new_data.get(field.field_name, False): - errors.setdefault(field.field_name, []).append('This field is required.') + errors.setdefault(field.field_name, []).append(gettext_lazy('This field is required.')) continue try: validator_list = field.validator_list @@ -237,11 +238,12 @@ class TextField(FormField): def isValidLength(self, data, form): if data and self.maxlength and len(data.decode(DEFAULT_CHARSET)) > self.maxlength: - raise validators.ValidationError, "Ensure your text is less than %s characters." % self.maxlength + raise validators.ValidationError, ngettext("Ensure your text is less than %s character.", + "Ensure your text is less than %s characters.", self.maxlength) % self.maxlength def hasNoNewlines(self, data, form): if data and '\n' in data: - raise validators.ValidationError, "Line breaks are not allowed here." + raise validators.ValidationError, _("Line breaks are not allowed here.") def render(self, data): if data is None: @@ -334,7 +336,7 @@ class SelectField(FormField): str_data = str(data) str_choices = [str(item[0]) for item in self.choices] if str_data not in str_choices: - raise validators.ValidationError, "Select a valid choice; '%s' is not in %s." % (str_data, str_choices) + raise validators.ValidationError, _("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data': str_data, 'choices': str_choices} class NullSelectField(SelectField): "This SelectField converts blank fields to None" @@ -403,7 +405,7 @@ class RadioSelectField(FormField): str_data = str(data) str_choices = [str(item[0]) for item in self.choices] if str_data not in str_choices: - raise validators.ValidationError, "Select a valid choice; '%s' is not in %s." % (str_data, str_choices) + raise validators.ValidationError, _("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data':str_data, 'choices':str_choices} class NullBooleanField(SelectField): "This SelectField provides 'Yes', 'No' and 'Unknown', mapping results to True, False or None" @@ -441,7 +443,7 @@ class SelectMultipleField(SelectField): str_choices = [str(item[0]) for item in self.choices] for val in map(str, field_data): if val not in str_choices: - raise validators.ValidationError, "Select a valid choice; '%s' is not in %s." % (val, str_choices) + raise validators.ValidationError, _("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data':val, 'choices':str_choices} def html2python(data): if data is None: @@ -497,7 +499,7 @@ class FileUploadField(FormField): def isNonEmptyFile(self, field_data, all_data): if not field_data['content']: - raise validators.CriticalValidationError, "The submitted file is empty." + raise validators.CriticalValidationError, _("The submitted file is empty.") def render(self, data): return '' % \ @@ -549,7 +551,7 @@ class SmallIntegerField(IntegerField): def isSmallInteger(self, field_data, all_data): if not -32768 <= int(field_data) <= 32767: - 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): def __init__(self, field_name, length=10, maxlength=None, is_required=False, validator_list=[]): @@ -558,7 +560,7 @@ class PositiveIntegerField(IntegerField): def isPositive(self, field_data, all_data): if int(field_data) < 0: - raise validators.CriticalValidationError, "Enter a positive number." + raise validators.CriticalValidationError, _("Enter a positive number.") class PositiveSmallIntegerField(IntegerField): def __init__(self, field_name, length=5, maxlength=None, is_required=False, validator_list=[]): @@ -567,7 +569,7 @@ class PositiveSmallIntegerField(IntegerField): def isPositiveSmall(self, field_data, all_data): if not 0 <= int(field_data) <= 32767: - 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): def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=[]): From 807b406859653f1737865276a2bb796ab3809453 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 02:37:57 +0000 Subject: [PATCH 09/13] Added translation strings to django/core/meta/fields.py. Taken from new-admin. git-svn-id: http://code.djangoproject.com/svn/django/trunk@1423 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/core/meta/fields.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/django/core/meta/fields.py b/django/core/meta/fields.py index 3ae9587579..299348e629 100644 --- a/django/core/meta/fields.py +++ b/django/core/meta/fields.py @@ -3,7 +3,7 @@ from django.core import formfields, validators from django.core.exceptions import ObjectDoesNotExist from django.utils.functional import curry, lazy from django.utils.text import capfirst -from django.utils.translation import gettext_lazy +from django.utils.translation import gettext_lazy, ngettext import datetime, os # Random entropy string used by "default" param. @@ -43,7 +43,7 @@ def manipulator_valid_rel_key(f, self, field_data, all_data): try: mod.get_object(pk=field_data) except ObjectDoesNotExist: - raise validators.ValidationError, "Please enter a valid %s." % f.verbose_name + raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name def manipulator_validator_unique(f, opts, self, field_data, all_data): "Validates that the value is unique for this field." @@ -57,7 +57,7 @@ def manipulator_validator_unique(f, opts, self, field_data, all_data): return if hasattr(self, 'original_object') and getattr(self.original_object, opts.pk.attname) == getattr(old_obj, opts.pk.attname): return - raise validators.ValidationError, "%s with this %s already exists." % (capfirst(opts.verbose_name), f.verbose_name) + raise validators.ValidationError, _("%(optname)s with this %(fieldname)s already exists.") % {'optname': capfirst(opts.verbose_name), 'fieldname': f.verbose_name} # A guide to Field parameters: @@ -264,7 +264,7 @@ class Field(object): core_field_names.extend(f.get_manipulator_field_names(name_prefix)) # Now, if there are any, add the validator to this FormField. if core_field_names: - params['validator_list'].append(validators.RequiredIfOtherFieldsGiven(core_field_names, "This field is required.")) + params['validator_list'].append(validators.RequiredIfOtherFieldsGiven(core_field_names, gettext_lazy("This field is required."))) # BooleanFields (CheckboxFields) are a special case. They don't take # is_required or validator_list. @@ -418,7 +418,7 @@ class FileField(Field): self.always_test = True def __call__(self, field_data, all_data): if not all_data.get(self.other_file_field_name, False): - c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, "This field is required.") + c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, gettext_lazy("This field is required.")) c(field_data, all_data) # First, get the core fields, if any. core_field_names = [] @@ -429,7 +429,7 @@ class FileField(Field): if core_field_names: field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name)) else: - v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, "This field is required.") + v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, gettext_lazy("This field is required.")) v.always_test = True field_list[0].validator_list.append(v) field_list[0].is_required = field_list[1].is_required = False @@ -438,7 +438,7 @@ class FileField(Field): def isWithinMediaRoot(field_data, all_data): f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data)) if not f.startswith(os.path.normpath(settings.MEDIA_ROOT)): - raise validators.ValidationError, "Enter a valid filename." + raise validators.ValidationError, _("Enter a valid filename.") field_list[1].validator_list.append(isWithinMediaRoot) return field_list @@ -682,10 +682,11 @@ class ManyToManyField(Field): objects = mod.get_in_bulk(pks) if len(objects) != len(pks): badkeys = [k for k in pks if k not in objects] - raise validators.ValidationError, "Please enter valid %s IDs. The value%s %r %s invalid." % \ - (self.verbose_name, len(badkeys) > 1 and 's' or '', - len(badkeys) == 1 and badkeys[0] or tuple(badkeys), - len(badkeys) == 1 and "is" or "are") + raise validators.ValidationError, ngettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.", + "Please enter valid %(self)s IDs. The values %(value)r are invalid.", len(badkeys)) % { + 'self': self.verbose_name, + 'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys), + } class OneToOneField(IntegerField): def __init__(self, to, to_field=None, **kwargs): From fe15c01a1797bfdcc456196b9a556b98089e3cff Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 03:15:09 +0000 Subject: [PATCH 10/13] Fixed typo in docs/model-api.txt git-svn-id: http://code.djangoproject.com/svn/django/trunk@1426 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- docs/model-api.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/model-api.txt b/docs/model-api.txt index 344f34ef2c..3245b2a78a 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -909,7 +909,7 @@ object, which takes the following parameters. All are optional. list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff'), list_filter = ('is_staff', 'is_superuser'), - This results in a admin that looks like: + The above code results in an admin that looks like this: .. image:: http://media.djangoproject.com/img/doc/users_changelist.png From 3ddf250f91dd3fd03aba235fca3294fdd651bea5 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 04:25:50 +0000 Subject: [PATCH 11/13] Fixed #830 -- Added an AUTHORS file, which is inevitably incomplete git-svn-id: http://code.djangoproject.com/svn/django/trunk@1428 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 AUTHORS diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000000..af8c723f02 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,96 @@ +Django was originally created in late 2003 at World Online, the Web division +of the Lawrence Journal-World newspaper in Lawrence, Kansas. + + +The PRIMARY AUTHORS are (and/or have been): + +Adrian Holovaty , who originally created Django with +Simon and currently oversees things with Jacob. + +Simon Willison , who originally created Django with +Adrian during his year-long internship/placement at World Online and currently +helps from the sidelines. + +Jacob Kaplan-Moss , who joined the team shortly +before Simon departed and currently oversees things with Adrian. + +Wilson Miner , who designed Django's admin +interface, pretty error pages, official Web site (djangoproject.com) and has +made many other contributions. + +Georg "Hugo" Bauer , who added +internationalization support, manages i18n contributions and has made a ton +of excellent tweaks, feature additions and bug fixes. + +Robert Wittams , who majorly refactored the Django +admin application to allow for easier reuse and has made a ton of excellent +tweaks, feature additions and bug fixes. + + +And here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS -- +people who have submitted patches, reported bugs, added translations, helped +answer newbie questions, and generally made Django that much better: + + Andreas + David Ascher + James Bennett + Paul Bissex + Simon Blanchard + Andrew Brehaut + Antonio Cavedoni + Amit Chakradeo + Matt Croydon + Jeremy Dunck + Clint Ecker + Baishampayan Ghose + Espen Grindhaug + Brant Harris + Ian Holsman + Kieran Holland + Robert Rock Howard + Jason Huggins + Michael Josephson + Garth Kidd + Sune Kirkeby + lakin.wecker@gmail.com + Stuart Langridge + Eugene Lazutkin + Martin Maney + Maniac + Manuzhai + Petar Marić + mark@junklight.com + mattycakes@gmail.com + Jason McBrayer + mmarshall + Eric Moritz + Robin Munn + nesh + Sam Newman + Luke Plant + phaedo + plisk + David Schein + sopel + Radek Švarz + Aaron Swartz + Tom Tobin + Joe Topjian + Amit Upadhyay + Milton Waddams + Rachel Willmer + wojtek + + +A big THANK YOU goes to: + + Rob Curley and Ralph Gage for letting us open-source Django. + + Frank Wiles for making excellent arguments for open-sourcing, and for + his sage sysadmin advice. + + Ian Bicking for convincing Adrian to ditch code generation. + + Mark Pilgrim for diveintopython.org. + + Guido van Rossum for creating Python. From 69f884090056b6a0ac24591d10c9ca1a41d3280d Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Fri, 25 Nov 2005 04:27:50 +0000 Subject: [PATCH 12/13] Fixed #882 -- Fixed bug when doing django-admin.py sqlclear with SQLite. Thanks, ye7cakf02 git-svn-id: http://code.djangoproject.com/svn/django/trunk@1429 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 1 + django/core/management.py | 1 + 2 files changed, 2 insertions(+) diff --git a/AUTHORS b/AUTHORS index af8c723f02..fe6e68f177 100644 --- a/AUTHORS +++ b/AUTHORS @@ -80,6 +80,7 @@ answer newbie questions, and generally made Django that much better: Milton Waddams Rachel Willmer wojtek + ye7cakf02@sneakemail.com A big THANK YOU goes to: diff --git a/django/core/management.py b/django/core/management.py index 205cdec3e5..efc1d9f42c 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -187,6 +187,7 @@ def get_sql_delete(mod): # Close database connection explicitly, in case this output is being piped # directly into a database client, to avoid locking issues. + cursor.close() db.db.close() return output[::-1] # Reverse it, to deal with table dependencies. From 4fe5c9b7ee09dc25921918a6dbb7605edb374bc9 Mon Sep 17 00:00:00 2001 From: Jacob Kaplan-Moss Date: Fri, 25 Nov 2005 15:00:14 +0000 Subject: [PATCH 13/13] Fixed #906 - thanks, Esaj git-svn-id: http://code.djangoproject.com/svn/django/trunk@1432 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- .../admin/templates/registration/password_reset_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django/contrib/admin/templates/registration/password_reset_form.html b/django/contrib/admin/templates/registration/password_reset_form.html index 9a8ac1a6d6..1b6a2c9a17 100644 --- a/django/contrib/admin/templates/registration/password_reset_form.html +++ b/django/contrib/admin/templates/registration/password_reset_form.html @@ -7,7 +7,7 @@ {% block content %} -

{% trans "Password reset") %}

+

{% trans "Password reset" %}

{% trans "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." %}