1
0
mirror of https://github.com/django/django.git synced 2025-07-05 10:19:20 +00:00

[multi-db] Merge trunk to [3302]

git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@3303 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jason Pellerin 2006-07-09 17:11:34 +00:00
parent 60947322a5
commit ef1a9eeb64
42 changed files with 406 additions and 227 deletions

View File

@ -54,6 +54,7 @@ answer newbie questions, and generally made Django that much better:
Jason Davies (Esaj) <http://www.jasondavies.com/> Jason Davies (Esaj) <http://www.jasondavies.com/>
Alex Dedul Alex Dedul
deric@monowerks.com deric@monowerks.com
dne@mayonnaise.net
Jeremy Dunck <http://dunck.us/> Jeremy Dunck <http://dunck.us/>
Clint Ecker Clint Ecker
gandalf@owca.info gandalf@owca.info

View File

@ -116,7 +116,7 @@ class UserSettingsHolder(object):
""" """
Holder for user configured settings. Holder for user configured settings.
""" """
# SETTINGS_MODULE does not really make sense in the manually configured # SETTINGS_MODULE doesn't make much sense in the manually configured
# (standalone) case. # (standalone) case.
SETTINGS_MODULE = None SETTINGS_MODULE = None
@ -135,6 +135,13 @@ class UserSettingsHolder(object):
settings = LazySettings() settings = LazySettings()
# install the translation machinery so that it is available # This function replaces itself with django.utils.translation.gettext() the
from django.utils import translation # first time it's run. This is necessary because the import of
translation.install() # django.utils.translation requires a working settings module, and loading it
# from within this file would cause a circular import.
def first_time_gettext(*args):
from django.utils.translation import gettext
__builtins__['_'] = gettext
return gettext(*args)
__builtins__['_'] = first_time_gettext

View File

@ -1,7 +1,9 @@
# Default Django settings. Override these with settings in the module # Default Django settings. Override these with settings in the module
# pointed-to by the DJANGO_SETTINGS_MODULE environment variable. # pointed-to by the DJANGO_SETTINGS_MODULE environment variable.
from django.utils.translation import gettext_lazy as _ # This is defined here as a do-nothing function because we can't import
# django.utils.translation -- that module depends on the settings.
gettext_noop = lambda s: s
#################### ####################
# CORE # # CORE #
@ -34,34 +36,34 @@ LANGUAGE_CODE = 'en-us'
# Languages we provide translations for, out of the box. The language name # Languages we provide translations for, out of the box. The language name
# should be the utf-8 encoded local name for the language. # should be the utf-8 encoded local name for the language.
LANGUAGES = ( LANGUAGES = (
('bn', _('Bengali')), ('bn', gettext_noop('Bengali')),
('cs', _('Czech')), ('cs', gettext_noop('Czech')),
('cy', _('Welsh')), ('cy', gettext_noop('Welsh')),
('da', _('Danish')), ('da', gettext_noop('Danish')),
('de', _('German')), ('de', gettext_noop('German')),
('el', _('Greek')), ('el', gettext_noop('Greek')),
('en', _('English')), ('en', gettext_noop('English')),
('es', _('Spanish')), ('es', gettext_noop('Spanish')),
('es_AR', _('Argentinean Spanish')), ('es_AR', gettext_noop('Argentinean Spanish')),
('fr', _('French')), ('fr', gettext_noop('French')),
('gl', _('Galician')), ('gl', gettext_noop('Galician')),
('hu', _('Hungarian')), ('hu', gettext_noop('Hungarian')),
('he', _('Hebrew')), ('he', gettext_noop('Hebrew')),
('is', _('Icelandic')), ('is', gettext_noop('Icelandic')),
('it', _('Italian')), ('it', gettext_noop('Italian')),
('ja', _('Japanese')), ('ja', gettext_noop('Japanese')),
('nl', _('Dutch')), ('nl', gettext_noop('Dutch')),
('no', _('Norwegian')), ('no', gettext_noop('Norwegian')),
('pt-br', _('Brazilian')), ('pt-br', gettext_noop('Brazilian')),
('ro', _('Romanian')), ('ro', gettext_noop('Romanian')),
('ru', _('Russian')), ('ru', gettext_noop('Russian')),
('sk', _('Slovak')), ('sk', gettext_noop('Slovak')),
('sl', _('Slovenian')), ('sl', gettext_noop('Slovenian')),
('sr', _('Serbian')), ('sr', gettext_noop('Serbian')),
('sv', _('Swedish')), ('sv', gettext_noop('Swedish')),
('uk', _('Ukrainian')), ('uk', gettext_noop('Ukrainian')),
('zh-cn', _('Simplified Chinese')), ('zh-cn', gettext_noop('Simplified Chinese')),
('zh-tw', _('Traditional Chinese')), ('zh-tw', gettext_noop('Traditional Chinese')),
) )
# Languages using BiDi (right-to-left) layout # Languages using BiDi (right-to-left) layout

View File

@ -514,7 +514,7 @@ msgstr "Supprimé %s."
#: contrib/admin/views/main.py:343 #: contrib/admin/views/main.py:343
msgid "No fields changed." msgid "No fields changed."
msgstr "Aucun champs modifié." msgstr "Aucun champ modifié."
#: contrib/admin/views/main.py:346 #: contrib/admin/views/main.py:346
#, python-format #, python-format
@ -1906,7 +1906,7 @@ msgstr ""
#: db/models/fields/__init__.py:40 #: db/models/fields/__init__.py:40
#, python-format #, python-format
msgid "%(optname)s with this %(fieldname)s already exists." msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "%(optname)s avec le champs %(fieldname)s existe déjà." msgstr "%(optname)s avec le champ %(fieldname)s existe déjà."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 #: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553 #: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: django\n" "Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-05-16 10:11+0200\n" "POT-Creation-Date: 2006-05-16 10:11+0200\n"
"PO-Revision-Date: 2005-12-20 10:48+0100\n" "PO-Revision-Date: 2006-07-03 14:06+0200\n"
"Last-Translator: Afonso Fernández Nogueira <fonzzo.django@gmail.com>\n" "Last-Translator: Afonso Fernández Nogueira <fonzzo.django@gmail.com>\n"
"Language-Team: Galego\n" "Language-Team: Galego\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -91,9 +91,8 @@ msgstr ""
"comentario foi borrado\" no canto do seu contido." "comentario foi borrado\" no canto do seu contido."
#: contrib/comments/models.py:91 #: contrib/comments/models.py:91
#, fuzzy
msgid "comments" msgid "comments"
msgstr "comentario" msgstr "comentarios"
#: contrib/comments/models.py:131 contrib/comments/models.py:207 #: contrib/comments/models.py:131 contrib/comments/models.py:207
msgid "Content object" msgid "Content object"
@ -120,21 +119,19 @@ msgstr "nome da persoa"
#: contrib/comments/models.py:171 #: contrib/comments/models.py:171
msgid "ip address" msgid "ip address"
msgstr "Enderezo IP" msgstr "enderezo IP"
#: contrib/comments/models.py:173 #: contrib/comments/models.py:173
msgid "approved by staff" msgid "approved by staff"
msgstr "aprobado polos moderadores" msgstr "aprobado polos moderadores"
#: contrib/comments/models.py:176 #: contrib/comments/models.py:176
#, fuzzy
msgid "free comment" msgid "free comment"
msgstr "Comentario libre" msgstr "comentario libre"
#: contrib/comments/models.py:177 #: contrib/comments/models.py:177
#, fuzzy
msgid "free comments" msgid "free comments"
msgstr "Comentarios libres" msgstr "comentarios libres"
#: contrib/comments/models.py:233 #: contrib/comments/models.py:233
msgid "score" msgid "score"
@ -145,14 +142,12 @@ msgid "score date"
msgstr "data da puntuación" msgstr "data da puntuación"
#: contrib/comments/models.py:237 #: contrib/comments/models.py:237
#, fuzzy
msgid "karma score" msgid "karma score"
msgstr "Puntuación de karma" msgstr "puntos de karma"
#: contrib/comments/models.py:238 #: contrib/comments/models.py:238
#, fuzzy
msgid "karma scores" msgid "karma scores"
msgstr "Puntuacións de karma" msgstr "puntos de karma"
#: contrib/comments/models.py:242 #: contrib/comments/models.py:242
#, python-format #, python-format
@ -175,14 +170,12 @@ msgid "flag date"
msgstr "data da marca" msgstr "data da marca"
#: contrib/comments/models.py:268 #: contrib/comments/models.py:268
#, fuzzy
msgid "user flag" msgid "user flag"
msgstr "Marca de usuario" msgstr "marca de usuario"
#: contrib/comments/models.py:269 #: contrib/comments/models.py:269
#, fuzzy
msgid "user flags" msgid "user flags"
msgstr "Marcas de usuario" msgstr "marcas de usuario"
#: contrib/comments/models.py:273 #: contrib/comments/models.py:273
#, python-format #, python-format
@ -194,19 +187,17 @@ msgid "deletion date"
msgstr "data de borrado" msgstr "data de borrado"
#: contrib/comments/models.py:280 #: contrib/comments/models.py:280
#, fuzzy
msgid "moderator deletion" msgid "moderator deletion"
msgstr "Borrado de moderación" msgstr "borrado de moderador"
#: contrib/comments/models.py:281 #: contrib/comments/models.py:281
#, fuzzy
msgid "moderator deletions" msgid "moderator deletions"
msgstr "Borrados de moderación" msgstr "borrados de moderador"
#: contrib/comments/models.py:285 #: contrib/comments/models.py:285
#, python-format #, python-format
msgid "Moderator deletion by %r" msgid "Moderator deletion by %r"
msgstr "Borrado de moderación por %r" msgstr "Borrado polo moderador %r"
#: contrib/comments/views/karma.py:19 #: contrib/comments/views/karma.py:19
msgid "Anonymous users cannot vote" msgid "Anonymous users cannot vote"
@ -218,7 +209,7 @@ msgstr "ID de comentario non válida"
#: contrib/comments/views/karma.py:25 #: contrib/comments/views/karma.py:25
msgid "No voting for yourself" msgid "No voting for yourself"
msgstr "Non se pode votar a si mesmo" msgstr "Vostede non se pode votar a si mesmo"
#: contrib/comments/views/comments.py:28 #: contrib/comments/views/comments.py:28
msgid "" msgid ""
@ -297,9 +288,8 @@ msgid "Password:"
msgstr "Contrasinal:" msgstr "Contrasinal:"
#: contrib/comments/templates/comments/form.html:6 #: contrib/comments/templates/comments/form.html:6
#, fuzzy
msgid "Forgotten your password?" msgid "Forgotten your password?"
msgstr "Cambiar o contrasinal" msgstr "Esqueceu o contrasinal?"
#: contrib/comments/templates/comments/form.html:8 #: contrib/comments/templates/comments/form.html:8
#: contrib/admin/templates/admin/object_history.html:3 #: contrib/admin/templates/admin/object_history.html:3
@ -320,7 +310,7 @@ msgstr "Cambiar o contrasinal"
#: contrib/admin/templates/admin_doc/index.html:4 #: contrib/admin/templates/admin_doc/index.html:4
#: contrib/admin/templates/admin_doc/model_index.html:5 #: contrib/admin/templates/admin_doc/model_index.html:5
msgid "Log out" msgid "Log out"
msgstr "Saír" msgstr "Rematar sesión"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
msgid "Ratings" msgid "Ratings"
@ -329,33 +319,30 @@ msgstr ""
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Required" msgid "Required"
msgstr "" msgstr "Requirido"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Optional" msgid "Optional"
msgstr "" msgstr "Opcional"
#: contrib/comments/templates/comments/form.html:23 #: contrib/comments/templates/comments/form.html:23
msgid "Post a photo" msgid "Post a photo"
msgstr "" msgstr "Publicar unha foto"
#: contrib/comments/templates/comments/form.html:27 #: contrib/comments/templates/comments/form.html:27
#: contrib/comments/templates/comments/freeform.html:5 #: contrib/comments/templates/comments/freeform.html:5
#, fuzzy
msgid "Comment:" msgid "Comment:"
msgstr "Comentario" msgstr "Comentario:"
#: contrib/comments/templates/comments/form.html:32 #: contrib/comments/templates/comments/form.html:32
#: contrib/comments/templates/comments/freeform.html:9 #: contrib/comments/templates/comments/freeform.html:9
#, fuzzy
msgid "Preview comment" msgid "Preview comment"
msgstr "Comentario libre" msgstr "Previsualizar comentario"
#: contrib/comments/templates/comments/freeform.html:4 #: contrib/comments/templates/comments/freeform.html:4
#, fuzzy
msgid "Your name:" msgid "Your name:"
msgstr "nome de usuario" msgstr "Nome:"
#: contrib/admin/filterspecs.py:40 #: contrib/admin/filterspecs.py:40
#, python-format #, python-format
@ -440,12 +427,13 @@ msgstr "Todas as datas"
msgid "" msgid ""
"Please enter a correct username and password. Note that both fields are case-" "Please enter a correct username and password. Note that both fields are case-"
"sensitive." "sensitive."
msgstr "" msgstr "Insira un nome de usuario e un contrasinal correctos. Teña en conta que "
"nos dous campos se distingue entre maiúsculas e minúsculas."
#: contrib/admin/views/decorators.py:23 #: contrib/admin/views/decorators.py:23
#: contrib/admin/templates/admin/login.html:25 #: contrib/admin/templates/admin/login.html:25
msgid "Log in" msgid "Log in"
msgstr "Entrar" msgstr "Iniciar sesión"
#: contrib/admin/views/decorators.py:61 #: contrib/admin/views/decorators.py:61
msgid "" msgid ""
@ -757,7 +745,7 @@ msgstr "Sentímolo, pero non se atopou a páxina solicitada."
#: contrib/admin/templates/admin/index.html:17 #: contrib/admin/templates/admin/index.html:17
#, python-format #, python-format
msgid "Models available in the %(name)s application." msgid "Models available in the %(name)s application."
msgstr "" msgstr "Modelos dispoñíbeis na aplicación %(name)s."
#: contrib/admin/templates/admin/index.html:28 #: contrib/admin/templates/admin/index.html:28
#: contrib/admin/templates/admin/change_form.html:15 #: contrib/admin/templates/admin/change_form.html:15
@ -1061,12 +1049,11 @@ msgstr "Hora"
#: contrib/admin/templates/widget/file.html:2 #: contrib/admin/templates/widget/file.html:2
msgid "Currently:" msgid "Currently:"
msgstr "" msgstr "Agora:"
#: contrib/admin/templates/widget/file.html:3 #: contrib/admin/templates/widget/file.html:3
#, fuzzy
msgid "Change:" msgid "Change:"
msgstr "Modificar" msgstr "Modificar:"
#: contrib/redirects/models.py:7 #: contrib/redirects/models.py:7
msgid "redirect from" msgid "redirect from"
@ -1155,24 +1142,20 @@ msgid "codename"
msgstr "código" msgstr "código"
#: contrib/auth/models.py:17 #: contrib/auth/models.py:17
#, fuzzy
msgid "permission" msgid "permission"
msgstr "Permiso" msgstr "permiso"
#: contrib/auth/models.py:18 contrib/auth/models.py:27 #: contrib/auth/models.py:18 contrib/auth/models.py:27
#, fuzzy
msgid "permissions" msgid "permissions"
msgstr "Permisos" msgstr "permisos"
#: contrib/auth/models.py:29 #: contrib/auth/models.py:29
#, fuzzy
msgid "group" msgid "group"
msgstr "Grupo" msgstr "grupo"
#: contrib/auth/models.py:30 contrib/auth/models.py:65 #: contrib/auth/models.py:30 contrib/auth/models.py:65
#, fuzzy
msgid "groups" msgid "groups"
msgstr "Grupos" msgstr "grupos"
#: contrib/auth/models.py:55 #: contrib/auth/models.py:55
msgid "username" msgid "username"
@ -1231,19 +1214,16 @@ msgstr ""
"permisos concedidos a cada un dos grupos aos que pertence." "permisos concedidos a cada un dos grupos aos que pertence."
#: contrib/auth/models.py:67 #: contrib/auth/models.py:67
#, fuzzy
msgid "user permissions" msgid "user permissions"
msgstr "Permisos" msgstr "permisos de usuario"
#: contrib/auth/models.py:70 #: contrib/auth/models.py:70
#, fuzzy
msgid "user" msgid "user"
msgstr "Usuario" msgstr "usuario"
#: contrib/auth/models.py:71 #: contrib/auth/models.py:71
#, fuzzy
msgid "users" msgid "users"
msgstr "Usuarios" msgstr "usuarios"
#: contrib/auth/models.py:76 #: contrib/auth/models.py:76
msgid "Personal info" msgid "Personal info"
@ -1262,18 +1242,17 @@ msgid "Groups"
msgstr "Grupos" msgstr "Grupos"
#: contrib/auth/models.py:219 #: contrib/auth/models.py:219
#, fuzzy
msgid "message" msgid "message"
msgstr "Mensaxe" msgstr "mensaxe"
#: contrib/auth/forms.py:30 #: contrib/auth/forms.py:30
msgid "" msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are " "Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in." "required for logging in."
msgstr "" msgstr "Semella que o seu navegador non acepta 'cookies'. Requírense "
"'cookies' para iniciar sesión."
#: contrib/contenttypes/models.py:25 #: contrib/contenttypes/models.py:25
#, fuzzy
msgid "python model class name" msgid "python model class name"
msgstr "nome do módulo Python" msgstr "nome do módulo Python"
@ -1410,54 +1389,52 @@ msgid "December"
msgstr "decembro" msgstr "decembro"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy
msgid "jan" msgid "jan"
msgstr "e" msgstr "xan"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "feb" msgid "feb"
msgstr "" msgstr "feb"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "mar" msgid "mar"
msgstr "" msgstr "mar"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "apr" msgid "apr"
msgstr "" msgstr "abr"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy
msgid "may" msgid "may"
msgstr "día" msgstr "mai"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "jun" msgid "jun"
msgstr "" msgstr "xuñ"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "jul" msgid "jul"
msgstr "" msgstr "xul"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "aug" msgid "aug"
msgstr "" msgstr "ago"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "sep" msgid "sep"
msgstr "" msgstr "set"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "oct" msgid "oct"
msgstr "" msgstr "out"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "nov" msgid "nov"
msgstr "" msgstr "nov"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "dec" msgid "dec"
msgstr "" msgstr "dec"
#: utils/dates.py:27 #: utils/dates.py:27
msgid "Jan." msgid "Jan."
@ -1502,8 +1479,8 @@ msgstr[1] "meses"
#: utils/timesince.py:14 #: utils/timesince.py:14
msgid "week" msgid "week"
msgid_plural "weeks" msgid_plural "weeks"
msgstr[0] "" msgstr[0] "semana"
msgstr[1] "" msgstr[1] "semanas"
#: utils/timesince.py:15 #: utils/timesince.py:15
msgid "day" msgid "day"
@ -1545,7 +1522,7 @@ msgstr "alemán"
#: conf/global_settings.py:42 #: conf/global_settings.py:42
msgid "Greek" msgid "Greek"
msgstr "" msgstr "grego"
#: conf/global_settings.py:43 #: conf/global_settings.py:43
msgid "English" msgid "English"
@ -1565,11 +1542,11 @@ msgstr "galego"
#: conf/global_settings.py:47 #: conf/global_settings.py:47
msgid "Hungarian" msgid "Hungarian"
msgstr "" msgstr "húngaro"
#: conf/global_settings.py:48 #: conf/global_settings.py:48
msgid "Hebrew" msgid "Hebrew"
msgstr "" msgstr "hebreo"
#: conf/global_settings.py:49 #: conf/global_settings.py:49
msgid "Icelandic" msgid "Icelandic"
@ -1581,11 +1558,11 @@ msgstr "italiano"
#: conf/global_settings.py:51 #: conf/global_settings.py:51
msgid "Japanese" msgid "Japanese"
msgstr "" msgstr "xaponés"
#: conf/global_settings.py:52 #: conf/global_settings.py:52
msgid "Dutch" msgid "Dutch"
msgstr "" msgstr "holandés"
#: conf/global_settings.py:53 #: conf/global_settings.py:53
msgid "Norwegian" msgid "Norwegian"
@ -1608,9 +1585,8 @@ msgid "Slovak"
msgstr "eslovaco" msgstr "eslovaco"
#: conf/global_settings.py:58 #: conf/global_settings.py:58
#, fuzzy
msgid "Slovenian" msgid "Slovenian"
msgstr "eslovaco" msgstr "esloveno"
#: conf/global_settings.py:59 #: conf/global_settings.py:59
msgid "Serbian" msgid "Serbian"
@ -1621,9 +1597,8 @@ msgid "Swedish"
msgstr "sueco" msgstr "sueco"
#: conf/global_settings.py:61 #: conf/global_settings.py:61
#, fuzzy
msgid "Ukrainian" msgid "Ukrainian"
msgstr "brasileiro" msgstr "ucraíno"
#: conf/global_settings.py:62 #: conf/global_settings.py:62
msgid "Simplified Chinese" msgid "Simplified Chinese"
@ -1631,20 +1606,19 @@ msgstr "chinés simplificado"
#: conf/global_settings.py:63 #: conf/global_settings.py:63
msgid "Traditional Chinese" msgid "Traditional Chinese"
msgstr "" msgstr "chinés tradicional"
#: core/validators.py:60 #: core/validators.py:60
msgid "This value must contain only letters, numbers and underscores." msgid "This value must contain only letters, numbers and underscores."
msgstr "Este valor soamente pode conter letras, números e guións baixos (_)." msgstr "Este valor soamente pode conter letras, números e guións baixos (_)."
#: core/validators.py:64 #: core/validators.py:64
#, fuzzy
msgid "" msgid ""
"This value must contain only letters, numbers, underscores, dashes or " "This value must contain only letters, numbers, underscores, dashes or "
"slashes." "slashes."
msgstr "" msgstr ""
"Este valor soamente pode conter letras, números, guións baixos (_) e barras " "Este valor soamente pode conter letras, números, guións baixos (_), guións (-) e barras "
"inclinadas." "inclinadas (/)."
#: core/validators.py:72 #: core/validators.py:72
msgid "Uppercase letters are not allowed here." msgid "Uppercase letters are not allowed here."
@ -1903,9 +1877,9 @@ msgstr ""
"comeza con \"%(start)s\")." "comeza con \"%(start)s\")."
#: db/models/manipulators.py:302 #: db/models/manipulators.py:302
#, fuzzy, python-format #, python-format
msgid "%(object)s with this %(type)s already exists for the given %(field)s." msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr "Xa existe un/ha %(optname)s con este/a %(fieldname)s." msgstr "Xa existe un obxecto %(object)s con este %(type)s para o campo %(field)s."
#: db/models/fields/__init__.py:40 #: db/models/fields/__init__.py:40
#, python-format #, python-format
@ -1919,19 +1893,16 @@ msgid "This field is required."
msgstr "Requírese este campo." msgstr "Requírese este campo."
#: db/models/fields/__init__.py:337 #: db/models/fields/__init__.py:337
#, fuzzy
msgid "This value must be an integer." msgid "This value must be an integer."
msgstr "Este valor ten que ser unha potencia de %s." msgstr "Este valor ten que ser un número enteiro."
#: db/models/fields/__init__.py:369 #: db/models/fields/__init__.py:369
#, fuzzy
msgid "This value must be either True or False." msgid "This value must be either True or False."
msgstr "Este valor ten que ser unha potencia de %s." msgstr "Este valor ten que verdadeiro ou falso."
#: db/models/fields/__init__.py:385 #: db/models/fields/__init__.py:385
#, fuzzy
msgid "This field cannot be null." msgid "This field cannot be null."
msgstr "Este campo non é válido." msgstr "Este campo non pode ser nulo."
#: db/models/fields/__init__.py:562 #: db/models/fields/__init__.py:562
msgid "Enter a valid filename." msgid "Enter a valid filename."
@ -1943,12 +1914,10 @@ msgid "Please enter a valid %s."
msgstr "Insira un %s válido/a." msgstr "Insira un %s válido/a."
#: db/models/fields/related.py:579 #: db/models/fields/related.py:579
#, fuzzy
msgid "Separate multiple IDs with commas." msgid "Separate multiple IDs with commas."
msgstr " Separe IDs múltiplas con comas." msgstr "Separe IDs múltiplas con comas."
#: db/models/fields/related.py:581 #: db/models/fields/related.py:581
#, fuzzy
msgid "" msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr "" msgstr ""

View File

@ -8,7 +8,7 @@ msgstr ""
"Project-Id-Version: django\n" "Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n" "POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2005-12-08 15:28+0100\n" "PO-Revision-Date: 2005-07-02 13:25+0200\n"
"Last-Translator: Afonso Fernández Nogueira <fonzzo.django@gmail.com>\n" "Last-Translator: Afonso Fernández Nogueira <fonzzo.django@gmail.com>\n"
"Language-Team: Galego\n" "Language-Team: Galego\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -18,33 +18,32 @@ msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:33 #: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format #, perl-format
msgid "Available %s" msgid "Available %s"
msgstr "" msgstr "%s dispoñíbeis"
#: contrib/admin/media/js/SelectFilter2.js:41 #: contrib/admin/media/js/SelectFilter2.js:41
#, fuzzy
msgid "Choose all" msgid "Choose all"
msgstr "Escolla unha hora" msgstr "Escoller todo"
#: contrib/admin/media/js/SelectFilter2.js:46 #: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add" msgid "Add"
msgstr "" msgstr "Engadir"
#: contrib/admin/media/js/SelectFilter2.js:48 #: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove" msgid "Remove"
msgstr "" msgstr "Quitar"
#: contrib/admin/media/js/SelectFilter2.js:53 #: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format #, perl-format
msgid "Chosen %s" msgid "Chosen %s"
msgstr "" msgstr "%s escollido/a(s)"
#: contrib/admin/media/js/SelectFilter2.js:54 #: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click " msgid "Select your choice(s) and click "
msgstr "" msgstr "Seleccione unha ou varias entrada e faga clic "
#: contrib/admin/media/js/SelectFilter2.js:59 #: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all" msgid "Clear all"
msgstr "" msgstr "Quitar todo"
#: contrib/admin/media/js/dateparse.js:26 #: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24 #: contrib/admin/media/js/calendar.js:24
@ -52,7 +51,7 @@ msgid ""
"January February March April May June July August September October November " "January February March April May June July August September October November "
"December" "December"
msgstr "" msgstr ""
"xaneiro febeiro marzo abril maio xuño xullo agosto setembro outubro novembro " "xaneiro febreiro marzo abril maio xuño xullo agosto setembro outubro novembro "
"decembro" "decembro"
#: contrib/admin/media/js/dateparse.js:27 #: contrib/admin/media/js/dateparse.js:27

View File

@ -217,7 +217,7 @@ var DateTimeShortcuts = {
DateTimeShortcuts.dismissCalendar(num); DateTimeShortcuts.dismissCalendar(num);
}, },
cancelEventPropagation: function(e) { cancelEventPropagation: function(e) {
if (!e) var e = window.event; if (!e) e = window.event;
e.cancelBubble = true; e.cancelBubble = true;
if (e.stopPropagation) e.stopPropagation(); if (e.stopPropagation) e.stopPropagation();
} }

View File

@ -19,6 +19,7 @@ function removeEvent(obj, evType, fn) {
return true; return true;
} else if (obj.detachEvent) { } else if (obj.detachEvent) {
obj.detachEvent("on" + evType, fn); obj.detachEvent("on" + evType, fn);
return true;
} else { } else {
return false; return false;
} }

View File

@ -30,7 +30,7 @@
{% endif %} {% endif %}
{% if messages %} {% if messages %}
<ul class="messagelist">{% for message in messages %}<li>{{ message }}</li>{% endfor %}</ul> <ul class="messagelist">{% for message in messages %}<li>{{ message|escape }}</li>{% endfor %}</ul>
{% endif %} {% endif %}
<!-- Content --> <!-- Content -->

View File

@ -15,7 +15,7 @@
{% for app in app_list %} {% for app in app_list %}
<div class="module"> <div class="module">
<table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}"> <table summary="{% blocktrans with app.name as name %}Models available in the {{ name }} application.{% endblocktrans %}">
<caption>{{ app.name }}</caption> <caption>{% blocktrans with app.name as name %}{{ name }}{% endblocktrans %}</caption>
{% for model in app.models %} {% for model in app.models %}
<tr> <tr>
{% if model.perms.change %} {% if model.perms.change %}

View File

@ -188,7 +188,7 @@ def model_detail(request, app_label, model_name):
'name': field.name, 'name': field.name,
'data_type': data_type, 'data_type': data_type,
'verbose': verbose, 'verbose': verbose,
'help': field.help_text, 'help_text': field.help_text,
}) })
# Gather model methods. # Gather model methods.

View File

@ -28,9 +28,11 @@
<p><label for="id_comment">{% trans "Comment:" %}</label><br /> <p><label for="id_comment">{% trans "Comment:" %}</label><br />
<textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p> <textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p>
<p>
<input type="hidden" name="options" value="{{ options }}" /> <input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" /> <input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" /> <input type="hidden" name="gonzo" value="{{ hash }}" />
<p><input type="submit" name="preview" value="{% trans "Preview comment" %}" /></p> <input type="submit" name="preview" value="{% trans "Preview comment" %}" />
</p>
</form> </form>
{% endif %} {% endif %}

View File

@ -3,9 +3,11 @@
<form action="/comments/postfree/" method="post"> <form action="/comments/postfree/" method="post">
<p><label for="id_person_name">{% trans "Your name:" %}</label> <input type="text" id="id_person_name" name="person_name" /></p> <p><label for="id_person_name">{% trans "Your name:" %}</label> <input type="text" id="id_person_name" name="person_name" /></p>
<p><label for="id_comment">{% trans "Comment:" %}</label><br /><textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p> <p><label for="id_comment">{% trans "Comment:" %}</label><br /><textarea name="comment" id="id_comment" rows="10" cols="60"></textarea></p>
<p>
<input type="hidden" name="options" value="{{ options }}" /> <input type="hidden" name="options" value="{{ options }}" />
<input type="hidden" name="target" value="{{ target }}" /> <input type="hidden" name="target" value="{{ target }}" />
<input type="hidden" name="gonzo" value="{{ hash }}" /> <input type="hidden" name="gonzo" value="{{ hash }}" />
<p><input type="submit" name="preview" value="{% trans "Preview comment" %}" /></p> <input type="submit" name="preview" value="{% trans "Preview comment" %}" />
</p>
</form> </form>
{% endif %} {% endif %}

View File

@ -1006,6 +1006,8 @@ def get_validation_errors(outfile, app=None):
# Check core=True, if needed. # Check core=True, if needed.
for related in opts.get_followed_related_objects(): for related in opts.get_followed_related_objects():
if not related.edit_inline:
continue
try: try:
for f in related.opts.fields: for f in related.opts.fields:
if f.core: if f.core:
@ -1045,7 +1047,10 @@ def _check_for_validation_errors(app=None):
s = StringIO() s = StringIO()
num_errors = get_validation_errors(s, app) num_errors = get_validation_errors(s, app)
if num_errors: if num_errors:
sys.stderr.write(style.ERROR("Error: %s couldn't be installed, because there were errors in your model:\n" % app)) if app:
sys.stderr.write(style.ERROR("Error: %s couldn't be installed, because there were errors in your model:\n" % app))
else:
sys.stderr.write(style.ERROR("Error: Couldn't install apps, because there were errors in one or more models:\n"))
s.seek(0) s.seek(0)
sys.stderr.write(s.read()) sys.stderr.write(s.read())
sys.exit(1) sys.exit(1)

View File

@ -2,13 +2,14 @@ from django.conf import settings
import os import os
def runshell(): def runshell():
args = [''] args = ['psql']
args += ["-U%s" % settings.DATABASE_USER] if settings.DATABASE_USER:
args += ["-U", settings.DATABASE_USER]
if settings.DATABASE_PASSWORD: if settings.DATABASE_PASSWORD:
args += ["-W"] args += ["-W"]
if settings.DATABASE_HOST: if settings.DATABASE_HOST:
args += ["-h %s" % settings.DATABASE_HOST] args.extend(["-h", settings.DATABASE_HOST])
if settings.DATABASE_PORT: if settings.DATABASE_PORT:
args += ["-p %s" % settings.DATABASE_PORT] args.extend(["-p", str(settings.DATABASE_PORT)])
args += [settings.DATABASE_NAME] args += [settings.DATABASE_NAME]
os.execvp('psql', args) os.execvp('psql', args)

View File

@ -2,18 +2,56 @@ from django.db import transaction
from django.db.backends.sqlite3.base import quote_name from django.db.backends.sqlite3.base import quote_name
def get_table_list(cursor): def get_table_list(cursor):
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name") "Returns a list of table names in the current database."
# Skip the sqlite_sequence system table used for autoincrement key
# generation.
cursor.execute("""
SELECT name FROM sqlite_master
WHERE type='table' AND NOT name='sqlite_sequence'
ORDER BY name""")
return [row[0] for row in cursor.fetchall()] return [row[0] for row in cursor.fetchall()]
def get_table_description(cursor, table_name): def get_table_description(cursor, table_name):
cursor.execute("PRAGMA table_info(%s)" % quote_name(table_name)) "Returns a description of the table, with the DB-API cursor.description interface."
return [(row[1], row[2], None, None) for row in cursor.fetchall()] return [(info['name'], info['type'], None, None, None, None,
info['null_ok']) for info in _table_info(cursor, table_name)]
def get_relations(cursor, table_name): def get_relations(cursor, table_name):
raise NotImplementedError raise NotImplementedError
def get_indexes(cursor, table_name): def get_indexes(cursor, table_name):
raise NotImplementedError """
Returns a dictionary of fieldname -> infodict for the given table,
where each infodict is in the format:
{'primary_key': boolean representing whether it's the primary key,
'unique': boolean representing whether it's a unique index}
"""
indexes = {}
for info in _table_info(cursor, table_name):
indexes[info['name']] = {'primary_key': info['pk'] != 0,
'unique': False}
cursor.execute('PRAGMA index_list(%s)' % quote_name(table_name))
# seq, name, unique
for index, unique in [(field[1], field[2]) for field in cursor.fetchall()]:
if not unique:
continue
cursor.execute('PRAGMA index_info(%s)' % quote_name(index))
info = cursor.fetchall()
# Skip indexes across multiple fields
if len(info) != 1:
continue
name = info[0][2] # seqno, cid, name
indexes[name]['unique'] = True
return indexes
def _table_info(cursor, name):
cursor.execute('PRAGMA table_info(%s)' % quote_name(name))
# cid, name, type, notnull, dflt_value, pk
return [{'name': field[1],
'type': field[2],
'null_ok': not field[3],
'pk': field[5] # undocumented
} for field in cursor.fetchall()]
# Maps SQL types to Django Field types. Some of the SQL types have multiple # Maps SQL types to Django Field types. Some of the SQL types have multiple
# entries here because SQLite allows for anything and doesn't normalize the # entries here because SQLite allows for anything and doesn't normalize the

View File

@ -44,6 +44,11 @@ class ModelBase(type):
# For 'django.contrib.sites.models', this would be 'sites'. # For 'django.contrib.sites.models', this would be 'sites'.
new_class._meta.app_label = model_module.__name__.split('.')[-2] new_class._meta.app_label = model_module.__name__.split('.')[-2]
# Bail out early if we have already created this class.
m = get_model(new_class._meta.app_label, name)
if m is not None:
return m
# Add all attributes to the class. # Add all attributes to the class.
for obj_name, obj in attrs.items(): for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj) new_class.add_to_class(obj_name, obj)
@ -60,10 +65,10 @@ class ModelBase(type):
new_class._prepare() new_class._prepare()
register_models(new_class._meta.app_label, new_class) register_models(new_class._meta.app_label, new_class)
# Because of the way imports happen (recursively), we may or may not be # Because of the way imports happen (recursively), we may or may not be
# the first class for this model to register with the framework. There # the first class for this model to register with the framework. There
# should only be one class for each model, so we must always return the # should only be one class for each model, so we must always return the
# registered version. # registered version.
return get_model(new_class._meta.app_label, name) return get_model(new_class._meta.app_label, name)
class Model(object): class Model(object):

View File

@ -679,7 +679,7 @@ def get_cached_row(klass, row, index_start):
def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen): def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen):
""" """
Helper function that recursively populates the select, tables and where (in Helper function that recursively populates the select, tables and where (in
place) for fill-cache queries. place) for select_related queries.
""" """
backend = opts.connection_info.backend backend = opts.connection_info.backend
for f in opts.fields: for f in opts.fields:
@ -701,6 +701,7 @@ def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen)
def parse_lookup(kwarg_items, opts): def parse_lookup(kwarg_items, opts):
# Helper function that handles converting API kwargs # Helper function that handles converting API kwargs
# (e.g. "name__exact": "tom") to SQL. # (e.g. "name__exact": "tom") to SQL.
# Returns a tuple of (tables, joins, where, params).
# 'joins' is a sorted dictionary describing the tables that must be joined # 'joins' is a sorted dictionary describing the tables that must be joined
# to complete the query. The dictionary is sorted because creation order # to complete the query. The dictionary is sorted because creation order

View File

@ -773,15 +773,18 @@ class DatetimeField(TextField):
def html2python(data): def html2python(data):
"Converts the field into a datetime.datetime object" "Converts the field into a datetime.datetime object"
import datetime import datetime
date, time = data.split() try:
y, m, d = date.split('-') date, time = data.split()
timebits = time.split(':') y, m, d = date.split('-')
h, mn = timebits[:2] timebits = time.split(':')
if len(timebits) > 2: h, mn = timebits[:2]
s = int(timebits[2]) if len(timebits) > 2:
else: s = int(timebits[2])
s = 0 else:
return datetime.datetime(int(y), int(m), int(d), int(h), int(mn), s) s = 0
return datetime.datetime(int(y), int(m), int(d), int(h), int(mn), s)
except ValueError:
return None
html2python = staticmethod(html2python) html2python = staticmethod(html2python)
class DateField(TextField): class DateField(TextField):
@ -806,7 +809,7 @@ class DateField(TextField):
time_tuple = time.strptime(data, '%Y-%m-%d') time_tuple = time.strptime(data, '%Y-%m-%d')
return datetime.date(*time_tuple[0:3]) return datetime.date(*time_tuple[0:3])
except (ValueError, TypeError): except (ValueError, TypeError):
return data return None
html2python = staticmethod(html2python) html2python = staticmethod(html2python)
class TimeField(TextField): class TimeField(TextField):

View File

@ -318,7 +318,7 @@ class Parser(object):
self.tags.update(lib.tags) self.tags.update(lib.tags)
self.filters.update(lib.filters) self.filters.update(lib.filters)
def compile_filter(self,token): def compile_filter(self, token):
"Convenient wrapper for FilterExpression" "Convenient wrapper for FilterExpression"
return FilterExpression(token, self) return FilterExpression(token, self)
@ -543,11 +543,14 @@ class FilterExpression(object):
raise TemplateSyntaxError, "Could not parse the remainder: %s" % token[upto:] raise TemplateSyntaxError, "Could not parse the remainder: %s" % token[upto:]
self.var, self.filters = var, filters self.var, self.filters = var, filters
def resolve(self, context): def resolve(self, context, ignore_failures=False):
try: try:
obj = resolve_variable(self.var, context) obj = resolve_variable(self.var, context)
except VariableDoesNotExist: except VariableDoesNotExist:
obj = settings.TEMPLATE_STRING_IF_INVALID if ignore_failures:
return None
else:
return settings.TEMPLATE_STRING_IF_INVALID
for func, args in self.filters: for func, args in self.filters:
arg_vals = [] arg_vals = []
for lookup, arg in args: for lookup, arg in args:
@ -611,7 +614,11 @@ def resolve_variable(path, context):
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.') (The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
""" """
if path[0].isdigit(): if path == 'False':
current = False
elif path == 'True':
current = True
elif path[0].isdigit():
number_type = '.' in path and float or int number_type = '.' in path and float or int
try: try:
current = number_type(path) current = number_type(path)

View File

@ -37,7 +37,7 @@ class Context(object):
for d in self.dicts: for d in self.dicts:
if d.has_key(key): if d.has_key(key):
return d[key] return d[key]
return settings.TEMPLATE_STRING_IF_INVALID raise KeyError(key)
def __delitem__(self, key): def __delitem__(self, key):
"Delete a variable from the current context" "Delete a variable from the current context"
@ -49,7 +49,7 @@ class Context(object):
return True return True
return False return False
def get(self, key, otherwise): def get(self, key, otherwise=None):
for d in self.dicts: for d in self.dicts:
if d.has_key(key): if d.has_key(key):
return d[key] return d[key]

View File

@ -430,20 +430,32 @@ def filesizeformat(bytes):
return "%.1f MB" % (bytes / (1024 * 1024)) return "%.1f MB" % (bytes / (1024 * 1024))
return "%.1f GB" % (bytes / (1024 * 1024 * 1024)) return "%.1f GB" % (bytes / (1024 * 1024 * 1024))
def pluralize(value): def pluralize(value, arg='s'):
"Returns 's' if the value is not 1, for '1 vote' vs. '2 votes'" """
Returns a plural suffix if the value is not 1, for '1 vote' vs. '2 votes'
By default, 's' is used as a suffix; if an argument is provided, that string
is used instead. If the provided argument contains a comma, the text before
the comma is used for the singular case.
"""
if not ',' in arg:
arg = ',' + arg
bits = arg.split(',')
if len(bits) > 2:
return ''
singular_suffix, plural_suffix = bits[:2]
try: try:
if int(value) != 1: if int(value) != 1:
return 's' return plural_suffix
except ValueError: # invalid string that's not a number except ValueError: # invalid string that's not a number
pass pass
except TypeError: # value isn't a string or a number; maybe it's a list? except TypeError: # value isn't a string or a number; maybe it's a list?
try: try:
if len(value) != 1: if len(value) != 1:
return 's' return plural_suffix
except TypeError: # len() of unsized object except TypeError: # len() of unsized object
pass pass
return '' return singular_suffix
def phone2numeric(value): def phone2numeric(value):
"Takes a phone number and converts it in to its numerical equivalent" "Takes a phone number and converts it in to its numerical equivalent"

View File

@ -45,7 +45,10 @@ class FirstOfNode(Node):
def render(self, context): def render(self, context):
for var in self.vars: for var in self.vars:
value = resolve_variable(var, context) try:
value = resolve_variable(var, context)
except VariableDoesNotExist:
continue
if value: if value:
return str(value) return str(value)
return '' return ''
@ -144,8 +147,14 @@ class IfEqualNode(Node):
return "<IfEqualNode>" return "<IfEqualNode>"
def render(self, context): def render(self, context):
val1 = resolve_variable(self.var1, context) try:
val2 = resolve_variable(self.var2, context) val1 = resolve_variable(self.var1, context)
except VariableDoesNotExist:
val1 = None
try:
val2 = resolve_variable(self.var2, context)
except VariableDoesNotExist:
val2 = None
if (self.negate and val1 != val2) or (not self.negate and val1 == val2): if (self.negate and val1 != val2) or (not self.negate and val1 == val2):
return self.nodelist_true.render(context) return self.nodelist_true.render(context)
return self.nodelist_false.render(context) return self.nodelist_false.render(context)
@ -177,7 +186,7 @@ class IfNode(Node):
if self.link_type == IfNode.LinkTypes.or_: if self.link_type == IfNode.LinkTypes.or_:
for ifnot, bool_expr in self.bool_exprs: for ifnot, bool_expr in self.bool_exprs:
try: try:
value = bool_expr.resolve(context) value = bool_expr.resolve(context, True)
except VariableDoesNotExist: except VariableDoesNotExist:
value = None value = None
if (value and not ifnot) or (ifnot and not value): if (value and not ifnot) or (ifnot and not value):
@ -186,7 +195,7 @@ class IfNode(Node):
else: else:
for ifnot, bool_expr in self.bool_exprs: for ifnot, bool_expr in self.bool_exprs:
try: try:
value = bool_expr.resolve(context) value = bool_expr.resolve(context, True)
except VariableDoesNotExist: except VariableDoesNotExist:
value = None value = None
if not ((value and not ifnot) or (ifnot and not value)): if not ((value and not ifnot) or (ifnot and not value)):

View File

@ -12,7 +12,7 @@ class GetAvailableLanguagesNode(Node):
def render(self, context): def render(self, context):
from django.conf import settings from django.conf import settings
context[self.variable] = settings.LANGUAGES context[self.variable] = [(k, translation.gettext(v)) for k, v in settings.LANGUAGES]
return '' return ''
class GetCurrentLanguageNode(Node): class GetCurrentLanguageNode(Node):
@ -30,7 +30,7 @@ class GetCurrentLanguageBidiNode(Node):
def render(self, context): def render(self, context):
context[self.variable] = translation.get_language_bidi() context[self.variable] = translation.get_language_bidi()
return '' return ''
class TranslateNode(Node): class TranslateNode(Node):
def __init__(self, value, noop): def __init__(self, value, noop):
self.value = value self.value = value
@ -171,7 +171,7 @@ def do_translate(parser, token):
else: else:
noop = False noop = False
return (value, noop) return (value, noop)
(value, noop) = TranslateParser(token.contents).top() value, noop = TranslateParser(token.contents).top()
return TranslateNode(value, noop) return TranslateNode(value, noop)
def do_block_translate(parser, token): def do_block_translate(parser, token):
@ -216,7 +216,7 @@ def do_block_translate(parser, token):
raise TemplateSyntaxError, "unknown subtag %s for 'blocktrans' found" % tag raise TemplateSyntaxError, "unknown subtag %s for 'blocktrans' found" % tag
return (countervar, counter, extra_context) return (countervar, counter, extra_context)
(countervar, counter, extra_context) = BlockTranslateParser(token.contents).top() countervar, counter, extra_context = BlockTranslateParser(token.contents).top()
singular = [] singular = []
plural = [] plural = []

View File

@ -6,7 +6,10 @@ Synchronization primitives:
(Contributed to Django by eugene@lazutkin.com) (Contributed to Django by eugene@lazutkin.com)
""" """
import threading try:
import threading
except ImportError:
import dummy_threading as threading
class RWLock: class RWLock:
""" """

View File

@ -0,0 +1,8 @@
from django.conf import settings
if settings.USE_I18N:
from trans_real import *
else:
from trans_null import *
del settings

View File

@ -0,0 +1,18 @@
# These are versions of the functions in django.utils.translation.trans_real
# that don't actually do anything. This is purely for performance, so that
# settings.USE_I18N = False can use this module rather than trans_real.py.
from django.conf import settings
def ngettext(singular, plural, number):
if number == 1: return singular
return plural
ngettext_lazy = ngettext
gettext = gettext_noop = gettext_lazy = _ = lambda x: x
string_concat = lambda *strings: ''.join([str(el) for el in strings])
activate = lambda x: None
deactivate = install = lambda: None
get_language = lambda: settings.LANGUAGE_CODE
get_date_formats = lambda: settings.DATE_FORMAT, settings.DATETIME_FORMAT, settings.TIME_FORMAT
get_partial_date_formats = lambda: settings.YEAR_MONTH_FORMAT, settings.MONTH_DAY_FORMAT

View File

@ -1,4 +1,4 @@
"translation helper functions" "Translation helper functions"
import os, re, sys import os, re, sys
import gettext as gettext_module import gettext as gettext_module
@ -221,7 +221,6 @@ def get_language_bidi():
False = left-to-right layout False = left-to-right layout
True = right-to-left layout True = right-to-left layout
""" """
from django.conf import settings from django.conf import settings
return get_language() in settings.LANGUAGES_BIDI return get_language() in settings.LANGUAGES_BIDI
@ -389,7 +388,7 @@ def get_partial_date_formats():
def install(): def install():
""" """
Installs the gettext function as the default translation function under Installs the gettext function as the default translation function under
the name _. the name '_'.
""" """
__builtins__['_'] = gettext __builtins__['_'] = gettext

View File

@ -1121,35 +1121,37 @@ Note this is only available in MySQL and requires direct manipulation of the
database to add the full-text index. database to add the full-text index.
Default lookups are exact Default lookups are exact
~~~~~~~~~~~~~~~~~~~~~~~~~ -------------------------
If you don't provide a lookup type -- that is, if your keyword argument doesn't If you don't provide a lookup type -- that is, if your keyword argument doesn't
contain a double underscore -- the lookup type is assumed to be ``exact``. contain a double underscore -- the lookup type is assumed to be ``exact``.
For example, the following two statements are equivalent:: For example, the following two statements are equivalent::
Blog.objects.get(id=14) Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(id__exact=14) Blog.objects.get(id=14) # __exact is implied
This is for convenience, because ``exact`` lookups are the common case. This is for convenience, because ``exact`` lookups are the common case.
The pk lookup shortcut The pk lookup shortcut
~~~~~~~~~~~~~~~~~~~~~~ ----------------------
For convenience, Django provides a ``pk`` lookup type, which stands for For convenience, Django provides a ``pk`` lookup type, which stands for
"primary_key". This is shorthand for "an exact lookup on the primary-key." "primary_key". This is shorthand for "an exact lookup on the primary-key."
In the example ``Blog`` model, the primary key is the ``id`` field, so these In the example ``Blog`` model, the primary key is the ``id`` field, so these
two statements are equivalent:: three statements are equivalent::
Blog.objects.get(id__exact=14) Blog.objects.get(id__exact=14) # Explicit form
Blog.objects.get(pk=14) Blog.objects.get(id=14) # __exact is implied
Blog.objects.get(pk=14) # pk implies id__exact
``pk`` lookups also work across joins. For example, these two statements are ``pk`` lookups also work across joins. For example, these three statements are
equivalent:: equivalent::
Entry.objects.filter(blog__id__exact=3) Entry.objects.filter(blog__id__exact=3) # Explicit form
Entry.objects.filter(blog__pk=3) Entry.objects.filter(blog__id=3) # __exact is implied
Entry.objects.filter(blog__pk=3) # __pk implies __id__exact
Lookups that span relationships Lookups that span relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1550,6 +1552,21 @@ loaded, Django iterates over every model in ``INSTALLED_APPS`` and creates the
backward relationships in memory as needed. Essentially, one of the functions backward relationships in memory as needed. Essentially, one of the functions
of ``INSTALLED_APPS`` is to tell Django the entire model domain. of ``INSTALLED_APPS`` is to tell Django the entire model domain.
Queries over related objects
----------------------------
Queries involving related objects follow the same rules as queries involving
normal value fields. When specifying the the value for a query to match, you
may use either an object instance itself, or the primary key value for the
object.
For example, if you have a Blog object ``b`` with ``id=5``, the following
three queries would be identical::
Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly
Deleting objects Deleting objects
================ ================

View File

@ -126,8 +126,9 @@ you run it, you'll want to look over the generated models yourself to make
customizations. In particular, you'll need to rearrange models' order, so that customizations. In particular, you'll need to rearrange models' order, so that
models that refer to other models are ordered properly. models that refer to other models are ordered properly.
Primary keys are automatically introspected for PostgreSQL and MySQL, in which Primary keys are automatically introspected for PostgreSQL, MySQL and
case Django puts in the ``primary_key=True`` where needed. SQLite, in which case Django puts in the ``primary_key=True`` where
needed.
``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection ``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection
only works in PostgreSQL and with certain types of MySQL tables. only works in PostgreSQL and with certain types of MySQL tables.

View File

@ -50,7 +50,7 @@ model that "knows" how to create or modify instances of that model and how to
validate data for the object. Manipulators come in two flavors: validate data for the object. Manipulators come in two flavors:
``AddManipulators`` and ``ChangeManipulators``. Functionally they are quite ``AddManipulators`` and ``ChangeManipulators``. Functionally they are quite
similar, but the former knows how to create new instances of the model, while similar, but the former knows how to create new instances of the model, while
the later modifies existing instances. Both types of classes are automatically the latter modifies existing instances. Both types of classes are automatically
created when you define a new class:: created when you define a new class::
>>> from mysite.myapp.models import Place >>> from mysite.myapp.models import Place

View File

@ -110,7 +110,7 @@ efficient. Here's the above "Hello World" example rewritten to use
from cStringIO import StringIO from cStringIO import StringIO
from reportlab.pdfgen import canvas from reportlab.pdfgen import canvas
from django.utils.httpwrappers import HttpResponse from django.http import HttpResponse
def some_view(request): def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers. # Create the HttpResponse object with the appropriate PDF headers.

View File

@ -10,18 +10,22 @@ Cookies contain a session ID -- not the data itself.
Enabling sessions Enabling sessions
================= =================
Sessions are implemented via middleware_. Sessions are implemented via a piece of middleware_ and a Django model.
Turn session functionality on and off by editing the ``MIDDLEWARE_CLASSES`` To enable session functionality, do these two things:
setting. To activate sessions, make sure ``MIDDLEWARE_CLASSES`` contains
``'django.contrib.sessions.middleware.SessionMiddleware'``.
The default ``settings.py`` created by ``django-admin.py startproject`` has * Edit the ``MIDDLEWARE_CLASSES`` setting and make sure
``SessionMiddleware`` activated. ``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``.
The default ``settings.py`` created by ``django-admin.py startproject`` has
``SessionMiddleware`` activated.
* Add ``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting, and
run ``manage.py syncdb`` to install the single database table that stores
session data.
If you don't want to use sessions, you might as well remove the If you don't want to use sessions, you might as well remove the
``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES``. It'll save you a small ``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'``
bit of overhead. from your ``INSTALLED_APPS``. It'll save you a small bit of overhead.
.. _middleware: http://www.djangoproject.com/documentation/middleware/ .. _middleware: http://www.djangoproject.com/documentation/middleware/

View File

@ -729,6 +729,10 @@ TIME_ZONE
Default: ``'America/Chicago'`` Default: ``'America/Chicago'``
A string representing the time zone for this installation. `See available choices`_. A string representing the time zone for this installation. `See available choices`_.
(Note that list of available choices lists more than one on the same line;
you'll want to use just one of the choices for a given time zone. For instance,
one line says ``'Europe/London GB GB-Eire'``, but you should use the first bit
of that -- ``'Europe/London'`` -- as your ``TIME_ZONE`` setting.)
Note that this is the time zone to which Django will convert all dates/times -- Note that this is the time zone to which Django will convert all dates/times --
not necessarily the timezone of the server. For example, one server may serve not necessarily the timezone of the server. For example, one server may serve
@ -750,7 +754,7 @@ Default: ``True``
A boolean that specifies whether Django's internationalization system should be A boolean that specifies whether Django's internationalization system should be
enabled. This provides an easy way to turn it off, for performance. If this is enabled. This provides an easy way to turn it off, for performance. If this is
set to ``False, Django will make some optimizations so as not to load the set to ``False``, Django will make some optimizations so as not to load the
internationalization machinery. internationalization machinery.
YEAR_MONTH_FORMAT YEAR_MONTH_FORMAT

View File

@ -951,12 +951,26 @@ any string.
pluralize pluralize
~~~~~~~~~ ~~~~~~~~~
Returns ``'s'`` if the value is not 1. Returns a plural suffix if the value is not 1. By default, this suffix is ``'s'``.
Example:: Example::
You have {{ num_messages }} message{{ num_messages|pluralize }}. You have {{ num_messages }} message{{ num_messages|pluralize }}.
For words that require a suffix other than ``'s'``, you can provide an alternate
suffix as a parameter to the filter.
Example::
You have {{ num_walruses }} walrus{{ num_walrus|pluralize:"es" }}.
For words that don't pluralize by simple suffix, you can specify both a
singular and plural suffix, separated by a comma.
Example::
You have {{ num_cherries }} cherr{{ num_cherries|pluralize:"y,ies" }}.
pprint pprint
~~~~~~ ~~~~~~

View File

@ -313,6 +313,36 @@ False
>>> pluralize(2) >>> pluralize(2)
's' 's'
>>> pluralize([1])
''
>>> pluralize([])
's'
>>> pluralize([1,2,3])
's'
>>> pluralize(1,'es')
''
>>> pluralize(0,'es')
'es'
>>> pluralize(2,'es')
'es'
>>> pluralize(1,'y,ies')
'y'
>>> pluralize(0,'y,ies')
'ies'
>>> pluralize(2,'y,ies')
'ies'
>>> pluralize(0,'y,ies,error')
''
>>> phone2numeric('0800 flowers') >>> phone2numeric('0800 flowers')
'0800 3569377' '0800 3569377'

View File

@ -78,7 +78,7 @@ TEMPLATE_TESTS = {
'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"), 'basic-syntax03': ("{{ first }} --- {{ second }}", {"first" : 1, "second" : 2}, "1 --- 2"),
# Fail silently when a variable is not found in the current context # Fail silently when a variable is not found in the current context
'basic-syntax04': ("as{{ missing }}df", {}, "asdf"), 'basic-syntax04': ("as{{ missing }}df", {}, "asINVALIDdf"),
# A variable may not contain more than one word # A variable may not contain more than one word
'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError), 'basic-syntax06': ("{{ multi word variable }}", {}, template.TemplateSyntaxError),
@ -94,7 +94,7 @@ TEMPLATE_TESTS = {
'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"), 'basic-syntax10': ("{{ var.otherclass.method }}", {"var": SomeClass()}, "OtherClass.method"),
# Fail silently when a variable's attribute isn't found # Fail silently when a variable's attribute isn't found
'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, ""), 'basic-syntax11': ("{{ var.blech }}", {"var": SomeClass()}, "INVALID"),
# Raise TemplateSyntaxError when trying to access a variable beginning with an underscore # Raise TemplateSyntaxError when trying to access a variable beginning with an underscore
'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError), 'basic-syntax12': ("{{ var.__dict__ }}", {"var": SomeClass()}, template.TemplateSyntaxError),
@ -110,10 +110,10 @@ TEMPLATE_TESTS = {
'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"), 'basic-syntax18': ("{{ foo.bar }}", {"foo" : {"bar" : "baz"}}, "baz"),
# Fail silently when a variable's dictionary key isn't found # Fail silently when a variable's dictionary key isn't found
'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, ""), 'basic-syntax19': ("{{ foo.spam }}", {"foo" : {"bar" : "baz"}}, "INVALID"),
# Fail silently when accessing a non-simple method # Fail silently when accessing a non-simple method
'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, ""), 'basic-syntax20': ("{{ var.method2 }}", {"var": SomeClass()}, "INVALID"),
# Basic filter usage # Basic filter usage
'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"), 'basic-syntax21': ("{{ var|upper }}", {"var": "Django is the greatest!"}, "DJANGO IS THE GREATEST!"),
@ -152,7 +152,7 @@ TEMPLATE_TESTS = {
'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'), 'basic-syntax32': (r'{{ var|yesno:"yup,nup,mup" }} {{ var|yesno }}', {"var": True}, 'yup yes'),
# Fail silently for methods that raise an exception with a "silent_variable_failure" attribute # Fail silently for methods that raise an exception with a "silent_variable_failure" attribute
'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "12"), 'basic-syntax33': (r'1{{ var.method3 }}2', {"var": SomeClass()}, "1INVALID2"),
# In methods that raise an exception without a "silent_variable_attribute" set to True, # In methods that raise an exception without a "silent_variable_attribute" set to True,
# the exception propogates # the exception propogates
@ -495,7 +495,7 @@ TEMPLATE_TESTS = {
'{{ item.foo }}' + \ '{{ item.foo }}' + \
'{% endfor %},' + \ '{% endfor %},' + \
'{% endfor %}', '{% endfor %}',
{}, ''), {}, 'INVALID:INVALIDINVALIDINVALIDINVALIDINVALIDINVALIDINVALID,'),
### TEMPLATETAG TAG ####################################################### ### TEMPLATETAG TAG #######################################################
'templatetag01': ('{% templatetag openblock %}', {}, '{%'), 'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
@ -579,6 +579,9 @@ def run_tests(verbosity=0, standalone=False):
# Turn TEMPLATE_DEBUG off, because tests assume that. # Turn TEMPLATE_DEBUG off, because tests assume that.
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
# Set TEMPLATE_STRING_IF_INVALID to a known string
old_invalid, settings.TEMPLATE_STRING_IF_INVALID = settings.TEMPLATE_STRING_IF_INVALID, 'INVALID'
for name, vals in tests: for name, vals in tests:
install() install()
if 'LANGUAGE_CODE' in vals[1]: if 'LANGUAGE_CODE' in vals[1]:
@ -609,6 +612,7 @@ def run_tests(verbosity=0, standalone=False):
loader.template_source_loaders = old_template_loaders loader.template_source_loaders = old_template_loaders
deactivate() deactivate()
settings.TEMPLATE_DEBUG = old_td settings.TEMPLATE_DEBUG = old_td
settings.TEMPLATE_STRING_IF_INVALID = old_invalid
if failed_tests and not standalone: if failed_tests and not standalone:
msg = "Template tests %s failed." % failed_tests msg = "Template tests %s failed." % failed_tests

View File

@ -0,0 +1,13 @@
from django.db import models
class First(models.Model):
second = models.IntegerField()
class Second(models.Model):
first = models.ForeignKey(First, related_name = 'the_first')
# If ticket #1578 ever slips back in, these models will not be able to be
# created (the field names being lower-cased versions of their opposite
# classes is important here).
API_TESTS = ""