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:
parent
25c15b17a8
commit
132cf258cb
2
AUTHORS
2
AUTHORS
@ -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
|
||||||
|
@ -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')),
|
||||||
|
Binary file not shown.
@ -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"
|
||||||
|
BIN
django/conf/locale/pl/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/pl/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
112
django/conf/locale/pl/LC_MESSAGES/djangojs.po
Normal file
112
django/conf/locale/pl/LC_MESSAGES/djangojs.po
Normal 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"
|
||||||
|
|
BIN
django/conf/locale/pt/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/pt/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2125
django/conf/locale/pt/LC_MESSAGES/django.po
Normal file
2125
django/conf/locale/pt/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/pt/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/pt/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
108
django/conf/locale/pt/LC_MESSAGES/djangojs.po
Normal file
108
django/conf/locale/pt/LC_MESSAGES/djangojs.po
Normal 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ã"
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ta/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/ta/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
112
django/conf/locale/ta/LC_MESSAGES/djangojs.po
Normal file
112
django/conf/locale/ta/LC_MESSAGES/djangojs.po
Normal 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 "நாளை"
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||||
|
@ -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 %}
|
||||||
|
@ -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 %}
|
||||||
|
0
django/contrib/localflavor/fr/__init__.py
Normal file
0
django/contrib/localflavor/fr/__init__.py
Normal file
44
django/contrib/localflavor/fr/forms.py
Normal file
44
django/contrib/localflavor/fr/forms.py
Normal 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)
|
||||||
|
|
112
django/contrib/localflavor/fr/fr_department.py
Normal file
112
django/contrib/localflavor/fr/fr_department.py
Normal 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'),
|
||||||
|
)
|
0
django/contrib/localflavor/jp/__init__.py
Normal file
0
django/contrib/localflavor/jp/__init__.py
Normal file
38
django/contrib/localflavor/jp/forms.py
Normal file
38
django/contrib/localflavor/jp/forms.py
Normal 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)
|
51
django/contrib/localflavor/jp/jp_prefectures.py
Normal file
51
django/contrib/localflavor/jp/jp_prefectures.py
Normal 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'),),
|
||||||
|
)
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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.
|
||||||
|
@ -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()
|
||||||
|
@ -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
|
||||||
|
0
django/db/backends/mysql_old/__init__.py
Normal file
0
django/db/backends/mysql_old/__init__.py
Normal file
233
django/db/backends/mysql_old/base.py
Normal file
233
django/db/backends/mysql_old/base.py
Normal 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',
|
||||||
|
}
|
14
django/db/backends/mysql_old/client.py
Normal file
14
django/db/backends/mysql_old/client.py
Normal 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)
|
29
django/db/backends/mysql_old/creation.py
Normal file
29
django/db/backends/mysql_old/creation.py
Normal 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)',
|
||||||
|
}
|
95
django/db/backends/mysql_old/introspection.py
Normal file
95
django/db/backends/mysql_old/introspection.py
Normal 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',
|
||||||
|
}
|
@ -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
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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).
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 %}
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
@ -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/
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
264
docs/release_notes_0.96.txt
Normal 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
|
@ -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.
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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.,
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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")
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
"""
|
"""
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
"""
|
"""
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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).
|
||||||
|
@ -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/')
|
||||||
|
@ -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)
|
||||||
|
@ -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')
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""
|
"""
|
||||||
30. Validation
|
31. Validation
|
||||||
|
|
||||||
This is an experimental feature!
|
This is an experimental feature!
|
||||||
|
|
||||||
|
@ -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 '
|
||||||
|
|
||||||
|
@ -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'Or</option>
|
||||||
|
<option value="22">22 - Cotes-d'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'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 #
|
||||||
#################################
|
#################################
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user