1
0
mirror of https://github.com/django/django.git synced 2025-07-04 09:49:12 +00:00

[multi-db] Merged trunk to [4000]. Some tests still failing.

git-svn-id: http://code.djangoproject.com/svn/django/branches/multiple-db-support@4156 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jason Pellerin 2006-12-04 20:29:44 +00:00
parent 040f2272e0
commit b7a897eebb
33 changed files with 1068 additions and 289 deletions

View File

@ -91,6 +91,7 @@ answer newbie questions, and generally made Django that much better:
Kieran Holland <http://www.kieranholland.com> Kieran Holland <http://www.kieranholland.com>
Robert Rock Howard <http://djangomojo.com/> Robert Rock Howard <http://djangomojo.com/>
Jason Huggins <http://www.jrandolph.com/blog/> Jason Huggins <http://www.jrandolph.com/blog/>
Baurzhan Ismagulov <ibr@radix50.net>
jcrasta@gmail.com jcrasta@gmail.com
Michael Josephson <http://www.sdjournal.com/> Michael Josephson <http://www.sdjournal.com/>
jpellerin@gmail.com jpellerin@gmail.com

View File

@ -77,7 +77,7 @@ class Settings(object):
self.SETTINGS_MODULE = settings_module self.SETTINGS_MODULE = settings_module
try: try:
mod = __import__(self.SETTINGS_MODULE, '', '', ['']) mod = __import__(self.SETTINGS_MODULE, {}, {}, [''])
except ImportError, e: except ImportError, e:
raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e) raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
@ -97,7 +97,7 @@ class Settings(object):
new_installed_apps = [] new_installed_apps = []
for app in self.INSTALLED_APPS: for app in self.INSTALLED_APPS:
if app.endswith('.*'): if app.endswith('.*'):
appdir = os.path.dirname(__import__(app[:-2], '', '', ['']).__file__) appdir = os.path.dirname(__import__(app[:-2], {}, {}, ['']).__file__)
for d in os.listdir(appdir): for d in os.listdir(appdir):
if d.isalpha() and os.path.isdir(os.path.join(appdir, d)): if d.isalpha() and os.path.isdir(os.path.join(appdir, d)):
new_installed_apps.append('%s.%s' % (app[:-2], d)) new_installed_apps.append('%s.%s' % (app[:-2], d))

View File

@ -2,14 +2,15 @@
# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# João Marcus Christ <joaoma@gmail.com>, 2006. # João Marcus Christ <joaoma@gmail.com>, 2006.
# Carlos Eduardo de Paula <carlosedp@gmail.com>, 2006.
# #
msgid "" msgid ""
msgstr "" 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: 2006-01-23 19:54-0200\n" "PO-Revision-Date: 2006-11-01 17:45-0300\n"
"Last-Translator: João Marcus Christ <joaoma@gmail.com>\n" "Last-Translator: Carlos Eduardo de Paula <carlosedp@gmail.com>\n"
"Language-Team: Português do Brasil <pt-br@li.org>\n" "Language-Team: Português do Brasil <pt-br@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -86,12 +87,12 @@ msgid ""
"removed\" message will be displayed instead." "removed\" message will be displayed instead."
msgstr "" msgstr ""
"Selecione esta opção se o comentário é inapropriado. Uma mensagem \"Este " "Selecione esta opção se o comentário é inapropriado. Uma mensagem \"Este "
"comentário foi removido\" será mostrada no lugar." "comentário foi removido\" a mensagem será mostrada no lugar."
#: contrib/comments/models.py:91 #: contrib/comments/models.py:91
#, fuzzy #, fuzzy
msgid "comments" msgid "comments"
msgstr "comentário" msgstr "comentários"
#: 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"
@ -150,7 +151,7 @@ msgstr "Pontuação de Karma"
#: contrib/comments/models.py:238 #: contrib/comments/models.py:238
#, fuzzy #, fuzzy
msgid "karma scores" msgid "karma scores"
msgstr "Pontuação de Karma" msgstr "Pontuações de Karma"
#: contrib/comments/models.py:242 #: contrib/comments/models.py:242
#, python-format #, python-format
@ -170,17 +171,17 @@ msgstr ""
#: contrib/comments/models.py:265 #: contrib/comments/models.py:265
msgid "flag date" msgid "flag date"
msgstr "marca de data" msgstr "flag de data"
#: contrib/comments/models.py:268 #: contrib/comments/models.py:268
#, fuzzy #, fuzzy
msgid "user flag" msgid "user flag"
msgstr "Flag de usuário" msgstr "flag de usuário"
#: contrib/comments/models.py:269 #: contrib/comments/models.py:269
#, fuzzy #, fuzzy
msgid "user flags" msgid "user flags"
msgstr "Flags de usuário" msgstr "flags de usuário"
#: contrib/comments/models.py:273 #: contrib/comments/models.py:273
#, python-format #, python-format
@ -189,22 +190,22 @@ msgstr "Flag por %r"
#: contrib/comments/models.py:278 #: contrib/comments/models.py:278
msgid "deletion date" msgid "deletion date"
msgstr "data de apagamento" msgstr "data de exclusão"
#: contrib/comments/models.py:280 #: contrib/comments/models.py:280
#, fuzzy #, fuzzy
msgid "moderator deletion" msgid "moderator deletion"
msgstr "Apagamento feito por moderador" msgstr "Exclusão feita pelo moderador"
#: contrib/comments/models.py:281 #: contrib/comments/models.py:281
#, fuzzy #, fuzzy
msgid "moderator deletions" msgid "moderator deletions"
msgstr "Apagamentos feitos por moderador" msgstr "Exclusões feitas pelo 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 "Apagamento feito pelo moderador %r" msgstr "Exclusao feita pelo moderador %r"
#: contrib/comments/views/karma.py:19 #: contrib/comments/views/karma.py:19
msgid "Anonymous users cannot vote" msgid "Anonymous users cannot vote"
@ -237,12 +238,12 @@ msgid_plural ""
"\n" "\n"
"%(text)s" "%(text)s"
msgstr[0] "" msgstr[0] ""
"Este comentário foi feito por um usuário esboço:\n" "Este comentário foi feito por um usuário que postou menos de %(count)s "
"\n" "comentário:\n"
"%(text)s" "%(text)s"
msgstr[1] "" msgstr[1] ""
"Este comentário foi feito por um usuário esboço:\n" "Este comentário foi feito por um usuário que postou menos de %(count)s "
"\n" "comentários:\n"
"%(text)s" "%(text)s"
#: contrib/comments/views/comments.py:117 #: contrib/comments/views/comments.py:117
@ -252,7 +253,7 @@ msgid ""
"\n" "\n"
"%(text)s" "%(text)s"
msgstr "" msgstr ""
"Este comentário foi feito por um usuário esboço:\n" "Este comentário foi feito por um usuário incompleto:\n"
"\n" "\n"
"%(text)s" "%(text)s"
@ -299,7 +300,7 @@ msgstr "Senha:"
#: contrib/comments/templates/comments/form.html:6 #: contrib/comments/templates/comments/form.html:6
#, fuzzy #, fuzzy
msgid "Forgotten your password?" msgid "Forgotten your password?"
msgstr "Alterar minha senha" msgstr "Esqueceu sua senha?"
#: 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
@ -325,21 +326,21 @@ msgstr "Encerrar sessão"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
#, fuzzy #, fuzzy
msgid "Ratings" msgid "Ratings"
msgstr "avaliação #1" msgstr "Avaliações"
#: 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 "Requerido"
#: 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 "Postar uma 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
@ -351,12 +352,12 @@ msgstr "Comentário"
#: contrib/comments/templates/comments/freeform.html:9 #: contrib/comments/templates/comments/freeform.html:9
#, fuzzy #, fuzzy
msgid "Preview comment" msgid "Preview comment"
msgstr "Comentário livre" msgstr "Pré visualizar comentário"
#: contrib/comments/templates/comments/freeform.html:4 #: contrib/comments/templates/comments/freeform.html:4
#, fuzzy #, fuzzy
msgid "Your name:" msgid "Your name:"
msgstr "usuário" msgstr "Seu nome:"
#: contrib/admin/filterspecs.py:40 #: contrib/admin/filterspecs.py:40
#, python-format #, python-format
@ -443,7 +444,7 @@ msgid ""
"sensitive." "sensitive."
msgstr "" msgstr ""
"Por favor entre usuário e senha corretos. Note que ambos os " "Por favor entre usuário e senha corretos. Note que ambos os "
"camposdiferenciam maiúsculas e minúsculas." "campos diferenciam 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
@ -468,7 +469,7 @@ msgstr ""
#: contrib/admin/views/decorators.py:82 #: contrib/admin/views/decorators.py:82
msgid "Usernames cannot contain the '@' character." msgid "Usernames cannot contain the '@' character."
msgstr "Nomes de usuário não podem conter o caracter '@'." msgstr "Nomes de usuário não podem conter o caractere '@'."
#: contrib/admin/views/decorators.py:84 #: contrib/admin/views/decorators.py:84
#, python-format #, python-format
@ -553,7 +554,7 @@ msgstr "Um(a) ou mais %(fieldname)s em %(name)s:"
#: contrib/admin/views/main.py:508 #: contrib/admin/views/main.py:508
#, python-format #, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully." msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "O(A) %(name)s \"%(obj)s\" foi adicionado com sucesso." msgstr "O(A) %(name)s \"%(obj)s\" foi excluído com sucesso."
#: contrib/admin/views/main.py:511 #: contrib/admin/views/main.py:511
msgid "Are you sure?" msgid "Are you sure?"
@ -746,7 +747,7 @@ msgid ""
"mail and should be fixed shortly. Thanks for your patience." "mail and should be fixed shortly. Thanks for your patience."
msgstr "" msgstr ""
"Houve um erro. Este foi reportado aos administradores do site através d e-" "Houve um erro. Este foi reportado aos administradores do site através d e-"
"mail e deve ser consertado em breve. Obrigado pela compreensão." "mail e deve ser corrigido em breve. Obrigado pela compreensão."
#: contrib/admin/templates/admin/404.html:4 #: contrib/admin/templates/admin/404.html:4
#: contrib/admin/templates/admin/404.html:8 #: contrib/admin/templates/admin/404.html:8
@ -760,7 +761,7 @@ msgstr "Desculpe, mas a página requisitada não pode ser encontrada."
#: 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 disponíveis na aplicação %(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
@ -794,7 +795,7 @@ msgstr "Adicionar %(name)s"
#: contrib/admin/templates/admin/login.html:22 #: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?" msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "Você <a href=\"/password_reset/\"esqueceu a senha</a>?" msgstr "Você <a href=\"/password_reset/\">esqueceu sua senha</a>?"
#: contrib/admin/templates/admin/base.html:23 #: contrib/admin/templates/admin/base.html:23
msgid "Welcome," msgid "Welcome,"
@ -836,7 +837,7 @@ msgstr "Por %(title)s "
#: contrib/admin/templates/admin/search_form.html:8 #: contrib/admin/templates/admin/search_form.html:8
msgid "Go" msgid "Go"
msgstr "" msgstr "Ir"
#: contrib/admin/templates/admin/change_form.html:21 #: contrib/admin/templates/admin/change_form.html:21
msgid "View on site" msgid "View on site"
@ -847,7 +848,7 @@ msgstr "Ver no site"
msgid "Please correct the error below." msgid "Please correct the error below."
msgid_plural "Please correct the errors below." msgid_plural "Please correct the errors below."
msgstr[0] "Por favor, corrija o erro abaixo." msgstr[0] "Por favor, corrija o erro abaixo."
msgstr[1] "Por favor, corrija o erro abaixo." msgstr[1] "Por favor, corrija os erros abaixo."
#: contrib/admin/templates/admin/change_form.html:48 #: contrib/admin/templates/admin/change_form.html:48
msgid "Ordering" msgid "Ordering"
@ -930,8 +931,8 @@ msgid ""
"We've e-mailed a new password to the e-mail address you submitted. You " "We've e-mailed a new password to the e-mail address you submitted. You "
"should be receiving it shortly." "should be receiving it shortly."
msgstr "" msgstr ""
"Nós enviamos uma nova senha para o e-mail que você informou. Você deve estar " "Nós enviamos uma nova senha para o e-mail que você informou. Você deverá "
"recebendo uma mensagem em breve." "receber uma mensagem em breve."
#: contrib/admin/templates/registration/password_change_form.html:12 #: contrib/admin/templates/registration/password_change_form.html:12
msgid "" msgid ""
@ -973,7 +974,7 @@ msgstr "Sua nova senha é: %(new_password)s"
#: contrib/admin/templates/registration/password_reset_email.html:7 #: contrib/admin/templates/registration/password_reset_email.html:7
msgid "Feel free to change this password by going to this page:" msgid "Feel free to change this password by going to this page:"
msgstr "Sinta-se livre para alterar esta senha visitando esta página:" msgstr "Sinta-se a vontade para alterar esta senha visitando esta página:"
#: contrib/admin/templates/registration/password_reset_email.html:11 #: contrib/admin/templates/registration/password_reset_email.html:11
msgid "Your username, in case you've forgotten:" msgid "Your username, in case you've forgotten:"
@ -1040,17 +1041,17 @@ msgstr ""
#: contrib/admin/templates/admin_doc/bookmarklets.html:25 #: contrib/admin/templates/admin_doc/bookmarklets.html:25
msgid "Edit this object (current window)" msgid "Edit this object (current window)"
msgstr "Edita este objeto (janela atual)" msgstr "Editar este objeto (janela atual)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:26 #: contrib/admin/templates/admin_doc/bookmarklets.html:26
msgid "Jumps to the admin page for pages that represent a single object." msgid "Jumps to the admin page for pages that represent a single object."
msgstr "" msgstr ""
"Vai para a página de administração para páginas que representam um objeto " "Vai para a página de administração que representam um objeto "
"único." "único."
#: contrib/admin/templates/admin_doc/bookmarklets.html:28 #: contrib/admin/templates/admin_doc/bookmarklets.html:28
msgid "Edit this object (new window)" msgid "Edit this object (new window)"
msgstr "Edita este objeto (nova janela)" msgstr "Editar este objeto (nova janela)"
#: contrib/admin/templates/admin_doc/bookmarklets.html:29 #: contrib/admin/templates/admin_doc/bookmarklets.html:29
msgid "As above, but opens the admin page in a new window." msgid "As above, but opens the admin page in a new window."
@ -1135,7 +1136,7 @@ msgstr ""
#: contrib/flatpages/models.py:14 #: contrib/flatpages/models.py:14
msgid "registration required" msgid "registration required"
msgstr "é obrigatório registrar" msgstr "registro obrigatório"
#: contrib/flatpages/models.py:14 #: contrib/flatpages/models.py:14
msgid "If this is checked, only logged-in users will be able to view the page." msgid "If this is checked, only logged-in users will be able to view the page."
@ -1160,22 +1161,22 @@ msgstr "nome código"
#: contrib/auth/models.py:17 #: contrib/auth/models.py:17
#, fuzzy #, fuzzy
msgid "permission" msgid "permission"
msgstr "Permissão" msgstr "permissão"
#: contrib/auth/models.py:18 contrib/auth/models.py:27 #: contrib/auth/models.py:18 contrib/auth/models.py:27
#, fuzzy #, fuzzy
msgid "permissions" msgid "permissions"
msgstr "Permissões" msgstr "permissões"
#: contrib/auth/models.py:29 #: contrib/auth/models.py:29
#, fuzzy #, 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 #, fuzzy
msgid "groups" msgid "groups"
msgstr "Grupos" msgstr "grupos"
#: contrib/auth/models.py:55 #: contrib/auth/models.py:55
msgid "username" msgid "username"
@ -1236,17 +1237,17 @@ msgstr ""
#: contrib/auth/models.py:67 #: contrib/auth/models.py:67
#, fuzzy #, fuzzy
msgid "user permissions" msgid "user permissions"
msgstr "Permissões" msgstr "permissões do usuário"
#: contrib/auth/models.py:70 #: contrib/auth/models.py:70
#, fuzzy #, fuzzy
msgid "user" msgid "user"
msgstr "Usuário" msgstr "usuário"
#: contrib/auth/models.py:71 #: contrib/auth/models.py:71
#, fuzzy #, fuzzy
msgid "users" msgid "users"
msgstr "Usuários" msgstr "usuários"
#: contrib/auth/models.py:76 #: contrib/auth/models.py:76
msgid "Personal info" msgid "Personal info"
@ -1267,7 +1268,7 @@ msgstr "Grupos"
#: contrib/auth/models.py:219 #: contrib/auth/models.py:219
#, fuzzy #, fuzzy
msgid "message" msgid "message"
msgstr "Mensagem" msgstr "mensagem"
#: contrib/auth/forms.py:30 #: contrib/auth/forms.py:30
msgid "" msgid ""
@ -1275,7 +1276,7 @@ msgid ""
"required for logging in." "required for logging in."
msgstr "" msgstr ""
"Seu navegador Web não parece estar com os cookies habilitados. Cookies são " "Seu navegador Web não parece estar com os cookies habilitados. Cookies são "
"requeridos para acesssar." "requeridos para acessar."
#: contrib/contenttypes/models.py:25 #: contrib/contenttypes/models.py:25
#, fuzzy #, fuzzy
@ -1417,52 +1418,52 @@ msgstr "Dezembro"
#: utils/dates.py:19 #: utils/dates.py:19
#, fuzzy #, fuzzy
msgid "jan" msgid "jan"
msgstr "e" msgstr "jan"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "feb" msgid "feb"
msgstr "" msgstr "fev"
#: 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 #, fuzzy
msgid "may" msgid "may"
msgstr "dia" msgstr "mai"
#: utils/dates.py:19 #: utils/dates.py:19
msgid "jun" msgid "jun"
msgstr "" msgstr "jun"
#: utils/dates.py:20 #: utils/dates.py:20
msgid "jul" msgid "jul"
msgstr "" msgstr "jul"
#: 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 "dez"
#: utils/dates.py:27 #: utils/dates.py:27
msgid "Jan." msgid "Jan."
@ -1497,45 +1498,45 @@ msgstr "Dez."
msgid "year" msgid "year"
msgid_plural "years" msgid_plural "years"
msgstr[0] "ano" msgstr[0] "ano"
msgstr[1] "ano" msgstr[1] "anos"
#: utils/timesince.py:13 #: utils/timesince.py:13
#, fuzzy #, fuzzy
msgid "month" msgid "month"
msgid_plural "months" msgid_plural "months"
msgstr[0] "mês" msgstr[0] "mês"
msgstr[1] "mês" 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
#, fuzzy #, fuzzy
msgid "day" msgid "day"
msgid_plural "days" msgid_plural "days"
msgstr[0] "dia" msgstr[0] "dia"
msgstr[1] "dia" msgstr[1] "dias"
#: utils/timesince.py:16 #: utils/timesince.py:16
#, fuzzy #, fuzzy
msgid "hour" msgid "hour"
msgid_plural "hours" msgid_plural "hours"
msgstr[0] "hora" msgstr[0] "hora"
msgstr[1] "hora" msgstr[1] "horas"
#: utils/timesince.py:17 #: utils/timesince.py:17
#, fuzzy #, fuzzy
msgid "minute" msgid "minute"
msgid_plural "minutes" msgid_plural "minutes"
msgstr[0] "minuto" msgstr[0] "minuto"
msgstr[1] "minuto" msgstr[1] "minutos"
#: conf/global_settings.py:37 #: conf/global_settings.py:37
msgid "Bengali" msgid "Bengali"
msgstr "" msgstr "Bengalês"
#: conf/global_settings.py:38 #: conf/global_settings.py:38
msgid "Czech" msgid "Czech"
@ -1548,7 +1549,7 @@ msgstr ""
#: conf/global_settings.py:40 #: conf/global_settings.py:40
#, fuzzy #, fuzzy
msgid "Danish" msgid "Danish"
msgstr "Espanhol" msgstr "Dinamarquês"
#: conf/global_settings.py:41 #: conf/global_settings.py:41
msgid "German" msgid "German"
@ -1556,7 +1557,7 @@ msgstr "Alemão"
#: 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"
@ -1576,11 +1577,11 @@ msgstr "Galiciano"
#: 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 "Hebraico"
#: conf/global_settings.py:49 #: conf/global_settings.py:49
msgid "Icelandic" msgid "Icelandic"
@ -1604,7 +1605,7 @@ msgstr "Norueguês"
#: conf/global_settings.py:54 #: conf/global_settings.py:54
msgid "Brazilian" msgid "Brazilian"
msgstr "Brazileiro" msgstr "Brasileiro"
#: conf/global_settings.py:55 #: conf/global_settings.py:55
msgid "Romanian" msgid "Romanian"
@ -1621,7 +1622,7 @@ msgstr "Eslovaco"
#: conf/global_settings.py:58 #: conf/global_settings.py:58
#, fuzzy #, fuzzy
msgid "Slovenian" msgid "Slovenian"
msgstr "Eslovaco" msgstr "Esloveno"
#: conf/global_settings.py:59 #: conf/global_settings.py:59
msgid "Serbian" msgid "Serbian"
@ -1634,7 +1635,7 @@ msgstr "Sueco"
#: conf/global_settings.py:61 #: conf/global_settings.py:61
#, fuzzy #, fuzzy
msgid "Ukrainian" msgid "Ukrainian"
msgstr "Brazileiro" msgstr "Ucraniano"
#: conf/global_settings.py:62 #: conf/global_settings.py:62
msgid "Simplified Chinese" msgid "Simplified Chinese"
@ -1689,7 +1690,7 @@ msgstr "Este valor não pode conter apenas dígitos."
#: core/validators.py:116 #: core/validators.py:116
msgid "Enter a whole number." msgid "Enter a whole number."
msgstr "Informe um número inteiro." msgstr "Informe um número completo."
#: core/validators.py:120 #: core/validators.py:120
msgid "Only alphabetical characters are allowed here." msgid "Only alphabetical characters are allowed here."
@ -1772,7 +1773,7 @@ msgstr "Informe uma abreviação válida de nome de um estado dos EUA."
msgid "Watch your mouth! The word %s is not allowed here." msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Lave sua boca! A palavra %s não é permitida aqui." msgstr[0] "Lave sua boca! A palavra %s não é permitida aqui."
msgstr[1] "Lave sua boca! A palavra %s não é permitida aqui." msgstr[1] "Lave sua boca! As palavras %s não são permitidas aqui."
#: core/validators.py:236 #: core/validators.py:236
#, python-format #, python-format
@ -1808,14 +1809,14 @@ msgstr "Este valor deve ser uma potência de %s."
#: core/validators.py:347 #: core/validators.py:347
msgid "Please enter a valid decimal number." msgid "Please enter a valid decimal number."
msgstr "Informe um número decimal." msgstr "Informe um número decimal válido."
#: core/validators.py:349 #: core/validators.py:349
#, fuzzy, python-format #, fuzzy, python-format
msgid "Please enter a valid decimal number with at most %s total digit." msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural "" msgid_plural ""
"Please enter a valid decimal number with at most %s total digits." "Please enter a valid decimal number with at most %s total digits."
msgstr[0] "Por favor entre com um número decimal com no máximo %s digitos." msgstr[0] "Por favor entre com um número decimal com no máximo %s digito."
msgstr[1] "Por favor entre com um número decimal com no máximo %s digitos." msgstr[1] "Por favor entre com um número decimal com no máximo %s digitos."
#: core/validators.py:352 #: core/validators.py:352
@ -1824,7 +1825,7 @@ msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural "" msgid_plural ""
"Please enter a valid decimal number with at most %s decimal places." "Please enter a valid decimal number with at most %s decimal places."
msgstr[0] "Informe um número decimal com no máximo %s casa decimal." msgstr[0] "Informe um número decimal com no máximo %s casa decimal."
msgstr[1] "Informe um número decimal com no máximo %s casa decimal." msgstr[1] "Informe um número decimal com no máximo %s casas decimais."
#: core/validators.py:362 #: core/validators.py:362
#, python-format #, python-format
@ -1930,17 +1931,17 @@ msgstr "Este campo é requerido."
#: db/models/fields/__init__.py:337 #: db/models/fields/__init__.py:337
#, fuzzy #, fuzzy
msgid "This value must be an integer." msgid "This value must be an integer."
msgstr "Este valor deve ser uma potência de %s." msgstr "Este valor deve ser um inteiro."
#: db/models/fields/__init__.py:369 #: db/models/fields/__init__.py:369
#, fuzzy #, fuzzy
msgid "This value must be either True or False." msgid "This value must be either True or False."
msgstr "Este valor deve ser uma potência de %s." msgstr "Este valor deve ser Verdadeiro ou Falso."
#: db/models/fields/__init__.py:385 #: db/models/fields/__init__.py:385
#, fuzzy #, fuzzy
msgid "This field cannot be null." msgid "This field cannot be null."
msgstr "Este campo é inválido." msgstr "Este campo não 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."
@ -1954,14 +1955,14 @@ msgstr "Por favor informe um %s válido."
#: db/models/fields/related.py:579 #: db/models/fields/related.py:579
#, fuzzy #, fuzzy
msgid "Separate multiple IDs with commas." msgid "Separate multiple IDs with commas."
msgstr " Separe IDs múltiplos com vírgulas." msgstr "Separe IDs múltiplos com vírgulas."
#: db/models/fields/related.py:581 #: db/models/fields/related.py:581
#, fuzzy #, 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 ""
" Mantenha pressionado \"Control\", ou \"Command\" num Mac para selecionar " " Mantenha pressionado \"Control\", ou \"Command\" no Mac para selecionar "
"mais de uma opção." "mais de uma opção."
#: db/models/fields/related.py:625 #: db/models/fields/related.py:625
@ -1972,18 +1973,18 @@ msgid_plural ""
msgstr[0] "" msgstr[0] ""
"Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido." "Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido."
msgstr[1] "" msgstr[1] ""
"Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido." "Por favor, entre IDs válidos para %(self)s. Os valores %(value)r são inválidos."
#: forms/__init__.py:380 #: forms/__init__.py:380
#, fuzzy, python-format #, fuzzy, python-format
msgid "Ensure your text is less than %s character." msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters." msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "Certifique-se de que seu texto tenha menos que %s caracteres." msgstr[0] "Certifique-se de que seu texto tenha menos que %s caractere."
msgstr[1] "Certifique-se de que seu texto tenha menos que %s caracteres." msgstr[1] "Certifique-se de que seu texto tenha menos que %s caracteres."
#: forms/__init__.py:385 #: forms/__init__.py:385
msgid "Line breaks are not allowed here." msgid "Line breaks are not allowed here."
msgstr "Não são permitidas múltiplas linhas aqui." msgstr "Não são permitidas quebras de linha aqui."
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589 #: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
#, python-format #, python-format
@ -2037,7 +2038,7 @@ msgstr "sim,não,talvez"
#~ "\n" #~ "\n"
#~ "%(text)s" #~ "%(text)s"
#~ msgstr "" #~ msgstr ""
#~ "Este comentário foi envidao por um usuário que enviou menos de %(count)s " #~ "Este comentário foi enviado por um usuário que enviou menos de %(count)s "
#~ "comentário:\n" #~ "comentário:\n"
#~ "\n" #~ "\n"
#~ "%(text)sEste comentário foi enviado por um usuário que enviou menos de %" #~ "%(text)sEste comentário foi enviado por um usuário que enviou menos de %"
@ -2047,4 +2048,4 @@ msgstr "sim,não,talvez"
#, fuzzy #, fuzzy
#~ msgid "count" #~ msgid "count"
#~ msgstr "conteúdo" #~ msgstr "contagem"

View File

@ -1,15 +1,15 @@
# SOME DESCRIPTIVE TITLE. # Português do Brasil translation of django.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package. # This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # Carlos Eduardo de Paula <carlosedp@gmail.com>, 2006.
# #
msgid "" msgid ""
msgstr "" 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: 2006-01-23 19:54-0200\n" "PO-Revision-Date: 2006-11-01 17:45-0300\n"
"Last-Translator: João Marcus Christ <joaoma@gmail.com>\n" "Last-Translator: Carlos Eduardo de Paula <carlosedp@gmail.com>\n"
"Language-Team: Português do Brasil <pt-br@li.org>\n" "Language-Team: Português do Brasil <pt-br@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -51,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 ""
"Janeiro Fevereiro Março Abrio Maio Junho Julho Agosto Setembro Outubro Novembro " "Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro "
"Dezembro" "Dezembro"
#: contrib/admin/media/js/dateparse.js:27 #: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"

View File

@ -98,13 +98,13 @@ def view_index(request):
return missing_docutils_page(request) return missing_docutils_page(request)
if settings.ADMIN_FOR: if settings.ADMIN_FOR:
settings_modules = [__import__(m, '', '', ['']) for m in settings.ADMIN_FOR] settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR]
else: else:
settings_modules = [settings] settings_modules = [settings]
views = [] views = []
for settings_mod in settings_modules: for settings_mod in settings_modules:
urlconf = __import__(settings_mod.ROOT_URLCONF, '', '', ['']) urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, [''])
view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns) view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
if Site._meta.installed: if Site._meta.installed:
site_obj = Site.objects.get(pk=settings_mod.SITE_ID) site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
@ -127,7 +127,7 @@ def view_detail(request, view):
mod, func = urlresolvers.get_mod_func(view) mod, func = urlresolvers.get_mod_func(view)
try: try:
view_func = getattr(__import__(mod, '', '', ['']), func) view_func = getattr(__import__(mod, {}, {}, ['']), func)
except (ImportError, AttributeError): except (ImportError, AttributeError):
raise Http404 raise Http404
title, body, metadata = utils.parse_docstring(view_func.__doc__) title, body, metadata = utils.parse_docstring(view_func.__doc__)
@ -235,7 +235,7 @@ model_detail = staff_member_required(model_detail)
def template_detail(request, template): def template_detail(request, template):
templates = [] templates = []
for site_settings_module in settings.ADMIN_FOR: for site_settings_module in settings.ADMIN_FOR:
settings_mod = __import__(site_settings_module, '', '', ['']) settings_mod = __import__(site_settings_module, {}, {}, [''])
if Site._meta.installed: if Site._meta.installed:
site_obj = Site.objects.get(pk=settings_mod.SITE_ID) site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
else: else:

View File

@ -14,7 +14,7 @@ def template_validator(request):
# get a dict of {site_id : settings_module} for the validator # get a dict of {site_id : settings_module} for the validator
settings_modules = {} settings_modules = {}
for mod in settings.ADMIN_FOR: for mod in settings.ADMIN_FOR:
settings_module = __import__(mod, '', '', ['']) settings_module = __import__(mod, {}, {}, [''])
settings_modules[settings_module.SITE_ID] = settings_module settings_modules[settings_module.SITE_ID] = settings_module
manipulator = TemplateValidator(settings_modules) manipulator = TemplateValidator(settings_modules)
new_data, errors = {}, {} new_data, errors = {}, {}

View File

@ -9,7 +9,7 @@ def load_backend(path):
i = path.rfind('.') i = path.rfind('.')
module, attr = path[:i], path[i+1:] module, attr = path[:i], path[i+1:]
try: try:
mod = __import__(module, '', '', [attr]) mod = __import__(module, {}, {}, [attr])
except ImportError, e: except ImportError, e:
raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e) raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e)
try: try:

View File

@ -48,7 +48,7 @@ def get_cache(backend_uri):
if host.endswith('/'): if host.endswith('/'):
host = host[:-1] host = host[:-1]
cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], '', '', ['']), 'CacheClass') cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], {}, {}, ['']), 'CacheClass')
return cache_class(host, params) return cache_class(host, params)
cache = get_cache(settings.CACHE_BACKEND) cache = get_cache(settings.CACHE_BACKEND)

View File

@ -26,7 +26,7 @@ class BaseHandler(object):
raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:] mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
try: try:
mod = __import__(mw_module, '', '', ['']) mod = __import__(mw_module, {}, {}, [''])
except ImportError, e: except ImportError, e:
raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e) raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
try: try:

View File

@ -289,7 +289,7 @@ def syncdb(verbosity=1, interactive=True):
# Import the 'management' module within each installed app, to register # Import the 'management' module within each installed app, to register
# dispatcher events. # dispatcher events.
try: try:
__import__(app_name + '.management', '', '', ['']) __import__(app_name + '.management', {}, {}, [''])
except ImportError: except ImportError:
pass pass
@ -1078,7 +1078,7 @@ def test(app_labels, verbosity=1):
test_module_name = '.'.join(test_path[:-1]) test_module_name = '.'.join(test_path[:-1])
else: else:
test_module_name = '.' test_module_name = '.'
test_module = __import__(test_module_name, [],[],test_path[-1]) test_module = __import__(test_module_name, {}, {}, test_path[-1])
test_runner = getattr(test_module, test_path[-1]) test_runner = getattr(test_module, test_path[-1])
test_runner(app_list, verbosity) test_runner(app_list, verbosity)
@ -1267,7 +1267,7 @@ def setup_environ(settings_mod):
project_directory = os.path.dirname(settings_mod.__file__) project_directory = os.path.dirname(settings_mod.__file__)
project_name = os.path.basename(project_directory) project_name = os.path.basename(project_directory)
sys.path.append(os.path.join(project_directory, '..')) sys.path.append(os.path.join(project_directory, '..'))
project_module = __import__(project_name, '', '', ['']) project_module = __import__(project_name, {}, {}, [''])
sys.path.pop() sys.path.pop()
# Set DJANGO_SETTINGS_MODULE appropriately. # Set DJANGO_SETTINGS_MODULE appropriately.

View File

@ -29,7 +29,7 @@ _serializers = {}
def register_serializer(format, serializer_module): def register_serializer(format, serializer_module):
"""Register a new serializer by passing in a module name.""" """Register a new serializer by passing in a module name."""
module = __import__(serializer_module, '', '', ['']) module = __import__(serializer_module, {}, {}, [''])
_serializers[format] = module _serializers[format] = module
def unregister_serializer(format): def unregister_serializer(format):

View File

@ -31,6 +31,8 @@ Optional Fcgi settings: (setting=value)
port=PORTNUM port to listen on. port=PORTNUM port to listen on.
socket=FILE UNIX socket to listen on. socket=FILE UNIX socket to listen on.
method=IMPL prefork or threaded (default prefork) method=IMPL prefork or threaded (default prefork)
maxrequests=NUMBER number of requests a child handles before it is
killed and a new child is forked (0 = no limit).
maxspare=NUMBER max number of spare processes to keep running. maxspare=NUMBER max number of spare processes to keep running.
minspare=NUMBER min number of spare processes to prefork. minspare=NUMBER min number of spare processes to prefork.
maxchildren=NUMBER hard limit number of processes in prefork mode. maxchildren=NUMBER hard limit number of processes in prefork mode.
@ -66,6 +68,7 @@ FASTCGI_OPTIONS = {
'maxspare': 5, 'maxspare': 5,
'minspare': 2, 'minspare': 2,
'maxchildren': 50, 'maxchildren': 50,
'maxrequests': 0,
} }
def fastcgi_help(message=None): def fastcgi_help(message=None):
@ -103,6 +106,7 @@ def runfastcgi(argset=[], **kwargs):
'maxSpare': int(options["maxspare"]), 'maxSpare': int(options["maxspare"]),
'minSpare': int(options["minspare"]), 'minSpare': int(options["minspare"]),
'maxChildren': int(options["maxchildren"]), 'maxChildren': int(options["maxchildren"]),
'maxRequests': int(options["maxrequests"]),
} }
elif options['method'] in ('thread', 'threaded'): elif options['method'] in ('thread', 'threaded'):
from flup.server.fcgi import WSGIServer from flup.server.fcgi import WSGIServer

View File

@ -119,7 +119,7 @@ class RegexURLPattern(object):
return self._callback return self._callback
mod_name, func_name = get_mod_func(self._callback_str) mod_name, func_name = get_mod_func(self._callback_str)
try: try:
self._callback = getattr(__import__(mod_name, '', '', ['']), func_name) self._callback = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except ImportError, e: except ImportError, e:
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e)) raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
except AttributeError, e: except AttributeError, e:
@ -130,7 +130,7 @@ class RegexURLPattern(object):
def reverse(self, viewname, *args, **kwargs): def reverse(self, viewname, *args, **kwargs):
mod_name, func_name = get_mod_func(viewname) mod_name, func_name = get_mod_func(viewname)
try: try:
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name) lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except (ImportError, AttributeError): except (ImportError, AttributeError):
raise NoReverseMatch raise NoReverseMatch
if lookup_view != self.callback: if lookup_view != self.callback:
@ -171,7 +171,7 @@ class RegexURLResolver(object):
return self._urlconf_module return self._urlconf_module
except AttributeError: except AttributeError:
try: try:
self._urlconf_module = __import__(self.urlconf_name, '', '', ['']) self._urlconf_module = __import__(self.urlconf_name, {}, {}, [''])
except ValueError, e: except ValueError, e:
# Invalid urlconf_name, such as "foo.bar." (note trailing period) # Invalid urlconf_name, such as "foo.bar." (note trailing period)
raise ImproperlyConfigured, "Error while importing URLconf %r: %s" % (self.urlconf_name, e) raise ImproperlyConfigured, "Error while importing URLconf %r: %s" % (self.urlconf_name, e)
@ -186,7 +186,7 @@ class RegexURLResolver(object):
callback = getattr(self.urlconf_module, 'handler%s' % view_type) callback = getattr(self.urlconf_module, 'handler%s' % view_type)
mod_name, func_name = get_mod_func(callback) mod_name, func_name = get_mod_func(callback)
try: try:
return getattr(__import__(mod_name, '', '', ['']), func_name), {} return getattr(__import__(mod_name, {}, {}, ['']), func_name), {}
except (ImportError, AttributeError), e: except (ImportError, AttributeError), e:
raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e)) raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e))
@ -200,7 +200,7 @@ class RegexURLResolver(object):
if not callable(lookup_view): if not callable(lookup_view):
mod_name, func_name = get_mod_func(lookup_view) mod_name, func_name = get_mod_func(lookup_view)
try: try:
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name) lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
except (ImportError, AttributeError): except (ImportError, AttributeError):
raise NoReverseMatch raise NoReverseMatch
for pattern in self.urlconf_module.urlpatterns: for pattern in self.urlconf_module.urlpatterns:

View File

@ -73,16 +73,16 @@ class ConnectionInfo(object):
def get_introspection_module(self): def get_introspection_module(self):
return __import__('django.db.backends.%s.introspection' % return __import__('django.db.backends.%s.introspection' %
self.settings.DATABASE_ENGINE, '', '', ['']) self.settings.DATABASE_ENGINE, {}, {}, [''])
def get_creation_module(self): def get_creation_module(self):
return __import__('django.db.backends.%s.creation' % return __import__('django.db.backends.%s.creation' %
self.settings.DATABASE_ENGINE, '', '', ['']) self.settings.DATABASE_ENGINE, {}, {}, [''])
def load_backend(self): def load_backend(self):
try: try:
backend = __import__('django.db.backends.%s.base' % backend = __import__('django.db.backends.%s.base' %
self.settings.DATABASE_ENGINE, '', '', ['']) self.settings.DATABASE_ENGINE, {}, {}, [''])
except ImportError, e: except ImportError, e:
# The database backend wasn't found. Display a helpful error # The database backend wasn't found. Display a helpful error
# message listing all possible database backends. # message listing all possible database backends.
@ -108,7 +108,7 @@ class ConnectionInfo(object):
def runshell(self): def runshell(self):
__import__('django.db.backends.%s.client' % __import__('django.db.backends.%s.client' %
self.settings.DATABASE_ENGINE, '', '', [''] self.settings.DATABASE_ENGINE, {}, {}, ['']
).runshell(self.settings) ).runshell(self.settings)
def reset_queries(self): def reset_queries(self):

View File

@ -383,27 +383,6 @@ class Model(object):
setattr(self, cachename, get_image_dimensions(filename)) setattr(self, cachename, get_image_dimensions(filename))
return getattr(self, cachename) return getattr(self, cachename)
# Handles setting many-to-many related objects.
# Example: Album.set_songs()
def _set_related_many_to_many(self, rel_class, rel_field, id_list):
id_list = map(int, id_list) # normalize to integers
rel = rel_field.rel.to
m2m_table = rel_field.m2m_db_table()
this_id = self._get_pk_val()
db = self._default_manager.db
connection = db.connection
qn = db.backend.quote_name
cursor = connection.cursor()
cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
(qn(m2m_table),
qn(rel_field.m2m_column_name())), [this_id])
sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
(qn(m2m_table),
qn(rel_field.m2m_column_name()),
qn(rel_field.m2m_reverse_name()))
cursor.executemany(sql, [(this_id, i) for i in id_list])
transaction.commit_unless_managed([connection])
############################################ ############################################
# HELPER FUNCTIONS (CURRIED MODEL METHODS) # # HELPER FUNCTIONS (CURRIED MODEL METHODS) #
############################################ ############################################

View File

@ -457,7 +457,9 @@ class DateField(Field):
def get_db_prep_save(self, value): def get_db_prep_save(self, value):
# Casts dates into string format for entry into database. # Casts dates into string format for entry into database.
if value is not None: if isinstance(value, datetime.datetime):
value = value.date().strftime('%Y-%m-%d')
elif isinstance(value, datetime.date):
value = value.strftime('%Y-%m-%d') value = value.strftime('%Y-%m-%d')
return Field.get_db_prep_save(self, value) return Field.get_db_prep_save(self, value)
@ -487,7 +489,7 @@ class DateTimeField(DateField):
def pre_save(self, model_instance, add): def pre_save(self, model_instance, add):
value = super(DateField, self).pre_save(model_instance, add) value = super(DateField, self).pre_save(model_instance, add)
if value is not None: if isinstance(value, datetime.datetime):
# MySQL will throw a warning if microseconds are given, because it # MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds. # doesn't support microseconds.
settings = model_instance._default_manager.db.connection.settings settings = model_instance._default_manager.db.connection.settings
@ -499,6 +501,13 @@ class DateTimeField(DateField):
# Casts dates into string format for entry into database. # Casts dates into string format for entry into database.
if value is not None: if value is not None:
value = str(value) value = str(value)
elif isinstance(value, datetime.date):
# MySQL will throw a warning if microseconds are given, because it
# doesn't support microseconds.
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
value = datetime.datetime(value.year, value.month, value.day, microsecond=0)
value = str(value)
return Field.get_db_prep_save(self, value) return Field.get_db_prep_save(self, value)
def get_db_prep_lookup(self, lookup_type, value): def get_db_prep_lookup(self, lookup_type, value):

View File

@ -51,7 +51,7 @@ def get_app(app_label, emptyOK=False):
def load_app(app_name): def load_app(app_name):
"Loads the app with the provided fully qualified name, and returns the model module." "Loads the app with the provided fully qualified name, and returns the model module."
global _app_list global _app_list
mod = __import__(app_name, '', '', ['models']) mod = __import__(app_name, {}, {}, ['models'])
if not hasattr(mod, 'models'): if not hasattr(mod, 'models'):
return None return None
if mod.models not in _app_list: if mod.models not in _app_list:

View File

@ -2,8 +2,6 @@
Django validation and HTML form handling. Django validation and HTML form handling.
TODO: TODO:
Validation not tied to a particular field
<select> and validation of lists
Default value for field Default value for field
Field labels Field labels
Nestable Forms Nestable Forms
@ -12,6 +10,7 @@ TODO:
"This form field requires foo.js" and form.js_includes() "This form field requires foo.js" and form.js_includes()
""" """
from util import ValidationError
from widgets import * from widgets import *
from fields import * from fields import *
from forms import Form from forms import Form

View File

@ -3,7 +3,7 @@ Field classes
""" """
from util import ValidationError, DEFAULT_ENCODING from util import ValidationError, DEFAULT_ENCODING
from widgets import TextInput, CheckboxInput from widgets import TextInput, CheckboxInput, Select, SelectMultiple
import datetime import datetime
import re import re
import time import time
@ -12,12 +12,19 @@ __all__ = (
'Field', 'CharField', 'IntegerField', 'Field', 'CharField', 'IntegerField',
'DEFAULT_DATE_INPUT_FORMATS', 'DateField', 'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField', 'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
'RegexField', 'EmailField', 'BooleanField', 'RegexField', 'EmailField', 'URLField', 'BooleanField',
'ChoiceField', 'MultipleChoiceField',
'ComboField',
) )
# These values, if given to to_python(), will trigger the self.required check. # These values, if given to to_python(), will trigger the self.required check.
EMPTY_VALUES = (None, '') EMPTY_VALUES = (None, '')
try:
set # Only available in Python 2.4+
except NameError:
from sets import Set as set # Python 2.3 fallback
class Field(object): class Field(object):
widget = TextInput # Default widget to use when rendering this type of Field. widget = TextInput # Default widget to use when rendering this type of Field.
@ -28,9 +35,9 @@ class Field(object):
widget = widget() widget = widget()
self.widget = widget self.widget = widget
def to_python(self, value): def clean(self, value):
""" """
Validates the given value and returns its "normalized" value as an Validates the given value and returns its "cleaned" value as an
appropriate Python object. appropriate Python object.
Raises ValidationError for any errors. Raises ValidationError for any errors.
@ -44,9 +51,9 @@ class CharField(Field):
Field.__init__(self, required, widget) Field.__init__(self, required, widget)
self.max_length, self.min_length = max_length, min_length self.max_length, self.min_length = max_length, min_length
def to_python(self, value): def clean(self, value):
"Validates max_length and min_length. Returns a Unicode object." "Validates max_length and min_length. Returns a Unicode object."
Field.to_python(self, value) Field.clean(self, value)
if value in EMPTY_VALUES: value = u'' if value in EMPTY_VALUES: value = u''
if not isinstance(value, basestring): if not isinstance(value, basestring):
value = unicode(str(value), DEFAULT_ENCODING) value = unicode(str(value), DEFAULT_ENCODING)
@ -59,12 +66,12 @@ class CharField(Field):
return value return value
class IntegerField(Field): class IntegerField(Field):
def to_python(self, value): def clean(self, value):
""" """
Validates that int() can be called on the input. Returns the result Validates that int() can be called on the input. Returns the result
of int(). of int().
""" """
super(IntegerField, self).to_python(value) super(IntegerField, self).clean(value)
try: try:
return int(value) return int(value)
except (ValueError, TypeError): except (ValueError, TypeError):
@ -83,12 +90,12 @@ class DateField(Field):
Field.__init__(self, required, widget) Field.__init__(self, required, widget)
self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS
def to_python(self, value): def clean(self, value):
""" """
Validates that the input can be converted to a date. Returns a Python Validates that the input can be converted to a date. Returns a Python
datetime.date object. datetime.date object.
""" """
Field.to_python(self, value) Field.clean(self, value)
if value in EMPTY_VALUES: if value in EMPTY_VALUES:
return None return None
if isinstance(value, datetime.datetime): if isinstance(value, datetime.datetime):
@ -119,12 +126,12 @@ class DateTimeField(Field):
Field.__init__(self, required, widget) Field.__init__(self, required, widget)
self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
def to_python(self, value): def clean(self, value):
""" """
Validates that the input can be converted to a datetime. Returns a Validates that the input can be converted to a datetime. Returns a
Python datetime.datetime object. Python datetime.datetime object.
""" """
Field.to_python(self, value) Field.clean(self, value)
if value in EMPTY_VALUES: if value in EMPTY_VALUES:
return None return None
if isinstance(value, datetime.datetime): if isinstance(value, datetime.datetime):
@ -151,12 +158,12 @@ class RegexField(Field):
self.regex = regex self.regex = regex
self.error_message = error_message or u'Enter a valid value.' self.error_message = error_message or u'Enter a valid value.'
def to_python(self, value): def clean(self, value):
""" """
Validates that the input matches the regular expression. Returns a Validates that the input matches the regular expression. Returns a
Unicode object. Unicode object.
""" """
Field.to_python(self, value) Field.clean(self, value)
if value in EMPTY_VALUES: value = u'' if value in EMPTY_VALUES: value = u''
if not isinstance(value, basestring): if not isinstance(value, basestring):
value = unicode(str(value), DEFAULT_ENCODING) value = unicode(str(value), DEFAULT_ENCODING)
@ -175,10 +182,96 @@ class EmailField(RegexField):
def __init__(self, required=True, widget=None): def __init__(self, required=True, widget=None):
RegexField.__init__(self, email_re, u'Enter a valid e-mail address.', required, widget) RegexField.__init__(self, email_re, u'Enter a valid e-mail address.', required, widget)
url_re = re.compile(
r'^https?://' # http:// or https://
r'(?:[A-Z0-9-]+\.)+[A-Z]{2,6}' # domain
r'(?::\d+)?' # optional port
r'(?:/?|/\S+)$', re.IGNORECASE)
class URLField(RegexField):
def __init__(self, required=True, verify_exists=False, widget=None):
RegexField.__init__(self, url_re, u'Enter a valid URL.', required, widget)
self.verify_exists = verify_exists
def clean(self, value):
value = RegexField.clean(self, value)
if self.verify_exists:
import urllib2
try:
u = urllib2.urlopen(value)
except ValueError:
raise ValidationError(u'Enter a valid URL.')
except: # urllib2.URLError, httplib.InvalidURL, etc.
raise ValidationError(u'This URL appears to be a broken link.')
return value
class BooleanField(Field): class BooleanField(Field):
widget = CheckboxInput widget = CheckboxInput
def to_python(self, value): def clean(self, value):
"Returns a Python boolean object." "Returns a Python boolean object."
Field.to_python(self, value) Field.clean(self, value)
return bool(value) return bool(value)
class ChoiceField(Field):
def __init__(self, choices=(), required=True, widget=Select):
if isinstance(widget, type):
widget = widget(choices=choices)
Field.__init__(self, required, widget)
self.choices = choices
def clean(self, value):
"""
Validates that the input is in self.choices.
"""
value = Field.clean(self, value)
if value in EMPTY_VALUES: value = u''
if not isinstance(value, basestring):
value = unicode(str(value), DEFAULT_ENCODING)
elif not isinstance(value, unicode):
value = unicode(value, DEFAULT_ENCODING)
valid_values = set([str(k) for k, v in self.choices])
if value not in valid_values:
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % value)
return value
class MultipleChoiceField(ChoiceField):
def __init__(self, choices=(), required=True, widget=SelectMultiple):
ChoiceField.__init__(self, choices, required, widget)
def clean(self, value):
"""
Validates that the input is a list or tuple.
"""
if not isinstance(value, (list, tuple)):
raise ValidationError(u'Enter a list of values.')
if self.required and not value:
raise ValidationError(u'This field is required.')
new_value = []
for val in value:
if not isinstance(val, basestring):
value = unicode(str(val), DEFAULT_ENCODING)
elif not isinstance(val, unicode):
value = unicode(val, DEFAULT_ENCODING)
new_value.append(value)
# Validate that each value in the value list is in self.choices.
valid_values = set([k for k, v in self.choices])
for val in new_value:
if val not in valid_values:
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % val)
return new_value
class ComboField(Field):
def __init__(self, fields=(), required=True, widget=None):
Field.__init__(self, required, widget)
self.fields = fields
def clean(self, value):
"""
Validates the given value against all of self.fields, which is a
list of Field instances.
"""
Field.clean(self, value)
for field in self.fields:
value = field.clean(value)
return value

View File

@ -6,6 +6,13 @@ from fields import Field
from widgets import TextInput, Textarea from widgets import TextInput, Textarea
from util import ErrorDict, ErrorList, ValidationError from util import ErrorDict, ErrorList, ValidationError
NON_FIELD_ERRORS = '__all__'
def pretty_name(name):
"Converts 'first_name' to 'First name'"
name = name[0].upper() + name[1:]
return name.replace('_', ' ')
class DeclarativeFieldsMetaclass(type): class DeclarativeFieldsMetaclass(type):
"Metaclass that converts Field attributes to a dictionary called 'fields'." "Metaclass that converts Field attributes to a dictionary called 'fields'."
def __new__(cls, name, bases, attrs): def __new__(cls, name, bases, attrs):
@ -18,22 +25,33 @@ class Form(object):
def __init__(self, data=None): # TODO: prefix stuff def __init__(self, data=None): # TODO: prefix stuff
self.data = data or {} self.data = data or {}
self.__data_python = None # Stores the data after to_python() has been called. self.clean_data = None # Stores the data after clean() has been called.
self.__errors = None # Stores the errors after to_python() has been called. self.__errors = None # Stores the errors after clean() has been called.
def __str__(self):
return self.as_table()
def __iter__(self): def __iter__(self):
for name, field in self.fields.items(): for name, field in self.fields.items():
yield BoundField(self, field, name) yield BoundField(self, field, name)
def to_python(self): def __getitem__(self, name):
"Returns a BoundField with the given name."
try:
field = self.fields[name]
except KeyError:
raise KeyError('Key %r not found in Form' % name)
return BoundField(self, field, name)
def clean(self):
if self.__errors is None: if self.__errors is None:
self._validate() self.full_clean()
return self.__data_python return self.clean_data
def errors(self): def errors(self):
"Returns an ErrorDict for self.data" "Returns an ErrorDict for self.data"
if self.__errors is None: if self.__errors is None:
self._validate() self.full_clean()
return self.__errors return self.__errors
def is_valid(self): def is_valid(self):
@ -44,27 +62,75 @@ class Form(object):
""" """
return not bool(self.errors()) return not bool(self.errors())
def __getitem__(self, name): def as_table(self):
"Returns a BoundField with the given name." "Returns this form rendered as an HTML <table>."
try: output = u'\n'.join(['<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()])
field = self.fields[name] return '<table>\n%s\n</table>' % output
except KeyError:
raise KeyError('Key %r not found in Form' % name)
return BoundField(self, field, name)
def _validate(self): def as_ul(self):
data_python = {} "Returns this form rendered as an HTML <ul>."
output = u'\n'.join(['<li>%s: %s</li>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()])
return '<ul>\n%s\n</ul>' % output
def as_table_with_errors(self):
"Returns this form rendered as an HTML <table>, with errors."
output = []
if self.errors().get(NON_FIELD_ERRORS):
# Errors not corresponding to a particular field are displayed at the top.
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
for name, field in self.fields.items():
bf = BoundField(self, field, name)
if bf.errors:
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors]))
output.append('<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), bf))
return '<table>\n%s\n</table>' % '\n'.join(output)
def as_ul_with_errors(self):
"Returns this form rendered as an HTML <ul>, with errors."
output = []
if self.errors().get(NON_FIELD_ERRORS):
# Errors not corresponding to a particular field are displayed at the top.
output.append('<li><ul>%s</ul></li>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
for name, field in self.fields.items():
bf = BoundField(self, field, name)
line = '<li>'
if bf.errors:
line += '<ul>%s</ul>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors])
line += '%s: %s</li>' % (pretty_name(name), bf)
output.append(line)
return '<ul>\n%s\n</ul>' % '\n'.join(output)
def full_clean(self):
"""
Cleans all of self.data and populates self.__errors and self.clean_data.
"""
self.clean_data = {}
errors = ErrorDict() errors = ErrorDict()
for name, field in self.fields.items(): for name, field in self.fields.items():
value = self.data.get(name, None)
try: try:
value = field.to_python(self.data.get(name, None)) value = field.clean(value)
data_python[name] = value self.clean_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.clean_data[name] = value
except ValidationError, e: except ValidationError, e:
errors[name] = e.messages errors[name] = e.messages
if not errors: # Only set self.data_python if there weren't errors. try:
self.__data_python = data_python self.clean_data = self.clean()
except ValidationError, e:
errors[NON_FIELD_ERRORS] = e.messages
if errors:
self.clean_data = None
self.__errors = errors self.__errors = errors
def clean(self):
"""
Hook for doing any extra form-wide cleaning after Field.clean() been
called on every field.
"""
return self.clean_data
class BoundField(object): class BoundField(object):
"A Field plus data" "A Field plus data"
def __init__(self, form, field, name): def __init__(self, form, field, name):

View File

@ -2,30 +2,55 @@
HTML Widget classes HTML Widget classes
""" """
__all__ = ('Widget', 'TextInput', 'Textarea', 'CheckboxInput') __all__ = (
'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'FileInput',
'Textarea', 'CheckboxInput',
'Select', 'SelectMultiple',
)
from django.utils.html import escape from django.utils.html import escape
from itertools import chain
try:
set # Only available in Python 2.4+
except NameError:
from sets import Set as set # Python 2.3 fallback
# Converts a dictionary to a single string with key="value", XML-style. # Converts a dictionary to a single string with key="value", XML-style.
# Assumes keys do not need to be XML-escaped. # Assumes keys do not need to be XML-escaped.
flatatt = lambda attrs: ' '.join(['%s="%s"' % (k, escape(v)) for k, v in attrs.items()]) flatatt = lambda attrs: ' '.join(['%s="%s"' % (k, escape(v)) for k, v in attrs.items()])
class Widget(object): class Widget(object):
requires_data_list = False # Determines whether render()'s 'value' argument should be a list.
def __init__(self, attrs=None): def __init__(self, attrs=None):
self.attrs = attrs or {} self.attrs = attrs or {}
def render(self, name, value): def render(self, name, value):
raise NotImplementedError raise NotImplementedError
class TextInput(Widget): class Input(Widget):
"Base class for all <input> widgets (except type='checkbox', which is special)"
input_type = None # Subclasses must define this.
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
if value is None: value = '' if value is None: value = ''
final_attrs = dict(self.attrs, type='text', name=name) final_attrs = dict(self.attrs, type=self.input_type, name=name)
if attrs: if attrs:
final_attrs.update(attrs) final_attrs.update(attrs)
if value != '': final_attrs['value'] = value # Only add the 'value' attribute if a value is non-empty. if value != '': final_attrs['value'] = value # Only add the 'value' attribute if a value is non-empty.
return u'<input %s />' % flatatt(final_attrs) return u'<input %s />' % flatatt(final_attrs)
class TextInput(Input):
input_type = 'text'
class PasswordInput(Input):
input_type = 'password'
class HiddenInput(Input):
input_type = 'hidden'
class FileInput(Input):
input_type = 'file'
class Textarea(Widget): class Textarea(Widget):
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
if value is None: value = '' if value is None: value = ''
@ -41,3 +66,48 @@ class CheckboxInput(Widget):
final_attrs.update(attrs) final_attrs.update(attrs)
if value: final_attrs['checked'] = 'checked' if value: final_attrs['checked'] = 'checked'
return u'<input %s />' % flatatt(final_attrs) return u'<input %s />' % flatatt(final_attrs)
class Select(Widget):
def __init__(self, attrs=None, choices=()):
# choices can be any iterable
self.attrs = attrs or {}
self.choices = choices
def render(self, name, value, attrs=None, choices=()):
if value is None: value = ''
final_attrs = dict(self.attrs, name=name)
if attrs:
final_attrs.update(attrs)
output = [u'<select %s>' % flatatt(final_attrs)]
str_value = str(value) # Normalize to string.
for option_value, option_label in chain(self.choices, choices):
selected_html = (str(option_value) == str_value) and ' selected="selected"' or ''
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(option_label)))
output.append(u'</select>')
return u'\n'.join(output)
class SelectMultiple(Widget):
requires_data_list = True
def __init__(self, attrs=None, choices=()):
# choices can be any iterable
self.attrs = attrs or {}
self.choices = choices
def render(self, name, value, attrs=None, choices=()):
if value is None: value = []
final_attrs = dict(self.attrs, name=name)
if attrs:
final_attrs.update(attrs)
output = [u'<select multiple="multiple" %s>' % flatatt(final_attrs)]
str_values = set([str(v) for v in value]) # Normalize to strings.
for option_value, option_label in chain(self.choices, choices):
selected_html = (str(option_value) in str_values) and ' selected="selected"' or ''
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(option_label)))
output.append(u'</select>')
return u'\n'.join(output)
class RadioSelect(Widget):
pass
class CheckboxSelectMultiple(Widget):
pass

View File

@ -883,7 +883,7 @@ def get_library(module_name):
lib = libraries.get(module_name, None) lib = libraries.get(module_name, None)
if not lib: if not lib:
try: try:
mod = __import__(module_name, '', '', ['']) mod = __import__(module_name, {}, {}, [''])
except ImportError, e: except ImportError, e:
raise InvalidTemplateLibrary, "Could not load template library from %s, %s" % (module_name, e) raise InvalidTemplateLibrary, "Could not load template library from %s, %s" % (module_name, e)
try: try:

View File

@ -69,7 +69,7 @@ def get_standard_processors():
i = path.rfind('.') i = path.rfind('.')
module, attr = path[:i], path[i+1:] module, attr = path[:i], path[i+1:]
try: try:
mod = __import__(module, '', '', [attr]) mod = __import__(module, {}, {}, [attr])
except ImportError, e: except ImportError, e:
raise ImproperlyConfigured, 'Error importing request processor module %s: "%s"' % (module, e) raise ImproperlyConfigured, 'Error importing request processor module %s: "%s"' % (module, e)
try: try:

View File

@ -15,9 +15,9 @@ for app in settings.INSTALLED_APPS:
m, a = app[:i], app[i+1:] m, a = app[:i], app[i+1:]
try: try:
if a is None: if a is None:
mod = __import__(m, '', '', []) mod = __import__(m, {}, {}, [])
else: else:
mod = getattr(__import__(m, '', '', [a]), a) mod = getattr(__import__(m, {}, {}, [a]), a)
except ImportError, e: except ImportError, e:
raise ImproperlyConfigured, 'ImportError %s: %s' % (app, e.args[0]) raise ImproperlyConfigured, 'ImportError %s: %s' % (app, e.args[0])
template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates') template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')

View File

@ -2,6 +2,6 @@ from django.conf import settings
for a in settings.INSTALLED_APPS: for a in settings.INSTALLED_APPS:
try: try:
__path__.extend(__import__(a + '.templatetags', '', '', ['']).__path__) __path__.extend(__import__(a + '.templatetags', {}, {}, ['']).__path__)
except ImportError: except ImportError:
pass pass

View File

@ -28,7 +28,7 @@ def build_suite(app_module):
# models module # models module
try: try:
app_path = app_module.__name__.split('.')[:-1] app_path = app_module.__name__.split('.')[:-1]
test_module = __import__('.'.join(app_path + [TEST_MODULE]), [], [], TEST_MODULE) test_module = __import__('.'.join(app_path + [TEST_MODULE]), {}, {}, TEST_MODULE)
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module)) suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
try: try:

View File

@ -75,7 +75,7 @@ def technical_500_response(request, exc_type, exc_value, tb):
loader_debug_info = [] loader_debug_info = []
for loader in template_source_loaders: for loader in template_source_loaders:
try: try:
source_list_func = getattr(__import__(loader.__module__, '', '', ['get_template_sources']), 'get_template_sources') source_list_func = getattr(__import__(loader.__module__, {}, {}, ['get_template_sources']), 'get_template_sources')
# NOTE: This assumes exc_value is the name of the template that # NOTE: This assumes exc_value is the name of the template that
# the loader attempted to load. # the loader attempted to load.
template_list = [{'name': t, 'exists': os.path.exists(t)} \ template_list = [{'name': t, 'exists': os.path.exists(t)} \

View File

@ -745,7 +745,7 @@ messages are made available in the `template context`_ as the template variable
{% if messages %} {% if messages %}
<ul> <ul>
{% for message in messages %} {% for message in messages %}
<li>{{ message.message }}</li> <li>{{ message }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}

View File

@ -97,7 +97,8 @@ which is a dictionary of the parameters captured in the URL.
* ``extra_context``: A dictionary of values to add to the template * ``extra_context``: A dictionary of values to add to the template
context. By default, this is an empty dictionary. If a value in the context. By default, this is an empty dictionary. If a value in the
dictionary is callable, the generic view will call it dictionary is callable, the generic view will call it
just before rendering the template. just before rendering the template. (**This is new in the
Django development version.**)
**Example:** **Example:**

View File

@ -31,7 +31,7 @@ How to do it
Just put this in your URLconf_:: Just put this in your URLconf_::
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}), (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
...where ``site_media`` is the URL where your media will be rooted, and ...where ``site_media`` is the URL where your media will be rooted, and
``/path/to/media`` is the filesystem root for your media. ``/path/to/media`` is the filesystem root for your media.
@ -60,7 +60,7 @@ listings for directories.
Example:: Example::
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}), (r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
You can customize the index view by creating a template called You can customize the index view by creating a template called
``static/directory_index``. That template gets two objects in its context: ``static/directory_index``. That template gets two objects in its context:

View File

@ -29,6 +29,84 @@ u'<input type="text" class="fun" value="foo@example.com" name="email" />'
>>> w.render('email', '', attrs={'class': 'special'}) >>> w.render('email', '', attrs={'class': 'special'})
u'<input type="text" class="special" name="email" />' u'<input type="text" class="special" name="email" />'
# PasswordInput Widget ############################################################
>>> w = PasswordInput()
>>> w.render('email', '')
u'<input type="password" name="email" />'
>>> w.render('email', None)
u'<input type="password" name="email" />'
>>> w.render('email', 'test@example.com')
u'<input type="password" name="email" value="test@example.com" />'
>>> w.render('email', 'some "quoted" & ampersanded value')
u'<input type="password" name="email" value="some &quot;quoted&quot; &amp; ampersanded value" />'
>>> w.render('email', 'test@example.com', attrs={'class': 'fun'})
u'<input type="password" name="email" value="test@example.com" class="fun" />'
You can also pass 'attrs' to the constructor:
>>> w = PasswordInput(attrs={'class': 'fun'})
>>> w.render('email', '')
u'<input type="password" class="fun" name="email" />'
>>> w.render('email', 'foo@example.com')
u'<input type="password" class="fun" value="foo@example.com" name="email" />'
'attrs' passed to render() get precedence over those passed to the constructor:
>>> w = PasswordInput(attrs={'class': 'pretty'})
>>> w.render('email', '', attrs={'class': 'special'})
u'<input type="password" class="special" name="email" />'
# HiddenInput Widget ############################################################
>>> w = HiddenInput()
>>> w.render('email', '')
u'<input type="hidden" name="email" />'
>>> w.render('email', None)
u'<input type="hidden" name="email" />'
>>> w.render('email', 'test@example.com')
u'<input type="hidden" name="email" value="test@example.com" />'
>>> w.render('email', 'some "quoted" & ampersanded value')
u'<input type="hidden" name="email" value="some &quot;quoted&quot; &amp; ampersanded value" />'
>>> w.render('email', 'test@example.com', attrs={'class': 'fun'})
u'<input type="hidden" name="email" value="test@example.com" class="fun" />'
You can also pass 'attrs' to the constructor:
>>> w = HiddenInput(attrs={'class': 'fun'})
>>> w.render('email', '')
u'<input type="hidden" class="fun" name="email" />'
>>> w.render('email', 'foo@example.com')
u'<input type="hidden" class="fun" value="foo@example.com" name="email" />'
'attrs' passed to render() get precedence over those passed to the constructor:
>>> w = HiddenInput(attrs={'class': 'pretty'})
>>> w.render('email', '', attrs={'class': 'special'})
u'<input type="hidden" class="special" name="email" />'
# FileInput Widget ############################################################
>>> w = FileInput()
>>> w.render('email', '')
u'<input type="file" name="email" />'
>>> w.render('email', None)
u'<input type="file" name="email" />'
>>> w.render('email', 'test@example.com')
u'<input type="file" name="email" value="test@example.com" />'
>>> w.render('email', 'some "quoted" & ampersanded value')
u'<input type="file" name="email" value="some &quot;quoted&quot; &amp; ampersanded value" />'
>>> w.render('email', 'test@example.com', attrs={'class': 'fun'})
u'<input type="file" name="email" value="test@example.com" class="fun" />'
You can also pass 'attrs' to the constructor:
>>> w = FileInput(attrs={'class': 'fun'})
>>> w.render('email', '')
u'<input type="file" class="fun" name="email" />'
>>> w.render('email', 'foo@example.com')
u'<input type="file" class="fun" value="foo@example.com" name="email" />'
'attrs' passed to render() get precedence over those passed to the constructor:
>>> w = HiddenInput(attrs={'class': 'pretty'})
>>> w.render('email', '', attrs={'class': 'special'})
u'<input type="hidden" class="special" name="email" />'
# Textarea Widget ############################################################# # Textarea Widget #############################################################
>>> w = Textarea() >>> w = Textarea()
@ -77,66 +155,251 @@ u'<input type="checkbox" class="pretty" name="is_cool" />'
>>> w.render('is_cool', '', attrs={'class': 'special'}) >>> w.render('is_cool', '', attrs={'class': 'special'})
u'<input type="checkbox" class="special" name="is_cool" />' u'<input type="checkbox" class="special" name="is_cool" />'
# Select Widget ###############################################################
>>> w = Select()
>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select name="beatle">
<option value="J" selected="selected">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
If the value is None, none of the options are selected:
>>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select name="beatle">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
If the value corresponds to a label (but not to an option value), none of the options are selected:
>>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select name="beatle">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
The value is compared to its str():
>>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')])
<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>
>>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)])
<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>
>>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)])
<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>
The 'choices' argument can be any iterable:
>>> def get_choices():
... for i in range(5):
... yield (i, i)
>>> print w.render('num', 2, choices=get_choices())
<select name="num">
<option value="0">0</option>
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
You can also pass 'choices' to the constructor:
>>> w = Select(choices=[(1, 1), (2, 2), (3, 3)])
>>> print w.render('num', 2)
<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>
If 'choices' is passed to both the constructor and render(), then they'll both be in the output:
>>> print w.render('num', 2, choices=[(4, 4), (5, 5)])
<select name="num">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
# SelectMultiple Widget #######################################################
>>> w = SelectMultiple()
>>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select multiple="multiple" name="beatles">
<option value="J" selected="selected">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
>>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select multiple="multiple" name="beatles">
<option value="J" selected="selected">John</option>
<option value="P" selected="selected">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
>>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select multiple="multiple" name="beatles">
<option value="J" selected="selected">John</option>
<option value="P" selected="selected">Paul</option>
<option value="G">George</option>
<option value="R" selected="selected">Ringo</option>
</select>
If the value is None, none of the options are selected:
>>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select multiple="multiple" name="beatles">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
If the value corresponds to a label (but not to an option value), none of the options are selected:
>>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select multiple="multiple" name="beatles">
<option value="J">John</option>
<option value="P">Paul</option>
<option value="G">George</option>
<option value="R">Ringo</option>
</select>
If multiple values are given, but some of them are not valid, the valid ones are selected:
>>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<select multiple="multiple" name="beatles">
<option value="J" selected="selected">John</option>
<option value="P">Paul</option>
<option value="G" selected="selected">George</option>
<option value="R">Ringo</option>
</select>
The value is compared to its str():
>>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')])
<select multiple="multiple" name="nums">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>
>>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)])
<select multiple="multiple" name="nums">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>
>>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)])
<select multiple="multiple" name="nums">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>
The 'choices' argument can be any iterable:
>>> def get_choices():
... for i in range(5):
... yield (i, i)
>>> print w.render('nums', [2], choices=get_choices())
<select multiple="multiple" name="nums">
<option value="0">0</option>
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
You can also pass 'choices' to the constructor:
>>> w = SelectMultiple(choices=[(1, 1), (2, 2), (3, 3)])
>>> print w.render('nums', [2])
<select multiple="multiple" name="nums">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
</select>
If 'choices' is passed to both the constructor and render(), then they'll both be in the output:
>>> print w.render('nums', [2], choices=[(4, 4), (5, 5)])
<select multiple="multiple" name="nums">
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
# CharField ################################################################### # CharField ###################################################################
>>> f = CharField(required=False) >>> f = CharField(required=False)
>>> f.to_python(1) >>> f.clean(1)
u'1' u'1'
>>> f.to_python('hello') >>> f.clean('hello')
u'hello' u'hello'
>>> f.to_python(None) >>> f.clean(None)
u'' u''
>>> f.to_python([1, 2, 3]) >>> f.clean([1, 2, 3])
u'[1, 2, 3]' u'[1, 2, 3]'
CharField accepts an optional max_length parameter: CharField accepts an optional max_length parameter:
>>> f = CharField(max_length=10, required=False) >>> f = CharField(max_length=10, required=False)
>>> f.to_python('') >>> f.clean('')
u'' u''
>>> f.to_python('12345') >>> f.clean('12345')
u'12345' u'12345'
>>> f.to_python('1234567890') >>> f.clean('1234567890')
u'1234567890' u'1234567890'
>>> f.to_python('1234567890a') >>> f.clean('1234567890a')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Ensure this value has at most 10 characters.'] ValidationError: [u'Ensure this value has at most 10 characters.']
CharField accepts an optional min_length parameter: CharField accepts an optional min_length parameter:
>>> f = CharField(min_length=10, required=False) >>> f = CharField(min_length=10, required=False)
>>> f.to_python('') >>> f.clean('')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Ensure this value has at least 10 characters.'] ValidationError: [u'Ensure this value has at least 10 characters.']
>>> f.to_python('12345') >>> f.clean('12345')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Ensure this value has at least 10 characters.'] ValidationError: [u'Ensure this value has at least 10 characters.']
>>> f.to_python('1234567890') >>> f.clean('1234567890')
u'1234567890' u'1234567890'
>>> f.to_python('1234567890a') >>> f.clean('1234567890a')
u'1234567890a' u'1234567890a'
# IntegerField ################################################################ # IntegerField ################################################################
>>> f = IntegerField() >>> f = IntegerField()
>>> f.to_python('1') >>> f.clean('1')
1 1
>>> isinstance(f.to_python('1'), int) >>> isinstance(f.clean('1'), int)
True True
>>> f.to_python('23') >>> f.clean('23')
23 23
>>> f.to_python('a') >>> f.clean('a')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a whole number.'] ValidationError: [u'Enter a whole number.']
>>> f.to_python('1 ') >>> f.clean('1 ')
1 1
>>> f.to_python(' 1') >>> f.clean(' 1')
1 1
>>> f.to_python(' 1 ') >>> f.clean(' 1 ')
1 1
>>> f.to_python('1a') >>> f.clean('1a')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a whole number.'] ValidationError: [u'Enter a whole number.']
@ -145,75 +408,75 @@ ValidationError: [u'Enter a whole number.']
>>> import datetime >>> import datetime
>>> f = DateField() >>> f = DateField()
>>> f.to_python(datetime.date(2006, 10, 25)) >>> f.clean(datetime.date(2006, 10, 25))
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30))
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30, 59)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59))
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200))
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('2006-10-25') >>> f.clean('2006-10-25')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('10/25/2006') >>> f.clean('10/25/2006')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('10/25/06') >>> f.clean('10/25/06')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('Oct 25 2006') >>> f.clean('Oct 25 2006')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('October 25 2006') >>> f.clean('October 25 2006')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('October 25, 2006') >>> f.clean('October 25, 2006')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('25 October 2006') >>> f.clean('25 October 2006')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('25 October, 2006') >>> f.clean('25 October, 2006')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('2006-4-31') >>> f.clean('2006-4-31')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date.'] ValidationError: [u'Enter a valid date.']
>>> f.to_python('200a-10-25') >>> f.clean('200a-10-25')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date.'] ValidationError: [u'Enter a valid date.']
>>> f.to_python('25/10/06') >>> f.clean('25/10/06')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date.'] ValidationError: [u'Enter a valid date.']
>>> f.to_python(None) >>> f.clean(None)
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'This field is required.'] ValidationError: [u'This field is required.']
>>> f = DateField(required=False) >>> f = DateField(required=False)
>>> f.to_python(None) >>> f.clean(None)
>>> repr(f.to_python(None)) >>> repr(f.clean(None))
'None' 'None'
>>> f.to_python('') >>> f.clean('')
>>> repr(f.to_python('')) >>> repr(f.clean(''))
'None' 'None'
DateField accepts an optional input_formats parameter: DateField accepts an optional input_formats parameter:
>>> f = DateField(input_formats=['%Y %m %d']) >>> f = DateField(input_formats=['%Y %m %d'])
>>> f.to_python(datetime.date(2006, 10, 25)) >>> f.clean(datetime.date(2006, 10, 25))
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30))
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
>>> f.to_python('2006 10 25') >>> f.clean('2006 10 25')
datetime.date(2006, 10, 25) datetime.date(2006, 10, 25)
The input_formats parameter overrides all default input formats, The input_formats parameter overrides all default input formats,
so the default formats won't work unless you specify them: so the default formats won't work unless you specify them:
>>> f.to_python('2006-10-25') >>> f.clean('2006-10-25')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date.'] ValidationError: [u'Enter a valid date.']
>>> f.to_python('10/25/2006') >>> f.clean('10/25/2006')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date.'] ValidationError: [u'Enter a valid date.']
>>> f.to_python('10/25/06') >>> f.clean('10/25/06')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date.'] ValidationError: [u'Enter a valid date.']
@ -222,63 +485,63 @@ ValidationError: [u'Enter a valid date.']
>>> import datetime >>> import datetime
>>> f = DateTimeField() >>> f = DateTimeField()
>>> f.to_python(datetime.date(2006, 10, 25)) >>> f.clean(datetime.date(2006, 10, 25))
datetime.datetime(2006, 10, 25, 0, 0) datetime.datetime(2006, 10, 25, 0, 0)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30))
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30, 59)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59))
datetime.datetime(2006, 10, 25, 14, 30, 59) datetime.datetime(2006, 10, 25, 14, 30, 59)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200))
datetime.datetime(2006, 10, 25, 14, 30, 59, 200) datetime.datetime(2006, 10, 25, 14, 30, 59, 200)
>>> f.to_python('2006-10-25 14:30:45') >>> f.clean('2006-10-25 14:30:45')
datetime.datetime(2006, 10, 25, 14, 30, 45) datetime.datetime(2006, 10, 25, 14, 30, 45)
>>> f.to_python('2006-10-25 14:30:00') >>> f.clean('2006-10-25 14:30:00')
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
>>> f.to_python('2006-10-25 14:30') >>> f.clean('2006-10-25 14:30')
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
>>> f.to_python('2006-10-25') >>> f.clean('2006-10-25')
datetime.datetime(2006, 10, 25, 0, 0) datetime.datetime(2006, 10, 25, 0, 0)
>>> f.to_python('10/25/2006 14:30:45') >>> f.clean('10/25/2006 14:30:45')
datetime.datetime(2006, 10, 25, 14, 30, 45) datetime.datetime(2006, 10, 25, 14, 30, 45)
>>> f.to_python('10/25/2006 14:30:00') >>> f.clean('10/25/2006 14:30:00')
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
>>> f.to_python('10/25/2006 14:30') >>> f.clean('10/25/2006 14:30')
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
>>> f.to_python('10/25/2006') >>> f.clean('10/25/2006')
datetime.datetime(2006, 10, 25, 0, 0) datetime.datetime(2006, 10, 25, 0, 0)
>>> f.to_python('10/25/06 14:30:45') >>> f.clean('10/25/06 14:30:45')
datetime.datetime(2006, 10, 25, 14, 30, 45) datetime.datetime(2006, 10, 25, 14, 30, 45)
>>> f.to_python('10/25/06 14:30:00') >>> f.clean('10/25/06 14:30:00')
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
>>> f.to_python('10/25/06 14:30') >>> f.clean('10/25/06 14:30')
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
>>> f.to_python('10/25/06') >>> f.clean('10/25/06')
datetime.datetime(2006, 10, 25, 0, 0) datetime.datetime(2006, 10, 25, 0, 0)
>>> f.to_python('hello') >>> f.clean('hello')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date/time.'] ValidationError: [u'Enter a valid date/time.']
>>> f.to_python('2006-10-25 4:30 p.m.') >>> f.clean('2006-10-25 4:30 p.m.')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date/time.'] ValidationError: [u'Enter a valid date/time.']
DateField accepts an optional input_formats parameter: DateField accepts an optional input_formats parameter:
>>> f = DateTimeField(input_formats=['%Y %m %d %I:%M %p']) >>> f = DateTimeField(input_formats=['%Y %m %d %I:%M %p'])
>>> f.to_python(datetime.date(2006, 10, 25)) >>> f.clean(datetime.date(2006, 10, 25))
datetime.datetime(2006, 10, 25, 0, 0) datetime.datetime(2006, 10, 25, 0, 0)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30))
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30, 59)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59))
datetime.datetime(2006, 10, 25, 14, 30, 59) datetime.datetime(2006, 10, 25, 14, 30, 59)
>>> f.to_python(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200))
datetime.datetime(2006, 10, 25, 14, 30, 59, 200) datetime.datetime(2006, 10, 25, 14, 30, 59, 200)
>>> f.to_python('2006 10 25 2:30 PM') >>> f.clean('2006 10 25 2:30 PM')
datetime.datetime(2006, 10, 25, 14, 30) datetime.datetime(2006, 10, 25, 14, 30)
The input_formats parameter overrides all default input formats, The input_formats parameter overrides all default input formats,
so the default formats won't work unless you specify them: so the default formats won't work unless you specify them:
>>> f.to_python('2006-10-25 14:30:45') >>> f.clean('2006-10-25 14:30:45')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid date/time.'] ValidationError: [u'Enter a valid date/time.']
@ -286,51 +549,51 @@ ValidationError: [u'Enter a valid date/time.']
# RegexField ################################################################## # RegexField ##################################################################
>>> f = RegexField('^\d[A-F]\d$') >>> f = RegexField('^\d[A-F]\d$')
>>> f.to_python('2A2') >>> f.clean('2A2')
u'2A2' u'2A2'
>>> f.to_python('3F3') >>> f.clean('3F3')
u'3F3' u'3F3'
>>> f.to_python('3G3') >>> f.clean('3G3')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid value.'] ValidationError: [u'Enter a valid value.']
>>> f.to_python(' 2A2') >>> f.clean(' 2A2')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid value.'] ValidationError: [u'Enter a valid value.']
>>> f.to_python('2A2 ') >>> f.clean('2A2 ')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid value.'] ValidationError: [u'Enter a valid value.']
Alternatively, RegexField can take a compiled regular expression: Alternatively, RegexField can take a compiled regular expression:
>>> f = RegexField(re.compile('^\d[A-F]\d$')) >>> f = RegexField(re.compile('^\d[A-F]\d$'))
>>> f.to_python('2A2') >>> f.clean('2A2')
u'2A2' u'2A2'
>>> f.to_python('3F3') >>> f.clean('3F3')
u'3F3' u'3F3'
>>> f.to_python('3G3') >>> f.clean('3G3')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid value.'] ValidationError: [u'Enter a valid value.']
>>> f.to_python(' 2A2') >>> f.clean(' 2A2')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid value.'] ValidationError: [u'Enter a valid value.']
>>> f.to_python('2A2 ') >>> f.clean('2A2 ')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid value.'] ValidationError: [u'Enter a valid value.']
RegexField takes an optional error_message argument: RegexField takes an optional error_message argument:
>>> f = RegexField('^\d\d\d\d$', 'Enter a four-digit number.') >>> f = RegexField('^\d\d\d\d$', 'Enter a four-digit number.')
>>> f.to_python('1234') >>> f.clean('1234')
u'1234' u'1234'
>>> f.to_python('123') >>> f.clean('123')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a four-digit number.'] ValidationError: [u'Enter a four-digit number.']
>>> f.to_python('abcd') >>> f.clean('abcd')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a four-digit number.'] ValidationError: [u'Enter a four-digit number.']
@ -338,41 +601,208 @@ ValidationError: [u'Enter a four-digit number.']
# EmailField ################################################################## # EmailField ##################################################################
>>> f = EmailField() >>> f = EmailField()
>>> f.to_python('person@example.com') >>> f.clean('person@example.com')
u'person@example.com' u'person@example.com'
>>> f.to_python('foo') >>> f.clean('foo')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid e-mail address.'] ValidationError: [u'Enter a valid e-mail address.']
>>> f.to_python('foo@') >>> f.clean('foo@')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid e-mail address.'] ValidationError: [u'Enter a valid e-mail address.']
>>> f.to_python('foo@bar') >>> f.clean('foo@bar')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid e-mail address.'] ValidationError: [u'Enter a valid e-mail address.']
# URLField ##################################################################
>>> f = URLField()
>>> f.clean('http://example.com')
u'http://example.com'
>>> f.clean('http://www.example.com')
u'http://www.example.com'
>>> f.clean('foo')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('example.com')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://example')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://example.')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://.com')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
URLField takes an optional verify_exists parameter, which is False by default.
This verifies that the URL is live on the Internet and doesn't return a 404 or 500:
>>> f = URLField(verify_exists=True)
>>> f.clean('http://www.google.com') # This will fail if there's no Internet connection
u'http://www.google.com'
>>> f.clean('http://example')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid URL.']
>>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') # bad domain
Traceback (most recent call last):
...
ValidationError: [u'This URL appears to be a broken link.']
>>> f.clean('http://google.com/we-love-microsoft.html') # good domain, bad page
Traceback (most recent call last):
...
ValidationError: [u'This URL appears to be a broken link.']
# BooleanField ################################################################ # BooleanField ################################################################
>>> f = BooleanField() >>> f = BooleanField()
>>> f.to_python(True) >>> f.clean(True)
True True
>>> f.to_python(False) >>> f.clean(False)
False False
>>> f.to_python(1) >>> f.clean(1)
True True
>>> f.to_python(0) >>> f.clean(0)
False False
>>> f.to_python('Django rocks') >>> f.clean('Django rocks')
True True
# ChoiceField #################################################################
>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')])
>>> f.clean(1)
u'1'
>>> f.clean('1')
u'1'
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('3')
Traceback (most recent call last):
...
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
>>> f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')])
>>> f.clean('J')
u'J'
>>> f.clean('John')
Traceback (most recent call last):
...
ValidationError: [u'Select a valid choice. John is not one of the available choices.']
# MultipleChoiceField #########################################################
>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')])
>>> f.clean([1])
[u'1']
>>> f.clean(['1'])
[u'1']
>>> f.clean(['1', '2'])
[u'1', u'2']
>>> f.clean([1, '2'])
[u'1', u'2']
>>> f.clean((1, '2'))
[u'1', u'2']
>>> f.clean('hello')
Traceback (most recent call last):
...
ValidationError: [u'Enter a list of values.']
>>> f.clean([])
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(())
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(['3'])
Traceback (most recent call last):
...
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
# ComboField ##################################################################
ComboField takes a list of fields that should be used to validate a value,
in that order:
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()])
>>> f.clean('test@example.com')
u'test@example.com'
>>> f.clean('longemailaddress@example.com')
Traceback (most recent call last):
...
ValidationError: [u'Ensure this value has at most 20 characters.']
>>> f.clean('not an e-mail')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid e-mail address.']
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
# Form ######################################################################## # Form ########################################################################
>>> class Person(Form): >>> class Person(Form):
... first_name = CharField() ... first_name = CharField()
... last_name = CharField() ... last_name = CharField()
... birthday = DateField() ... birthday = DateField()
>>> p = Person()
>>> print p
<table>
<tr><td>First name:</td><td><input type="text" name="first_name" /></td></tr>
<tr><td>Last name:</td><td><input type="text" name="last_name" /></td></tr>
<tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr>
</table>
>>> print p.as_table()
<table>
<tr><td>First name:</td><td><input type="text" name="first_name" /></td></tr>
<tr><td>Last name:</td><td><input type="text" name="last_name" /></td></tr>
<tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr>
</table>
>>> print p.as_ul()
<ul>
<li>First name: <input type="text" name="first_name" /></li>
<li>Last name: <input type="text" name="last_name" /></li>
<li>Birthday: <input type="text" name="birthday" /></li>
</ul>
>>> print p.as_table_with_errors()
<table>
<tr><td colspan="2"><ul><li>This field is required.</li></ul></td></tr>
<tr><td>First name:</td><td><input type="text" name="first_name" /></td></tr>
<tr><td colspan="2"><ul><li>This field is required.</li></ul></td></tr>
<tr><td>Last name:</td><td><input type="text" name="last_name" /></td></tr>
<tr><td colspan="2"><ul><li>This field is required.</li></ul></td></tr>
<tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr>
</table>
>>> print p.as_ul_with_errors()
<ul>
<li><ul><li>This field is required.</li></ul>First name: <input type="text" name="first_name" /></li>
<li><ul><li>This field is required.</li></ul>Last name: <input type="text" name="last_name" /></li>
<li><ul><li>This field is required.</li></ul>Birthday: <input type="text" name="birthday" /></li>
</ul>
>>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'}) >>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'})
>>> p.errors() >>> p.errors()
{} {}
@ -382,7 +812,7 @@ True
u'' u''
>>> p.errors().as_text() >>> p.errors().as_text()
u'' u''
>>> p.to_python() >>> p.clean()
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
>>> print p['first_name'] >>> print p['first_name']
<input type="text" name="first_name" value="John" /> <input type="text" name="first_name" value="John" />
@ -395,6 +825,12 @@ u''
<input type="text" name="first_name" value="John" /> <input type="text" name="first_name" value="John" />
<input type="text" name="last_name" value="Lennon" /> <input type="text" name="last_name" value="Lennon" />
<input type="text" name="birthday" value="1940-10-9" /> <input type="text" name="birthday" value="1940-10-9" />
>>> print p
<table>
<tr><td>First name:</td><td><input type="text" name="first_name" value="John" /></td></tr>
<tr><td>Last name:</td><td><input type="text" name="last_name" value="Lennon" /></td></tr>
<tr><td>Birthday:</td><td><input type="text" name="birthday" value="1940-10-9" /></td></tr>
</table>
>>> p = Person({'last_name': u'Lennon'}) >>> p = Person({'last_name': u'Lennon'})
>>> p.errors() >>> p.errors()
@ -408,8 +844,8 @@ u'<ul class="errorlist"><li>first_name<ul class="errorlist"><li>This field is re
* This field is required. * This field is required.
* birthday * birthday
* This field is required. * This field is required.
>>> p.to_python() >>> p.clean()
>>> repr(p.to_python()) >>> repr(p.clean())
'None' 'None'
>>> p['first_name'].errors >>> p['first_name'].errors
[u'This field is required.'] [u'This field is required.']
@ -474,6 +910,126 @@ u'<textarea name="subject">Hello</textarea>'
>>> f['message'].as_text() >>> f['message'].as_text()
u'<input type="text" name="message" value="I love you." />' u'<input type="text" name="message" value="I love you." />'
For a form with a <select>, use ChoiceField:
>>> class FrameworkForm(Form):
... name = CharField()
... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')])
>>> f = FrameworkForm()
>>> print f['language']
<select name="language">
<option value="P">Python</option>
<option value="J">Java</option>
</select>
>>> f = FrameworkForm({'name': 'Django', 'language': 'P'})
>>> print f['language']
<select name="language">
<option value="P" selected="selected">Python</option>
<option value="J">Java</option>
</select>
MultipleChoiceField is a special case, as its data is required to be a list:
>>> class SongForm(Form):
... name = CharField()
... composers = MultipleChoiceField()
>>> f = SongForm()
>>> print f['composers']
<select multiple="multiple" name="composers">
</select>
>>> class SongForm(Form):
... name = CharField()
... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')])
>>> f = SongForm()
>>> print f['composers']
<select multiple="multiple" name="composers">
<option value="J">John Lennon</option>
<option value="P">Paul McCartney</option>
</select>
>>> f = SongForm({'name': 'Yesterday', 'composers': ['P']})
>>> print f['name']
<input type="text" name="name" value="Yesterday" />
>>> print f['composers']
<select multiple="multiple" name="composers">
<option value="J">John Lennon</option>
<option value="P" selected="selected">Paul McCartney</option>
</select>
There are a couple of ways to do multiple-field validation. If you want the
validation message to be associated with a particular field, implement the
clean_XXX() method on the Form, where XXX is the field name. As in
Field.clean(), the clean_XXX() method should return the cleaned value:
>>> class UserRegistration(Form):
... username = CharField(max_length=10)
... password1 = CharField(widget=PasswordInput)
... password2 = CharField(widget=PasswordInput)
... def clean_password2(self):
... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']:
... raise ValidationError(u'Please make sure your passwords match.')
... return self.clean_data['password2']
>>> f = UserRegistration()
>>> f.errors()
{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']}
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'})
>>> f.errors()
{'password2': [u'Please make sure your passwords match.']}
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'})
>>> f.errors()
{}
>>> f.clean()
{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
Another way of doing multiple-field validation is by implementing the
Form's clean() method. If you do this, any ValidationError raised by that
method will not be associated with a particular field; it will have a
special-case association with the field named '__all__'. Note that
Form.clean() still needs to return a dictionary of all clean data:
>>> class UserRegistration(Form):
... username = CharField(max_length=10)
... password1 = CharField(widget=PasswordInput)
... password2 = CharField(widget=PasswordInput)
... def clean(self):
... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']:
... raise ValidationError(u'Please make sure your passwords match.')
... return self.clean_data
>>> f = UserRegistration()
>>> print f.as_table()
<table>
<tr><td>Username:</td><td><input type="text" name="username" /></td></tr>
<tr><td>Password1:</td><td><input type="password" name="password1" /></td></tr>
<tr><td>Password2:</td><td><input type="password" name="password2" /></td></tr>
</table>
>>> f.errors()
{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']}
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'})
>>> f.errors()
{'__all__': [u'Please make sure your passwords match.']}
>>> print f.as_table()
<table>
<tr><td>Username:</td><td><input type="text" name="username" value="adrian" /></td></tr>
<tr><td>Password1:</td><td><input type="password" name="password1" value="foo" /></td></tr>
<tr><td>Password2:</td><td><input type="password" name="password2" value="bar" /></td></tr>
</table>
>>> print f.as_table_with_errors()
<table>
<tr><td colspan="2"><ul><li>Please make sure your passwords match.</li></ul></td></tr>
<tr><td>Username:</td><td><input type="text" name="username" value="adrian" /></td></tr>
<tr><td>Password1:</td><td><input type="password" name="password1" value="foo" /></td></tr>
<tr><td>Password2:</td><td><input type="password" name="password2" value="bar" /></td></tr>
</table>
>>> print f.as_ul_with_errors()
<ul>
<li><ul><li>Please make sure your passwords match.</li></ul></li>
<li>Username: <input type="text" name="username" value="adrian" /></li>
<li>Password1: <input type="password" name="password1" value="foo" /></li>
<li>Password2: <input type="password" name="password2" value="bar" /></li>
</ul>
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'})
>>> f.errors()
{}
>>> f.clean()
{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
""" """
if __name__ == "__main__": if __name__ == "__main__":