mirror of
https://github.com/django/django.git
synced 2025-07-06 10:49:17 +00:00
queryset-refactor: Merged from trunk up to [7098] (because I need the last
commit on this branch). git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7099 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
accc20d799
commit
748e1bdf42
@ -47,7 +47,7 @@ LANGUAGES = (
|
|||||||
('el', gettext_noop('Greek')),
|
('el', gettext_noop('Greek')),
|
||||||
('en', gettext_noop('English')),
|
('en', gettext_noop('English')),
|
||||||
('es', gettext_noop('Spanish')),
|
('es', gettext_noop('Spanish')),
|
||||||
('es_AR', gettext_noop('Argentinean Spanish')),
|
('es-ar', gettext_noop('Argentinean Spanish')),
|
||||||
('fa', gettext_noop('Persian')),
|
('fa', gettext_noop('Persian')),
|
||||||
('fi', gettext_noop('Finnish')),
|
('fi', gettext_noop('Finnish')),
|
||||||
('fr', gettext_noop('French')),
|
('fr', gettext_noop('French')),
|
||||||
|
Binary file not shown.
@ -153,6 +153,7 @@ msgstr "Sgorau Carma"
|
|||||||
|
|
||||||
#: contrib/comments/models.py:242
|
#: contrib/comments/models.py:242
|
||||||
#, python-format
|
#, python-format
|
||||||
|
#, fuzzy
|
||||||
msgid "%(score)d rating by %(user)s"
|
msgid "%(score)d rating by %(user)s"
|
||||||
msgstr "%(score)d"
|
msgstr "%(score)d"
|
||||||
|
|
||||||
|
Binary file not shown.
@ -971,6 +971,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/delete_confirmation.html:21
|
#: contrib/admin/templates/admin/delete_confirmation.html:21
|
||||||
#, python-format
|
#, python-format
|
||||||
|
#,fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
|
"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
|
||||||
"All of the following related items will be deleted:"
|
"All of the following related items will be deleted:"
|
||||||
@ -2181,6 +2182,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: core/validators.py:256
|
#: core/validators.py:256
|
||||||
#, python-format
|
#, python-format
|
||||||
|
#,fuzzy
|
||||||
msgid "Watch your mouth! The word %s is not allowed here."
|
msgid "Watch your mouth! The word %s is not allowed here."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"ನಾಲಿಗೆ ಬಿಗಿ ಹಿಡಿಯಿರಿ! %s "
|
"ನಾಲಿಗೆ ಬಿಗಿ ಹಿಡಿಯಿರಿ! %s "
|
||||||
@ -2486,6 +2488,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: forms/__init__.py:381
|
#: forms/__init__.py:381
|
||||||
#, python-format
|
#, python-format
|
||||||
|
#,fuzzy
|
||||||
msgid "Ensure your text is less than %s character."
|
msgid "Ensure your text is less than %s character."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"ನಿಮ್ಮ ಗದ್ಯ %s ಅಕ್ಷರಕ್ಕಿಂತ "
|
"ನಿಮ್ಮ ಗದ್ಯ %s ಅಕ್ಷರಕ್ಕಿಂತ "
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -851,6 +851,7 @@ msgstr "Remover"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/delete_confirmation.html:14
|
#: contrib/admin/templates/admin/delete_confirmation.html:14
|
||||||
#, python-format
|
#, python-format
|
||||||
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
|
"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
|
||||||
"related objects, but your account doesn't have permission to delete the "
|
"related objects, but your account doesn't have permission to delete the "
|
||||||
@ -1933,6 +1934,7 @@ msgstr[1] "Por favor introduza um número décimal com um máximo de %s digitos.
|
|||||||
|
|
||||||
#: core/validators.py:381
|
#: core/validators.py:381
|
||||||
#, python-format
|
#, python-format
|
||||||
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
"Please enter a valid decimal number with a whole part of at most %s digit."
|
"Please enter a valid decimal number with a whole part of at most %s digit."
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
@ -1973,6 +1975,7 @@ msgstr "Não foi possível extrair nada de %s."
|
|||||||
|
|
||||||
#: core/validators.py:466
|
#: core/validators.py:466
|
||||||
#, python-format
|
#, python-format
|
||||||
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
||||||
msgstr "O URL %(url)s devolveu um tipo de conteúdo inválido no header: '%s(contenttype)s'."
|
msgstr "O URL %(url)s devolveu um tipo de conteúdo inválido no header: '%s(contenttype)s'."
|
||||||
|
@ -24,7 +24,8 @@ class ModelBase(type):
|
|||||||
def __new__(cls, name, bases, attrs):
|
def __new__(cls, name, bases, attrs):
|
||||||
# If this isn't a subclass of Model, don't do anything special.
|
# If this isn't a subclass of Model, don't do anything special.
|
||||||
try:
|
try:
|
||||||
if not filter(lambda b: issubclass(b, Model), bases):
|
parents = [b for b in bases if issubclass(b, Model)]
|
||||||
|
if not parents:
|
||||||
return super(ModelBase, cls).__new__(cls, name, bases, attrs)
|
return super(ModelBase, cls).__new__(cls, name, bases, attrs)
|
||||||
except NameError:
|
except NameError:
|
||||||
# 'Model' isn't defined yet, meaning we're looking at Django's own
|
# 'Model' isn't defined yet, meaning we're looking at Django's own
|
||||||
@ -39,9 +40,8 @@ class ModelBase(type):
|
|||||||
types.ClassType('MultipleObjectsReturned', (MultipleObjectsReturned, ), {}))
|
types.ClassType('MultipleObjectsReturned', (MultipleObjectsReturned, ), {}))
|
||||||
|
|
||||||
# Build complete list of parents
|
# Build complete list of parents
|
||||||
for base in bases:
|
for base in parents:
|
||||||
# TODO: Checking for the presence of '_meta' is hackish.
|
if base is not Model:
|
||||||
if '_meta' in dir(base):
|
|
||||||
new_class._meta.parents.append(base)
|
new_class._meta.parents.append(base)
|
||||||
new_class._meta.parents.extend(base._meta.parents)
|
new_class._meta.parents.extend(base._meta.parents)
|
||||||
|
|
||||||
@ -79,6 +79,35 @@ class ModelBase(type):
|
|||||||
# registered version.
|
# registered version.
|
||||||
return get_model(new_class._meta.app_label, name, False)
|
return get_model(new_class._meta.app_label, name, False)
|
||||||
|
|
||||||
|
def add_to_class(cls, name, value):
|
||||||
|
if name == 'Admin':
|
||||||
|
assert type(value) == types.ClassType, "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value))
|
||||||
|
value = AdminOptions(**dict([(k, v) for k, v in value.__dict__.items() if not k.startswith('_')]))
|
||||||
|
if hasattr(value, 'contribute_to_class'):
|
||||||
|
value.contribute_to_class(cls, name)
|
||||||
|
else:
|
||||||
|
setattr(cls, name, value)
|
||||||
|
|
||||||
|
def _prepare(cls):
|
||||||
|
# Creates some methods once self._meta has been populated.
|
||||||
|
opts = cls._meta
|
||||||
|
opts._prepare(cls)
|
||||||
|
|
||||||
|
if opts.order_with_respect_to:
|
||||||
|
cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
|
||||||
|
cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
|
||||||
|
setattr(opts.order_with_respect_to.rel.to, 'get_%s_order' % cls.__name__.lower(), curry(method_get_order, cls))
|
||||||
|
setattr(opts.order_with_respect_to.rel.to, 'set_%s_order' % cls.__name__.lower(), curry(method_set_order, cls))
|
||||||
|
|
||||||
|
# Give the class a docstring -- its definition.
|
||||||
|
if cls.__doc__ is None:
|
||||||
|
cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join([f.attname for f in opts.fields]))
|
||||||
|
|
||||||
|
if hasattr(cls, 'get_absolute_url'):
|
||||||
|
cls.get_absolute_url = curry(get_absolute_url, opts, cls.get_absolute_url)
|
||||||
|
|
||||||
|
dispatcher.send(signal=signals.class_prepared, sender=cls)
|
||||||
|
|
||||||
class Model(object):
|
class Model(object):
|
||||||
__metaclass__ = ModelBase
|
__metaclass__ = ModelBase
|
||||||
|
|
||||||
@ -176,38 +205,6 @@ class Model(object):
|
|||||||
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
|
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
|
||||||
dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self)
|
dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self)
|
||||||
|
|
||||||
def add_to_class(cls, name, value):
|
|
||||||
if name == 'Admin':
|
|
||||||
assert type(value) == types.ClassType, "%r attribute of %s model must be a class, not a %s object" % (name, cls.__name__, type(value))
|
|
||||||
value = AdminOptions(**dict([(k, v) for k, v in value.__dict__.items() if not k.startswith('_')]))
|
|
||||||
if hasattr(value, 'contribute_to_class'):
|
|
||||||
value.contribute_to_class(cls, name)
|
|
||||||
else:
|
|
||||||
setattr(cls, name, value)
|
|
||||||
add_to_class = classmethod(add_to_class)
|
|
||||||
|
|
||||||
def _prepare(cls):
|
|
||||||
# Creates some methods once self._meta has been populated.
|
|
||||||
opts = cls._meta
|
|
||||||
opts._prepare(cls)
|
|
||||||
|
|
||||||
if opts.order_with_respect_to:
|
|
||||||
cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
|
|
||||||
cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
|
|
||||||
setattr(opts.order_with_respect_to.rel.to, 'get_%s_order' % cls.__name__.lower(), curry(method_get_order, cls))
|
|
||||||
setattr(opts.order_with_respect_to.rel.to, 'set_%s_order' % cls.__name__.lower(), curry(method_set_order, cls))
|
|
||||||
|
|
||||||
# Give the class a docstring -- its definition.
|
|
||||||
if cls.__doc__ is None:
|
|
||||||
cls.__doc__ = "%s(%s)" % (cls.__name__, ", ".join([f.attname for f in opts.fields]))
|
|
||||||
|
|
||||||
if hasattr(cls, 'get_absolute_url'):
|
|
||||||
cls.get_absolute_url = curry(get_absolute_url, opts, cls.get_absolute_url)
|
|
||||||
|
|
||||||
dispatcher.send(signal=signals.class_prepared, sender=cls)
|
|
||||||
|
|
||||||
_prepare = classmethod(_prepare)
|
|
||||||
|
|
||||||
def save(self, raw=False):
|
def save(self, raw=False):
|
||||||
dispatcher.send(signal=signals.pre_save, sender=self.__class__,
|
dispatcher.send(signal=signals.pre_save, sender=self.__class__,
|
||||||
instance=self, raw=raw)
|
instance=self, raw=raw)
|
||||||
|
@ -42,7 +42,10 @@ accept_language_re = re.compile(r'''
|
|||||||
''', re.VERBOSE)
|
''', re.VERBOSE)
|
||||||
|
|
||||||
def to_locale(language, to_lower=False):
|
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). If 'to_lower' is
|
||||||
|
True, the last component is lower-cased (en_us).
|
||||||
|
"""
|
||||||
p = language.find('-')
|
p = language.find('-')
|
||||||
if p >= 0:
|
if p >= 0:
|
||||||
if to_lower:
|
if to_lower:
|
||||||
@ -357,19 +360,20 @@ def get_language_from_request(request):
|
|||||||
return lang_code
|
return lang_code
|
||||||
|
|
||||||
accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
|
accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
|
||||||
for lang, unused in parse_accept_lang_header(accept):
|
for accept_lang, unused in parse_accept_lang_header(accept):
|
||||||
if lang == '*':
|
if accept_lang == '*':
|
||||||
break
|
break
|
||||||
|
|
||||||
# We have a very restricted form for our language files (no encoding
|
# We have a very restricted form for our language files (no encoding
|
||||||
# specifier, since they all must be UTF-8 and only one possible
|
# specifier, since they all must be UTF-8 and only one possible
|
||||||
# language each time. So we avoid the overhead of gettext.find() and
|
# language each time. So we avoid the overhead of gettext.find() and
|
||||||
# look up the MO file manually.
|
# work out the MO file manually.
|
||||||
|
|
||||||
normalized = locale.locale_alias.get(to_locale(lang, True))
|
# 'normalized' is the root name of the locale in POSIX format (which is
|
||||||
|
# the format used for the directories holding the MO files).
|
||||||
|
normalized = locale.locale_alias.get(to_locale(accept_lang, True))
|
||||||
if not normalized:
|
if not normalized:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Remove the default encoding from locale_alias
|
# Remove the default encoding from locale_alias
|
||||||
normalized = normalized.split('.')[0]
|
normalized = normalized.split('.')[0]
|
||||||
|
|
||||||
@ -378,10 +382,11 @@ def get_language_from_request(request):
|
|||||||
# need to check again.
|
# need to check again.
|
||||||
return _accepted[normalized]
|
return _accepted[normalized]
|
||||||
|
|
||||||
for lang in (normalized, normalized.split('_')[0]):
|
for lang, dirname in ((accept_lang, normalized),
|
||||||
|
(accept_lang.split('-')[0], normalized.split('_')[0])):
|
||||||
if lang not in supported:
|
if lang not in supported:
|
||||||
continue
|
continue
|
||||||
langfile = os.path.join(globalpath, lang, 'LC_MESSAGES',
|
langfile = os.path.join(globalpath, dirname, 'LC_MESSAGES',
|
||||||
'django.mo')
|
'django.mo')
|
||||||
if os.path.exists(langfile):
|
if os.path.exists(langfile):
|
||||||
_accepted[normalized] = lang
|
_accepted[normalized] = lang
|
||||||
|
@ -2,6 +2,11 @@ tests = """
|
|||||||
>>> from django.utils.translation.trans_real import parse_accept_lang_header
|
>>> from django.utils.translation.trans_real import parse_accept_lang_header
|
||||||
>>> p = parse_accept_lang_header
|
>>> p = parse_accept_lang_header
|
||||||
|
|
||||||
|
#
|
||||||
|
# Testing HTTP header parsing. First, we test that we can parse the values
|
||||||
|
# according to the spec (and that we extract all the pieces in the right order).
|
||||||
|
#
|
||||||
|
|
||||||
Good headers.
|
Good headers.
|
||||||
>>> p('de')
|
>>> p('de')
|
||||||
[('de', 1.0)]
|
[('de', 1.0)]
|
||||||
@ -54,4 +59,44 @@ Bad headers; should always return [].
|
|||||||
>>> p('')
|
>>> p('')
|
||||||
[]
|
[]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Now test that we parse a literal HTTP header correctly.
|
||||||
|
#
|
||||||
|
|
||||||
|
>>> from django.utils.translation.trans_real import get_language_from_request
|
||||||
|
>>> g = get_language_from_request
|
||||||
|
>>> from django.http import HttpRequest
|
||||||
|
>>> r = HttpRequest
|
||||||
|
>>> r.COOKIES = {}
|
||||||
|
|
||||||
|
These tests assumes the es, es_AR, pt and pt_BR translations exit in the Django
|
||||||
|
source tree.
|
||||||
|
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'pt-br'}
|
||||||
|
>>> g(r)
|
||||||
|
'pt-br'
|
||||||
|
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'pt'}
|
||||||
|
>>> g(r)
|
||||||
|
'pt'
|
||||||
|
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es,de'}
|
||||||
|
>>> g(r)
|
||||||
|
'es'
|
||||||
|
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-ar,de'}
|
||||||
|
>>> g(r)
|
||||||
|
'es-ar'
|
||||||
|
|
||||||
|
This test assumes there won't be a Django translation to a US variation
|
||||||
|
of the Spanish language, a safe assumption. When the user sets it
|
||||||
|
as the preferred language, the main 'es' translation should be selected
|
||||||
|
instead.
|
||||||
|
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'es-us'}
|
||||||
|
>>> g(r)
|
||||||
|
'es'
|
||||||
|
|
||||||
|
This tests the following scenario: there isn't a main language (zh)
|
||||||
|
translation of Django but there is a translation to variation (zh_CN)
|
||||||
|
the user sets zh-cn as the preferred language, it should be selected by
|
||||||
|
Django without falling back nor ignoring it.
|
||||||
|
>>> r.META = {'HTTP_ACCEPT_LANGUAGE': 'zh-cn,de'}
|
||||||
|
>>> g(r)
|
||||||
|
'zh-cn'
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user