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

newforms-admin: Merged to [4823]

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@4824 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-03-25 21:49:00 +00:00
parent 25c15b17a8
commit 132cf258cb
80 changed files with 5495 additions and 1437 deletions

View File

@ -44,6 +44,7 @@ answer newbie questions, and generally made Django that much better:
adurdin@gmail.com adurdin@gmail.com
Andreas Andreas
andy@jadedplanet.net andy@jadedplanet.net
Fabrice Aneche <akh@nobugware.com>
ant9000@netwise.it ant9000@netwise.it
David Ascher <http://ascher.ca/> David Ascher <http://ascher.ca/>
Arthur <avandorp@gmail.com> Arthur <avandorp@gmail.com>
@ -133,6 +134,7 @@ answer newbie questions, and generally made Django that much better:
masonsimon+django@gmail.com masonsimon+django@gmail.com
Manuzhai Manuzhai
Petar Marić <http://www.petarmaric.com/> Petar Marić <http://www.petarmaric.com/>
Nuno Mariz <nmariz@gmail.com>
mark@junklight.com mark@junklight.com
Yasushi Masuda <whosaysni@gmail.com> Yasushi Masuda <whosaysni@gmail.com>
mattycakes@gmail.com mattycakes@gmail.com

View File

@ -61,6 +61,7 @@ LANGUAGES = (
('nl', gettext_noop('Dutch')), ('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')), ('no', gettext_noop('Norwegian')),
('pl', gettext_noop('Polish')), ('pl', gettext_noop('Polish')),
('pt', gettext_noop('Portugese')),
('pt-br', gettext_noop('Brazilian')), ('pt-br', gettext_noop('Brazilian')),
('ro', gettext_noop('Romanian')), ('ro', gettext_noop('Romanian')),
('ru', gettext_noop('Russian')), ('ru', gettext_noop('Russian')),

View File

@ -11,7 +11,7 @@ msgstr ""
"Project-Id-Version: django\n" "Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-02-26 20:44+0100\n" "POT-Creation-Date: 2007-02-26 20:44+0100\n"
"PO-Revision-Date: 2007-02-27 20:06+0100\n" "PO-Revision-Date: 2007-03-14 19:29+0100\n"
"Last-Translator: Nicola Larosa <nico@tekNico.net>\n" "Last-Translator: Nicola Larosa <nico@tekNico.net>\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"
@ -523,7 +523,7 @@ msgstr ""
#: contrib/auth/forms.py:17 contrib/auth/forms.py:138 #: contrib/auth/forms.py:17 contrib/auth/forms.py:138
msgid "The two password fields didn't match." msgid "The two password fields didn't match."
msgstr "I due campi parola chiave non corrispondono." msgstr "I due campi password non corrispondono."
#: contrib/auth/forms.py:25 #: contrib/auth/forms.py:25
msgid "A user with that username already exists." msgid "A user with that username already exists."
@ -555,7 +555,7 @@ msgstr "Questo indirizzo email non è associato ad alcun account utente. Sei sic
#: contrib/auth/forms.py:117 #: contrib/auth/forms.py:117
msgid "The two 'new password' fields didn't match." msgid "The two 'new password' fields didn't match."
msgstr "I due campi 'nuova parola chiave' non corrispondono." msgstr "I due campi 'nuova password' non corrispondono."
#: contrib/auth/forms.py:124 #: contrib/auth/forms.py:124
msgid "Your old password was entered incorrectly. Please enter it again." msgid "Your old password was entered incorrectly. Please enter it again."
@ -609,13 +609,13 @@ msgstr "indirizzo e-mail"
#: contrib/auth/models.py:94 #: contrib/auth/models.py:94
msgid "password" msgid "password"
msgstr "parola chiave" msgstr "password"
#: contrib/auth/models.py:94 #: contrib/auth/models.py:94
msgid "" msgid ""
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
"password form</a>." "password form</a>."
msgstr "Usare '[algo]$[salt]$[hexdigest]' oppure la maschera di <a href=\"password/\">cambio parola chiave</a>." msgstr "Usare '[algo]$[salt]$[hexdigest]' oppure la maschera di <a href=\"password/\">cambio password</a>."
#: contrib/auth/models.py:95 #: contrib/auth/models.py:95
msgid "staff status" msgid "staff status"
@ -1040,12 +1040,12 @@ msgstr "Aggiungi utente"
#: contrib/admin/views/auth.py:57 #: contrib/admin/views/auth.py:57
msgid "Password changed successfully." msgid "Password changed successfully."
msgstr "La parola chiave è stata cambiata correttamente." msgstr "La password è stata cambiata correttamente."
#: contrib/admin/views/auth.py:64 #: contrib/admin/views/auth.py:64
#, python-format #, python-format
msgid "Change password: %s" msgid "Change password: %s"
msgstr "Cambia la parola chiave: %s" msgstr "Cambia la password: %s"
#: contrib/admin/templatetags/admin_list.py:247 #: contrib/admin/templatetags/admin_list.py:247
msgid "All dates" msgid "All dates"
@ -1088,7 +1088,7 @@ msgstr "Documentazione"
#: contrib/admin/templates/registration/password_change_form.html:3 #: contrib/admin/templates/registration/password_change_form.html:3
#: contrib/admin/templates/registration/password_change_done.html:3 #: contrib/admin/templates/registration/password_change_done.html:3
msgid "Change password" msgid "Change password"
msgstr "Cambia la parola chiave" msgstr "Cambia la password"
#: contrib/admin/templates/admin/delete_confirmation.html:3 #: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/change_form.html:10 #: contrib/admin/templates/admin/change_form.html:10
@ -1335,11 +1335,11 @@ msgstr "Nome utente:"
#: contrib/admin/templates/admin/login.html:20 #: contrib/admin/templates/admin/login.html:20
#: contrib/comments/templates/comments/form.html:8 #: contrib/comments/templates/comments/form.html:8
msgid "Password:" msgid "Password:"
msgstr "Parola chiave:" msgstr "Password:"
#: 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 "Hai <a href=\"/password_reset/\">dimenticato la parola chiave</a>?" msgstr "Hai <a href=\"/password_reset/\">dimenticato la password</a>?"
#: contrib/admin/templates/admin/base.html:25 #: contrib/admin/templates/admin/base.html:25
msgid "Welcome," msgid "Welcome,"
@ -1349,7 +1349,7 @@ msgstr "Benvenuto,"
msgid "" msgid ""
"First, enter a username and password. Then, you'll be able to edit more user " "First, enter a username and password. Then, you'll be able to edit more user "
"options." "options."
msgstr "Inserire innanzitutto nome utente e parola chiave. Si potrà quindi modificare le altre impostazioni dell'utente." msgstr "Inserire innanzitutto nome utente e password. Si potrà quindi modificare le altre impostazioni dell'utente."
#: contrib/admin/templates/admin/auth/user/add_form.html:12 #: contrib/admin/templates/admin/auth/user/add_form.html:12
msgid "Username" msgid "Username"
@ -1358,22 +1358,22 @@ msgstr "Nome utente"
#: contrib/admin/templates/admin/auth/user/add_form.html:18 #: contrib/admin/templates/admin/auth/user/add_form.html:18
#: contrib/admin/templates/admin/auth/user/change_password.html:34 #: contrib/admin/templates/admin/auth/user/change_password.html:34
msgid "Password" msgid "Password"
msgstr "Parola chiave" msgstr "Password"
#: contrib/admin/templates/admin/auth/user/add_form.html:23 #: contrib/admin/templates/admin/auth/user/add_form.html:23
#: contrib/admin/templates/admin/auth/user/change_password.html:39 #: contrib/admin/templates/admin/auth/user/change_password.html:39
msgid "Password (again)" msgid "Password (again)"
msgstr "Parola chiave (di nuovo)" msgstr "Password (di nuovo)"
#: contrib/admin/templates/admin/auth/user/add_form.html:24 #: contrib/admin/templates/admin/auth/user/add_form.html:24
#: contrib/admin/templates/admin/auth/user/change_password.html:40 #: contrib/admin/templates/admin/auth/user/change_password.html:40
msgid "Enter the same password as above, for verification." msgid "Enter the same password as above, for verification."
msgstr "Inserire la stessa parola chiave inserita sopra, come verifica." msgstr "Inserire la stessa password inserita sopra, come verifica."
#: contrib/admin/templates/admin/auth/user/change_password.html:28 #: contrib/admin/templates/admin/auth/user/change_password.html:28
#, python-format #, python-format
msgid "Enter a new password for the user <strong>%(username)s</strong>." msgid "Enter a new password for the user <strong>%(username)s</strong>."
msgstr "Inserire una nuova parola chiave per l'utente <strong>%(username)s</strong>." msgstr "Inserire una nuova password per l'utente <strong>%(username)s</strong>."
#: contrib/admin/templates/admin_doc/bookmarklets.html:3 #: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Bookmarklets" msgid "Bookmarklets"
@ -1460,13 +1460,13 @@ msgstr "Modifica:"
#: contrib/admin/templates/registration/password_reset_form.html:10 #: contrib/admin/templates/registration/password_reset_form.html:10
#: contrib/admin/templates/registration/password_reset_done.html:4 #: contrib/admin/templates/registration/password_reset_done.html:4
msgid "Password reset" msgid "Password reset"
msgstr "Reimposta la parola chiave" msgstr "Reimposta la password"
#: contrib/admin/templates/registration/password_reset_form.html:12 #: contrib/admin/templates/registration/password_reset_form.html:12
msgid "" msgid ""
"Forgotten your password? Enter your e-mail address below, and we'll reset " "Forgotten your password? Enter your e-mail address below, and we'll reset "
"your password and e-mail the new one to you." "your password and e-mail the new one to you."
msgstr "Dimenticata la parola chiave? Inserire il proprio indirizzo e-mail qui sotto: la parola chiave sarà reimpostata, e la nuova ti verrà inviata per e-mail." msgstr "Dimenticata la password? Inserire il proprio indirizzo e-mail qui sotto: la password sarà reimpostata, e la nuova ti verrà inviata per e-mail."
#: contrib/admin/templates/registration/password_reset_form.html:16 #: contrib/admin/templates/registration/password_reset_form.html:16
msgid "E-mail address:" msgid "E-mail address:"
@ -1474,11 +1474,11 @@ msgstr "Indirizzo e-mail:"
#: contrib/admin/templates/registration/password_reset_form.html:16 #: contrib/admin/templates/registration/password_reset_form.html:16
msgid "Reset my password" msgid "Reset my password"
msgstr "Reimposta la mia parola chiave" msgstr "Reimposta la mia password"
#: contrib/admin/templates/registration/password_reset_email.html:2 #: contrib/admin/templates/registration/password_reset_email.html:2
msgid "You're receiving this e-mail because you requested a password reset" msgid "You're receiving this e-mail because you requested a password reset"
msgstr "Hai ricevuto questa e-mail perché hai chiesto di reimpostare la parola chiave" msgstr "Hai ricevuto questa e-mail perché hai chiesto di reimpostare la password"
#: contrib/admin/templates/registration/password_reset_email.html:3 #: contrib/admin/templates/registration/password_reset_email.html:3
#, python-format #, python-format
@ -1488,11 +1488,11 @@ msgstr "per il tuo account utente su %(site_name)s"
#: contrib/admin/templates/registration/password_reset_email.html:5 #: contrib/admin/templates/registration/password_reset_email.html:5
#, python-format #, python-format
msgid "Your new password is: %(new_password)s" msgid "Your new password is: %(new_password)s"
msgstr "La tua nuova parola chiave è: %(new_password)s" msgstr "La tua nuova password è: %(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 "Puoi liberamente cambiare la tua parola chiave tramite questa pagina:" msgstr "Puoi liberamente cambiare la tua password tramite questa pagina:"
#: 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:"
@ -1518,51 +1518,51 @@ msgstr "Accedi di nuovo"
#: contrib/admin/templates/registration/password_reset_done.html:6 #: contrib/admin/templates/registration/password_reset_done.html:6
#: contrib/admin/templates/registration/password_reset_done.html:10 #: contrib/admin/templates/registration/password_reset_done.html:10
msgid "Password reset successful" msgid "Password reset successful"
msgstr "Parola chiave reimpostata correttamente" msgstr "Password reimpostata correttamente"
#: contrib/admin/templates/registration/password_reset_done.html:12 #: contrib/admin/templates/registration/password_reset_done.html:12
msgid "" 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 "La nuova parola chiave è stata inviata all'indirizzo e-mail inserito. Arriverà a breve." msgstr "La nuova password è stata inviata all'indirizzo e-mail inserito. Arriverà a breve."
#: contrib/admin/templates/registration/password_change_form.html:4 #: contrib/admin/templates/registration/password_change_form.html:4
#: contrib/admin/templates/registration/password_change_form.html:6 #: contrib/admin/templates/registration/password_change_form.html:6
#: contrib/admin/templates/registration/password_change_form.html:10 #: contrib/admin/templates/registration/password_change_form.html:10
#: contrib/admin/templates/registration/password_change_done.html:4 #: contrib/admin/templates/registration/password_change_done.html:4
msgid "Password change" msgid "Password change"
msgstr "Cambio di parola chiave" msgstr "Cambio password"
#: contrib/admin/templates/registration/password_change_form.html:12 #: contrib/admin/templates/registration/password_change_form.html:12
msgid "" msgid ""
"Please enter your old password, for security's sake, and then enter your new " "Please enter your old password, for security's sake, and then enter your new "
"password twice so we can verify you typed it in correctly." "password twice so we can verify you typed it in correctly."
msgstr "Inserire l'attuale parola chiave, per ragioni di sicurezza, e poi la nuova parola chiave due volte, per verificare di averla scritta correttamente." msgstr "Inserire l'attuale password, per ragioni di sicurezza, e poi la nuova password due volte, per verificare di averla scritta correttamente."
#: contrib/admin/templates/registration/password_change_form.html:17 #: contrib/admin/templates/registration/password_change_form.html:17
msgid "Old password:" msgid "Old password:"
msgstr "Parola chiave attuale:" msgstr "Password attuale:"
#: contrib/admin/templates/registration/password_change_form.html:19 #: contrib/admin/templates/registration/password_change_form.html:19
msgid "New password:" msgid "New password:"
msgstr "Nuova parola chiave:" msgstr "Nuova password:"
#: contrib/admin/templates/registration/password_change_form.html:21 #: contrib/admin/templates/registration/password_change_form.html:21
msgid "Confirm password:" msgid "Confirm password:"
msgstr "Confermare la parola chiave:" msgstr "Confermare la password:"
#: contrib/admin/templates/registration/password_change_form.html:23 #: contrib/admin/templates/registration/password_change_form.html:23
msgid "Change my password" msgid "Change my password"
msgstr "Modifica la mia parola chiave" msgstr "Modifica la mia password"
#: contrib/admin/templates/registration/password_change_done.html:6 #: contrib/admin/templates/registration/password_change_done.html:6
#: contrib/admin/templates/registration/password_change_done.html:10 #: contrib/admin/templates/registration/password_change_done.html:10
msgid "Password change successful" msgid "Password change successful"
msgstr "Cambio di parola chiave avvenuto correttamente" msgstr "Cambio di password avvenuto correttamente"
#: contrib/admin/templates/registration/password_change_done.html:12 #: contrib/admin/templates/registration/password_change_done.html:12
msgid "Your password was changed." msgid "Your password was changed."
msgstr "La parola chiave è stata cambiata." msgstr "La password è stata cambiata."
#: contrib/sites/models.py:10 #: contrib/sites/models.py:10
msgid "domain name" msgid "domain name"
@ -1905,7 +1905,7 @@ msgstr "Il modulo di commento non fornisce né 'anteprima' né 'invia'"
#: contrib/comments/templates/comments/form.html:8 #: contrib/comments/templates/comments/form.html:8
msgid "Forgotten your password?" msgid "Forgotten your password?"
msgstr "Hai dimenticato la parola chiave?" msgstr "Hai dimenticato la password?"
#: contrib/comments/templates/comments/form.html:12 #: contrib/comments/templates/comments/form.html:12
msgid "Ratings" msgid "Ratings"

Binary file not shown.

View File

@ -0,0 +1,112 @@
# translation of djangojs.po to Polish
# Copyright (C) 2007 Michal Chruszcz
# This file is distributed under the same license as the django package.
#
# Michal Chruszcz <troll@pld-linux.org>, 2007.
msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2007-03-12 11:42+0100\n"
"Last-Translator: Michal Chruszcz <troll@pld-linux.org>\n"
"Language-Team: Polish <pl@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Dostępne %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Wybierz wszystko"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Dodaj"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Usuń"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Wybrano %s"
#: contrib/admin/media/js/SelectFilter2.js:54
#, fuzzy
msgid "Select your choice(s) and click "
msgstr "Zaznacz swój wybór i kliknij "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Wyczyść wszystko"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr "Styczeń Luty Marzec Kwiecień Maj Czerwiec Lipiec Sierpień Wrzesień Październik Listopad Grudzień"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Niedziela Poniedziałek Wtorek Środa Czwartek Piątek Sobota"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "N Pn Wt Śr Cz Pt So"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "Teraz"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "Zegar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "Wybierz czas"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "Północ"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "6 rano"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "Południe"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "Anuluj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "Dzisiaj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "Kalendarz"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "Wczoraj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "Jutro"

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,108 @@
# Portuguese translation of Django.
# Copyright (C) 2007 the Lawrence Journal-World
# This file is distributed under the same license as the PACKAGE package.
# Nuno Mariz <nmariz@gmail.com>, 2007.
#
msgid ""
msgstr ""
"Project-Id-Version: Django 0.96pre\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-03-15 11:51+0100\n"
"PO-Revision-Date: 2007-03-16 10:01+0000\n"
"Last-Translator: Nuno Mariz <nmariz@gmail.com>\n"
"Language-Team: pt_PT <nmariz@gmail.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Disponível %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Escolher todos"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Adicionar"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Remover"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Escolhido %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Seleccione a(s) sua(s) escolha(s) e clique "
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Limpar tudo"
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr "Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro Dezembro"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Domingo Segunda Terça Quarta Quinta Sexta Sábado"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "D S T Q Q S S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "Agora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "Relógio"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "Escolha a hora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "Meia-noite"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "Meio-dia"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "Cancelar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "Hoje"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "Calendário"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "Ontem"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "Amanhã"

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,112 @@
# translation of djangojs.po to tamil
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# PONNUSAMY.A <ponnusamy.simpleman@gmail.com>, 2007.
msgid ""
msgstr ""
"Project-Id-Version: djangojs\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-12-09 11:51+0100\n"
"PO-Revision-Date: 2007-03-14 16:40+0530\n"
"Last-Translator: PONNUSAMY <ponnusamy.simpleman@gmail.com>\n"
"Language-Team: tamil <tamilinix@yahoogroups.com>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "%s இருக்கிறதா "
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "எல்லாவற்றையும் தேர்ந்த்தெடுக்க"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "சேர்க்க"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "அழிக்க"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "%s தேர்ந்த்தெடுக்கப்பட்ட"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "தேவையானவற்றை தேர்ந்த்தெடுத்து கிளிக் செய்க"
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "எல்லாவற்றையும் அழிக்க "
#: contrib/admin/media/js/dateparse.js:26
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"ஜனவரி பிப்ரவரி மார்ச் ஏப்ரல் மே ஜூன் ஜூலை ஆகஸ்டு செப்டம்பர் அக்டோபர் நவம்பர் "
"டிசம்பர்"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "ஞாயிறு திங்கள் செவ்வாய் புதன் வியாழன் வெள்ளி சனி "
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "ஞா தி செ பு வி வெ ச"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "இப்பொழுது "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "கடிகாரம் "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "ஒரு நேரத்தை தேர்ந்த்தெடுக்க "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "நடு இரவு "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "காலை 6 மணி "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "மதியம் "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "வேண்டாம் "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "இன்று "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "நாள்காட்டி "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "நேற்று "
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "நாளை"

File diff suppressed because it is too large Load Diff

View File

@ -45,7 +45,7 @@ class Permission(models.Model):
ordering = ('content_type', 'codename') ordering = ('content_type', 'codename')
def __str__(self): def __str__(self):
return "%s | %s" % (self.content_type, self.name) return "%s | %s | %s" % (self.content_type.app_label, self.content_type, self.name)
class Group(models.Model): class Group(models.Model):
"""Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups. """Groups are a generic way of categorizing users to apply permissions, or some other label, to those users. A user can belong to any number of groups.

View File

@ -9,7 +9,7 @@
{{ form }} {{ form }}
</table> </table>
<input type="hidden" name="{{ stage_field }}" value="1" /> <input type="hidden" name="{{ stage_field }}" value="1" />
<p><input type="submit" value="Submit" /></p> <p><input type="submit" value="Preview" /></p>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -7,7 +7,7 @@
<table> <table>
{% for field in form %} {% for field in form %}
<tr> <tr>
<th>{{ field.verbose_name }}:</th> <th>{{ field.label }}:</th>
<td>{{ field.data|escape }}</td> <td>{{ field.data|escape }}</td>
</tr> </tr>
{% endfor %} {% endfor %}
@ -30,7 +30,7 @@
{{ form }} {{ form }}
</table> </table>
<input type="hidden" name="{{ stage_field }}" value="1" /> <input type="hidden" name="{{ stage_field }}" value="1" />
<p><input type="submit" value="Submit changes" /></p> <p><input type="submit" value="Preview" /></p>
</form> </form>
{% endblock %} {% endblock %}

View File

@ -0,0 +1,44 @@
"""
FR-specific Form helpers
"""
from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.newforms.util import smart_unicode
from django.utils.translation import gettext
import re
phone_digits_re = re.compile(r'^0\d(\s|\.)?(\d{2}(\s|\.)?){3}\d{2}$')
class FRZipCodeField(RegexField):
def __init__(self, *args, **kwargs):
super(FRZipCodeField, self).__init__(r'^\d{5}$',
max_length=None, min_length=None,
error_message=gettext(u'Enter a zip code in the format XXXXX.'),
*args, **kwargs)
class FRPhoneNumberField(Field):
"""
Validate local French phone number (not international ones)
The correct format is '0X XX XX XX XX'.
'0X.XX.XX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
'0X XX XX XX XX'.
"""
def clean(self, value):
super(FRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return u''
value = re.sub('(\.|\s)', '', smart_unicode(value))
m = phone_digits_re.search(value)
if m:
return u'%s %s %s %s %s' % (value[0:2], value[2:4], value[4:6], value[6:8], value[8:10])
raise ValidationError(u'Phone numbers must be in 0X XX XX XX XX format.')
class FRDepartmentSelect(Select):
"""
A Select widget that uses a list of FR departments as its choices.
"""
def __init__(self, attrs=None):
from fr_department import DEPARTMENT_ASCII_CHOICES # relative import
super(FRDepartmentSelect, self).__init__(attrs, choices=DEPARTMENT_ASCII_CHOICES)

View File

@ -0,0 +1,112 @@
# -*- coding: utf-8 -*-
DEPARTMENT_ASCII_CHOICES = (
('01', '01 - Ain'),
('02', '02 - Aisne'),
('03', '03 - Allier'),
('04', '04 - Alpes-de-Haute-Provence'),
('05', '05 - Hautes-Alpes'),
('06', '06 - Alpes-Maritimes'),
('07', '07 - Ardeche'),
('08', '08 - Ardennes'),
('09', '09 - Ariege'),
('10', '10 - Aube'),
('11', '11 - Aude'),
('12', '12 - Aveyron'),
('13', '13 - Bouches-du-Rhone'),
('14', '14 - Calvados'),
('15', '15 - Cantal'),
('16', '16 - Charente'),
('17', '17 - Charente-Maritime'),
('18', '18 - Cher'),
('19', '19 - Correze'),
('21', '21 - Cote-d\'Or'),
('22', '22 - Cotes-d\'Armor'),
('23', '23 - Creuse'),
('24', '24 - Dordogne'),
('25', '25 - Doubs'),
('26', '26 - Drome'),
('27', '27 - Eure'),
('28', '28 - Eure-et-Loire'),
('29', '29 - Finistere'),
('2A', '2A - Corse-du-Sud'),
('2B', '2B - Haute-Corse'),
('30', '30 - Gard'),
('31', '31 - Haute-Garonne'),
('32', '32 - Gers'),
('33', '33 - Gironde'),
('34', '34 - Herault'),
('35', '35 - Ille-et-Vilaine'),
('36', '36 - Indre'),
('37', '37 - Indre-et-Loire'),
('38', '38 - Isere'),
('39', '39 - Jura'),
('40', '40 - Landes'),
('41', '41 - Loir-et-Cher'),
('42', '42 - Loire'),
('43', '43 - Haute-Loire'),
('44', '44 - Loire-Atlantique'),
('45', '45 - Loiret'),
('46', '46 - Lot'),
('47', '47 - Lot-et-Garonne'),
('48', '48 - Lozere'),
('49', '49 - Maine-et-Loire'),
('50', '50 - Manche'),
('51', '51 - Marne'),
('52', '52 - Haute-Marne'),
('53', '53 - Mayenne'),
('54', '54 - Meurthe-et-Moselle'),
('55', '55 - Meuse'),
('56', '56 - Morbihan'),
('57', '57 - Moselle'),
('58', '58 - Nievre'),
('59', '59 - Nord'),
('60', '60 - Oise'),
('61', '61 - Orne'),
('62', '62 - Pas-de-Calais'),
('63', '63 - Puy-de-Dome'),
('64', '64 - Pyrenees-Atlantiques'),
('65', '65 - Hautes-Pyrenees'),
('66', '66 - Pyrenees-Orientales'),
('67', '67 - Bas-Rhin'),
('68', '68 - Haut-Rhin'),
('69', '69 - Rhone'),
('70', '70 - Haute-Saone'),
('71', '71 - Saone-et-Loire'),
('72', '72 - Sarthe'),
('73', '73 - Savoie'),
('74', '74 - Haute-Savoie'),
('75', '75 - Paris'),
('76', '76 - Seine-Maritime'),
('77', '77 - Seine-et-Marne'),
('78', '78 - Yvelines'),
('79', '79 - Deux-Sevres'),
('80', '80 - Somme'),
('81', '81 - Tarn'),
('82', '82 - Tarn-et-Garonne'),
('83', '83 - Var'),
('84', '84 - Vaucluse'),
('85', '85 - Vendee'),
('86', '86 - Vienne'),
('87', '87 - Haute-Vienne'),
('88', '88 - Vosges'),
('89', '89 - Yonne'),
('90', '90 - Territoire de Belfort'),
('91', '91 - Essonne'),
('92', '92 - Hauts-de-Seine'),
('93', '93 - Seine-Saint-Denis'),
('94', '94 - Val-de-Marne'),
('95', '95 - Val-d\'Oise'),
('2A', '2A - Corse du sud'),
('2B', '2B - Haute Corse'),
('971', '971 - Guadeloupe'),
('972', '972 - Martinique'),
('973', '973 - Guyane'),
('974', '974 - La Reunion'),
('975', '975 - Saint-Pierre-et-Miquelon'),
('976', '976 - Mayotte'),
('984', '984 - Terres Australes et Antarctiques'),
('986', '986 - Wallis et Futuna'),
('987', '987 - Polynesie Francaise'),
('988', '988 - Nouvelle-Caledonie'),
)

View File

@ -0,0 +1,38 @@
"""
JP-specific Form helpers
"""
from django.core import validators
from django.newforms import ValidationError
from django.utils.translation import gettext
from django.newforms.fields import RegexField, Select
import re
class JPPostalCodeField(RegexField):
"""
A form field that validates its input is a Japanese postcode.
Accepts 7 digits, with or without a hyphen.
"""
def __init__(self, *args, **kwargs):
super(JPPostalCodeField, self).__init__(r'^\d{3}-\d{4}$|^\d{7}$',
max_length=None, min_length=None,
error_message=gettext(u'Enter a postal code in the format XXXXXXX or XXX-XXXX.'),
*args, **kwargs)
def clean(self, value):
"""
Validates the input and returns a string that contains only numbers.
Returns an empty string for empty values.
"""
v = super(JPPostalCodeField, self).clean(value)
return v.replace('-', '')
class JPPrefectureSelect(Select):
"""
A Select widget that uses a list of Japanese prefectures as its choices.
"""
def __init__(self, attrs=None):
from jp_prefectures import JP_PREFECTURES
super(JPPrefectureSelect, self).__init__(attrs, choices=JP_PREFECTURES)

View File

@ -0,0 +1,51 @@
from django.utils.translation import gettext_lazy as gettext_lazy
JP_PREFECTURES = (
('hokkaido', gettext_lazy('Hokkaido'),),
('aomori', gettext_lazy('Aomori'),),
('iwate', gettext_lazy('Iwate'),),
('miyagi', gettext_lazy('Miyagi'),),
('akita', gettext_lazy('Akita'),),
('yamagata', gettext_lazy('Yamagata'),),
('fukushima', gettext_lazy('Fukushima'),),
('ibaraki', gettext_lazy('Ibaraki'),),
('tochigi', gettext_lazy('Tochigi'),),
('gunma', gettext_lazy('Gunma'),),
('saitama', gettext_lazy('Saitama'),),
('chiba', gettext_lazy('Chiba'),),
('tokyo', gettext_lazy('Tokyo'),),
('kanagawa', gettext_lazy('Kanagawa'),),
('yamanashi', gettext_lazy('Yamanashi'),),
('nagano', gettext_lazy('Nagano'),),
('niigata', gettext_lazy('Niigata'),),
('toyama', gettext_lazy('Toyama'),),
('ishikawa', gettext_lazy('Ishikawa'),),
('fukui', gettext_lazy('Fukui'),),
('gifu', gettext_lazy('Gifu'),),
('shizuoka', gettext_lazy('Shizuoka'),),
('aichi', gettext_lazy('Aichi'),),
('mie', gettext_lazy('Mie'),),
('shiga', gettext_lazy('Shiga'),),
('kyoto', gettext_lazy('Kyoto'),),
('osaka', gettext_lazy('Osaka'),),
('hyogo', gettext_lazy('Hyogo'),),
('nara', gettext_lazy('Nara'),),
('wakayama', gettext_lazy('Wakayama'),),
('tottori', gettext_lazy('Tottori'),),
('shimane', gettext_lazy('Shimane'),),
('okayama', gettext_lazy('Okayama'),),
('hiroshima', gettext_lazy('Hiroshima'),),
('yamaguchi', gettext_lazy('Yamaguchi'),),
('tokushima', gettext_lazy('Tokushima'),),
('kagawa', gettext_lazy('Kagawa'),),
('ehime', gettext_lazy('Ehime'),),
('kochi', gettext_lazy('Kochi'),),
('fukuoka', gettext_lazy('Fukuoka'),),
('saga', gettext_lazy('Saga'),),
('nagasaki', gettext_lazy('Nagasaki'),),
('kumamoto', gettext_lazy('Kumamoto'),),
('oita', gettext_lazy('Oita'),),
('miyazaki', gettext_lazy('Miyazaki'),),
('kagoshima', gettext_lazy('Kagoshima'),),
('okinawa', gettext_lazy('Okinawa'),),
)

View File

@ -83,7 +83,12 @@ class SessionMiddleware(object):
if accessed: if accessed:
patch_vary_headers(response, ('Cookie',)) patch_vary_headers(response, ('Cookie',))
if modified or settings.SESSION_SAVE_EVERY_REQUEST: if modified or settings.SESSION_SAVE_EVERY_REQUEST:
session_key = request.session.session_key or Session.objects.get_new_session_key() if request.session.session_key:
session_key = request.session.session_key
else:
obj = Session.objects.get_new_session_object()
session_key = obj.session_key
if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE: if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
max_age = None max_age = None
expires = None expires = None

View File

@ -1,4 +1,4 @@
import base64, md5, random, sys import base64, md5, random, sys, datetime
import cPickle as pickle import cPickle as pickle
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -23,6 +23,23 @@ class SessionManager(models.Manager):
break break
return session_key return session_key
def get_new_session_object(self):
"""
Returns a new session object.
"""
# FIXME: There is a *small* chance of collision here, meaning we will
# return an existing object. That can be fixed when we add a way to
# validate (and guarantee) that non-auto primary keys are unique. For
# now, we save immediately in order to reduce the "window of
# misfortune" as much as possible.
created = False
while not created:
obj, created = self.get_or_create(session_key=self.get_new_session_key(),
expire_date = datetime.datetime.now())
# Collision in key generation, so re-seed the generator
random.seed()
return obj
def save(self, session_key, session_dict, expire_date): def save(self, session_key, session_dict, expire_date):
s = self.model(session_key, self.encode(session_dict), expire_date) s = self.model(session_key, self.encode(session_dict), expire_date)
if session_dict: if session_dict:

View File

@ -280,7 +280,7 @@ def get_sql_delete(app):
from django.db import backend, connection, models, get_introspection_module from django.db import backend, connection, models, get_introspection_module
introspection = get_introspection_module() introspection = get_introspection_module()
# This should work even if a connecton isn't available # This should work even if a connection isn't available
try: try:
cursor = connection.cursor() cursor = connection.cursor()
except: except:
@ -512,6 +512,7 @@ def syncdb(verbosity=1, interactive=True):
created_models = set() created_models = set()
pending_references = {} pending_references = {}
# Create the tables for each model
for app in models.get_apps(): for app in models.get_apps():
app_name = app.__name__.split('.')[-2] app_name = app.__name__.split('.')[-2]
model_list = models.get_models(app) model_list = models.get_models(app)
@ -533,6 +534,11 @@ def syncdb(verbosity=1, interactive=True):
cursor.execute(statement) cursor.execute(statement)
table_list.append(model._meta.db_table) table_list.append(model._meta.db_table)
# Create the m2m tables. This must be done after all tables have been created
# to ensure that all referred tables will exist.
for app in models.get_apps():
app_name = app.__name__.split('.')[-2]
model_list = models.get_models(app)
for model in model_list: for model in model_list:
if model in created_models: if model in created_models:
sql = _get_many_to_many_sql_for_model(model) sql = _get_many_to_many_sql_for_model(model)
@ -542,7 +548,7 @@ def syncdb(verbosity=1, interactive=True):
for statement in sql: for statement in sql:
cursor.execute(statement) cursor.execute(statement)
transaction.commit_unless_managed() transaction.commit_unless_managed()
# Send the post_syncdb signal, so individual apps can do whatever they need # Send the post_syncdb signal, so individual apps can do whatever they need
# to do at this point. # to do at this point.

View File

@ -34,17 +34,17 @@ class Serializer(object):
for obj in queryset: for obj in queryset:
self.start_object(obj) self.start_object(obj)
for field in obj._meta.fields: for field in obj._meta.fields:
if field is obj._meta.pk: if field.serialize:
continue if field.rel is None:
elif field.rel is None: if self.selected_fields is None or field.attname in self.selected_fields:
if self.selected_fields is None or field.attname in self.selected_fields: self.handle_field(obj, field)
self.handle_field(obj, field) else:
else: if self.selected_fields is None or field.attname[:-3] in self.selected_fields:
if self.selected_fields is None or field.attname[:-3] in self.selected_fields: self.handle_fk_field(obj, field)
self.handle_fk_field(obj, field)
for field in obj._meta.many_to_many: for field in obj._meta.many_to_many:
if self.selected_fields is None or field.attname in self.selected_fields: if field.serialize:
self.handle_m2m_field(obj, field) if self.selected_fields is None or field.attname in self.selected_fields:
self.handle_m2m_field(obj, field)
self.end_object(obj) self.end_object(obj)
self.end_serialization() self.end_serialization()
return self.getvalue() return self.getvalue()

View File

@ -10,8 +10,14 @@ try:
except ImportError, e: except ImportError, e:
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e
if Database.version_info < (1,2,1,'final',2):
raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % MySQLdb.__version__ # We want version (1, 2, 1, 'final', 2) or later. We can't just use
# lexicographic ordering in this check because then (1, 2, 1, 'gamma')
# inadvertently passes the version test.
version = Database.version_info
if (version < (1,2,1) or (version[:3] == (1, 2, 1) and
(len(version) < 5 or version[3] != 'final' or version[4] < 2))):
raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__
from MySQLdb.converters import conversions from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE from MySQLdb.constants import FIELD_TYPE
@ -74,6 +80,8 @@ class DatabaseWrapper(local):
if not self._valid_connection(): if not self._valid_connection():
kwargs = { kwargs = {
'conv': django_conversions, 'conv': django_conversions,
'charset': 'utf8',
'use_unicode': False,
} }
if settings.DATABASE_USER: if settings.DATABASE_USER:
kwargs['user'] = settings.DATABASE_USER kwargs['user'] = settings.DATABASE_USER

View File

View File

@ -0,0 +1,233 @@
"""
MySQL database backend for Django.
Requires MySQLdb: http://sourceforge.net/projects/mysql-python
"""
from django.db.backends import util
try:
import MySQLdb as Database
except ImportError, e:
from django.core.exceptions import ImproperlyConfigured
raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e
from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE
import types
import re
DatabaseError = Database.DatabaseError
django_conversions = conversions.copy()
django_conversions.update({
types.BooleanType: util.rev_typecast_boolean,
FIELD_TYPE.DATETIME: util.typecast_timestamp,
FIELD_TYPE.DATE: util.typecast_date,
FIELD_TYPE.TIME: util.typecast_time,
})
# This should match the numerical portion of the version numbers (we can treat
# versions like 5.0.24 and 5.0.24a as the same). Based on the list of version
# at http://dev.mysql.com/doc/refman/4.1/en/news.html and
# http://dev.mysql.com/doc/refman/5.0/en/news.html .
server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
# This is an extra debug layer over MySQL queries, to display warnings.
# It's only used when DEBUG=True.
class MysqlDebugWrapper:
def __init__(self, cursor):
self.cursor = cursor
def execute(self, sql, params=()):
try:
return self.cursor.execute(sql, params)
except Database.Warning, w:
self.cursor.execute("SHOW WARNINGS")
raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
def executemany(self, sql, param_list):
try:
return self.cursor.executemany(sql, param_list)
except Database.Warning, w:
self.cursor.execute("SHOW WARNINGS")
raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
def __getattr__(self, attr):
if self.__dict__.has_key(attr):
return self.__dict__[attr]
else:
return getattr(self.cursor, attr)
try:
# Only exists in Python 2.4+
from threading import local
except ImportError:
# Import copy of _thread_local.py from Python 2.4
from django.utils._threading_local import local
class DatabaseWrapper(local):
def __init__(self, **kwargs):
self.connection = None
self.queries = []
self.server_version = None
self.options = kwargs
def _valid_connection(self):
if self.connection is not None:
try:
self.connection.ping()
return True
except DatabaseError:
self.connection.close()
self.connection = None
return False
def cursor(self):
from django.conf import settings
if not self._valid_connection():
kwargs = {
'user': settings.DATABASE_USER,
'db': settings.DATABASE_NAME,
'passwd': settings.DATABASE_PASSWORD,
'conv': django_conversions,
}
if settings.DATABASE_HOST.startswith('/'):
kwargs['unix_socket'] = settings.DATABASE_HOST
else:
kwargs['host'] = settings.DATABASE_HOST
if settings.DATABASE_PORT:
kwargs['port'] = int(settings.DATABASE_PORT)
kwargs.update(self.options)
self.connection = Database.connect(**kwargs)
cursor = self.connection.cursor()
if self.connection.get_server_info() >= '4.1':
cursor.execute("SET NAMES 'utf8'")
else:
cursor = self.connection.cursor()
if settings.DEBUG:
return util.CursorDebugWrapper(MysqlDebugWrapper(cursor), self)
return cursor
def _commit(self):
if self.connection is not None:
self.connection.commit()
def _rollback(self):
if self.connection is not None:
try:
self.connection.rollback()
except Database.NotSupportedError:
pass
def close(self):
if self.connection is not None:
self.connection.close()
self.connection = None
def get_server_version(self):
if not self.server_version:
if not self._valid_connection():
self.cursor()
m = server_version_re.match(self.connection.get_server_info())
if not m:
raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
self.server_version = tuple([int(x) for x in m.groups()])
return self.server_version
supports_constraints = True
def quote_name(name):
if name.startswith("`") and name.endswith("`"):
return name # Quoting once is enough.
return "`%s`" % name
dictfetchone = util.dictfetchone
dictfetchmany = util.dictfetchmany
dictfetchall = util.dictfetchall
def get_last_insert_id(cursor, table_name, pk_name):
return cursor.lastrowid
def get_date_extract_sql(lookup_type, table_name):
# lookup_type is 'year', 'month', 'day'
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), table_name)
def get_date_trunc_sql(lookup_type, field_name):
# lookup_type is 'year', 'month', 'day'
fields = ['year', 'month', 'day', 'hour', 'minute', 'second']
format = ('%%Y-', '%%m', '-%%d', ' %%H:', '%%i', ':%%s') # Use double percents to escape.
format_def = ('0000-', '01', '-01', ' 00:', '00', ':00')
try:
i = fields.index(lookup_type) + 1
except ValueError:
sql = field_name
else:
format_str = ''.join([f for f in format[:i]] + [f for f in format_def[i:]])
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
return sql
def get_limit_offset_sql(limit, offset=None):
sql = "LIMIT "
if offset and offset != 0:
sql += "%s," % offset
return sql + str(limit)
def get_random_function_sql():
return "RAND()"
def get_deferrable_sql():
return ""
def get_fulltext_search_sql(field_name):
return 'MATCH (%s) AGAINST (%%s IN BOOLEAN MODE)' % field_name
def get_drop_foreignkey_sql():
return "DROP FOREIGN KEY"
def get_pk_default_value():
return "DEFAULT"
def get_sql_flush(style, tables, sequences):
"""Return a list of SQL statements required to remove all data from
all tables in the database (without actually removing the tables
themselves) and put the database in an empty 'initial' state
"""
# NB: The generated SQL below is specific to MySQL
# 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
# to clear all tables of all data
if tables:
sql = ['SET FOREIGN_KEY_CHECKS = 0;'] + \
['%s %s;' % \
(style.SQL_KEYWORD('TRUNCATE'),
style.SQL_FIELD(quote_name(table))
) for table in tables] + \
['SET FOREIGN_KEY_CHECKS = 1;']
# 'ALTER TABLE table AUTO_INCREMENT = 1;'... style SQL statements
# to reset sequence indices
sql.extend(["%s %s %s %s %s;" % \
(style.SQL_KEYWORD('ALTER'),
style.SQL_KEYWORD('TABLE'),
style.SQL_TABLE(quote_name(sequence['table'])),
style.SQL_KEYWORD('AUTO_INCREMENT'),
style.SQL_FIELD('= 1'),
) for sequence in sequences])
return sql
else:
return []
OPERATOR_MAPPING = {
'exact': '= %s',
'iexact': 'LIKE %s',
'contains': 'LIKE BINARY %s',
'icontains': 'LIKE %s',
'gt': '> %s',
'gte': '>= %s',
'lt': '< %s',
'lte': '<= %s',
'startswith': 'LIKE BINARY %s',
'endswith': 'LIKE BINARY %s',
'istartswith': 'LIKE %s',
'iendswith': 'LIKE %s',
}

View File

@ -0,0 +1,14 @@
from django.conf import settings
import os
def runshell():
args = ['']
args += ["--user=%s" % settings.DATABASE_USER]
if settings.DATABASE_PASSWORD:
args += ["--password=%s" % settings.DATABASE_PASSWORD]
if settings.DATABASE_HOST:
args += ["--host=%s" % settings.DATABASE_HOST]
if settings.DATABASE_PORT:
args += ["--port=%s" % settings.DATABASE_PORT]
args += [settings.DATABASE_NAME]
os.execvp('mysql', args)

View File

@ -0,0 +1,29 @@
# This dictionary maps Field objects to their associated MySQL column
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
DATA_TYPES = {
'AutoField': 'integer AUTO_INCREMENT',
'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(%(maxlength)s)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'USStateField': 'varchar(2)',
}

View File

@ -0,0 +1,95 @@
from django.db.backends.mysql_old.base import quote_name
from MySQLdb import ProgrammingError, OperationalError
from MySQLdb.constants import FIELD_TYPE
import re
foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
def get_table_list(cursor):
"Returns a list of table names in the current database."
cursor.execute("SHOW TABLES")
return [row[0] for row in cursor.fetchall()]
def get_table_description(cursor, table_name):
"Returns a description of the table, with the DB-API cursor.description interface."
cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name))
return cursor.description
def _name_to_index(cursor, table_name):
"""
Returns a dictionary of {field_name: field_index} for the given table.
Indexes are 0-based.
"""
return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name))])
def get_relations(cursor, table_name):
"""
Returns a dictionary of {field_index: (field_index_other_table, other_table)}
representing all relationships to the given table. Indexes are 0-based.
"""
my_field_dict = _name_to_index(cursor, table_name)
constraints = []
relations = {}
try:
# This should work for MySQL 5.0.
cursor.execute("""
SELECT column_name, referenced_table_name, referenced_column_name
FROM information_schema.key_column_usage
WHERE table_name = %s
AND table_schema = DATABASE()
AND referenced_table_name IS NOT NULL
AND referenced_column_name IS NOT NULL""", [table_name])
constraints.extend(cursor.fetchall())
except (ProgrammingError, OperationalError):
# Fall back to "SHOW CREATE TABLE", for previous MySQL versions.
# Go through all constraints and save the equal matches.
cursor.execute("SHOW CREATE TABLE %s" % quote_name(table_name))
for row in cursor.fetchall():
pos = 0
while True:
match = foreign_key_re.search(row[1], pos)
if match == None:
break
pos = match.end()
constraints.append(match.groups())
for my_fieldname, other_table, other_field in constraints:
other_field_index = _name_to_index(cursor, other_table)[other_field]
my_field_index = my_field_dict[my_fieldname]
relations[my_field_index] = (other_field_index, other_table)
return relations
def get_indexes(cursor, table_name):
"""
Returns a dictionary of fieldname -> infodict for the given table,
where each infodict is in the format:
{'primary_key': boolean representing whether it's the primary key,
'unique': boolean representing whether it's a unique index}
"""
cursor.execute("SHOW INDEX FROM %s" % quote_name(table_name))
indexes = {}
for row in cursor.fetchall():
indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])}
return indexes
DATA_TYPES_REVERSE = {
FIELD_TYPE.BLOB: 'TextField',
FIELD_TYPE.CHAR: 'CharField',
FIELD_TYPE.DECIMAL: 'FloatField',
FIELD_TYPE.DATE: 'DateField',
FIELD_TYPE.DATETIME: 'DateTimeField',
FIELD_TYPE.DOUBLE: 'FloatField',
FIELD_TYPE.FLOAT: 'FloatField',
FIELD_TYPE.INT24: 'IntegerField',
FIELD_TYPE.LONG: 'IntegerField',
FIELD_TYPE.LONGLONG: 'IntegerField',
FIELD_TYPE.SHORT: 'IntegerField',
FIELD_TYPE.STRING: 'TextField',
FIELD_TYPE.TIMESTAMP: 'DateTimeField',
FIELD_TYPE.TINY: 'IntegerField',
FIELD_TYPE.TINY_BLOB: 'TextField',
FIELD_TYPE.MEDIUM_BLOB: 'TextField',
FIELD_TYPE.LONG_BLOB: 'TextField',
FIELD_TYPE.VAR_STRING: 'CharField',
}

View File

@ -66,7 +66,7 @@ class Field(object):
def __init__(self, verbose_name=None, name=None, primary_key=False, def __init__(self, verbose_name=None, name=None, primary_key=False,
maxlength=None, unique=False, blank=False, null=False, db_index=False, maxlength=None, unique=False, blank=False, null=False, db_index=False,
core=False, rel=None, default=NOT_PROVIDED, editable=True, core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True,
unique_for_date=None, unique_for_month=None, unique_for_year=None, unique_for_date=None, unique_for_month=None, unique_for_year=None,
validator_list=None, choices=None, radio_admin=None, help_text='', db_column=None): validator_list=None, choices=None, radio_admin=None, help_text='', db_column=None):
self.name = name self.name = name
@ -76,6 +76,7 @@ class Field(object):
self.blank, self.null = blank, null self.blank, self.null = blank, null
self.core, self.rel, self.default = core, rel, default self.core, self.rel, self.default = core, rel, default
self.editable = editable self.editable = editable
self.serialize = serialize
self.validator_list = validator_list or [] self.validator_list = validator_list or []
self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month
self.unique_for_year = unique_for_year self.unique_for_year = unique_for_year

View File

@ -94,6 +94,7 @@ class GenericRelation(RelatedField, Field):
kwargs['blank'] = True kwargs['blank'] = True
kwargs['editable'] = False kwargs['editable'] = False
kwargs['serialize'] = False
Field.__init__(self, **kwargs) Field.__init__(self, **kwargs)
def get_manipulator_field_objs(self): def get_manipulator_field_objs(self):

View File

@ -83,6 +83,7 @@ class Options(object):
self.fields.insert(bisect(self.fields, field), field) self.fields.insert(bisect(self.fields, field), field)
if not self.pk and field.primary_key: if not self.pk and field.primary_key:
self.pk = field self.pk = field
field.serialize = False
def __repr__(self): def __repr__(self):
return '<Options for %s>' % self.object_name return '<Options for %s>' % self.object_name

View File

@ -109,6 +109,8 @@ class QuerySet(object):
def __getitem__(self, k): def __getitem__(self, k):
"Retrieve an item or slice from the set of results." "Retrieve an item or slice from the set of results."
if not isinstance(k, (slice, int)):
raise TypeError
assert (not isinstance(k, slice) and (k >= 0)) \ assert (not isinstance(k, slice) and (k >= 0)) \
or (isinstance(k, slice) and (k.start is None or k.start >= 0) and (k.stop is None or k.stop >= 0)), \ or (isinstance(k, slice) and (k.start is None or k.start >= 0) and (k.stop is None or k.stop >= 0)), \
"Negative indexing is not supported." "Negative indexing is not supported."
@ -780,7 +782,7 @@ def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen,
def parse_lookup(kwarg_items, opts): def parse_lookup(kwarg_items, opts):
# Helper function that handles converting API kwargs # Helper function that handles converting API kwargs
# (e.g. "name__exact": "tom") to SQL. # (e.g. "name__exact": "tom") to SQL.
# Returns a tuple of (tables, joins, where, params). # Returns a tuple of (joins, where, params).
# 'joins' is a sorted dictionary describing the tables that must be joined # 'joins' is a sorted dictionary describing the tables that must be joined
# to complete the query. The dictionary is sorted because creation order # to complete the query. The dictionary is sorted because creation order

View File

@ -10,7 +10,7 @@ class CacheMiddleware(object):
Only parameter-less GET or HEAD-requests with status code 200 are cached. Only parameter-less GET or HEAD-requests with status code 200 are cached.
If CACHE_MIDDLEWARE_ANONYMOUS_ONLY is set to True, only anonymous requests If CACHE_MIDDLEWARE_ANONYMOUS_ONLY is set to True, only anonymous requests
(i.e., those node made by a logged-in user) will be cached. This is a (i.e., those not made by a logged-in user) will be cached. This is a
simple and effective way of avoiding the caching of the Django admin (and simple and effective way of avoiding the caching of the Django admin (and
any other user-specific content). any other user-specific content).

View File

@ -19,7 +19,7 @@ def get_object_or_404(klass, *args, **kwargs):
try: try:
return manager.get(*args, **kwargs) return manager.get(*args, **kwargs)
except klass.DoesNotExist: except klass.DoesNotExist:
raise Http404 raise Http404('No %s matches the given query.' % klass._meta.object_name)
def get_list_or_404(klass, *args, **kwargs): def get_list_or_404(klass, *args, **kwargs):
if isinstance(klass, Manager): if isinstance(klass, Manager):
@ -28,5 +28,5 @@ def get_list_or_404(klass, *args, **kwargs):
manager = klass._default_manager manager = klass._default_manager
obj_list = list(manager.filter(*args, **kwargs)) obj_list = list(manager.filter(*args, **kwargs))
if not obj_list: if not obj_list:
raise Http404 raise Http404('No %s matches the given query.' % manager.model._meta.object_name)
return obj_list return obj_list

View File

@ -595,8 +595,8 @@ def do_if(parser, token):
:: ::
{% if althlete_list %} {% if athlete_list %}
Number of athletes: {{ althete_list|count }} Number of athletes: {{ athlete_list|count }}
{% else %} {% else %}
No athletes. No athletes.
{% endif %} {% endif %}

View File

@ -69,6 +69,14 @@ def encode_multipart(boundary, data):
'', '',
value.read() value.read()
]) ])
elif hasattr(value, '__iter__'):
for item in value:
lines.extend([
'--' + boundary,
'Content-Disposition: form-data; name="%s"' % key,
'',
str(item)
])
else: else:
lines.extend([ lines.extend([
'--' + boundary, '--' + boundary,

View File

@ -17,7 +17,7 @@ def wrap(text, width):
pos = len(word) - word.rfind('\n') - 1 pos = len(word) - word.rfind('\n') - 1
for word in it: for word in it:
if "\n" in word: if "\n" in word:
lines = word.splitlines() lines = word.split('\n')
else: else:
lines = (word,) lines = (word,)
pos += len(lines[0]) + 1 pos += len(lines[0]) + 1

View File

@ -1,6 +1,6 @@
===================== ============================
The "contrib" add-ons The "django.contrib" add-ons
===================== ============================
Django aims to follow Python's `"batteries included" philosophy`_. It ships Django aims to follow Python's `"batteries included" philosophy`_. It ships
with a variety of extra, optional tools that solve common Web-development with a variety of extra, optional tools that solve common Web-development
@ -51,8 +51,6 @@ See the `csrf documentation`_.
formtools formtools
========= =========
**New in Django development version**
A set of high-level abstractions for Django forms (django.newforms). A set of high-level abstractions for Django forms (django.newforms).
django.contrib.formtools.preview django.contrib.formtools.preview
@ -142,8 +140,6 @@ See the `flatpages documentation`_.
localflavor localflavor
=========== ===========
**New in Django development version**
A collection of various Django snippets that are useful only for a particular A collection of various Django snippets that are useful only for a particular
country or culture. For example, ``django.contrib.localflavor.usa.forms`` country or culture. For example, ``django.contrib.localflavor.usa.forms``
contains a ``USZipCodeField`` that you can use to validate U.S. zip codes. contains a ``USZipCodeField`` that you can use to validate U.S. zip codes.
@ -153,12 +149,16 @@ markup
A collection of template filters that implement these common markup languages: A collection of template filters that implement these common markup languages:
* Textile * `Textile`_
* Markdown * `Markdown`_
* ReST (ReStructured Text) * `ReST (ReStructured Text)`_
For documentation, read the source code in django/contrib/markup/templatetags/markup.py. For documentation, read the source code in django/contrib/markup/templatetags/markup.py.
.. _Textile: http://en.wikipedia.org/wiki/Textile_%28markup_language%29
.. _Markdown: http://en.wikipedia.org/wiki/Markdown
.. _ReST (ReStructured Text): http://en.wikipedia.org/wiki/ReStructuredText
redirects redirects
========= =========

View File

@ -100,8 +100,6 @@ if you're ever curious to see the full list of defaults.
dumpdata [appname appname ...] dumpdata [appname appname ...]
------------------------------ ------------------------------
**New in Django development version**
Output to standard output all data in the database associated with the named Output to standard output all data in the database associated with the named
application(s). application(s).
@ -117,8 +115,6 @@ The output of ``dumpdata`` can be used as input for ``loaddata``.
flush flush
----- -----
**New in Django development version**
Return the database to the state it was in immediately after syncdb was Return the database to the state it was in immediately after syncdb was
executed. This means that all data will be removed from the database, any executed. This means that all data will be removed from the database, any
post-synchronization handlers will be re-executed, and the ``initial_data`` post-synchronization handlers will be re-executed, and the ``initial_data``
@ -165,18 +161,9 @@ needed.
``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection ``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection
only works in PostgreSQL and with certain types of MySQL tables. only works in PostgreSQL and with certain types of MySQL tables.
install [appname appname ...]
-----------------------------
**Removed in Django development version**
Executes the equivalent of ``sqlall`` for the given appnames.
loaddata [fixture fixture ...] loaddata [fixture fixture ...]
------------------------------ ------------------------------
**New in Django development version**
Searches for and loads the contents of the named fixture into the database. Searches for and loads the contents of the named fixture into the database.
A *Fixture* is a collection of files that contain the serialized contents of A *Fixture* is a collection of files that contain the serialized contents of
@ -350,14 +337,12 @@ Prints the DROP TABLE SQL statements for the given appnames.
sqlcustom [appname appname ...] sqlcustom [appname appname ...]
------------------------------- -------------------------------
**New in Django development version**
Prints the custom SQL statements for the given appnames. Prints the custom SQL statements for the given appnames.
For each model in each specified app, this command looks for the file For each model in each specified app, this command looks for the file
``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given appname and ``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given appname and
``<modelname>`` is the model's name in lowercase. For example, if you have an ``<modelname>`` is the model's name in lowercase. For example, if you have an
app ``news`` that includes a ``Story`` model, ``sqlinitialdata`` will attempt app ``news`` that includes a ``Story`` model, ``sqlcustom`` will attempt
to read a file ``news/sql/story.sql`` and append it to the output of this to read a file ``news/sql/story.sql`` and append it to the output of this
command. command.
@ -373,13 +358,6 @@ sqlindexes [appname appname ...]
Prints the CREATE INDEX SQL statements for the given appnames. Prints the CREATE INDEX SQL statements for the given appnames.
sqlinitialdata [appname appname ...]
--------------------------------------------
**Removed in Django development version**
This method has been renamed ``sqlcustom`` in the development version of Django.
sqlreset [appname appname ...] sqlreset [appname appname ...]
-------------------------------------- --------------------------------------
@ -426,8 +404,6 @@ fixture data files.
test test
---- ----
**New in Django development version**
Discover and run tests for all installed models. See `Testing Django applications`_ for more information. Discover and run tests for all installed models. See `Testing Django applications`_ for more information.
.. _testing django applications: ../testing/ .. _testing django applications: ../testing/
@ -475,8 +451,6 @@ setting the Python path for you.
--format --format
-------- --------
**New in Django development version**
Example usage:: Example usage::
django-admin.py dumpdata --format=xml django-admin.py dumpdata --format=xml
@ -493,8 +467,6 @@ options.
--indent --indent
-------- --------
**New in Django development version**
Example usage:: Example usage::
django-admin.py dumpdata --indent=4 django-admin.py dumpdata --indent=4
@ -506,8 +478,6 @@ Pretty-printing will only be enabled if the indent option is provided.
--noinput --noinput
--------- ---------
**New in Django development version**
Inform django-admin that the user should NOT be prompted for any input. Useful Inform django-admin that the user should NOT be prompted for any input. Useful
if the django-admin script will be executed as an unattended, automated if the django-admin script will be executed as an unattended, automated
script. script.
@ -530,8 +500,6 @@ Example output::
--verbosity --verbosity
----------- -----------
**New in Django development version**
Example usage:: Example usage::
django-admin.py syncdb --verbosity=2 django-admin.py syncdb --verbosity=2
@ -543,8 +511,6 @@ and `2` is verbose output.
--adminmedia --adminmedia
------------ ------------
**New in Django development version**
Example usage:: Example usage::
django-admin.py manage.py --adminmedia=/tmp/new-admin-style/ django-admin.py manage.py --adminmedia=/tmp/new-admin-style/

View File

@ -97,8 +97,7 @@ 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. (**This is new in the just before rendering the template.
Django development version.**)
**Example:** **Example:**
@ -752,10 +751,10 @@ If the results are paginated, the context will contain these extra variables:
* ``previous``: The previous page number, as an integer. This is 1-based. * ``previous``: The previous page number, as an integer. This is 1-based.
* `last_on_page`: **New in Django development version** The number of the * `last_on_page`: The number of the
last result on the current page. This is 1-based. last result on the current page. This is 1-based.
* `first_on_page`: **New in Django development version** The number of the * `first_on_page`: The number of the
first result on the current page. This is 1-based. first result on the current page. This is 1-based.
* ``pages``: The total number of pages, as an integer. * ``pages``: The total number of pages, as an integer.

View File

@ -86,25 +86,17 @@ Installing the official version
Distribution-provided packages will typically allow for automatic Distribution-provided packages will typically allow for automatic
installation of dependancies and easy upgrade paths. installation of dependancies and easy upgrade paths.
2. Download Django-0.95.tar.gz from our `download page`_. 2. Download the latest release from our `download page`_.
3. ``tar xzvf Django-0.95.tar.gz`` 3. Untar the downloaded file (e.g. ``tar xzvf Django-NNN.tar.gz``).
4. ``cd Django-0.95`` 4. Change into the downloaded directory (e.g. ``cd Django-NNN``).
5. ``sudo python setup.py install`` 5. Run ``sudo python setup.py install``.
Note that the last command will automatically download and install setuptools_
if you don't already have it installed. This requires a working Internet
connection and may cause problems on Python 2.5. If you run into problems,
try using our development version by following the instructions below. The
development version no longer uses setuptools nor requires an Internet
connection.
The command will install Django in your Python installation's ``site-packages`` The command will install Django in your Python installation's ``site-packages``
directory. directory.
.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
.. _distribution specific notes: ../distributions/ .. _distribution specific notes: ../distributions/
Installing the development version Installing the development version

View File

@ -104,8 +104,6 @@ Also removes the content from any response to a HEAD request and sets the
django.middleware.http.SetRemoteAddrFromForwardedFor django.middleware.http.SetRemoteAddrFromForwardedFor
---------------------------------------------------- ----------------------------------------------------
**New in Django development version**
Sets ``request.META['REMOTE_ADDR']`` based on Sets ``request.META['REMOTE_ADDR']`` based on
``request.META['HTTP_X_FORWARDED_FOR']``, if the latter is set. This is useful ``request.META['HTTP_X_FORWARDED_FOR']``, if the latter is set. This is useful
if you're sitting behind a reverse proxy that causes each request's if you're sitting behind a reverse proxy that causes each request's

View File

@ -362,9 +362,8 @@ Like a ``PositiveIntegerField``, but only allows values under a certain
containing only letters, numbers, underscores or hyphens. They're generally containing only letters, numbers, underscores or hyphens. They're generally
used in URLs. used in URLs.
In the Django development version, you can specify ``maxlength``. If Like a CharField, you can specify ``maxlength``. If ``maxlength`` is
``maxlength`` is not specified, Django will use a default length of 50. In not specified, Django will use a default length of 50.
previous Django versions, there's no way to override the length of 50.
Implies ``db_index=True``. Implies ``db_index=True``.
@ -1457,8 +1456,8 @@ user searches for ``john lennon``, Django will do the equivalent of this SQL
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%') WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%') AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
**New in Django development version:** For faster and/or more restrictive For faster and/or more restrictive searches, prefix the field name
searches, prefix the field name with an operator: with an operator:
``^`` ``^``
Matches the beginning of the field. For example, if ``search_fields`` is Matches the beginning of the field. For example, if ``search_fields`` is
@ -1754,8 +1753,6 @@ But this template code is good::
The ``permalink`` decorator The ``permalink`` decorator
~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version.**
The problem with the way we wrote ``get_absolute_url()`` above is that it The problem with the way we wrote ``get_absolute_url()`` above is that it
slightly violates the DRY principle: the URL for this object is defined both slightly violates the DRY principle: the URL for this object is defined both
in the URLConf file and in the model. in the URLConf file and in the model.

View File

@ -9,9 +9,10 @@ framework. This document explains how to use this new library.
Migration plan Migration plan
============== ==============
``django.newforms`` currently is only available in the Django development version ``django.newforms`` currently is only available in Django beginning
-- i.e., it's not available in the Django 0.95 release. For the next Django with the 0.96 release. the Django development version -- i.e., it's
release, our plan is to do the following: not available in the Django 0.95 release. For the next Django release,
our plan is to do the following:
* As of revision [4208], we've copied the current ``django.forms`` to * As of revision [4208], we've copied the current ``django.forms`` to
``django.oldforms``. This allows you to upgrade your code *now* rather ``django.oldforms``. This allows you to upgrade your code *now* rather
@ -859,6 +860,16 @@ level and at the form instance level, and the latter gets precedence::
<tr><th>Url:</th><td><input type="text" name="url" /></td></tr> <tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
Creating custom fields
----------------------
If the built-in ``Field`` classes don't meet your needs, you can easily create
custom ``Field`` classes. To do this, just create a subclass of
``django.newforms.Field``. Its only requirements are that it implement a
``clean()`` method and that its ``__init__()`` method accept the core arguments
mentioned above (``required``, ``label``, ``initial``, ``widget``,
``help_text``).
More coming soon More coming soon
================ ================

264
docs/release_notes_0.96.txt Normal file
View File

@ -0,0 +1,264 @@
=================================
Django version 0.96 release notes
=================================
Welcome to Django 0.96!
The primary goal for 0.96 is a cleanup and stabilization of the features
introduced in 0.95. There have been a few small `backwards-incompatible
changes`_ since 0.95, but the upgrade process should be fairly simple
and should not require major changes to existing applications.
However, we're also releasing 0.96 now because we have a set of
backwards-incompatible changes scheduled for the near future. Once
completed, they will involve some code changes for application
developers, so we recommend that you stick with Django 0.96 until the
next official release; then you'll be able to upgrade in one step
instead of needing to make incremental changes to keep up with the
development version of Django.
Backwards-incompatible changes
==============================
The following changes may require you to update your code when you switch from
0.95 to 0.96:
``MySQLdb`` version requirement
-------------------------------
Due to a bug in older versions of the ``MySQLdb`` Python module (which
Django uses to connect to MySQL databases), Django's MySQL backend now
requires version 1.2.1p2 or higher of `MySQLdb`, and will raise
exceptions if you attempt to use an older version.
If you're currently unable to upgrade your copy of ``MySQLdb`` to meet
this requirement, a separate, backwards-compatible backend, called
"mysql_old", has been added to Django. To use this backend, change
the ``DATABASE_ENGINE`` setting in your Django settings file from
this::
DATABASE_ENGINE = "mysql"
to this::
DATABASE_ENGINE = "mysql_old"
However, we strongly encourage MySQL users to upgrade to a more recent
version of `MySQLdb` as soon as possible, The "mysql_old" backend is
provided only to ease this transition, and is considered deprecated;
aside from any necessary security fixes, it will not be actively
maintained, and it will be removed in a future release of Django.
Also, note that some features, like the new ``DATABASE_OPTIONS``
setting (see the `databases documentation`_ for details), are only
available on the "mysql" backend, and will not be made available for
"mysql_old".
.. _databases documentation: ../databases/
Database constraint names changed
---------------------------------
The format of the constraint names Django generates for foreign key
references have changed slightly. These names are generally only used
when it is not possible to put the reference directly on the affected
column, so they is not always visible.
The effect of this change is that running ``manage.py reset`` and
similar commands against an existing database may generate SQL with
the new form of constraint name, while the database itself contains
constraints named in the old form; this will cause the database server
to raise an error message about modifying non-existent constraints.
If you need to work around this, there are two methods available:
1. Redirect the output of ``manage.py`` to a file, and edit the
generated SQL to use the correct constraint names before
executing it.
2. Examine the output of ``manage.py sqlall`` to see the new-style
constraint names, and use that as a guide to rename existing
constraints in your database.
Name changes in ``manage.py``
-----------------------------
A few of the options to ``manage.py`` have changed with the addition of fixture
support:
* There are new ``dumpdata`` and ``loaddata`` commands which, as
you might expect, will dump and load data to/from the
database. These commands can operate against any of Django's
supported serialization formats.
* The ``sqlinitialdata`` command has been renamed to ``sqlcustom`` to
emphasize that ``loaddata`` should be used for data (and ``sqlcustom`` for
other custom SQL -- views, stored procedures, etc.).
* The vestigial ``install`` command has been removed. Use ``syncdb``.
Backslash escaping changed
--------------------------
The Django database API now escapes backslashes given as query parameters. If
you have any database API code that matches backslashes, and it was working before
(despite the lack of escaping), you'll have to change your code to "unescape" the
slashes one level.
For example, this used to work::
# Find text containing a single backslash
MyModel.objects.filter(text__contains='\\\\')
The above is now incorrect, and should be rewritten as::
# Find text containing a single backslash
MyModel.objects.filter(text__contains='\\')
Removed ENABLE_PSYCO setting
----------------------------
The ``ENABLE_PSYCO`` setting no longer exists. If your settings file includes
``ENABLE_PSYCO`` it will have no effect; to use Psyco_, we recommend
writing a middleware class to activate it.
.. _psyco: http://psyco.sourceforge.net/
What's new in 0.96?
===================
This revision represents over a thousand source commits and over four hundred
bug fixes, so we can't possibly catalog all the changes. Here, we describe the
most notable changes in this release.
New forms library
-----------------
``django.newforms`` is Django's new form-handling library. It's a
replacement for ``django.forms``, the old form/manipulator/validation
framework. Both APIs are available in 0.96, but over the next two
releases we plan to switch completely to the new forms system, and
deprecate and remove the old system.
There are three elements to this transition:
* We've copied the current ``django.forms`` to
``django.oldforms``. This allows you to upgrade your code *now*
rather than waiting for the backwards-incompatible change and
rushing to fix your code after the fact. Just change your
import statements like this::
from django import forms # 0.95-style
from django import oldforms as forms # 0.96-style
* The next official release of Django will move the current
``django.newforms`` to ``django.forms``. This will be a
backwards-incompatible change, and anyone still using the old
version of ``django.forms`` at that time will need to change
their import statements as described above.
* The next release after that will completely remove
``django.oldforms``.
Although the ``newforms`` library will continue to evolve, it's ready for use
for most common cases. We recommend that anyone new to form handling skip the
old forms system and start with the new.
For more information about ``django.newforms``, read the `newforms
documentation`_.
.. _newforms documentation: ../newforms/
URLconf improvements
--------------------
You can now use any callable as the callback in URLconfs (previously, only
strings that referred to callables were allowed). This allows a much more
natural use of URLconfs. For example, this URLconf::
from django.conf.urls.defaults import *
urlpatterns = patterns('',
('^myview/$', 'mysite.myapp.views.myview')
)
can now be rewritten as::
from django.conf.urls.defaults import *
from mysite.myapp.views import myview
urlpatterns = patterns('',
('^myview/$', myview)
)
One useful application of this can be seen when using decorators; this
change allows you to apply decorators to views *in your
URLconf*. Thus, you can make a generic view require login very
easily::
from django.conf.urls.defaults import *
from django.contrib.auth.decorators import login_required
from django.views.generic.list_detail import object_list
from mysite.myapp.models import MyModel
info = {
"queryset" : MyModel.objects.all(),
}
urlpatterns = patterns('',
('^myview/$', login_required(object_list), info)
)
Note that both syntaxes (strings and callables) are valid, and will continue to
be valid for the foreseeable future.
The test framework
------------------
Django now includes a test framework so you can start transmuting fear into
boredom (with apologies to Kent Beck). You can write tests based on doctest_
or unittest_ and test your views with a simple test client.
There is also new support for "fixtures" -- initial data, stored in any of the
supported `serialization formats`_, that will be loaded into your database at the
start of your tests. This makes testing with real data much easier.
See `the testing documentation`_ for the full details.
.. _doctest: http://docs.python.org/lib/module-doctest.html
.. _unittest: http://docs.python.org/lib/module-unittest.html
.. _the testing documentation: ../testing/
.. _serialization formats: ../serialization/
Improvements to the admin interface
-----------------------------------
A small change, but a very nice one: dedicated views for adding and
updating users have been added to the admin interface, so you no
longer need to worry about working with hashed passwords in the admin.
Thanks
======
Since 0.95, a number of people have stepped forward and taken a major
new role in Django's development. We'd like to thank these people for
all their hard work:
* Russell Keith-Magee and Malcolm Tredinnick for their major code
contributions. This release wouldn't have been possible without them.
* Our new release manager, James Bennett, for his work in getting out
0.95.1, 0.96, and (hopefully) future release.
* Our ticket managers Chris Beaven (aka SmileyChris), Simon Greenhill,
Michael Radziej, and Gary Wilson. They agreed to take on the monumental
task of wrangling our tickets into nicely cataloged submission. Figuring
out what to work on is now about a million times easier; thanks again,
guys.
* Everyone who submitted a bug report, patch or ticket comment. We can't
possibly thank everyone by name -- over 200 developers submitted patches
that went into 0.96 -- but everyone who's contributed to Django is listed
in AUTHORS_.
.. _AUTHORS: http://code.djangoproject.com/browser/django/trunk/AUTHORS

View File

@ -384,7 +384,6 @@ Methods
Deletes the cookie with the given key. Fails silently if the key doesn't Deletes the cookie with the given key. Fails silently if the key doesn't
exist. exist.
The ``path`` and ``domain`` arguments are new in the Django development version.
Due to the way cookies work, ``path`` and ``domain`` should be the same Due to the way cookies work, ``path`` and ``domain`` should be the same
values you used in ``set_cookie()`` -- otherwise the cookie may not be deleted. values you used in ``set_cookie()`` -- otherwise the cookie may not be deleted.

View File

@ -31,7 +31,8 @@ but it'll almost always be a QuerySet).
You can also use a serializer object directly:: You can also use a serializer object directly::
xml_serializer = serializers.get_serializer("xml") XMLSerializer = serializers.get_serializer("xml")
xml_serializer = XMLSerializer()
xml_serializer.serialize(queryset) xml_serializer.serialize(queryset)
data = xml_serializer.getvalue() data = xml_serializer.getvalue()

View File

@ -265,8 +265,6 @@ The name of the cookie to use for sessions. This can be whatever you want.
SESSION_COOKIE_SECURE SESSION_COOKIE_SECURE
--------------------- ---------------------
**New in Django development version**
Default: ``False`` Default: ``False``
Whether to use a secure cookie for the session cookie. If this is set to Whether to use a secure cookie for the session cookie. If this is set to

View File

@ -245,7 +245,8 @@ DATABASE_ENGINE
Default: ``''`` (Empty string) Default: ``''`` (Empty string)
Which database backend to use. Either ``'postgresql_psycopg2'``, Which database backend to use. Either ``'postgresql_psycopg2'``,
``'postgresql'``, ``'mysql'``, ``'sqlite3'`` or ``'ado_mssql'``. ``'postgresql'``, ``'mysql'``, ``'mysql_old'``, ``'sqlite3'`` or
``'ado_mssql'``.
DATABASE_HOST DATABASE_HOST
------------- -------------
@ -428,8 +429,6 @@ trailing space.
FIXTURE_DIRS FIXTURE_DIRS
------------- -------------
**New in Django development version**
Default: ``()`` (Empty tuple) Default: ``()`` (Empty tuple)
List of locations of the fixture data files, in search order. Note that List of locations of the fixture data files, in search order. Note that
@ -715,8 +714,6 @@ See the `session docs`_.
SESSION_COOKIE_SECURE SESSION_COOKIE_SECURE
--------------------- ---------------------
**New in Django development version**
Default: ``False`` Default: ``False``
Whether to use a secure cookie for the session cookie. If this is set to Whether to use a secure cookie for the session cookie. If this is set to
@ -811,8 +808,6 @@ misspelled) variables. See `How invalid variables are handled`_.
TEST_RUNNER TEST_RUNNER
----------- -----------
**New in Django development version**
Default: ``'django.test.simple.run_tests'`` Default: ``'django.test.simple.run_tests'``
The name of the method to use for starting the test suite. See The name of the method to use for starting the test suite. See
@ -823,8 +818,6 @@ The name of the method to use for starting the test suite. See
TEST_DATABASE_NAME TEST_DATABASE_NAME
------------------ ------------------
**New in Django development version**
Default: ``None`` Default: ``None``
The name of database to use when running the test suite. If a value of The name of database to use when running the test suite. If a value of

View File

@ -112,8 +112,6 @@ know how to write Python code.
Comments Comments
======== ========
**New in Django development version**
To comment-out part of a template, use the comment syntax: ``{# #}``. To comment-out part of a template, use the comment syntax: ``{# #}``.
For example, this template would render as ``'hello'``:: For example, this template would render as ``'hello'``::
@ -253,8 +251,8 @@ Here are some tips for working with inheritance:
if you want to add to the contents of a parent block instead of if you want to add to the contents of a parent block instead of
completely overriding it. completely overriding it.
* **New in Django development version:** For extra readability, you can * For extra readability, you can optionally give a *name* to your
optionally give a *name* to your ``{% endblock %}`` tag. For example:: ``{% endblock %}`` tag. For example::
{% block content %} {% block content %}
... ...
@ -548,9 +546,9 @@ The 'ifchanged' block tag is used within a loop. It has two possible uses.
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a> <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %} {% endfor %}
2. **New in Django development version.** If given a variable, check whether that 2. If given a variable, check whether that variable has changed. For
variable has changed. For example, the following shows the date every time it example, the following shows the date every time it changes, but
changes, but only shows the hour if both the hour and the date has changed:: only shows the hour if both the hour and the date has changed::
{% for date in days %} {% for date in days %}
{% ifchanged date.date %} {{ date.date }} {% endifchanged %} {% ifchanged date.date %} {{ date.date }} {% endifchanged %}
@ -828,13 +826,9 @@ The argument tells which template bit to output:
``closecomment`` ``#}`` ``closecomment`` ``#}``
================== ======= ================== =======
Note: ``opencomment`` and ``closecomment`` are new in the Django development version.
url url
~~~ ~~~
**New in Django development version**
**Note that the syntax for this tag may change in the future, as we make it more robust.** **Note that the syntax for this tag may change in the future, as we make it more robust.**
Returns an absolute URL (i.e., a URL without the domain name) matching a given Returns an absolute URL (i.e., a URL without the domain name) matching a given
@ -976,8 +970,6 @@ place -- but only if there's a decimal part to be displayed. For example:
* ``36.15`` gets converted to ``36.2`` * ``36.15`` gets converted to ``36.2``
* ``36`` gets converted to ``36`` * ``36`` gets converted to ``36``
**New in Django development version**
If used with a numeric integer argument, ``floatformat`` rounds a number to that If used with a numeric integer argument, ``floatformat`` rounds a number to that
many decimal places. For example: many decimal places. For example:

View File

@ -2,8 +2,6 @@
Testing Django applications Testing Django applications
=========================== ===========================
**New in Django development version**.
Automated testing is an extremely useful weapon in the bug-killing arsenal Automated testing is an extremely useful weapon in the bug-killing arsenal
of the modern developer. When initially writing code, a test suite can be of the modern developer. When initially writing code, a test suite can be
used to validate that code behaves as expected. When refactoring or used to validate that code behaves as expected. When refactoring or
@ -227,6 +225,12 @@ can be invoked on the ``Client`` instance.
The key-value pairs in the data dictionary will be encoded as a multipart The key-value pairs in the data dictionary will be encoded as a multipart
message and used to create the POST data payload. message and used to create the POST data payload.
To submit multiple values for a given key (for example, to specify
the selections for a multiple selection list), provide the values as a
list or tuple for the required key. For example, a data dictionary of
``{'choices': ('a','b','d')}`` would submit three selected rows for the
field named ``choices``.
Submitting files is a special case. To POST a file, you need only Submitting files is a special case. To POST a file, you need only
provide the file field name as a key, and a file handle to the file you wish to provide the file field name as a key, and a file handle to the file you wish to
upload as a value. The Test Client will populate the two POST fields (i.e., upload as a value. The Test Client will populate the two POST fields (i.e.,

View File

@ -400,8 +400,6 @@ to pass metadata and options to views.
Passing extra options to ``include()`` Passing extra options to ``include()``
-------------------------------------- --------------------------------------
**New in Django development version.**
Similarly, you can pass extra options to ``include()``. When you pass extra Similarly, you can pass extra options to ``include()``. When you pass extra
options to ``include()``, *each* line in the included URLconf will be passed options to ``include()``, *each* line in the included URLconf will be passed
the extra options. the extra options.
@ -442,8 +440,6 @@ every view in the the included URLconf accepts the extra options you're passing.
Passing callable objects instead of strings Passing callable objects instead of strings
=========================================== ===========================================
**New in Django development version.**
Some developers find it more natural to pass the actual Python function object Some developers find it more natural to pass the actual Python function object
rather than a string containing the path to its module. This alternative is rather than a string containing the path to its module. This alternative is
supported -- you can pass any callable object as the view. supported -- you can pass any callable object as the view.

View File

@ -1,5 +1,5 @@
""" """
Empty model tests 39. Empty model tests
These test that things behave sensibly for the rare corner-case of a model with These test that things behave sensibly for the rare corner-case of a model with
no fields. no fields.

View File

@ -1,5 +1,5 @@
""" """
31. Callable defaults 32. Callable defaults
You can pass callable objects as the ``default`` parameter to a field. When You can pass callable objects as the ``default`` parameter to a field. When
the object is created without an explicit value passed in, Django will call the object is created without an explicit value passed in, Django will call

View File

@ -1,5 +1,5 @@
""" """
39. Fixtures. 37. Fixtures.
Fixtures are a way of loading data into the database in bulk. Fixure data Fixtures are a way of loading data into the database in bulk. Fixure data
can be stored in any serializable format (including JSON and XML). Fixtures can be stored in any serializable format (including JSON and XML). Fixtures

View File

@ -1,5 +1,5 @@
""" """
33. Generic relations 34. Generic relations
Generic relations let an object have a foreign key to any object through a Generic relations let an object have a foreign key to any object through a
content-type/object-id field. A generic foreign key can point to any object, content-type/object-id field. A generic foreign key can point to any object,

View File

@ -1,5 +1,5 @@
""" """
34. DB-API Shortcuts 35. DB-API Shortcuts
get_object_or_404 is a shortcut function to be used in view functions for get_object_or_404 is a shortcut function to be used in view functions for
performing a get() lookup and raising a Http404 exception if a DoesNotExist performing a get() lookup and raising a Http404 exception if a DoesNotExist
@ -44,7 +44,7 @@ __test__ = {'API_TESTS':"""
>>> get_object_or_404(Article, title="Foo") >>> get_object_or_404(Article, title="Foo")
Traceback (most recent call last): Traceback (most recent call last):
... ...
Http404 Http404: No Article matches the given query.
# Create an Article. # Create an Article.
>>> article = Article.objects.create(title="Run away!") >>> article = Article.objects.create(title="Run away!")
@ -63,7 +63,7 @@ Http404
>>> get_object_or_404(a.article_set, title__contains="Camelot") >>> get_object_or_404(a.article_set, title__contains="Camelot")
Traceback (most recent call last): Traceback (most recent call last):
... ...
Http404 Http404: No Article matches the given query.
# Custom managers can be used too. # Custom managers can be used too.
>>> get_object_or_404(Article.by_a_sir, title="Run away!") >>> get_object_or_404(Article.by_a_sir, title="Run away!")
@ -77,7 +77,7 @@ Http404
>>> get_list_or_404(a.article_set, title__icontains='Shrubbery') >>> get_list_or_404(a.article_set, title__icontains='Shrubbery')
Traceback (most recent call last): Traceback (most recent call last):
... ...
Http404 Http404: No Article matches the given query.
# Custom managers can be used too. # Custom managers can be used too.
>>> get_list_or_404(Article.by_a_sir, title__icontains="Run") >>> get_list_or_404(Article.by_a_sir, title__icontains="Run")

View File

@ -1,5 +1,5 @@
""" """
32. get_or_create() 33. get_or_create()
get_or_create() does what it says: it tries to look up an object with the given get_or_create() does what it says: it tries to look up an object with the given
parameters. If an object isn't found, it creates one with the given parameters. parameters. If an object isn't found, it creates one with the given parameters.

View File

@ -1,5 +1,5 @@
""" """
28. Many-to-many and many-to-one relationships to the same table 29. Many-to-many and many-to-one relationships to the same table
Make sure to set ``related_name`` if you use relationships to the same table. Make sure to set ``related_name`` if you use relationships to the same table.
""" """

View File

@ -1,5 +1,5 @@
""" """
27. Many-to-many relationships between the same two tables 28. Many-to-many relationships between the same two tables
In this example, A Person can have many friends, who are also people. Friendship is a In this example, A Person can have many friends, who are also people. Friendship is a
symmetrical relationship - if I am your friend, you are my friend. symmetrical relationship - if I am your friend, you are my friend.

View File

@ -1,5 +1,5 @@
""" """
26. Default manipulators 27. Default manipulators
Each model gets an AddManipulator and ChangeManipulator by default. Each model gets an AddManipulator and ChangeManipulator by default.
""" """

View File

@ -1,5 +1,5 @@
""" """
34. Generating HTML forms from models 36. Generating HTML forms from models
Django provides shortcuts for creating Form objects from a model class and a Django provides shortcuts for creating Form objects from a model class and a
model instance. model instance.

View File

@ -1,5 +1,5 @@
""" """
29. Object pagination 30. Object pagination
Django provides a framework for paginating a list of objects in a few lines Django provides a framework for paginating a list of objects in a few lines
of code. This is often useful for dividing search results or long lists of of code. This is often useful for dividing search results or long lists of

View File

@ -1,5 +1,5 @@
""" """
XXX. Tests for ``select_related()`` 40. Tests for select_related()
``select_related()`` follows all relationships and pre-caches any foreign key ``select_related()`` follows all relationships and pre-caches any foreign key
values so that complex trees can be fetched in a single query. However, this values so that complex trees can be fetched in a single query. However, this

View File

@ -1,5 +1,5 @@
""" """
XXX. Serialization 41. Serialization
``django.core.serializers`` provides interfaces to converting Django querysets ``django.core.serializers`` provides interfaces to converting Django querysets
to and from "flat" data (i.e. strings). to and from "flat" data (i.e. strings).

View File

@ -1,5 +1,5 @@
""" """
39. Testing using the Test Client 38. Testing using the Test Client
The test client is a class that can act like a simple The test client is a class that can act like a simple
browser for testing purposes. browser for testing purposes.
@ -82,6 +82,42 @@ class ClientTest(TestCase):
# Check that the response was a 302 (redirect) # Check that the response was a 302 (redirect)
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
def test_valid_form(self):
"POST valid data to a form"
post_data = {
'text': 'Hello World',
'email': 'foo@example.com',
'value': 37,
'single': 'b',
'multi': ('b','c','e')
}
response = self.client.post('/test_client/form_view/', post_data)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template.name, "Valid POST Template")
def test_incomplete_data_form(self):
"POST incomplete data to a form"
post_data = {
'text': 'Hello World',
'value': 37
}
response = self.client.post('/test_client/form_view/', post_data)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template.name, "Invalid POST Template")
def test_form_error(self):
"POST erroneous data to a form"
post_data = {
'text': 'Hello World',
'email': 'not an email address',
'value': 37,
'single': 'b',
'multi': ('b','c','e')
}
response = self.client.post('/test_client/form_view/', post_data)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template.name, "Invalid POST Template")
def test_unknown_page(self): def test_unknown_page(self):
"GET an invalid URL" "GET an invalid URL"
response = self.client.get('/test_client/unknown_view/') response = self.client.get('/test_client/unknown_view/')

View File

@ -6,6 +6,7 @@ urlpatterns = patterns('',
(r'^post_view/$', views.post_view), (r'^post_view/$', views.post_view),
(r'^raw_post_view/$', views.raw_post_view), (r'^raw_post_view/$', views.raw_post_view),
(r'^redirect_view/$', views.redirect_view), (r'^redirect_view/$', views.redirect_view),
(r'^form_view/$', views.form_view),
(r'^login_protected_view/$', views.login_protected_view), (r'^login_protected_view/$', views.login_protected_view),
(r'^session_view/$', views.session_view), (r'^session_view/$', views.session_view),
(r'^broken_view/$', views.broken_view) (r'^broken_view/$', views.broken_view)

View File

@ -2,6 +2,8 @@ from xml.dom.minidom import parseString
from django.template import Context, Template from django.template import Context, Template
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.newforms.forms import Form
from django.newforms import fields
def get_view(request): def get_view(request):
"A simple view that expects a GET request, and returns a rendered template" "A simple view that expects a GET request, and returns a rendered template"
@ -46,6 +48,38 @@ def redirect_view(request):
"A view that redirects all requests to the GET view" "A view that redirects all requests to the GET view"
return HttpResponseRedirect('/test_client/get_view/') return HttpResponseRedirect('/test_client/get_view/')
TestChoices = (
('a', 'First Choice'),
('b', 'Second Choice'),
('c', 'Third Choice'),
('d', 'Fourth Choice'),
('e', 'Fifth Choice')
)
class TestForm(Form):
text = fields.CharField()
email = fields.EmailField()
value = fields.IntegerField()
single = fields.ChoiceField(choices=TestChoices)
multi = fields.MultipleChoiceField(choices=TestChoices)
def form_view(request):
"A view that tests a simple form"
if request.method == 'POST':
form = TestForm(request.POST)
if form.is_valid():
t = Template('Valid POST data.', name='Valid POST Template')
c = Context()
else:
t = Template('Invalid POST data. {{ form.errors }}', name='Invalid POST Template')
c = Context({'form': form})
else:
form = TestForm()
t = Template('Viewing base form. {{ form }}.', name='Form GET Template')
c = Context({'form': form})
return HttpResponse(t.render(c))
def login_protected_view(request): def login_protected_view(request):
"A simple view that is login protected." "A simple view that is login protected."
t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template') t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')

View File

@ -1,5 +1,5 @@
""" """
30. Validation 31. Validation
This is an experimental feature! This is an experimental feature!

View File

@ -133,6 +133,12 @@ u'\xcb'
>>> wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14) >>> wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14)
"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid" "this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid"
>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',14)
'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented'
>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',15)
'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented'
>>> ljust('test', 10) >>> ljust('test', 10)
'test ' 'test '

View File

@ -3556,6 +3556,329 @@ u''
>>> f.clean('') >>> f.clean('')
u'' u''
# FRZipCodeField #############################################################
FRZipCodeField validates that the data is a valid FR zipcode.
>>> from django.contrib.localflavor.fr.forms import FRZipCodeField
>>> f = FRZipCodeField()
>>> f.clean('75001')
u'75001'
>>> f.clean('93200')
u'93200'
>>> f.clean('2A200')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX.']
>>> f.clean('980001')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX.']
>>> 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 = FRZipCodeField(required=False)
>>> f.clean('75001')
u'75001'
>>> f.clean('93200')
u'93200'
>>> f.clean('2A200')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX.']
>>> f.clean('980001')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX.']
>>> f.clean(None)
u''
>>> f.clean('')
u''
# FRPhoneNumberField ##########################################################
FRPhoneNumberField validates that the data is a valid french phone number.
It's normalized to 0X XX XX XX XX format. Dots are valid too.
>>> from django.contrib.localflavor.fr.forms import FRPhoneNumberField
>>> f = FRPhoneNumberField()
>>> f.clean('01 55 44 58 64')
u'01 55 44 58 64'
>>> f.clean('0155445864')
u'01 55 44 58 64'
>>> f.clean('01 5544 5864')
u'01 55 44 58 64'
>>> f.clean('01 55.44.58.64')
u'01 55 44 58 64'
>>> f.clean('01.55.44.58.64')
u'01 55 44 58 64'
>>> f.clean('01,55,44,58,64')
Traceback (most recent call last):
...
ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.']
>>> f.clean('555 015 544')
Traceback (most recent call last):
...
ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.']
>>> 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 = FRPhoneNumberField(required=False)
>>> f.clean('01 55 44 58 64')
u'01 55 44 58 64'
>>> f.clean('0155445864')
u'01 55 44 58 64'
>>> f.clean('01 5544 5864')
u'01 55 44 58 64'
>>> f.clean('01 55.44.58.64')
u'01 55 44 58 64'
>>> f.clean('01.55.44.58.64')
u'01 55 44 58 64'
>>> f.clean('01,55,44,58,64')
Traceback (most recent call last):
...
ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.']
>>> f.clean('555 015 544')
Traceback (most recent call last):
...
ValidationError: [u'Phone numbers must be in 0X XX XX XX XX format.']
>>> f.clean(None)
u''
>>> f.clean('')
u''
# FRDepartmentSelect ###############################################################
FRDepartmentSelect is a Select widget that uses a list of french departments
including DOM TOM
>>> from django.contrib.localflavor.fr.forms import FRDepartmentSelect
>>> w = FRDepartmentSelect()
>>> print w.render('dep', 'Paris')
<select name="dep">
<option value="01">01 - Ain</option>
<option value="02">02 - Aisne</option>
<option value="03">03 - Allier</option>
<option value="04">04 - Alpes-de-Haute-Provence</option>
<option value="05">05 - Hautes-Alpes</option>
<option value="06">06 - Alpes-Maritimes</option>
<option value="07">07 - Ardeche</option>
<option value="08">08 - Ardennes</option>
<option value="09">09 - Ariege</option>
<option value="10">10 - Aube</option>
<option value="11">11 - Aude</option>
<option value="12">12 - Aveyron</option>
<option value="13">13 - Bouches-du-Rhone</option>
<option value="14">14 - Calvados</option>
<option value="15">15 - Cantal</option>
<option value="16">16 - Charente</option>
<option value="17">17 - Charente-Maritime</option>
<option value="18">18 - Cher</option>
<option value="19">19 - Correze</option>
<option value="21">21 - Cote-d&#39;Or</option>
<option value="22">22 - Cotes-d&#39;Armor</option>
<option value="23">23 - Creuse</option>
<option value="24">24 - Dordogne</option>
<option value="25">25 - Doubs</option>
<option value="26">26 - Drome</option>
<option value="27">27 - Eure</option>
<option value="28">28 - Eure-et-Loire</option>
<option value="29">29 - Finistere</option>
<option value="2A">2A - Corse-du-Sud</option>
<option value="2B">2B - Haute-Corse</option>
<option value="30">30 - Gard</option>
<option value="31">31 - Haute-Garonne</option>
<option value="32">32 - Gers</option>
<option value="33">33 - Gironde</option>
<option value="34">34 - Herault</option>
<option value="35">35 - Ille-et-Vilaine</option>
<option value="36">36 - Indre</option>
<option value="37">37 - Indre-et-Loire</option>
<option value="38">38 - Isere</option>
<option value="39">39 - Jura</option>
<option value="40">40 - Landes</option>
<option value="41">41 - Loir-et-Cher</option>
<option value="42">42 - Loire</option>
<option value="43">43 - Haute-Loire</option>
<option value="44">44 - Loire-Atlantique</option>
<option value="45">45 - Loiret</option>
<option value="46">46 - Lot</option>
<option value="47">47 - Lot-et-Garonne</option>
<option value="48">48 - Lozere</option>
<option value="49">49 - Maine-et-Loire</option>
<option value="50">50 - Manche</option>
<option value="51">51 - Marne</option>
<option value="52">52 - Haute-Marne</option>
<option value="53">53 - Mayenne</option>
<option value="54">54 - Meurthe-et-Moselle</option>
<option value="55">55 - Meuse</option>
<option value="56">56 - Morbihan</option>
<option value="57">57 - Moselle</option>
<option value="58">58 - Nievre</option>
<option value="59">59 - Nord</option>
<option value="60">60 - Oise</option>
<option value="61">61 - Orne</option>
<option value="62">62 - Pas-de-Calais</option>
<option value="63">63 - Puy-de-Dome</option>
<option value="64">64 - Pyrenees-Atlantiques</option>
<option value="65">65 - Hautes-Pyrenees</option>
<option value="66">66 - Pyrenees-Orientales</option>
<option value="67">67 - Bas-Rhin</option>
<option value="68">68 - Haut-Rhin</option>
<option value="69">69 - Rhone</option>
<option value="70">70 - Haute-Saone</option>
<option value="71">71 - Saone-et-Loire</option>
<option value="72">72 - Sarthe</option>
<option value="73">73 - Savoie</option>
<option value="74">74 - Haute-Savoie</option>
<option value="75">75 - Paris</option>
<option value="76">76 - Seine-Maritime</option>
<option value="77">77 - Seine-et-Marne</option>
<option value="78">78 - Yvelines</option>
<option value="79">79 - Deux-Sevres</option>
<option value="80">80 - Somme</option>
<option value="81">81 - Tarn</option>
<option value="82">82 - Tarn-et-Garonne</option>
<option value="83">83 - Var</option>
<option value="84">84 - Vaucluse</option>
<option value="85">85 - Vendee</option>
<option value="86">86 - Vienne</option>
<option value="87">87 - Haute-Vienne</option>
<option value="88">88 - Vosges</option>
<option value="89">89 - Yonne</option>
<option value="90">90 - Territoire de Belfort</option>
<option value="91">91 - Essonne</option>
<option value="92">92 - Hauts-de-Seine</option>
<option value="93">93 - Seine-Saint-Denis</option>
<option value="94">94 - Val-de-Marne</option>
<option value="95">95 - Val-d&#39;Oise</option>
<option value="2A">2A - Corse du sud</option>
<option value="2B">2B - Haute Corse</option>
<option value="971">971 - Guadeloupe</option>
<option value="972">972 - Martinique</option>
<option value="973">973 - Guyane</option>
<option value="974">974 - La Reunion</option>
<option value="975">975 - Saint-Pierre-et-Miquelon</option>
<option value="976">976 - Mayotte</option>
<option value="984">984 - Terres Australes et Antarctiques</option>
<option value="986">986 - Wallis et Futuna</option>
<option value="987">987 - Polynesie Francaise</option>
<option value="988">988 - Nouvelle-Caledonie</option>
</select>
# JPPostalCodeField ###############################################################
A form field that validates its input is a Japanese postcode.
Accepts 7 digits(with/out hyphen).
>>> from django.contrib.localflavor.jp.forms import JPPostalCodeField
>>> f = JPPostalCodeField()
>>> f.clean('251-0032')
u'2510032'
>>> f.clean('2510032')
u'2510032'
>>> f.clean('2510-032')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
>>> f.clean('251a0032')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
>>> f.clean('a51-0032')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
>>> f.clean('25100321')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f = JPPostalCodeField(required=False)
>>> f.clean('251-0032')
u'2510032'
>>> f.clean('2510032')
u'2510032'
>>> f.clean('2510-032')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postal code in the format XXXXXXX or XXX-XXXX.']
>>> f.clean('')
u''
>>> f.clean(None)
u''
# JPPrefectureSelect ###############################################################
A Select widget that uses a list of Japanese prefectures as its choices.
>>> from django.contrib.localflavor.jp.forms import JPPrefectureSelect
>>> w = JPPrefectureSelect()
>>> print w.render('prefecture', 'kanagawa')
<select name="prefecture">
<option value="hokkaido">Hokkaido</option>
<option value="aomori">Aomori</option>
<option value="iwate">Iwate</option>
<option value="miyagi">Miyagi</option>
<option value="akita">Akita</option>
<option value="yamagata">Yamagata</option>
<option value="fukushima">Fukushima</option>
<option value="ibaraki">Ibaraki</option>
<option value="tochigi">Tochigi</option>
<option value="gunma">Gunma</option>
<option value="saitama">Saitama</option>
<option value="chiba">Chiba</option>
<option value="tokyo">Tokyo</option>
<option value="kanagawa" selected="selected">Kanagawa</option>
<option value="yamanashi">Yamanashi</option>
<option value="nagano">Nagano</option>
<option value="niigata">Niigata</option>
<option value="toyama">Toyama</option>
<option value="ishikawa">Ishikawa</option>
<option value="fukui">Fukui</option>
<option value="gifu">Gifu</option>
<option value="shizuoka">Shizuoka</option>
<option value="aichi">Aichi</option>
<option value="mie">Mie</option>
<option value="shiga">Shiga</option>
<option value="kyoto">Kyoto</option>
<option value="osaka">Osaka</option>
<option value="hyogo">Hyogo</option>
<option value="nara">Nara</option>
<option value="wakayama">Wakayama</option>
<option value="tottori">Tottori</option>
<option value="shimane">Shimane</option>
<option value="okayama">Okayama</option>
<option value="hiroshima">Hiroshima</option>
<option value="yamaguchi">Yamaguchi</option>
<option value="tokushima">Tokushima</option>
<option value="kagawa">Kagawa</option>
<option value="ehime">Ehime</option>
<option value="kochi">Kochi</option>
<option value="fukuoka">Fukuoka</option>
<option value="saga">Saga</option>
<option value="nagasaki">Nagasaki</option>
<option value="kumamoto">Kumamoto</option>
<option value="oita">Oita</option>
<option value="miyazaki">Miyazaki</option>
<option value="kagoshima">Kagoshima</option>
<option value="okinawa">Okinawa</option>
</select>
################################# #################################
# Tests of underlying functions # # Tests of underlying functions #
################################# #################################

View File

@ -6,6 +6,7 @@ This class sets up a model for each model field type
""" """
from django.db import models from django.db import models
from django.contrib.contenttypes.models import ContentType
# The following classes are for testing basic data # The following classes are for testing basic data
# marshalling, including NULL values. # marshalling, including NULL values.
@ -73,6 +74,22 @@ class USStateData(models.Model):
class XMLData(models.Model): class XMLData(models.Model):
data = models.XMLField(null=True) data = models.XMLField(null=True)
class Tag(models.Model):
"""A tag on an item."""
data = models.SlugField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = models.GenericForeignKey()
class Meta:
ordering = ["data"]
class GenericData(models.Model):
data = models.CharField(maxlength=30)
tags = models.GenericRelation(Tag)
# The following test classes are all for validation # The following test classes are all for validation
# of related objects; in particular, forward, backward, # of related objects; in particular, forward, backward,
# and self references. # and self references.

View File

@ -25,6 +25,14 @@ def data_create(pk, klass, data):
instance.save() instance.save()
return instance return instance
def generic_create(pk, klass, data):
instance = klass(id=pk)
instance.data = data[0]
instance.save()
for tag in data[1:]:
instance.tags.create(data=tag)
return instance
def fk_create(pk, klass, data): def fk_create(pk, klass, data):
instance = klass(id=pk) instance = klass(id=pk)
setattr(instance, 'data_id', data) setattr(instance, 'data_id', data)
@ -56,6 +64,11 @@ def data_compare(testcase, pk, klass, data):
testcase.assertEqual(data, instance.data, testcase.assertEqual(data, instance.data,
"Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data))) "Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data)))
def generic_compare(testcase, pk, klass, data):
instance = klass.objects.get(id=pk)
testcase.assertEqual(data[0], instance.data)
testcase.assertEqual(data[1:], [t.data for t in instance.tags.all()])
def fk_compare(testcase, pk, klass, data): def fk_compare(testcase, pk, klass, data):
instance = klass.objects.get(id=pk) instance = klass.objects.get(id=pk)
testcase.assertEqual(data, instance.data_id) testcase.assertEqual(data, instance.data_id)
@ -76,6 +89,7 @@ def pk_compare(testcase, pk, klass, data):
# actually a pair of functions; one to create # actually a pair of functions; one to create
# and one to compare objects of that type # and one to compare objects of that type
data_obj = (data_create, data_compare) data_obj = (data_create, data_compare)
generic_obj = (generic_create, generic_compare)
fk_obj = (fk_create, fk_compare) fk_obj = (fk_create, fk_compare)
m2m_obj = (m2m_create, m2m_compare) m2m_obj = (m2m_create, m2m_compare)
o2o_obj = (o2o_create, o2o_compare) o2o_obj = (o2o_create, o2o_compare)
@ -140,6 +154,9 @@ The end."""),
(data_obj, 190, XMLData, "<foo></foo>"), (data_obj, 190, XMLData, "<foo></foo>"),
(data_obj, 191, XMLData, None), (data_obj, 191, XMLData, None),
(generic_obj, 200, GenericData, ['Generic Object 1', 'tag1', 'tag2']),
(generic_obj, 201, GenericData, ['Generic Object 2', 'tag2', 'tag3']),
(data_obj, 300, Anchor, "Anchor 1"), (data_obj, 300, Anchor, "Anchor 1"),
(data_obj, 301, Anchor, "Anchor 2"), (data_obj, 301, Anchor, "Anchor 2"),
@ -222,6 +239,9 @@ def serializerTest(format, self):
transaction.commit() transaction.commit()
transaction.leave_transaction_management() transaction.leave_transaction_management()
# Add the generic tagged objects to the object list
objects.extend(Tag.objects.all())
# Serialize the test database # Serialize the test database
serialized_data = serializers.serialize(format, objects, indent=2) serialized_data = serializers.serialize(format, objects, indent=2)