mirror of
https://github.com/django/django.git
synced 2025-07-04 01:39:20 +00:00
newforms-admin: Merged from trunk up to [7766].
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7770 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f15845c573
commit
c8da0874c7
1
AUTHORS
1
AUTHORS
@ -385,6 +385,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Wang Chun <wangchun@exoweb.net>
|
Wang Chun <wangchun@exoweb.net>
|
||||||
Filip Wasilewski <filip.wasilewski@gmail.com>
|
Filip Wasilewski <filip.wasilewski@gmail.com>
|
||||||
Dan Watson <http://theidioteque.net/>
|
Dan Watson <http://theidioteque.net/>
|
||||||
|
Joel Watts <joel@joelwatts.com>
|
||||||
Chris Wesseling <Chris.Wesseling@cwi.nl>
|
Chris Wesseling <Chris.Wesseling@cwi.nl>
|
||||||
James Wheare <django@sparemint.com>
|
James Wheare <django@sparemint.com>
|
||||||
charly.wilhelm@gmail.com
|
charly.wilhelm@gmail.com
|
||||||
|
Binary file not shown.
@ -5,9 +5,9 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Django\n"
|
"Project-Id-Version: Django\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2008-04-14 18:02+0200\n"
|
"POT-Creation-Date: 2008-06-24 07:36+0200\n"
|
||||||
"PO-Revision-Date: 2008-02-25 15:53+0100\n"
|
"PO-Revision-Date: 2008-02-25 15:53+0100\n"
|
||||||
"Last-Translator: Piotr Lewandowski <django@icomputing.pl>\n"
|
"Last-Translator: Jarek Zgoda <jarek.zgoda@gmail.com>\n"
|
||||||
"Language-Team: Polish <pl@li.org>\n"
|
"Language-Team: Polish <pl@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@ -16,191 +16,199 @@ msgstr ""
|
|||||||
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=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"
|
"100<10 || n%100>=20) ? 1 : 2);\n"
|
||||||
|
|
||||||
#: conf/global_settings.py:39
|
#: conf/global_settings.py:44
|
||||||
msgid "Arabic"
|
msgid "Arabic"
|
||||||
msgstr "Arabski"
|
msgstr "Arabski"
|
||||||
|
|
||||||
#: conf/global_settings.py:40
|
#: conf/global_settings.py:45
|
||||||
msgid "Bengali"
|
msgid "Bengali"
|
||||||
msgstr "Bengalski"
|
msgstr "Bengalski"
|
||||||
|
|
||||||
#: conf/global_settings.py:41
|
#: conf/global_settings.py:46
|
||||||
msgid "Bulgarian"
|
msgid "Bulgarian"
|
||||||
msgstr "Bułgarski"
|
msgstr "Bułgarski"
|
||||||
|
|
||||||
#: conf/global_settings.py:42
|
#: conf/global_settings.py:47
|
||||||
msgid "Catalan"
|
msgid "Catalan"
|
||||||
msgstr "Kataloński"
|
msgstr "Kataloński"
|
||||||
|
|
||||||
#: conf/global_settings.py:43
|
#: conf/global_settings.py:48
|
||||||
msgid "Czech"
|
msgid "Czech"
|
||||||
msgstr "Czeski"
|
msgstr "Czeski"
|
||||||
|
|
||||||
#: conf/global_settings.py:44
|
#: conf/global_settings.py:49
|
||||||
msgid "Welsh"
|
msgid "Welsh"
|
||||||
msgstr "Walijski"
|
msgstr "Walijski"
|
||||||
|
|
||||||
#: conf/global_settings.py:45
|
#: conf/global_settings.py:50
|
||||||
msgid "Danish"
|
msgid "Danish"
|
||||||
msgstr "Duński"
|
msgstr "Duński"
|
||||||
|
|
||||||
#: conf/global_settings.py:46
|
#: conf/global_settings.py:51
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr "Niemiecki"
|
msgstr "Niemiecki"
|
||||||
|
|
||||||
#: conf/global_settings.py:47
|
#: conf/global_settings.py:52
|
||||||
msgid "Greek"
|
msgid "Greek"
|
||||||
msgstr "Grecki"
|
msgstr "Grecki"
|
||||||
|
|
||||||
#: conf/global_settings.py:48
|
#: conf/global_settings.py:53
|
||||||
msgid "English"
|
msgid "English"
|
||||||
msgstr "Angielski"
|
msgstr "Angielski"
|
||||||
|
|
||||||
#: conf/global_settings.py:49
|
#: conf/global_settings.py:54
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
msgstr "Hiszpański"
|
msgstr "Hiszpański"
|
||||||
|
|
||||||
#: conf/global_settings.py:50
|
#: conf/global_settings.py:55
|
||||||
|
msgid "Estonian"
|
||||||
|
msgstr "Estoński"
|
||||||
|
|
||||||
|
#: conf/global_settings.py:56
|
||||||
msgid "Argentinean Spanish"
|
msgid "Argentinean Spanish"
|
||||||
msgstr "Hiszpański argentyński"
|
msgstr "Hiszpański argentyński"
|
||||||
|
|
||||||
#: conf/global_settings.py:51
|
#: conf/global_settings.py:57
|
||||||
msgid "Basque"
|
msgid "Basque"
|
||||||
msgstr "Baskijski"
|
msgstr "Baskijski"
|
||||||
|
|
||||||
#: conf/global_settings.py:52
|
#: conf/global_settings.py:58
|
||||||
msgid "Persian"
|
msgid "Persian"
|
||||||
msgstr "Perski"
|
msgstr "Perski"
|
||||||
|
|
||||||
#: conf/global_settings.py:53
|
#: conf/global_settings.py:59
|
||||||
msgid "Finnish"
|
msgid "Finnish"
|
||||||
msgstr "Fiński"
|
msgstr "Fiński"
|
||||||
|
|
||||||
#: conf/global_settings.py:54
|
#: conf/global_settings.py:60
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr "Francuski"
|
msgstr "Francuski"
|
||||||
|
|
||||||
#: conf/global_settings.py:55
|
#: conf/global_settings.py:61
|
||||||
msgid "Irish"
|
msgid "Irish"
|
||||||
msgstr "Irlandzki"
|
msgstr "Irlandzki"
|
||||||
|
|
||||||
#: conf/global_settings.py:56
|
#: conf/global_settings.py:62
|
||||||
msgid "Galician"
|
msgid "Galician"
|
||||||
msgstr "Galicyjski"
|
msgstr "Galicyjski"
|
||||||
|
|
||||||
#: conf/global_settings.py:57
|
#: conf/global_settings.py:63
|
||||||
msgid "Hungarian"
|
msgid "Hungarian"
|
||||||
msgstr "Węgierski"
|
msgstr "Węgierski"
|
||||||
|
|
||||||
#: conf/global_settings.py:58
|
#: conf/global_settings.py:64
|
||||||
msgid "Hebrew"
|
msgid "Hebrew"
|
||||||
msgstr "Hebrajski"
|
msgstr "Hebrajski"
|
||||||
|
|
||||||
#: conf/global_settings.py:59
|
#: conf/global_settings.py:65
|
||||||
msgid "Croatian"
|
msgid "Croatian"
|
||||||
msgstr "Chorwacki"
|
msgstr "Chorwacki"
|
||||||
|
|
||||||
#: conf/global_settings.py:60
|
#: conf/global_settings.py:66
|
||||||
msgid "Icelandic"
|
msgid "Icelandic"
|
||||||
msgstr "Islandzki"
|
msgstr "Islandzki"
|
||||||
|
|
||||||
#: conf/global_settings.py:61
|
#: conf/global_settings.py:67
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr "Włoski"
|
msgstr "Włoski"
|
||||||
|
|
||||||
#: conf/global_settings.py:62
|
#: conf/global_settings.py:68
|
||||||
msgid "Japanese"
|
msgid "Japanese"
|
||||||
msgstr "Japoński"
|
msgstr "Japoński"
|
||||||
|
|
||||||
#: conf/global_settings.py:63
|
#: conf/global_settings.py:69
|
||||||
msgid "Georgian"
|
msgid "Georgian"
|
||||||
msgstr "Gruziński"
|
msgstr "Gruziński"
|
||||||
|
|
||||||
#: conf/global_settings.py:64
|
#: conf/global_settings.py:70
|
||||||
msgid "Korean"
|
msgid "Korean"
|
||||||
msgstr "Koreański"
|
msgstr "Koreański"
|
||||||
|
|
||||||
#: conf/global_settings.py:65
|
#: conf/global_settings.py:71
|
||||||
msgid "Khmer"
|
msgid "Khmer"
|
||||||
msgstr "Khmerski"
|
msgstr "Khmerski"
|
||||||
|
|
||||||
#: conf/global_settings.py:66
|
#: conf/global_settings.py:72
|
||||||
msgid "Kannada"
|
msgid "Kannada"
|
||||||
msgstr "Kannada"
|
msgstr "Kannada"
|
||||||
|
|
||||||
#: conf/global_settings.py:67
|
#: conf/global_settings.py:73
|
||||||
msgid "Latvian"
|
msgid "Latvian"
|
||||||
msgstr "Łotewski"
|
msgstr "Łotewski"
|
||||||
|
|
||||||
#: conf/global_settings.py:68
|
#: conf/global_settings.py:74
|
||||||
|
msgid "Lithuanian"
|
||||||
|
msgstr "Litewski"
|
||||||
|
|
||||||
|
#: conf/global_settings.py:75
|
||||||
msgid "Macedonian"
|
msgid "Macedonian"
|
||||||
msgstr "Macedoński"
|
msgstr "Macedoński"
|
||||||
|
|
||||||
#: conf/global_settings.py:69
|
#: conf/global_settings.py:76
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr "Holenderski"
|
msgstr "Holenderski"
|
||||||
|
|
||||||
#: conf/global_settings.py:70
|
#: conf/global_settings.py:77
|
||||||
msgid "Norwegian"
|
msgid "Norwegian"
|
||||||
msgstr "Norweski"
|
msgstr "Norweski"
|
||||||
|
|
||||||
#: conf/global_settings.py:71
|
#: conf/global_settings.py:78
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr "Polski"
|
msgstr "Polski"
|
||||||
|
|
||||||
#: conf/global_settings.py:72
|
#: conf/global_settings.py:79
|
||||||
msgid "Portugese"
|
msgid "Portugese"
|
||||||
msgstr "Portugalski"
|
msgstr "Portugalski"
|
||||||
|
|
||||||
#: conf/global_settings.py:73
|
#: conf/global_settings.py:80
|
||||||
msgid "Brazilian Portuguese"
|
msgid "Brazilian Portuguese"
|
||||||
msgstr "Brazylijski portugalski"
|
msgstr "Brazylijski portugalski"
|
||||||
|
|
||||||
#: conf/global_settings.py:74
|
#: conf/global_settings.py:81
|
||||||
msgid "Romanian"
|
msgid "Romanian"
|
||||||
msgstr "Rumuński"
|
msgstr "Rumuński"
|
||||||
|
|
||||||
#: conf/global_settings.py:75
|
#: conf/global_settings.py:82
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr "Rosyjski"
|
msgstr "Rosyjski"
|
||||||
|
|
||||||
#: conf/global_settings.py:76
|
#: conf/global_settings.py:83
|
||||||
msgid "Slovak"
|
msgid "Slovak"
|
||||||
msgstr "Słowacki"
|
msgstr "Słowacki"
|
||||||
|
|
||||||
#: conf/global_settings.py:77
|
#: conf/global_settings.py:84
|
||||||
msgid "Slovenian"
|
msgid "Slovenian"
|
||||||
msgstr "Słoweński"
|
msgstr "Słoweński"
|
||||||
|
|
||||||
#: conf/global_settings.py:78
|
#: conf/global_settings.py:85
|
||||||
msgid "Serbian"
|
msgid "Serbian"
|
||||||
msgstr "Serbski"
|
msgstr "Serbski"
|
||||||
|
|
||||||
#: conf/global_settings.py:79
|
#: conf/global_settings.py:86
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr "Szwedzki"
|
msgstr "Szwedzki"
|
||||||
|
|
||||||
#: conf/global_settings.py:80
|
#: conf/global_settings.py:87
|
||||||
msgid "Tamil"
|
msgid "Tamil"
|
||||||
msgstr "Tamilski"
|
msgstr "Tamilski"
|
||||||
|
|
||||||
#: conf/global_settings.py:81
|
#: conf/global_settings.py:88
|
||||||
msgid "Telugu"
|
msgid "Telugu"
|
||||||
msgstr "Telugu"
|
msgstr "Telugu"
|
||||||
|
|
||||||
#: conf/global_settings.py:82
|
#: conf/global_settings.py:89
|
||||||
msgid "Turkish"
|
msgid "Turkish"
|
||||||
msgstr "Turecki"
|
msgstr "Turecki"
|
||||||
|
|
||||||
#: conf/global_settings.py:83
|
#: conf/global_settings.py:90
|
||||||
msgid "Ukrainian"
|
msgid "Ukrainian"
|
||||||
msgstr "Ukraiński"
|
msgstr "Ukraiński"
|
||||||
|
|
||||||
#: conf/global_settings.py:84
|
#: conf/global_settings.py:91
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
msgstr "Uproszczony chiński"
|
msgstr "Uproszczony chiński"
|
||||||
|
|
||||||
#: conf/global_settings.py:85
|
#: conf/global_settings.py:92
|
||||||
msgid "Traditional Chinese"
|
msgid "Traditional Chinese"
|
||||||
msgstr "Chiński tradycyjny"
|
msgstr "Chiński tradycyjny"
|
||||||
|
|
||||||
@ -417,7 +425,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/delete_confirmation.html:25
|
#: contrib/admin/templates/admin/delete_confirmation.html:25
|
||||||
msgid "Yes, I'm sure"
|
msgid "Yes, I'm sure"
|
||||||
msgstr "Tak, usuń"
|
msgstr "Tak, na pewno"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/filter.html:2
|
#: contrib/admin/templates/admin/filter.html:2
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -824,15 +832,15 @@ msgstr ""
|
|||||||
"Twoja przeglądarka nie chce akceptować ciasteczek. Zmień jej ustawienia i "
|
"Twoja przeglądarka nie chce akceptować ciasteczek. Zmień jej ustawienia i "
|
||||||
"spróbuj ponownie."
|
"spróbuj ponownie."
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:90
|
#: contrib/admin/views/decorators.py:89
|
||||||
msgid "Usernames cannot contain the '@' character."
|
|
||||||
msgstr "Nazwy użytkowników nie mogą zawierać znaków '@'."
|
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:92
|
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your e-mail address is not your username. Try '%s' instead."
|
msgid "Your e-mail address is not your username. Try '%s' instead."
|
||||||
msgstr "Twój adres e-mail to nie jest twój login. Spróbuj '%s'."
|
msgstr "Twój adres e-mail to nie jest twój login. Spróbuj '%s'."
|
||||||
|
|
||||||
|
#: contrib/admin/views/decorators.py:93
|
||||||
|
msgid "Usernames cannot contain the '@' character."
|
||||||
|
msgstr "Nazwy użytkowników nie mogą zawierać znaków '@'."
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:48 contrib/admin/views/doc.py:50
|
#: contrib/admin/views/doc.py:48 contrib/admin/views/doc.py:50
|
||||||
#: contrib/admin/views/doc.py:52
|
#: contrib/admin/views/doc.py:52
|
||||||
msgid "tag:"
|
msgid "tag:"
|
||||||
@ -1063,7 +1071,7 @@ msgstr "Zaznacz %s"
|
|||||||
msgid "Select %s to change"
|
msgid "Select %s to change"
|
||||||
msgstr "Zaznacz %s aby zmienić"
|
msgstr "Zaznacz %s aby zmienić"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:784
|
#: contrib/admin/views/main.py:765
|
||||||
msgid "Database error"
|
msgid "Database error"
|
||||||
msgstr "Błąd bazy danych"
|
msgstr "Błąd bazy danych"
|
||||||
|
|
||||||
@ -1128,15 +1136,15 @@ msgstr "uprawnienia"
|
|||||||
msgid "group"
|
msgid "group"
|
||||||
msgstr "grupa"
|
msgstr "grupa"
|
||||||
|
|
||||||
#: contrib/auth/models.py:98 contrib/auth/models.py:141
|
#: contrib/auth/models.py:98 contrib/auth/models.py:148
|
||||||
msgid "groups"
|
msgid "groups"
|
||||||
msgstr "grupy"
|
msgstr "grupy"
|
||||||
|
|
||||||
#: contrib/auth/models.py:131
|
#: contrib/auth/models.py:138
|
||||||
msgid "username"
|
msgid "username"
|
||||||
msgstr "użytkownik"
|
msgstr "użytkownik"
|
||||||
|
|
||||||
#: contrib/auth/models.py:131
|
#: contrib/auth/models.py:138
|
||||||
msgid ""
|
msgid ""
|
||||||
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
||||||
"digits and underscores)."
|
"digits and underscores)."
|
||||||
@ -1144,23 +1152,23 @@ msgstr ""
|
|||||||
"Wymagane. 30 znaków lub mniej. Tylko znaki alfanumeryczne (litery, cyfry i "
|
"Wymagane. 30 znaków lub mniej. Tylko znaki alfanumeryczne (litery, cyfry i "
|
||||||
"podkreślenia)."
|
"podkreślenia)."
|
||||||
|
|
||||||
#: contrib/auth/models.py:132
|
#: contrib/auth/models.py:139
|
||||||
msgid "first name"
|
msgid "first name"
|
||||||
msgstr "Imię"
|
msgstr "Imię"
|
||||||
|
|
||||||
#: contrib/auth/models.py:133
|
#: contrib/auth/models.py:140
|
||||||
msgid "last name"
|
msgid "last name"
|
||||||
msgstr "Nazwisko"
|
msgstr "Nazwisko"
|
||||||
|
|
||||||
#: contrib/auth/models.py:134
|
#: contrib/auth/models.py:141
|
||||||
msgid "e-mail address"
|
msgid "e-mail address"
|
||||||
msgstr "adres e-mail"
|
msgstr "adres e-mail"
|
||||||
|
|
||||||
#: contrib/auth/models.py:135
|
#: contrib/auth/models.py:142
|
||||||
msgid "password"
|
msgid "password"
|
||||||
msgstr "hasło"
|
msgstr "hasło"
|
||||||
|
|
||||||
#: contrib/auth/models.py:135
|
#: contrib/auth/models.py:142
|
||||||
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>."
|
||||||
@ -1168,19 +1176,19 @@ msgstr ""
|
|||||||
"Użyj '[algo]$[salt]$[hexdigest]' lub <a href=\"password/\">formularza zmiany "
|
"Użyj '[algo]$[salt]$[hexdigest]' lub <a href=\"password/\">formularza zmiany "
|
||||||
"hasła</a>."
|
"hasła</a>."
|
||||||
|
|
||||||
#: contrib/auth/models.py:136
|
#: contrib/auth/models.py:143
|
||||||
msgid "staff status"
|
msgid "staff status"
|
||||||
msgstr "w zespole"
|
msgstr "w zespole"
|
||||||
|
|
||||||
#: contrib/auth/models.py:136
|
#: contrib/auth/models.py:143
|
||||||
msgid "Designates whether the user can log into this admin site."
|
msgid "Designates whether the user can log into this admin site."
|
||||||
msgstr "Oznacza czy użytkownik może zalogować się do panelu admina."
|
msgstr "Oznacza czy użytkownik może zalogować się do panelu admina."
|
||||||
|
|
||||||
#: contrib/auth/models.py:137
|
#: contrib/auth/models.py:144
|
||||||
msgid "active"
|
msgid "active"
|
||||||
msgstr "aktywny"
|
msgstr "aktywny"
|
||||||
|
|
||||||
#: contrib/auth/models.py:137
|
#: contrib/auth/models.py:144
|
||||||
msgid ""
|
msgid ""
|
||||||
"Designates whether this user should be treated as active. Unselect this "
|
"Designates whether this user should be treated as active. Unselect this "
|
||||||
"instead of deleting accounts."
|
"instead of deleting accounts."
|
||||||
@ -1188,11 +1196,11 @@ msgstr ""
|
|||||||
"Oznacza czy użytkownika należy uważać za aktywnego. Odznacz tozamiast usuwać "
|
"Oznacza czy użytkownika należy uważać za aktywnego. Odznacz tozamiast usuwać "
|
||||||
"konta."
|
"konta."
|
||||||
|
|
||||||
#: contrib/auth/models.py:138
|
#: contrib/auth/models.py:145
|
||||||
msgid "superuser status"
|
msgid "superuser status"
|
||||||
msgstr "Główny Administrator"
|
msgstr "Główny Administrator"
|
||||||
|
|
||||||
#: contrib/auth/models.py:138
|
#: contrib/auth/models.py:145
|
||||||
msgid ""
|
msgid ""
|
||||||
"Designates that this user has all permissions without explicitly assigning "
|
"Designates that this user has all permissions without explicitly assigning "
|
||||||
"them."
|
"them."
|
||||||
@ -1200,15 +1208,15 @@ msgstr ""
|
|||||||
"Oznacza, że ten użytkownik ma wszystkie uprawnienia bez jawnego "
|
"Oznacza, że ten użytkownik ma wszystkie uprawnienia bez jawnego "
|
||||||
"przypisywania ich."
|
"przypisywania ich."
|
||||||
|
|
||||||
#: contrib/auth/models.py:139
|
#: contrib/auth/models.py:146
|
||||||
msgid "last login"
|
msgid "last login"
|
||||||
msgstr "ostatnio zalogowany"
|
msgstr "ostatnio zalogowany"
|
||||||
|
|
||||||
#: contrib/auth/models.py:140
|
#: contrib/auth/models.py:147
|
||||||
msgid "date joined"
|
msgid "date joined"
|
||||||
msgstr "data przyłączenia"
|
msgstr "data przyłączenia"
|
||||||
|
|
||||||
#: contrib/auth/models.py:142
|
#: contrib/auth/models.py:149
|
||||||
msgid ""
|
msgid ""
|
||||||
"In addition to the permissions manually assigned, this user will also get "
|
"In addition to the permissions manually assigned, this user will also get "
|
||||||
"all permissions granted to each group he/she is in."
|
"all permissions granted to each group he/she is in."
|
||||||
@ -1216,39 +1224,39 @@ msgstr ""
|
|||||||
"Oprócz uprawnień przypisanych bezpośrednio użytkownikowi otrzyma on "
|
"Oprócz uprawnień przypisanych bezpośrednio użytkownikowi otrzyma on "
|
||||||
"uprawnienia grup, do których należy."
|
"uprawnienia grup, do których należy."
|
||||||
|
|
||||||
#: contrib/auth/models.py:143
|
#: contrib/auth/models.py:150
|
||||||
msgid "user permissions"
|
msgid "user permissions"
|
||||||
msgstr "uprawnienia użytkownika"
|
msgstr "uprawnienia użytkownika"
|
||||||
|
|
||||||
#: contrib/auth/models.py:147
|
#: contrib/auth/models.py:154
|
||||||
msgid "user"
|
msgid "user"
|
||||||
msgstr "użytkownik"
|
msgstr "użytkownik"
|
||||||
|
|
||||||
#: contrib/auth/models.py:148
|
#: contrib/auth/models.py:155
|
||||||
msgid "users"
|
msgid "users"
|
||||||
msgstr "użytkownicy"
|
msgstr "użytkownicy"
|
||||||
|
|
||||||
#: contrib/auth/models.py:154
|
#: contrib/auth/models.py:161
|
||||||
msgid "Personal info"
|
msgid "Personal info"
|
||||||
msgstr "Dane osobowe"
|
msgstr "Dane osobowe"
|
||||||
|
|
||||||
#: contrib/auth/models.py:155
|
#: contrib/auth/models.py:162
|
||||||
msgid "Permissions"
|
msgid "Permissions"
|
||||||
msgstr "Uprawnienia"
|
msgstr "Uprawnienia"
|
||||||
|
|
||||||
#: contrib/auth/models.py:156
|
#: contrib/auth/models.py:163
|
||||||
msgid "Important dates"
|
msgid "Important dates"
|
||||||
msgstr "Ważne daty"
|
msgstr "Ważne daty"
|
||||||
|
|
||||||
#: contrib/auth/models.py:157
|
#: contrib/auth/models.py:164
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "Grupy"
|
msgstr "Grupy"
|
||||||
|
|
||||||
#: contrib/auth/models.py:316
|
#: contrib/auth/models.py:323
|
||||||
msgid "message"
|
msgid "message"
|
||||||
msgstr "wiadomość"
|
msgstr "wiadomość"
|
||||||
|
|
||||||
#: contrib/auth/views.py:47
|
#: contrib/auth/views.py:48
|
||||||
msgid "Logged out"
|
msgid "Logged out"
|
||||||
msgstr "Wylogowany"
|
msgstr "Wylogowany"
|
||||||
|
|
||||||
@ -3516,23 +3524,23 @@ msgstr "przekieruj"
|
|||||||
msgid "redirects"
|
msgid "redirects"
|
||||||
msgstr "przekierowania"
|
msgstr "przekierowania"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:41
|
#: contrib/sessions/models.py:45
|
||||||
msgid "session key"
|
msgid "session key"
|
||||||
msgstr "klucz sesji"
|
msgstr "klucz sesji"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:42
|
#: contrib/sessions/models.py:47
|
||||||
msgid "session data"
|
msgid "session data"
|
||||||
msgstr "data sesji"
|
msgstr "data sesji"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:43
|
#: contrib/sessions/models.py:48
|
||||||
msgid "expire date"
|
msgid "expire date"
|
||||||
msgstr "data wygaśnięcia sesji"
|
msgstr "data wygaśnięcia sesji"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:48
|
#: contrib/sessions/models.py:53
|
||||||
msgid "session"
|
msgid "session"
|
||||||
msgstr "sesja"
|
msgstr "sesja"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:49
|
#: contrib/sessions/models.py:54
|
||||||
msgid "sessions"
|
msgid "sessions"
|
||||||
msgstr "sesje"
|
msgstr "sesje"
|
||||||
|
|
||||||
@ -3617,7 +3625,7 @@ msgstr "Rok nie może być wcześniejszy niż 1900."
|
|||||||
msgid "Invalid date: %s"
|
msgid "Invalid date: %s"
|
||||||
msgstr "Niepoprawna data: %s"
|
msgstr "Niepoprawna data: %s"
|
||||||
|
|
||||||
#: core/validators.py:156 db/models/fields/__init__.py:527
|
#: core/validators.py:156 db/models/fields/__init__.py:548
|
||||||
msgid "Enter a valid date in YYYY-MM-DD format."
|
msgid "Enter a valid date in YYYY-MM-DD format."
|
||||||
msgstr "Proszę wpisać poprawną datę w formacie RRRR-MM-DD."
|
msgstr "Proszę wpisać poprawną datę w formacie RRRR-MM-DD."
|
||||||
|
|
||||||
@ -3625,7 +3633,7 @@ msgstr "Proszę wpisać poprawną datę w formacie RRRR-MM-DD."
|
|||||||
msgid "Enter a valid time in HH:MM format."
|
msgid "Enter a valid time in HH:MM format."
|
||||||
msgstr "Proszę wpisać poprawną godzinę w formacie HH:MM."
|
msgstr "Proszę wpisać poprawną godzinę w formacie HH:MM."
|
||||||
|
|
||||||
#: core/validators.py:165 db/models/fields/__init__.py:604
|
#: core/validators.py:165 db/models/fields/__init__.py:625
|
||||||
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
||||||
msgstr "Wprowadź poprawną datę i godzinę w formacie RRRR-MM-DD GG:MM."
|
msgstr "Wprowadź poprawną datę i godzinę w formacie RRRR-MM-DD GG:MM."
|
||||||
|
|
||||||
@ -3888,60 +3896,60 @@ msgstr ""
|
|||||||
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
|
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
|
||||||
msgstr "%(object)s z %(type)s już istnieje dla %(field)s."
|
msgstr "%(object)s z %(type)s już istnieje dla %(field)s."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:52
|
#: db/models/fields/__init__.py:51
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(optname)s with this %(fieldname)s already exists."
|
msgid "%(optname)s with this %(fieldname)s already exists."
|
||||||
msgstr "Już istnieje %(optname)s z %(fieldname)s."
|
msgstr "Już istnieje %(optname)s z %(fieldname)s."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:161 db/models/fields/__init__.py:327
|
#: db/models/fields/__init__.py:176 db/models/fields/__init__.py:348
|
||||||
#: db/models/fields/__init__.py:759 db/models/fields/__init__.py:770
|
#: db/models/fields/__init__.py:780 db/models/fields/__init__.py:791
|
||||||
#: newforms/fields.py:46 oldforms/__init__.py:374
|
#: newforms/fields.py:46 oldforms/__init__.py:374
|
||||||
msgid "This field is required."
|
msgid "This field is required."
|
||||||
msgstr "To pole jest wymagane."
|
msgstr "To pole jest wymagane."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:427
|
#: db/models/fields/__init__.py:448
|
||||||
msgid "This value must be an integer."
|
msgid "This value must be an integer."
|
||||||
msgstr "Ta wartość musi być liczbą całkowitą."
|
msgstr "Ta wartość musi być liczbą całkowitą."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:466
|
#: db/models/fields/__init__.py:487
|
||||||
msgid "This value must be either True or False."
|
msgid "This value must be either True or False."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ta wartość musi być wartością logiczną (True, False - prawda lub fałsz)."
|
"Ta wartość musi być wartością logiczną (True, False - prawda lub fałsz)."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:490
|
#: db/models/fields/__init__.py:511
|
||||||
msgid "This field cannot be null."
|
msgid "This field cannot be null."
|
||||||
msgstr "To pole nie może być puste."
|
msgstr "To pole nie może być puste."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:668
|
#: db/models/fields/__init__.py:689
|
||||||
msgid "This value must be a decimal number."
|
msgid "This value must be a decimal number."
|
||||||
msgstr "Ta wartość musi być liczbą dziesiętną."
|
msgstr "Ta wartość musi być liczbą dziesiętną."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:779
|
#: db/models/fields/__init__.py:800
|
||||||
msgid "Enter a valid filename."
|
msgid "Enter a valid filename."
|
||||||
msgstr "Wpisz poprawną nazwę pliku."
|
msgstr "Wpisz poprawną nazwę pliku."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:960
|
#: db/models/fields/__init__.py:981
|
||||||
msgid "This value must be either None, True or False."
|
msgid "This value must be either None, True or False."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ta wartość musi być jedną z None (nic), True (prawda) lub False (fałsz)."
|
"Ta wartość musi być jedną z None (nic), True (prawda) lub False (fałsz)."
|
||||||
|
|
||||||
#: db/models/fields/related.py:93
|
#: db/models/fields/related.py:94
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid %s."
|
msgid "Please enter a valid %s."
|
||||||
msgstr "Proszę wpisać poprawne %s."
|
msgstr "Proszę wpisać poprawne %s."
|
||||||
|
|
||||||
#: db/models/fields/related.py:701
|
#: db/models/fields/related.py:746
|
||||||
msgid "Separate multiple IDs with commas."
|
msgid "Separate multiple IDs with commas."
|
||||||
msgstr "Oddziel identyfikatory przecinkami."
|
msgstr "Oddziel identyfikatory przecinkami."
|
||||||
|
|
||||||
#: db/models/fields/related.py:703
|
#: db/models/fields/related.py:748
|
||||||
msgid ""
|
msgid ""
|
||||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Przytrzymaj wciśnięty klawisz \"Ctrl\" lub \"Command\" na Mac'u aby "
|
"Przytrzymaj wciśnięty klawisz \"Ctrl\" lub \"Command\" na Mac'u aby "
|
||||||
"zaznaczyć więcej niż jeden wybór."
|
"zaznaczyć więcej niż jeden wybór."
|
||||||
|
|
||||||
#: db/models/fields/related.py:750
|
#: db/models/fields/related.py:795
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
@ -4003,11 +4011,11 @@ msgstr "Upewnij się, że jest nie więcej niż %s miejsc po przecinku."
|
|||||||
msgid "Ensure that there are no more than %s digits before the decimal point."
|
msgid "Ensure that there are no more than %s digits before the decimal point."
|
||||||
msgstr "Upewnij się, że jest nie więcej niż %s miejsc przed przecinkiem."
|
msgstr "Upewnij się, że jest nie więcej niż %s miejsc przed przecinkiem."
|
||||||
|
|
||||||
#: newforms/fields.py:263 newforms/fields.py:751
|
#: newforms/fields.py:263 newforms/fields.py:750
|
||||||
msgid "Enter a valid date."
|
msgid "Enter a valid date."
|
||||||
msgstr "Wpisz poprawną datę."
|
msgstr "Wpisz poprawną datę."
|
||||||
|
|
||||||
#: newforms/fields.py:296 newforms/fields.py:752
|
#: newforms/fields.py:296 newforms/fields.py:751
|
||||||
msgid "Enter a valid time."
|
msgid "Enter a valid time."
|
||||||
msgstr "Wpisz poprawną godzinę."
|
msgstr "Wpisz poprawną godzinę."
|
||||||
|
|
||||||
@ -4031,25 +4039,25 @@ msgstr "Wpisz poprawny URL."
|
|||||||
msgid "This URL appears to be a broken link."
|
msgid "This URL appears to be a broken link."
|
||||||
msgstr "Ten odnośnik jest nieprawidłowy."
|
msgstr "Ten odnośnik jest nieprawidłowy."
|
||||||
|
|
||||||
#: newforms/fields.py:560 newforms/models.py:299
|
#: newforms/fields.py:559 newforms/models.py:305
|
||||||
msgid "Select a valid choice. That choice is not one of the available choices."
|
msgid "Select a valid choice. That choice is not one of the available choices."
|
||||||
msgstr "Wybierz poprawną wartość. Podana nie jest jednym z dostępnych wyborów."
|
msgstr "Wybierz poprawną wartość. Podana nie jest jednym z dostępnych wyborów."
|
||||||
|
|
||||||
#: newforms/fields.py:599
|
#: newforms/fields.py:598
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Select a valid choice. %(value)s is not one of the available choices."
|
msgid "Select a valid choice. %(value)s is not one of the available choices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Wybierz poprawną wartość. %(value)s nie jest jednym z dostępnych wyborów."
|
"Wybierz poprawną wartość. %(value)s nie jest jednym z dostępnych wyborów."
|
||||||
|
|
||||||
#: newforms/fields.py:600 newforms/fields.py:662 newforms/models.py:371
|
#: newforms/fields.py:599 newforms/fields.py:661 newforms/models.py:372
|
||||||
msgid "Enter a list of values."
|
msgid "Enter a list of values."
|
||||||
msgstr "Podaj listę wartości."
|
msgstr "Podaj listę wartości."
|
||||||
|
|
||||||
#: newforms/fields.py:780
|
#: newforms/fields.py:779
|
||||||
msgid "Enter a valid IPv4 address."
|
msgid "Enter a valid IPv4 address."
|
||||||
msgstr "Wprowadź poprawny adres IPv4."
|
msgstr "Wprowadź poprawny adres IPv4."
|
||||||
|
|
||||||
#: newforms/models.py:372
|
#: newforms/models.py:373
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Select a valid choice. %s is not one of the available choices."
|
msgid "Select a valid choice. %s is not one of the available choices."
|
||||||
msgstr "Wybierz poprawną wartość. %s nie jest jednym z dostępnych wyborów."
|
msgstr "Wybierz poprawną wartość. %s nie jest jednym z dostępnych wyborów."
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth.forms import AuthenticationForm
|
from django.contrib.auth.forms import AuthenticationForm
|
||||||
from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm, AdminPasswordChangeForm
|
from django.contrib.auth.forms import PasswordResetForm, PasswordChangeForm, AdminPasswordChangeForm
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
from django.shortcuts import render_to_response, get_object_or_404
|
from django.shortcuts import render_to_response, get_object_or_404
|
||||||
from django.template import RequestContext
|
|
||||||
from django.contrib.sites.models import Site, RequestSite
|
from django.contrib.sites.models import Site, RequestSite
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.template import RequestContext
|
||||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
from django.utils.http import urlquote
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@ -62,7 +63,7 @@ def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_N
|
|||||||
if not login_url:
|
if not login_url:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
login_url = settings.LOGIN_URL
|
login_url = settings.LOGIN_URL
|
||||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, next))
|
return HttpResponseRedirect('%s?%s=%s' % (login_url, urlquote(redirect_field_name), urlquote(next)))
|
||||||
|
|
||||||
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
|
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
|
||||||
email_template_name='registration/password_reset_email.html',
|
email_template_name='registration/password_reset_email.html',
|
||||||
@ -73,7 +74,10 @@ def password_reset(request, is_admin_site=False, template_name='registration/pas
|
|||||||
if is_admin_site:
|
if is_admin_site:
|
||||||
form.save(domain_override=request.META['HTTP_HOST'])
|
form.save(domain_override=request.META['HTTP_HOST'])
|
||||||
else:
|
else:
|
||||||
|
if Site._meta.installed:
|
||||||
form.save(email_template_name=email_template_name)
|
form.save(email_template_name=email_template_name)
|
||||||
|
else:
|
||||||
|
form.save(domain_override=RequestSite(request).domain, email_template_name=email_template_name)
|
||||||
return HttpResponseRedirect('%sdone/' % request.path)
|
return HttpResponseRedirect('%sdone/' % request.path)
|
||||||
else:
|
else:
|
||||||
form = password_reset_form()
|
form = password_reset_form()
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
>>> # Make sure that get_current() does not return a deleted Site object.
|
>>> # Make sure that get_current() does not return a deleted Site object.
|
||||||
>>> from django.contrib.sites.models import Site
|
>>> from django.contrib.sites.models import Site
|
||||||
>>> s = Site.objects.get_current()
|
>>> s = Site.objects.get_current()
|
||||||
>>> s
|
>>> isinstance(s, Site)
|
||||||
<Site: example.com>
|
True
|
||||||
|
|
||||||
>>> s.delete()
|
>>> s.delete()
|
||||||
>>> Site.objects.get_current()
|
>>> Site.objects.get_current()
|
||||||
|
@ -17,7 +17,7 @@ import urllib
|
|||||||
from django.utils.http import http_date
|
from django.utils.http import http_date
|
||||||
|
|
||||||
__version__ = "0.1"
|
__version__ = "0.1"
|
||||||
__all__ = ['WSGIServer','WSGIRequestHandler','demo_app']
|
__all__ = ['WSGIServer','WSGIRequestHandler']
|
||||||
|
|
||||||
server_version = "WSGIServer/" + __version__
|
server_version = "WSGIServer/" + __version__
|
||||||
sys_version = "Python/" + sys.version.split()[0]
|
sys_version = "Python/" + sys.version.split()[0]
|
||||||
|
@ -45,7 +45,6 @@ class BaseDatabaseFeatures(object):
|
|||||||
autoindexes_primary_keys = True
|
autoindexes_primary_keys = True
|
||||||
inline_fk_references = True
|
inline_fk_references = True
|
||||||
needs_datetime_string_cast = True
|
needs_datetime_string_cast = True
|
||||||
needs_upper_for_iops = False
|
|
||||||
supports_constraints = True
|
supports_constraints = True
|
||||||
supports_tablespaces = False
|
supports_tablespaces = False
|
||||||
uses_case_insensitive_names = False
|
uses_case_insensitive_names = False
|
||||||
|
@ -27,7 +27,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||||||
allows_unique_and_pk = False # Suppress UNIQUE/PK for Oracle (ORA-02259)
|
allows_unique_and_pk = False # Suppress UNIQUE/PK for Oracle (ORA-02259)
|
||||||
empty_fetchmany_value = ()
|
empty_fetchmany_value = ()
|
||||||
needs_datetime_string_cast = False
|
needs_datetime_string_cast = False
|
||||||
needs_upper_for_iops = True
|
|
||||||
supports_tablespaces = True
|
supports_tablespaces = True
|
||||||
uses_case_insensitive_names = True
|
uses_case_insensitive_names = True
|
||||||
uses_custom_query_class = True
|
uses_custom_query_class = True
|
||||||
|
@ -5,9 +5,13 @@ from django.core import management
|
|||||||
# types, as strings. Column-type strings can contain format strings; they'll
|
# types, as strings. Column-type strings can contain format strings; they'll
|
||||||
# be interpolated against the values of Field.__dict__ before being output.
|
# 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.
|
# If a column type is set to None, it won't be included in the output.
|
||||||
|
#
|
||||||
|
# Any format strings starting with "qn_" are quoted before being used in the
|
||||||
|
# output (the "qn_" prefix is stripped before the lookup is performed.
|
||||||
|
|
||||||
DATA_TYPES = {
|
DATA_TYPES = {
|
||||||
'AutoField': 'NUMBER(11)',
|
'AutoField': 'NUMBER(11)',
|
||||||
'BooleanField': 'NUMBER(1) CHECK (%(column)s IN (0,1))',
|
'BooleanField': 'NUMBER(1) CHECK (%(qn_column)s IN (0,1))',
|
||||||
'CharField': 'NVARCHAR2(%(max_length)s)',
|
'CharField': 'NVARCHAR2(%(max_length)s)',
|
||||||
'CommaSeparatedIntegerField': 'VARCHAR2(%(max_length)s)',
|
'CommaSeparatedIntegerField': 'VARCHAR2(%(max_length)s)',
|
||||||
'DateField': 'DATE',
|
'DateField': 'DATE',
|
||||||
@ -19,11 +23,11 @@ DATA_TYPES = {
|
|||||||
'ImageField': 'NVARCHAR2(%(max_length)s)',
|
'ImageField': 'NVARCHAR2(%(max_length)s)',
|
||||||
'IntegerField': 'NUMBER(11)',
|
'IntegerField': 'NUMBER(11)',
|
||||||
'IPAddressField': 'VARCHAR2(15)',
|
'IPAddressField': 'VARCHAR2(15)',
|
||||||
'NullBooleanField': 'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))',
|
'NullBooleanField': 'NUMBER(1) CHECK ((%(qn_column)s IN (0,1)) OR (%(column)s IS NULL))',
|
||||||
'OneToOneField': 'NUMBER(11)',
|
'OneToOneField': 'NUMBER(11)',
|
||||||
'PhoneNumberField': 'VARCHAR2(20)',
|
'PhoneNumberField': 'VARCHAR2(20)',
|
||||||
'PositiveIntegerField': 'NUMBER(11) CHECK (%(column)s >= 0)',
|
'PositiveIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)',
|
||||||
'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(column)s >= 0)',
|
'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)',
|
||||||
'SlugField': 'NVARCHAR2(50)',
|
'SlugField': 'NVARCHAR2(50)',
|
||||||
'SmallIntegerField': 'NUMBER(11)',
|
'SmallIntegerField': 'NUMBER(11)',
|
||||||
'TextField': 'NCLOB',
|
'TextField': 'NCLOB',
|
||||||
|
@ -16,6 +16,7 @@ from django.core import validators
|
|||||||
from django import oldforms
|
from django import oldforms
|
||||||
from django import newforms as forms
|
from django import newforms as forms
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.utils.datastructures import DictWrapper
|
||||||
from django.utils.functional import curry
|
from django.utils.functional import curry
|
||||||
from django.utils.itercompat import tee
|
from django.utils.itercompat import tee
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
@ -153,8 +154,9 @@ class Field(object):
|
|||||||
# mapped to one of the built-in Django field types. In this case, you
|
# mapped to one of the built-in Django field types. In this case, you
|
||||||
# can implement db_type() instead of get_internal_type() to specify
|
# can implement db_type() instead of get_internal_type() to specify
|
||||||
# exactly which wacky database column type you want to use.
|
# exactly which wacky database column type you want to use.
|
||||||
|
data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
|
||||||
try:
|
try:
|
||||||
return get_creation_module().DATA_TYPES[self.get_internal_type()] % self.__dict__
|
return get_creation_module().DATA_TYPES[self.get_internal_type()] % data
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -103,13 +103,15 @@ class RelatedField(object):
|
|||||||
|
|
||||||
if hasattr(sup, 'contribute_to_class'):
|
if hasattr(sup, 'contribute_to_class'):
|
||||||
sup.contribute_to_class(cls, name)
|
sup.contribute_to_class(cls, name)
|
||||||
|
|
||||||
|
if not cls._meta.abstract and self.rel.related_name:
|
||||||
|
self.rel.related_name = self.rel.related_name % {'class': cls.__name__.lower()}
|
||||||
|
|
||||||
other = self.rel.to
|
other = self.rel.to
|
||||||
if isinstance(other, basestring):
|
if isinstance(other, basestring):
|
||||||
add_lazy_relation(cls, self, other)
|
add_lazy_relation(cls, self, other)
|
||||||
else:
|
else:
|
||||||
self.do_related_class(other, cls)
|
self.do_related_class(other, cls)
|
||||||
if not cls._meta.abstract and self.rel.related_name:
|
|
||||||
self.rel.related_name = self.rel.related_name % {'class': cls.__name__.lower()}
|
|
||||||
|
|
||||||
def set_attributes_from_rel(self):
|
def set_attributes_from_rel(self):
|
||||||
self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name)
|
self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name)
|
||||||
@ -119,6 +121,7 @@ class RelatedField(object):
|
|||||||
def do_related_class(self, other, cls):
|
def do_related_class(self, other, cls):
|
||||||
self.set_attributes_from_rel()
|
self.set_attributes_from_rel()
|
||||||
related = RelatedObject(other, cls, self)
|
related = RelatedObject(other, cls, self)
|
||||||
|
if not cls._meta.abstract:
|
||||||
self.contribute_to_related_class(other, related)
|
self.contribute_to_related_class(other, related)
|
||||||
|
|
||||||
def get_db_prep_lookup(self, lookup_type, value):
|
def get_db_prep_lookup(self, lookup_type, value):
|
||||||
|
@ -273,14 +273,17 @@ class Options(object):
|
|||||||
"""
|
"""
|
||||||
Initialises the field name -> field object mapping.
|
Initialises the field name -> field object mapping.
|
||||||
"""
|
"""
|
||||||
cache = dict([(f.name, (f, m, True, False)) for f, m in
|
cache = {}
|
||||||
self.get_fields_with_model()])
|
# We intentionally handle related m2m objects first so that symmetrical
|
||||||
for f, model in self.get_m2m_with_model():
|
# m2m accessor names can be overridden, if necessary.
|
||||||
cache[f.name] = (f, model, True, True)
|
|
||||||
for f, model in self.get_all_related_m2m_objects_with_model():
|
for f, model in self.get_all_related_m2m_objects_with_model():
|
||||||
cache[f.field.related_query_name()] = (f, model, False, True)
|
cache[f.field.related_query_name()] = (f, model, False, True)
|
||||||
for f, model in self.get_all_related_objects_with_model():
|
for f, model in self.get_all_related_objects_with_model():
|
||||||
cache[f.field.related_query_name()] = (f, model, False, False)
|
cache[f.field.related_query_name()] = (f, model, False, False)
|
||||||
|
for f, model in self.get_m2m_with_model():
|
||||||
|
cache[f.name] = (f, model, True, True)
|
||||||
|
for f, model in self.get_fields_with_model():
|
||||||
|
cache[f.name] = (f, model, True, False)
|
||||||
if self.order_with_respect_to:
|
if self.order_with_respect_to:
|
||||||
cache['_order'] = OrderWrt(), None, True, False
|
cache['_order'] = OrderWrt(), None, True, False
|
||||||
if app_cache_ready():
|
if app_cache_ready():
|
||||||
|
@ -218,6 +218,8 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def __and__(self, other):
|
def __and__(self, other):
|
||||||
self._merge_sanity_check(other)
|
self._merge_sanity_check(other)
|
||||||
|
if isinstance(other, EmptyQuerySet):
|
||||||
|
return other._clone()
|
||||||
combined = self._clone()
|
combined = self._clone()
|
||||||
combined.query.combine(other.query, sql.AND)
|
combined.query.combine(other.query, sql.AND)
|
||||||
return combined
|
return combined
|
||||||
@ -225,6 +227,8 @@ class QuerySet(object):
|
|||||||
def __or__(self, other):
|
def __or__(self, other):
|
||||||
self._merge_sanity_check(other)
|
self._merge_sanity_check(other)
|
||||||
combined = self._clone()
|
combined = self._clone()
|
||||||
|
if isinstance(other, EmptyQuerySet):
|
||||||
|
return combined
|
||||||
combined.query.combine(other.query, sql.OR)
|
combined.query.combine(other.query, sql.OR)
|
||||||
return combined
|
return combined
|
||||||
|
|
||||||
@ -488,7 +492,9 @@ class QuerySet(object):
|
|||||||
and usually it will be more natural to use other methods.
|
and usually it will be more natural to use other methods.
|
||||||
"""
|
"""
|
||||||
if isinstance(filter_obj, Q) or hasattr(filter_obj, 'add_to_query'):
|
if isinstance(filter_obj, Q) or hasattr(filter_obj, 'add_to_query'):
|
||||||
return self._filter_or_exclude(None, filter_obj)
|
clone = self._clone()
|
||||||
|
clone.query.add_q(filter_obj)
|
||||||
|
return clone
|
||||||
else:
|
else:
|
||||||
return self._filter_or_exclude(None, **filter_obj)
|
return self._filter_or_exclude(None, **filter_obj)
|
||||||
|
|
||||||
@ -583,11 +589,11 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def _merge_sanity_check(self, other):
|
def _merge_sanity_check(self, other):
|
||||||
"""
|
"""
|
||||||
Checks that we are merging two comparable queryset classes.
|
Checks that we are merging two comparable queryset classes. By default
|
||||||
|
this does nothing, but see the ValuesQuerySet for an example of where
|
||||||
|
it's useful.
|
||||||
"""
|
"""
|
||||||
if self.__class__ is not other.__class__:
|
pass
|
||||||
raise TypeError("Cannot merge querysets of different types ('%s' and '%s'."
|
|
||||||
% (self.__class__.__name__, other.__class__.__name__))
|
|
||||||
|
|
||||||
class ValuesQuerySet(QuerySet):
|
class ValuesQuerySet(QuerySet):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
@ -688,9 +694,9 @@ class DateQuerySet(QuerySet):
|
|||||||
"""
|
"""
|
||||||
self.query = self.query.clone(klass=sql.DateQuery, setup=True)
|
self.query = self.query.clone(klass=sql.DateQuery, setup=True)
|
||||||
self.query.select = []
|
self.query.select = []
|
||||||
self.query.add_date_select(self._field.column, self._kind, self._order)
|
self.query.add_date_select(self._field, self._kind, self._order)
|
||||||
if self._field.null:
|
if self._field.null:
|
||||||
self.query.add_filter(('%s__isnull' % self._field.name, True))
|
self.query.add_filter(('%s__isnull' % self._field.name, False))
|
||||||
|
|
||||||
def _clone(self, klass=None, setup=False, **kwargs):
|
def _clone(self, klass=None, setup=False, **kwargs):
|
||||||
c = super(DateQuerySet, self)._clone(klass, False, **kwargs)
|
c = super(DateQuerySet, self)._clone(klass, False, **kwargs)
|
||||||
@ -705,6 +711,12 @@ class EmptyQuerySet(QuerySet):
|
|||||||
super(EmptyQuerySet, self).__init__(model, query)
|
super(EmptyQuerySet, self).__init__(model, query)
|
||||||
self._result_cache = []
|
self._result_cache = []
|
||||||
|
|
||||||
|
def __and__(self, other):
|
||||||
|
return self._clone()
|
||||||
|
|
||||||
|
def __or__(self, other):
|
||||||
|
return other._clone()
|
||||||
|
|
||||||
def count(self):
|
def count(self):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@ -610,6 +610,10 @@ class Query(object):
|
|||||||
alias = joins[-1]
|
alias = joins[-1]
|
||||||
col = target.column
|
col = target.column
|
||||||
|
|
||||||
|
# Must use left outer joins for nullable fields.
|
||||||
|
for join in joins:
|
||||||
|
self.promote_alias(join)
|
||||||
|
|
||||||
# If we get to this point and the field is a relation to another model,
|
# If we get to this point and the field is a relation to another model,
|
||||||
# append the default ordering for that model.
|
# append the default ordering for that model.
|
||||||
if field.rel and len(joins) > 1 and opts.ordering:
|
if field.rel and len(joins) > 1 and opts.ordering:
|
||||||
@ -631,8 +635,10 @@ class Query(object):
|
|||||||
# We have to do the same "final join" optimisation as in
|
# We have to do the same "final join" optimisation as in
|
||||||
# add_filter, since the final column might not otherwise be part of
|
# add_filter, since the final column might not otherwise be part of
|
||||||
# the select set (so we can't order on it).
|
# the select set (so we can't order on it).
|
||||||
|
while 1:
|
||||||
join = self.alias_map[alias]
|
join = self.alias_map[alias]
|
||||||
if col == join[RHS_JOIN_COL]:
|
if col != join[RHS_JOIN_COL]:
|
||||||
|
break
|
||||||
self.unref_alias(alias)
|
self.unref_alias(alias)
|
||||||
alias = join[LHS_ALIAS]
|
alias = join[LHS_ALIAS]
|
||||||
col = join[LHS_JOIN_COL]
|
col = join[LHS_JOIN_COL]
|
||||||
@ -679,12 +685,16 @@ class Query(object):
|
|||||||
for the join to contain NULL values on the left. If 'unconditional' is
|
for the join to contain NULL values on the left. If 'unconditional' is
|
||||||
False, the join is only promoted if it is nullable, otherwise it is
|
False, the join is only promoted if it is nullable, otherwise it is
|
||||||
always promoted.
|
always promoted.
|
||||||
|
|
||||||
|
Returns True if the join was promoted.
|
||||||
"""
|
"""
|
||||||
if ((unconditional or self.alias_map[alias][NULLABLE]) and
|
if ((unconditional or self.alias_map[alias][NULLABLE]) and
|
||||||
self.alias_map[alias] != self.LOUTER):
|
self.alias_map[alias] != self.LOUTER):
|
||||||
data = list(self.alias_map[alias])
|
data = list(self.alias_map[alias])
|
||||||
data[JOIN_TYPE] = self.LOUTER
|
data[JOIN_TYPE] = self.LOUTER
|
||||||
self.alias_map[alias] = tuple(data)
|
self.alias_map[alias] = tuple(data)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def change_aliases(self, change_map):
|
def change_aliases(self, change_map):
|
||||||
"""
|
"""
|
||||||
@ -826,6 +836,10 @@ class Query(object):
|
|||||||
if not always_create:
|
if not always_create:
|
||||||
for alias in self.join_map.get(t_ident, ()):
|
for alias in self.join_map.get(t_ident, ()):
|
||||||
if alias not in exclusions:
|
if alias not in exclusions:
|
||||||
|
if lhs_table and not self.alias_refcount[self.alias_map[alias][LHS_ALIAS]]:
|
||||||
|
# The LHS of this join tuple is no longer part of the
|
||||||
|
# query, so skip this possibility.
|
||||||
|
continue
|
||||||
self.ref_alias(alias)
|
self.ref_alias(alias)
|
||||||
if promote:
|
if promote:
|
||||||
self.promote_alias(alias)
|
self.promote_alias(alias)
|
||||||
@ -985,13 +999,15 @@ class Query(object):
|
|||||||
col = target.column
|
col = target.column
|
||||||
alias = join_list[-1]
|
alias = join_list[-1]
|
||||||
|
|
||||||
if final > 1:
|
while final > 1:
|
||||||
# An optimization: if the final join is against the same column as
|
# An optimization: if the final join is against the same column as
|
||||||
# we are comparing against, we can go back one step in the join
|
# we are comparing against, we can go back one step in the join
|
||||||
# chain and compare against the lhs of the join instead. The result
|
# chain and compare against the lhs of the join instead (and then
|
||||||
# (potentially) involves one less table join.
|
# repeat the optimization). The result, potentially, involves less
|
||||||
|
# table joins.
|
||||||
join = self.alias_map[alias]
|
join = self.alias_map[alias]
|
||||||
if col == join[RHS_JOIN_COL]:
|
if col != join[RHS_JOIN_COL]:
|
||||||
|
break
|
||||||
self.unref_alias(alias)
|
self.unref_alias(alias)
|
||||||
alias = join[LHS_ALIAS]
|
alias = join[LHS_ALIAS]
|
||||||
col = join[LHS_JOIN_COL]
|
col = join[LHS_JOIN_COL]
|
||||||
@ -1033,17 +1049,27 @@ class Query(object):
|
|||||||
self.promote_alias(table)
|
self.promote_alias(table)
|
||||||
|
|
||||||
self.where.add((alias, col, field, lookup_type, value), connector)
|
self.where.add((alias, col, field, lookup_type, value), connector)
|
||||||
|
|
||||||
if negate:
|
if negate:
|
||||||
for alias in join_list:
|
for alias in join_list:
|
||||||
self.promote_alias(alias)
|
self.promote_alias(alias)
|
||||||
if final > 1 and lookup_type != 'isnull':
|
if lookup_type != 'isnull':
|
||||||
|
if final > 1:
|
||||||
for alias in join_list:
|
for alias in join_list:
|
||||||
if self.alias_map[alias] == self.LOUTER:
|
if self.alias_map[alias][JOIN_TYPE] == self.LOUTER:
|
||||||
j_col = self.alias_map[alias][RHS_JOIN_COL]
|
j_col = self.alias_map[alias][RHS_JOIN_COL]
|
||||||
entry = Node([(alias, j_col, None, 'isnull', True)])
|
entry = Node([(alias, j_col, None, 'isnull', True)])
|
||||||
entry.negate()
|
entry.negate()
|
||||||
self.where.add(entry, AND)
|
self.where.add(entry, AND)
|
||||||
break
|
break
|
||||||
|
elif not (lookup_type == 'in' and not value):
|
||||||
|
# Leaky abstraction artifact: We have to specifically
|
||||||
|
# exclude the "foo__in=[]" case from this handling, because
|
||||||
|
# it's short-circuited in the Where class.
|
||||||
|
entry = Node([(alias, col, field, 'isnull', True)])
|
||||||
|
entry.negate()
|
||||||
|
self.where.add(entry, AND)
|
||||||
|
|
||||||
if can_reuse is not None:
|
if can_reuse is not None:
|
||||||
can_reuse.update(join_list)
|
can_reuse.update(join_list)
|
||||||
|
|
||||||
@ -1294,10 +1320,12 @@ class Query(object):
|
|||||||
final_alias = join[LHS_ALIAS]
|
final_alias = join[LHS_ALIAS]
|
||||||
col = join[LHS_JOIN_COL]
|
col = join[LHS_JOIN_COL]
|
||||||
joins = joins[:-1]
|
joins = joins[:-1]
|
||||||
|
promote = False
|
||||||
for join in joins[1:]:
|
for join in joins[1:]:
|
||||||
# Only nullable aliases are promoted, so we don't end up
|
# Only nullable aliases are promoted, so we don't end up
|
||||||
# doing unnecessary left outer joins here.
|
# doing unnecessary left outer joins here.
|
||||||
self.promote_alias(join)
|
if self.promote_alias(join, promote):
|
||||||
|
promote = True
|
||||||
self.select.append((final_alias, col))
|
self.select.append((final_alias, col))
|
||||||
self.select_fields.append(field)
|
self.select_fields.append(field)
|
||||||
except MultiJoin:
|
except MultiJoin:
|
||||||
|
@ -357,12 +357,14 @@ class DateQuery(Query):
|
|||||||
date = typecast_timestamp(str(date))
|
date = typecast_timestamp(str(date))
|
||||||
yield date
|
yield date
|
||||||
|
|
||||||
def add_date_select(self, column, lookup_type, order='ASC'):
|
def add_date_select(self, field, lookup_type, order='ASC'):
|
||||||
"""
|
"""
|
||||||
Converts the query into a date extraction query.
|
Converts the query into a date extraction query.
|
||||||
"""
|
"""
|
||||||
alias = self.join((None, self.model._meta.db_table, None, None))
|
result = self.setup_joins([field.name], self.get_meta(),
|
||||||
select = Date((alias, column), lookup_type,
|
self.get_initial_alias(), False)
|
||||||
|
alias = result[3][-1]
|
||||||
|
select = Date((alias, field.column), lookup_type,
|
||||||
self.connection.ops.date_trunc_sql)
|
self.connection.ops.date_trunc_sql)
|
||||||
self.select = [select]
|
self.select = [select]
|
||||||
self.select_fields = [None]
|
self.select_fields = [None]
|
||||||
|
@ -39,12 +39,11 @@ class CommentNode(Node):
|
|||||||
|
|
||||||
class CycleNode(Node):
|
class CycleNode(Node):
|
||||||
def __init__(self, cyclevars, variable_name=None):
|
def __init__(self, cyclevars, variable_name=None):
|
||||||
self.cycle_iter = itertools_cycle(cyclevars)
|
self.cycle_iter = itertools_cycle([Variable(v) for v in cyclevars])
|
||||||
self.variable_name = variable_name
|
self.variable_name = variable_name
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
value = self.cycle_iter.next()
|
value = self.cycle_iter.next().resolve(context)
|
||||||
value = Variable(value).resolve(context)
|
|
||||||
if self.variable_name:
|
if self.variable_name:
|
||||||
context[self.variable_name] = value
|
context[self.variable_name] = value
|
||||||
return value
|
return value
|
||||||
@ -162,10 +161,12 @@ class IfChangedNode(Node):
|
|||||||
self.nodelist = nodelist
|
self.nodelist = nodelist
|
||||||
self._last_seen = None
|
self._last_seen = None
|
||||||
self._varlist = map(Variable, varlist)
|
self._varlist = map(Variable, varlist)
|
||||||
|
self._id = str(id(self))
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
if 'forloop' in context and context['forloop']['first']:
|
if 'forloop' in context and self._id not in context['forloop']:
|
||||||
self._last_seen = None
|
self._last_seen = None
|
||||||
|
context['forloop'][self._id] = 1
|
||||||
try:
|
try:
|
||||||
if self._varlist:
|
if self._varlist:
|
||||||
# Consider multiple parameters. This automatically behaves
|
# Consider multiple parameters. This automatically behaves
|
||||||
@ -452,7 +453,7 @@ def cycle(parser, token):
|
|||||||
<tr class="{% cycle rowcolors %}">...</tr>
|
<tr class="{% cycle rowcolors %}">...</tr>
|
||||||
<tr class="{% cycle rowcolors %}">...</tr>
|
<tr class="{% cycle rowcolors %}">...</tr>
|
||||||
|
|
||||||
You can use any number of values, seperated by spaces. Commas can also
|
You can use any number of values, separated by spaces. Commas can also
|
||||||
be used to separate values; if a comma is used, the cycle values are
|
be used to separate values; if a comma is used, the cycle values are
|
||||||
interpreted as literal strings.
|
interpreted as literal strings.
|
||||||
"""
|
"""
|
||||||
@ -462,7 +463,7 @@ def cycle(parser, token):
|
|||||||
# one returned from {% cycle name %} are the exact same object. This
|
# one returned from {% cycle name %} are the exact same object. This
|
||||||
# shouldn't cause problems (heh), but if it does, now you know.
|
# shouldn't cause problems (heh), but if it does, now you know.
|
||||||
#
|
#
|
||||||
# Ugly hack warning: this stuffs the named template dict into parser so
|
# Ugly hack warning: This stuffs the named template dict into parser so
|
||||||
# that names are only unique within each template (as opposed to using
|
# that names are only unique within each template (as opposed to using
|
||||||
# a global variable, which would make cycle names have to be unique across
|
# a global variable, which would make cycle names have to be unique across
|
||||||
# *all* templates.
|
# *all* templates.
|
||||||
@ -481,8 +482,7 @@ def cycle(parser, token):
|
|||||||
# {% cycle foo %} case.
|
# {% cycle foo %} case.
|
||||||
name = args[1]
|
name = args[1]
|
||||||
if not hasattr(parser, '_namedCycleNodes'):
|
if not hasattr(parser, '_namedCycleNodes'):
|
||||||
raise TemplateSyntaxError("No named cycles in template."
|
raise TemplateSyntaxError("No named cycles in template. '%s' is not defined" % name)
|
||||||
" '%s' is not defined" % name)
|
|
||||||
if not name in parser._namedCycleNodes:
|
if not name in parser._namedCycleNodes:
|
||||||
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
||||||
return parser._namedCycleNodes[name]
|
return parser._namedCycleNodes[name]
|
||||||
@ -682,8 +682,10 @@ ifnotequal = register.tag(ifnotequal)
|
|||||||
def do_if(parser, token):
|
def do_if(parser, token):
|
||||||
"""
|
"""
|
||||||
The ``{% if %}`` tag evaluates a variable, and if that variable is "true"
|
The ``{% if %}`` tag evaluates a variable, and if that variable is "true"
|
||||||
(i.e. exists, is not empty, and is not a false boolean value) the contents
|
(i.e., exists, is not empty, and is not a false boolean value), the
|
||||||
of the block are output::
|
contents of the block are output:
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
{% if athlete_list %}
|
{% if athlete_list %}
|
||||||
Number of athletes: {{ athlete_list|count }}
|
Number of athletes: {{ athlete_list|count }}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from django.template import Library, Node, TemplateSyntaxError
|
from django.template import Library, Node, TemplateSyntaxError, Variable, VariableDoesNotExist
|
||||||
from django.template import resolve_variable
|
from django.template import resolve_variable
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
@ -6,20 +6,27 @@ from django.utils.encoding import force_unicode
|
|||||||
register = Library()
|
register = Library()
|
||||||
|
|
||||||
class CacheNode(Node):
|
class CacheNode(Node):
|
||||||
def __init__(self, nodelist, expire_time, fragment_name, vary_on):
|
def __init__(self, nodelist, expire_time_var, fragment_name, vary_on):
|
||||||
self.nodelist = nodelist
|
self.nodelist = nodelist
|
||||||
self.expire_time = expire_time
|
self.expire_time_var = Variable(expire_time_var)
|
||||||
self.fragment_name = fragment_name
|
self.fragment_name = fragment_name
|
||||||
self.vary_on = vary_on
|
self.vary_on = vary_on
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
|
try:
|
||||||
|
expire_time = self.expire_time_var.resolve(context)
|
||||||
|
except VariableDoesNotExist:
|
||||||
|
raise TemplateSyntaxError('"cache" tag got an unknkown variable: %r' % self.expire_time_var.var)
|
||||||
|
try:
|
||||||
|
expire_time = int(expire_time)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
raise TemplateSyntaxError('"cache" tag got a non-integer timeout value: %r' % expire_time)
|
||||||
# Build a unicode key for this fragment and all vary-on's.
|
# Build a unicode key for this fragment and all vary-on's.
|
||||||
cache_key = u':'.join([self.fragment_name] + \
|
cache_key = u':'.join([self.fragment_name] + [force_unicode(resolve_variable(var, context)) for var in self.vary_on])
|
||||||
[force_unicode(resolve_variable(var, context)) for var in self.vary_on])
|
|
||||||
value = cache.get(cache_key)
|
value = cache.get(cache_key)
|
||||||
if value is None:
|
if value is None:
|
||||||
value = self.nodelist.render(context)
|
value = self.nodelist.render(context)
|
||||||
cache.set(cache_key, value, self.expire_time)
|
cache.set(cache_key, value, expire_time)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def do_cache(parser, token):
|
def do_cache(parser, token):
|
||||||
@ -48,10 +55,6 @@ def do_cache(parser, token):
|
|||||||
tokens = token.contents.split()
|
tokens = token.contents.split()
|
||||||
if len(tokens) < 3:
|
if len(tokens) < 3:
|
||||||
raise TemplateSyntaxError(u"'%r' tag requires at least 2 arguments." % tokens[0])
|
raise TemplateSyntaxError(u"'%r' tag requires at least 2 arguments." % tokens[0])
|
||||||
try:
|
return CacheNode(nodelist, tokens[1], tokens[2], tokens[3:])
|
||||||
expire_time = int(tokens[1])
|
|
||||||
except ValueError:
|
|
||||||
raise TemplateSyntaxError(u"First argument to '%r' must be an integer (got '%s')." % (tokens[0], tokens[1]))
|
|
||||||
return CacheNode(nodelist, expire_time, tokens[2], tokens[3:])
|
|
||||||
|
|
||||||
register.tag('cache', do_cache)
|
register.tag('cache', do_cache)
|
||||||
|
@ -343,3 +343,34 @@ class FileDict(dict):
|
|||||||
d = dict(self, content='<omitted>')
|
d = dict(self, content='<omitted>')
|
||||||
return dict.__repr__(d)
|
return dict.__repr__(d)
|
||||||
return dict.__repr__(self)
|
return dict.__repr__(self)
|
||||||
|
|
||||||
|
class DictWrapper(dict):
|
||||||
|
"""
|
||||||
|
Wraps accesses to a dictionary so that certain values (those starting with
|
||||||
|
the specified prefix) are passed through a function before being returned.
|
||||||
|
The prefix is removed before looking up the real value.
|
||||||
|
|
||||||
|
Used by the SQL construction code to ensure that values are correctly
|
||||||
|
quoted before being used.
|
||||||
|
"""
|
||||||
|
def __init__(self, data, func, prefix):
|
||||||
|
super(DictWrapper, self).__init__(data)
|
||||||
|
self.func = func
|
||||||
|
self.prefix = prefix
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
"""
|
||||||
|
Retrieves the real value after stripping the prefix string (if
|
||||||
|
present). If the prefix is present, pass the value through self.func
|
||||||
|
before returning, otherwise return the raw value.
|
||||||
|
"""
|
||||||
|
if key.startswith(self.prefix):
|
||||||
|
use_func = True
|
||||||
|
key = key[len(self.prefix):]
|
||||||
|
else:
|
||||||
|
use_func = False
|
||||||
|
value = super(DictWrapper, self).__getitem__(key)
|
||||||
|
if use_func:
|
||||||
|
return self.func(value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
@ -76,19 +76,19 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
|
|||||||
"""
|
"""
|
||||||
Converts any URLs in text into clickable links.
|
Converts any URLs in text into clickable links.
|
||||||
|
|
||||||
Works on http://, https://, and www. links. Links can have trailing
|
Works on http://, https://, www. links and links ending in .org, .net or
|
||||||
punctuation (periods, commas, close-parens) and leading punctuation
|
.com. Links can have trailing punctuation (periods, commas, close-parens)
|
||||||
(opening parens) and it'll still do the right thing.
|
and leading punctuation (opening parens) and it'll still do the right
|
||||||
|
thing.
|
||||||
|
|
||||||
If trim_url_limit is not None, the URLs in link text longer than this limit
|
If trim_url_limit is not None, the URLs in link text longer than this limit
|
||||||
will truncated to trim_url_limit-3 characters and appended with an elipsis.
|
will truncated to trim_url_limit-3 characters and appended with an elipsis.
|
||||||
|
|
||||||
If nofollow is True, the URLs in link text will get a rel="nofollow"
|
If nofollow is True, the URLs in link text will get a rel="nofollow"
|
||||||
attribute.
|
attribute.
|
||||||
|
|
||||||
|
If autoescape is True, the link text and URLs will get autoescaped.
|
||||||
"""
|
"""
|
||||||
if autoescape:
|
|
||||||
trim_url = lambda x, limit=trim_url_limit: conditional_escape(limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x)
|
|
||||||
else:
|
|
||||||
trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
|
trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
|
||||||
safe_input = isinstance(text, SafeData)
|
safe_input = isinstance(text, SafeData)
|
||||||
words = word_split_re.split(force_unicode(text))
|
words = word_split_re.split(force_unicode(text))
|
||||||
@ -97,29 +97,29 @@ def urlize(text, trim_url_limit=None, nofollow=False, autoescape=False):
|
|||||||
match = punctuation_re.match(word)
|
match = punctuation_re.match(word)
|
||||||
if match:
|
if match:
|
||||||
lead, middle, trail = match.groups()
|
lead, middle, trail = match.groups()
|
||||||
if safe_input:
|
# Make URL we want to point to.
|
||||||
middle = mark_safe(middle)
|
url = None
|
||||||
if middle.startswith('www.') or ('@' not in middle and not (middle.startswith('http://') or middle.startswith('https://')) and \
|
|
||||||
len(middle) > 0 and middle[0] in string.ascii_letters + string.digits and \
|
|
||||||
(middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))):
|
|
||||||
middle = 'http://%s' % middle
|
|
||||||
if middle.startswith('http://') or middle.startswith('https://'):
|
if middle.startswith('http://') or middle.startswith('https://'):
|
||||||
url = urlquote(middle, safe='/&=:;#?+*')
|
url = urlquote(middle, safe='/&=:;#?+*')
|
||||||
if autoescape and not safe_input:
|
elif middle.startswith('www.') or ('@' not in middle and \
|
||||||
url = escape(url)
|
len(middle) > 0 and middle[0] in string.ascii_letters + string.digits and \
|
||||||
trimmed_url = trim_url(middle)
|
(middle.endswith('.org') or middle.endswith('.net') or middle.endswith('.com'))):
|
||||||
middle = '<a href="%s"%s>%s</a>' % (url, nofollow_attr,
|
url = urlquote('http://%s' % middle, safe='/&=:;#?+*')
|
||||||
trimmed_url)
|
elif '@' in middle and not ':' in middle and simple_email_re.match(middle):
|
||||||
elif '@' in middle and not middle.startswith('www.') and \
|
url = 'mailto:%s' % middle
|
||||||
not ':' in middle and simple_email_re.match(middle):
|
nofollow_attr = ''
|
||||||
if autoescape:
|
# Make link.
|
||||||
middle = conditional_escape(middle)
|
if url:
|
||||||
middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
|
trimmed = trim_url(middle)
|
||||||
if lead + middle + trail != word:
|
|
||||||
if autoescape and not safe_input:
|
if autoescape and not safe_input:
|
||||||
lead, trail = escape(lead), escape(trail)
|
lead, trail = escape(lead), escape(trail)
|
||||||
|
url, trimmed = escape(url), escape(trimmed)
|
||||||
|
middle = '<a href="%s"%s>%s</a>' % (url, nofollow_attr, trimmed)
|
||||||
words[i] = mark_safe('%s%s%s' % (lead, middle, trail))
|
words[i] = mark_safe('%s%s%s' % (lead, middle, trail))
|
||||||
elif autoescape and not safe_input:
|
else:
|
||||||
|
if safe_input:
|
||||||
|
words[i] = mark_safe(word)
|
||||||
|
elif autoescape:
|
||||||
words[i] = escape(word)
|
words[i] = escape(word)
|
||||||
elif safe_input:
|
elif safe_input:
|
||||||
words[i] = mark_safe(word)
|
words[i] = mark_safe(word)
|
||||||
|
@ -336,6 +336,17 @@ template tag to uniquely identify the cache fragment::
|
|||||||
It's perfectly fine to specify more than one argument to identify the fragment.
|
It's perfectly fine to specify more than one argument to identify the fragment.
|
||||||
Simply pass as many arguments to ``{% cache %}`` as you need.
|
Simply pass as many arguments to ``{% cache %}`` as you need.
|
||||||
|
|
||||||
|
The cache timeout can be a template variable, as long as the template variable
|
||||||
|
resolves to an integer value. For example, if the template variable
|
||||||
|
``my_timeout`` is set to the value ``600``, then the following two examples are
|
||||||
|
equivalent::
|
||||||
|
|
||||||
|
{% cache 600 sidebar %} ... {% endcache %}
|
||||||
|
{% cache my_timeout sidebar %} ... {% endcache %}
|
||||||
|
|
||||||
|
This feature is useful in avoiding repetition in templates. You can set the
|
||||||
|
timeout in a variable, in one place, and just reuse that value.
|
||||||
|
|
||||||
The low-level cache API
|
The low-level cache API
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
@ -332,50 +332,49 @@ reopen tickets that have been marked as "wontfix" by core developers.
|
|||||||
Triage by the general community
|
Triage by the general community
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
Although the Core Developers and Ticket Triagers make the big decisions in
|
Although the core developers and ticket triagers make the big decisions in
|
||||||
the ticket triage process, there is also a lot that general community
|
the ticket triage process, there's also a lot that general community
|
||||||
members can do to help the triage process. In particular, you can help out by:
|
members can do to help the triage process. In particular, you can help out by:
|
||||||
|
|
||||||
* Closing "Unreviewed" tickets as "invalid", "worksforme", or "duplicate".
|
* Closing "Unreviewed" tickets as "invalid", "worksforme" or "duplicate."
|
||||||
|
|
||||||
* Promoting "Unreviewed" tickets to "Design Decision Required" if there
|
* Promoting "Unreviewed" tickets to "Design decision needed" if a design
|
||||||
is a design decision that needs to be made, or "Accepted" if they are
|
decision needs to be made, or "Accepted" in case of obvious bugs.
|
||||||
an obvious bug.
|
|
||||||
|
|
||||||
* Correcting the "Needs Tests", "Needs documentation", or "Has Patch" flags
|
* Correcting the "Needs tests", "Needs documentation", or "Has patch" flags
|
||||||
for tickets where they are incorrectly set.
|
for tickets where they are incorrectly set.
|
||||||
|
|
||||||
* Checking that old tickets are still valid. If a ticket hasn't seen
|
* Checking that old tickets are still valid. If a ticket hasn't seen
|
||||||
any activity in a long time, it's possible that the problem has been
|
any activity in a long time, it's possible that the problem has been
|
||||||
fixed, but the ticket hasn't been closed.
|
fixed but the ticket hasn't yet been closed.
|
||||||
|
|
||||||
* Contact the owners of tickets that have been claimed, but have not seen
|
* Contacting the owners of tickets that have been claimed but have not seen
|
||||||
any recent activity. If the owner doesn't respond after a week or so,
|
any recent activity. If the owner doesn't respond after a week or so,
|
||||||
remove the owner's claim on the ticket.
|
remove the owner's claim on the ticket.
|
||||||
|
|
||||||
* Identifying trends and themes in the tickets. If there a lot of bug reports
|
* Identifying trends and themes in the tickets. If there a lot of bug reports
|
||||||
about a particular part of Django, it possibly indicates that we need
|
about a particular part of Django, it may indicate we should consider
|
||||||
to consider refactoring that part of the code. If a trend is emerging,
|
refactoring that part of the code. If a trend is emerging, you should
|
||||||
you should raise it for discussion (referencing the relevant tickets)
|
raise it for discussion (referencing the relevant tickets) on
|
||||||
on `django-developers`_.
|
`django-developers`_.
|
||||||
|
|
||||||
However, we do ask that as a general community member working in the
|
However, we do ask the following of all general community members working in
|
||||||
ticket database:
|
the ticket database:
|
||||||
|
|
||||||
* Please **don't** close tickets as "wontfix". The core developers will
|
* Please **don't** close tickets as "wontfix." The core developers will
|
||||||
make the final determination of the fate of a ticket, usually after
|
make the final determination of the fate of a ticket, usually after
|
||||||
consultation with the community.
|
consultation with the community.
|
||||||
|
|
||||||
* Please **don't** promote tickets to "Ready for checkin" unless they are
|
* Please **don't** promote tickets to "Ready for checkin" unless they are
|
||||||
*trivial* changes - for example, spelling mistakes or
|
*trivial* changes -- for example, spelling mistakes or broken links in
|
||||||
broken links in documentation.
|
documentation.
|
||||||
|
|
||||||
* Please **don't** reverse a decision that has been made by a core
|
* Please **don't** reverse a decision that has been made by a core
|
||||||
developer. If you disagree with a discussion that has been made,
|
developer. If you disagree with a discussion that has been made,
|
||||||
please post a message to `django-developers`_.
|
please post a message to `django-developers`_.
|
||||||
|
|
||||||
* Please be conservative in your actions. If you're unsure if you should
|
* Please be conservative in your actions. If you're unsure if you should
|
||||||
be making a change, don't make the change - leave a comment with your
|
be making a change, don't make the change -- leave a comment with your
|
||||||
concerns on the ticket, or post a message to `django-developers`_.
|
concerns on the ticket, or post a message to `django-developers`_.
|
||||||
|
|
||||||
Submitting and maintaining translations
|
Submitting and maintaining translations
|
||||||
@ -739,8 +738,8 @@ If you're using another backend:
|
|||||||
deleted when the tests are finished. This means your user account needs
|
deleted when the tests are finished. This means your user account needs
|
||||||
permission to execute ``CREATE DATABASE``.
|
permission to execute ``CREATE DATABASE``.
|
||||||
|
|
||||||
If you want to run the full suite of tests, there are a number of dependencies that
|
If you want to run the full suite of tests, you'll need to install a number of
|
||||||
you should install:
|
dependencies:
|
||||||
|
|
||||||
* PyYAML_
|
* PyYAML_
|
||||||
* Markdown_
|
* Markdown_
|
||||||
@ -748,10 +747,8 @@ you should install:
|
|||||||
* Docutils_
|
* Docutils_
|
||||||
* setuptools_
|
* setuptools_
|
||||||
|
|
||||||
Of these dependencies, setuptools_ is the only dependency that is required - if
|
Each of these dependencies is optional. If you're missing any of them, the
|
||||||
setuptools_ is not installed, you will get import errors when running one of
|
associated tests will be skipped.
|
||||||
the template tests. The tests using the other libraries will be skipped if the
|
|
||||||
dependency can't be found.
|
|
||||||
|
|
||||||
.. _PyYAML: http://pyyaml.org/wiki/PyYAML
|
.. _PyYAML: http://pyyaml.org/wiki/PyYAML
|
||||||
.. _Markdown: http://pypi.python.org/pypi/Markdown/1.7
|
.. _Markdown: http://pypi.python.org/pypi/Markdown/1.7
|
||||||
@ -773,13 +770,13 @@ for generic relations and internationalization, type::
|
|||||||
Contrib apps
|
Contrib apps
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Tests for apps in ``django/contrib/`` go in their respective directories,
|
Tests for apps in ``django/contrib/`` go in their respective directories under
|
||||||
in a ``tests.py`` file. (You can split the tests over multiple modules
|
``django/contrib/``, in a ``tests.py`` file. (You can split the tests over
|
||||||
by using a ``tests`` folder in the normal Python way).
|
multiple modules by using a ``tests`` directory in the normal Python way.)
|
||||||
|
|
||||||
For the tests to be found, a ``models.py`` file must exist (it doesn't
|
For the tests to be found, a ``models.py`` file must exist (it doesn't
|
||||||
have to have anything in it). If you have URLs that need to be
|
have to have anything in it). If you have URLs that need to be
|
||||||
mapped, you must add them in ``tests/urls.py``.
|
mapped, put them in ``tests/urls.py``.
|
||||||
|
|
||||||
To run tests for just one contrib app (e.g. ``markup``), use the same
|
To run tests for just one contrib app (e.g. ``markup``), use the same
|
||||||
method as above::
|
method as above::
|
||||||
|
@ -382,7 +382,7 @@ Pickling QuerySets
|
|||||||
|
|
||||||
If you pickle_ a ``QuerySet``, this will also force all the results to be
|
If you pickle_ a ``QuerySet``, this will also force all the results to be
|
||||||
loaded into memory prior to pickling. This is because pickling is usually used
|
loaded into memory prior to pickling. This is because pickling is usually used
|
||||||
as a precursor to caching and when the cached queryset is reloaded, you want
|
as a precursor to caching and when the cached ``QuerySet`` is reloaded, you want
|
||||||
the results to already be present. This means that when you unpickle a
|
the results to already be present. This means that when you unpickle a
|
||||||
``QuerySet``, it contains the results at the moment it was pickled, rather
|
``QuerySet``, it contains the results at the moment it was pickled, rather
|
||||||
than the results that are currently in the database.
|
than the results that are currently in the database.
|
||||||
@ -2040,7 +2040,7 @@ automatically saved to the database.
|
|||||||
One-to-one relationships
|
One-to-one relationships
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
One-to-one relationships are very similar to Many-to-one relationships.
|
One-to-one relationships are very similar to many-to-one relationships.
|
||||||
If you define a OneToOneField on your model, instances of that model will have
|
If you define a OneToOneField on your model, instances of that model will have
|
||||||
access to the related object via a simple attribute of the model.
|
access to the related object via a simple attribute of the model.
|
||||||
|
|
||||||
@ -2053,8 +2053,8 @@ For example::
|
|||||||
ed = EntryDetail.objects.get(id=2)
|
ed = EntryDetail.objects.get(id=2)
|
||||||
ed.entry # Returns the related Entry object.
|
ed.entry # Returns the related Entry object.
|
||||||
|
|
||||||
The difference comes in reverse queries. The related model in a One-to-one
|
The difference comes in "reverse" queries. The related model in a one-to-one
|
||||||
relationship also has access to a ``Manager`` object; however, that ``Manager``
|
relationship also has access to a ``Manager`` object, but that ``Manager``
|
||||||
represents a single object, rather than a collection of objects::
|
represents a single object, rather than a collection of objects::
|
||||||
|
|
||||||
e = Entry.objects.get(id=2)
|
e = Entry.objects.get(id=2)
|
||||||
|
@ -1544,7 +1544,7 @@ the ``url`` function)::
|
|||||||
'django.views.generic.list_detail.object_detail',
|
'django.views.generic.list_detail.object_detail',
|
||||||
name='people_view'),
|
name='people_view'),
|
||||||
|
|
||||||
and then using that name to perform the reverse URL resolution instead
|
...and then using that name to perform the reverse URL resolution instead
|
||||||
of the view name::
|
of the view name::
|
||||||
|
|
||||||
from django.db.models import permalink
|
from django.db.models import permalink
|
||||||
@ -1553,7 +1553,7 @@ of the view name::
|
|||||||
return ('people_view', [str(self.id)])
|
return ('people_view', [str(self.id)])
|
||||||
get_absolute_url = permalink(get_absolute_url)
|
get_absolute_url = permalink(get_absolute_url)
|
||||||
|
|
||||||
More details on named URL patterns can be found in `URL dispatch documentation`_.
|
More details on named URL patterns are in the `URL dispatch documentation`_.
|
||||||
|
|
||||||
.. _URL dispatch documentation: ../url_dispatch/#naming-url-patterns
|
.. _URL dispatch documentation: ../url_dispatch/#naming-url-patterns
|
||||||
|
|
||||||
|
@ -38,6 +38,29 @@ class Student(CommonInfo):
|
|||||||
class Meta:
|
class Meta:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
#
|
||||||
|
# Abstract base classes with related models
|
||||||
|
#
|
||||||
|
|
||||||
|
class Post(models.Model):
|
||||||
|
title = models.CharField(max_length=50)
|
||||||
|
|
||||||
|
class Attachment(models.Model):
|
||||||
|
post = models.ForeignKey(Post, related_name='attached_%(class)s_set')
|
||||||
|
content = models.TextField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return self.content
|
||||||
|
|
||||||
|
class Comment(Attachment):
|
||||||
|
is_spam = models.BooleanField()
|
||||||
|
|
||||||
|
class Link(Attachment):
|
||||||
|
url = models.URLField()
|
||||||
|
|
||||||
#
|
#
|
||||||
# Multi-table inheritance
|
# Multi-table inheritance
|
||||||
#
|
#
|
||||||
@ -128,9 +151,25 @@ Traceback (most recent call last):
|
|||||||
...
|
...
|
||||||
AttributeError: type object 'CommonInfo' has no attribute 'objects'
|
AttributeError: type object 'CommonInfo' has no attribute 'objects'
|
||||||
|
|
||||||
# The Place/Restaurant/ItalianRestaurant models, on the other hand, all exist
|
# Create a Post
|
||||||
# as independent models. However, the subclasses also have transparent access
|
>>> post = Post(title='Lorem Ipsum')
|
||||||
# to the fields of their ancestors.
|
>>> post.save()
|
||||||
|
|
||||||
|
# The Post model has distinct accessors for the Comment and Link models.
|
||||||
|
>>> post.attached_comment_set.create(content='Save $ on V1agr@', is_spam=True)
|
||||||
|
<Comment: Save $ on V1agr@>
|
||||||
|
>>> post.attached_link_set.create(content='The Web framework for perfectionists with deadlines.', url='http://www.djangoproject.com/')
|
||||||
|
<Link: The Web framework for perfectionists with deadlines.>
|
||||||
|
|
||||||
|
# The Post model doesn't have an attribute called 'attached_%(class)s_set'.
|
||||||
|
>>> getattr(post, 'attached_%(class)s_set')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
AttributeError: 'Post' object has no attribute 'attached_%(class)s_set'
|
||||||
|
|
||||||
|
# The Place/Restaurant/ItalianRestaurant models all exist as independent
|
||||||
|
# models. However, the subclasses also have transparent access to the fields of
|
||||||
|
# their ancestors.
|
||||||
|
|
||||||
# Create a couple of Places.
|
# Create a couple of Places.
|
||||||
>>> p1 = Place(name='Master Shakes', address='666 W. Jersey')
|
>>> p1 = Place(name='Master Shakes', address='666 W. Jersey')
|
||||||
|
@ -125,4 +125,12 @@ Init from sequence of tuples
|
|||||||
>>> d = FileDict({'other-key': 'once upon a time...'})
|
>>> d = FileDict({'other-key': 'once upon a time...'})
|
||||||
>>> repr(d)
|
>>> repr(d)
|
||||||
"{'other-key': 'once upon a time...'}"
|
"{'other-key': 'once upon a time...'}"
|
||||||
|
|
||||||
|
### DictWrapper #############################################################
|
||||||
|
|
||||||
|
>>> f = lambda x: "*%s" % x
|
||||||
|
>>> d = DictWrapper({'a': 'a'}, f, 'xx_')
|
||||||
|
>>> "Normal: %(a)s. Modified: %(xx_a)s" % d
|
||||||
|
'Normal: a. Modified: *a'
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -150,7 +150,7 @@ u'fran%C3%A7ois%20%26%20jill'
|
|||||||
u'<a href="http://short.com/" rel="nofollow">http://short.com/</a>'
|
u'<a href="http://short.com/" rel="nofollow">http://short.com/</a>'
|
||||||
|
|
||||||
>>> urlizetrunc(u'http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20)
|
>>> urlizetrunc(u'http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20)
|
||||||
u'<a href="http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=" rel="nofollow">http://www.google....</a>'
|
u'<a href="http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=" rel="nofollow">http://www.google...</a>'
|
||||||
|
|
||||||
>>> urlizetrunc('http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20)
|
>>> urlizetrunc('http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=', 20)
|
||||||
u'<a href="http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=" rel="nofollow">http://www.google...</a>'
|
u'<a href="http://www.google.co.uk/search?hl=en&q=some+long+url&btnG=Search&meta=" rel="nofollow">http://www.google...</a>'
|
||||||
@ -174,10 +174,10 @@ u'<a href="http://google.com" rel="nofollow">http://google.com</a>'
|
|||||||
u'<a href="http://google.com/" rel="nofollow">http://google.com/</a>'
|
u'<a href="http://google.com/" rel="nofollow">http://google.com/</a>'
|
||||||
|
|
||||||
>>> urlize('www.google.com')
|
>>> urlize('www.google.com')
|
||||||
u'<a href="http://www.google.com" rel="nofollow">http://www.google.com</a>'
|
u'<a href="http://www.google.com" rel="nofollow">www.google.com</a>'
|
||||||
|
|
||||||
>>> urlize('djangoproject.org')
|
>>> urlize('djangoproject.org')
|
||||||
u'<a href="http://djangoproject.org" rel="nofollow">http://djangoproject.org</a>'
|
u'<a href="http://djangoproject.org" rel="nofollow">djangoproject.org</a>'
|
||||||
|
|
||||||
>>> urlize('info@djangoproject.org')
|
>>> urlize('info@djangoproject.org')
|
||||||
u'<a href="mailto:info@djangoproject.org">info@djangoproject.org</a>'
|
u'<a href="mailto:info@djangoproject.org">info@djangoproject.org</a>'
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
Regression tests for Model inheritance behaviour.
|
Regression tests for Model inheritance behaviour.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
class Place(models.Model):
|
class Place(models.Model):
|
||||||
@ -35,11 +37,17 @@ class ParkingLot(Place):
|
|||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u"%s the parking lot" % self.name
|
return u"%s the parking lot" % self.name
|
||||||
|
|
||||||
|
class Parent(models.Model):
|
||||||
|
created = models.DateTimeField(default=datetime.datetime.now)
|
||||||
|
|
||||||
|
class Child(Parent):
|
||||||
|
name = models.CharField(max_length=10)
|
||||||
|
|
||||||
__test__ = {'API_TESTS':"""
|
__test__ = {'API_TESTS':"""
|
||||||
# Regression for #7350, #7202
|
# Regression for #7350, #7202
|
||||||
# Check that when you create a Parent object with a specific reference to an existent
|
# Check that when you create a Parent object with a specific reference to an
|
||||||
# child instance, saving the Parent doesn't duplicate the child.
|
# existent child instance, saving the Parent doesn't duplicate the child. This
|
||||||
# This behaviour is only activated during a raw save - it is mostly relevant to
|
# behaviour is only activated during a raw save - it is mostly relevant to
|
||||||
# deserialization, but any sort of CORBA style 'narrow()' API would require a
|
# deserialization, but any sort of CORBA style 'narrow()' API would require a
|
||||||
# similar approach.
|
# similar approach.
|
||||||
|
|
||||||
@ -117,4 +125,10 @@ __test__ = {'API_TESTS':"""
|
|||||||
>>> [sorted(d.items()) for d in dicts]
|
>>> [sorted(d.items()) for d in dicts]
|
||||||
[[('name', u"Guido's All New House of Pasta"), ('serves_gnocchi', False), ('serves_hot_dogs', False)]]
|
[[('name', u"Guido's All New House of Pasta"), ('serves_gnocchi', False), ('serves_hot_dogs', False)]]
|
||||||
|
|
||||||
|
# Regressions tests for #7105: dates() queries should be able to use fields
|
||||||
|
# from the parent model as easily as the child.
|
||||||
|
>>> obj = Child.objects.create(name='child', created=datetime.datetime(2008, 6, 26, 17, 0, 0))
|
||||||
|
>>> Child.objects.dates('created', 'month')
|
||||||
|
[datetime.datetime(2008, 6, 1, 0, 0)]
|
||||||
|
|
||||||
"""}
|
"""}
|
||||||
|
@ -45,6 +45,7 @@ class Author(models.Model):
|
|||||||
class Item(models.Model):
|
class Item(models.Model):
|
||||||
name = models.CharField(max_length=10)
|
name = models.CharField(max_length=10)
|
||||||
created = models.DateTimeField()
|
created = models.DateTimeField()
|
||||||
|
modified = models.DateTimeField(blank=True, null=True)
|
||||||
tags = models.ManyToManyField(Tag, blank=True, null=True)
|
tags = models.ManyToManyField(Tag, blank=True, null=True)
|
||||||
creator = models.ForeignKey(Author)
|
creator = models.ForeignKey(Author)
|
||||||
note = models.ForeignKey(Note)
|
note = models.ForeignKey(Note)
|
||||||
@ -57,7 +58,7 @@ class Item(models.Model):
|
|||||||
|
|
||||||
class Report(models.Model):
|
class Report(models.Model):
|
||||||
name = models.CharField(max_length=10)
|
name = models.CharField(max_length=10)
|
||||||
creator = models.ForeignKey(Author, to_field='num')
|
creator = models.ForeignKey(Author, to_field='num', null=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
@ -89,6 +90,15 @@ class Number(models.Model):
|
|||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return unicode(self.num)
|
return unicode(self.num)
|
||||||
|
|
||||||
|
# Symmetrical m2m field with a normal field using the reverse accesor name
|
||||||
|
# ("valid").
|
||||||
|
class Valid(models.Model):
|
||||||
|
valid = models.CharField(max_length=10)
|
||||||
|
parent = models.ManyToManyField('self')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['valid']
|
||||||
|
|
||||||
# Some funky cross-linked models for testing a couple of infinite recursion
|
# Some funky cross-linked models for testing a couple of infinite recursion
|
||||||
# cases.
|
# cases.
|
||||||
class X(models.Model):
|
class X(models.Model):
|
||||||
@ -121,12 +131,12 @@ class LoopZ(models.Model):
|
|||||||
class CustomManager(models.Manager):
|
class CustomManager(models.Manager):
|
||||||
def get_query_set(self):
|
def get_query_set(self):
|
||||||
qs = super(CustomManager, self).get_query_set()
|
qs = super(CustomManager, self).get_query_set()
|
||||||
return qs.filter(is_public=True, tag__name='t1')
|
return qs.filter(public=True, tag__name='t1')
|
||||||
|
|
||||||
class ManagedModel(models.Model):
|
class ManagedModel(models.Model):
|
||||||
data = models.CharField(max_length=10)
|
data = models.CharField(max_length=10)
|
||||||
tag = models.ForeignKey(Tag)
|
tag = models.ForeignKey(Tag)
|
||||||
is_public = models.BooleanField(default=True)
|
public = models.BooleanField(default=True)
|
||||||
|
|
||||||
objects = CustomManager()
|
objects = CustomManager()
|
||||||
normal_manager = models.Manager()
|
normal_manager = models.Manager()
|
||||||
@ -134,6 +144,24 @@ class ManagedModel(models.Model):
|
|||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.data
|
return self.data
|
||||||
|
|
||||||
|
# An inter-related setup with multiple paths from Child to Detail.
|
||||||
|
class Detail(models.Model):
|
||||||
|
data = models.CharField(max_length=10)
|
||||||
|
|
||||||
|
class MemberManager(models.Manager):
|
||||||
|
def get_query_set(self):
|
||||||
|
return super(MemberManager, self).get_query_set().select_related("details")
|
||||||
|
|
||||||
|
class Member(models.Model):
|
||||||
|
name = models.CharField(max_length=10)
|
||||||
|
details = models.OneToOneField(Detail, primary_key=True)
|
||||||
|
|
||||||
|
objects = MemberManager()
|
||||||
|
|
||||||
|
class Child(models.Model):
|
||||||
|
person = models.OneToOneField(Member, primary_key=True)
|
||||||
|
parent = models.ForeignKey(Member, related_name="children")
|
||||||
|
|
||||||
|
|
||||||
__test__ = {'API_TESTS':"""
|
__test__ = {'API_TESTS':"""
|
||||||
>>> t1 = Tag(name='t1')
|
>>> t1 = Tag(name='t1')
|
||||||
@ -174,7 +202,7 @@ by 'info'. Helps detect some problems later.
|
|||||||
>>> time2 = datetime.datetime(2007, 12, 19, 21, 0, 0)
|
>>> time2 = datetime.datetime(2007, 12, 19, 21, 0, 0)
|
||||||
>>> time3 = datetime.datetime(2007, 12, 20, 22, 25, 0)
|
>>> time3 = datetime.datetime(2007, 12, 20, 22, 25, 0)
|
||||||
>>> time4 = datetime.datetime(2007, 12, 20, 21, 0, 0)
|
>>> time4 = datetime.datetime(2007, 12, 20, 21, 0, 0)
|
||||||
>>> i1 = Item(name='one', created=time1, creator=a1, note=n3)
|
>>> i1 = Item(name='one', created=time1, modified=time1, creator=a1, note=n3)
|
||||||
>>> i1.save()
|
>>> i1.save()
|
||||||
>>> i1.tags = [t1, t2]
|
>>> i1.tags = [t1, t2]
|
||||||
>>> i2 = Item(name='two', created=time2, creator=a2, note=n2)
|
>>> i2 = Item(name='two', created=time2, creator=a2, note=n2)
|
||||||
@ -190,6 +218,8 @@ by 'info'. Helps detect some problems later.
|
|||||||
>>> r1.save()
|
>>> r1.save()
|
||||||
>>> r2 = Report(name='r2', creator=a3)
|
>>> r2 = Report(name='r2', creator=a3)
|
||||||
>>> r2.save()
|
>>> r2.save()
|
||||||
|
>>> r3 = Report(name='r3')
|
||||||
|
>>> r3.save()
|
||||||
|
|
||||||
Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
|
Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
|
||||||
will be rank3, rank2, rank1.
|
will be rank3, rank2, rank1.
|
||||||
@ -478,7 +508,7 @@ FieldError: Infinite loop caused by ordering.
|
|||||||
# Ordering by a many-valued attribute (e.g. a many-to-many or reverse
|
# Ordering by a many-valued attribute (e.g. a many-to-many or reverse
|
||||||
# ForeignKey) is legal, but the results might not make sense. That isn't
|
# ForeignKey) is legal, but the results might not make sense. That isn't
|
||||||
# Django's problem. Garbage in, garbage out.
|
# Django's problem. Garbage in, garbage out.
|
||||||
>>> Item.objects.all().order_by('tags', 'id')
|
>>> Item.objects.filter(tags__isnull=False).order_by('tags', 'id')
|
||||||
[<Item: one>, <Item: two>, <Item: one>, <Item: two>, <Item: four>]
|
[<Item: one>, <Item: two>, <Item: one>, <Item: two>, <Item: four>]
|
||||||
|
|
||||||
# If we replace the default ordering, Django adjusts the required tables
|
# If we replace the default ordering, Django adjusts the required tables
|
||||||
@ -627,6 +657,10 @@ Bug #7087 -- dates with extra select columns
|
|||||||
>>> Item.objects.dates('created', 'day').extra(select={'a': 1})
|
>>> Item.objects.dates('created', 'day').extra(select={'a': 1})
|
||||||
[datetime.datetime(2007, 12, 19, 0, 0), datetime.datetime(2007, 12, 20, 0, 0)]
|
[datetime.datetime(2007, 12, 19, 0, 0), datetime.datetime(2007, 12, 20, 0, 0)]
|
||||||
|
|
||||||
|
Bug #7155 -- nullable dates
|
||||||
|
>>> Item.objects.dates('modified', 'day')
|
||||||
|
[datetime.datetime(2007, 12, 19, 0, 0)]
|
||||||
|
|
||||||
Test that parallel iterators work.
|
Test that parallel iterators work.
|
||||||
|
|
||||||
>>> qs = Tag.objects.all()
|
>>> qs = Tag.objects.all()
|
||||||
@ -705,8 +739,57 @@ More twisted cases, involving nested negations.
|
|||||||
Bug #7095
|
Bug #7095
|
||||||
Updates that are filtered on the model being updated are somewhat tricky to get
|
Updates that are filtered on the model being updated are somewhat tricky to get
|
||||||
in MySQL. This exercises that case.
|
in MySQL. This exercises that case.
|
||||||
>>> mm = ManagedModel.objects.create(data='mm1', tag=t1, is_public=True)
|
>>> mm = ManagedModel.objects.create(data='mm1', tag=t1, public=True)
|
||||||
>>> ManagedModel.objects.update(data='mm')
|
>>> ManagedModel.objects.update(data='mm')
|
||||||
|
|
||||||
|
A values() or values_list() query across joined models must use outer joins
|
||||||
|
appropriately.
|
||||||
|
>>> Report.objects.values_list("creator__extra__info", flat=True).order_by("name")
|
||||||
|
[u'e1', u'e2', None]
|
||||||
|
|
||||||
|
Similarly for select_related(), joins beyond an initial nullable join must
|
||||||
|
use outer joins so that all results are included.
|
||||||
|
>>> Report.objects.select_related("creator", "creator__extra").order_by("name")
|
||||||
|
[<Report: r1>, <Report: r2>, <Report: r3>]
|
||||||
|
|
||||||
|
When there are multiple paths to a table from another table, we have to be
|
||||||
|
careful not to accidentally reuse an inappropriate join when using
|
||||||
|
select_related(). We used to return the parent's Detail record here by mistake.
|
||||||
|
|
||||||
|
>>> d1 = Detail.objects.create(data="d1")
|
||||||
|
>>> d2 = Detail.objects.create(data="d2")
|
||||||
|
>>> m1 = Member.objects.create(name="m1", details=d1)
|
||||||
|
>>> m2 = Member.objects.create(name="m2", details=d2)
|
||||||
|
>>> c1 = Child.objects.create(person=m2, parent=m1)
|
||||||
|
>>> obj = m1.children.select_related("person__details")[0]
|
||||||
|
>>> obj.person.details.data
|
||||||
|
u'd2'
|
||||||
|
|
||||||
|
Bug #7076 -- excluding shouldn't eliminate NULL entries.
|
||||||
|
>>> Item.objects.exclude(modified=time1).order_by('name')
|
||||||
|
[<Item: four>, <Item: three>, <Item: two>]
|
||||||
|
>>> Tag.objects.exclude(parent__name=t1.name)
|
||||||
|
[<Tag: t1>, <Tag: t4>, <Tag: t5>]
|
||||||
|
|
||||||
|
Bug #7181 -- ordering by related tables should accomodate nullable fields (this
|
||||||
|
test is a little tricky, since NULL ordering is database dependent. Instead, we
|
||||||
|
just count the number of results).
|
||||||
|
>>> len(Tag.objects.order_by('parent__name'))
|
||||||
|
5
|
||||||
|
|
||||||
|
Bug #7107 -- this shouldn't create an infinite loop.
|
||||||
|
>>> Valid.objects.all()
|
||||||
|
[]
|
||||||
|
|
||||||
|
Empty querysets can be merged with others.
|
||||||
|
>>> Note.objects.none() | Note.objects.all()
|
||||||
|
[<Note: n1>, <Note: n2>, <Note: n3>]
|
||||||
|
>>> Note.objects.all() | Note.objects.none()
|
||||||
|
[<Note: n1>, <Note: n2>, <Note: n3>]
|
||||||
|
>>> Note.objects.none() & Note.objects.all()
|
||||||
|
[]
|
||||||
|
>>> Note.objects.all() & Note.objects.none()
|
||||||
|
[]
|
||||||
|
|
||||||
"""}
|
"""}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
"""
|
"""
|
||||||
Test cases for the template loaders
|
Test cases for the template loaders
|
||||||
|
|
||||||
|
Note: This test requires setuptools!
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -17,7 +18,7 @@ import StringIO
|
|||||||
from django.template import TemplateDoesNotExist
|
from django.template import TemplateDoesNotExist
|
||||||
from django.template.loaders.eggs import load_template_source as lts_egg
|
from django.template.loaders.eggs import load_template_source as lts_egg
|
||||||
|
|
||||||
#Mock classes and objects for pkg_resources functions
|
# Mock classes and objects for pkg_resources functions.
|
||||||
class MockProvider(pkg_resources.NullProvider):
|
class MockProvider(pkg_resources.NullProvider):
|
||||||
def __init__(self, module):
|
def __init__(self, module):
|
||||||
pkg_resources.NullProvider.__init__(self, module)
|
pkg_resources.NullProvider.__init__(self, module)
|
||||||
@ -35,13 +36,14 @@ class MockProvider(pkg_resources.NullProvider):
|
|||||||
def _get(self, path):
|
def _get(self, path):
|
||||||
return self.module._resources[path].read()
|
return self.module._resources[path].read()
|
||||||
|
|
||||||
class MockLoader(object): pass
|
class MockLoader(object):
|
||||||
|
pass
|
||||||
|
|
||||||
def create_egg(name, resources):
|
def create_egg(name, resources):
|
||||||
"""
|
"""
|
||||||
Creates a mock egg with a list of resources
|
Creates a mock egg with a list of resources.
|
||||||
|
|
||||||
name: The name of the module
|
name: The name of the module.
|
||||||
resources: A dictionary of resources. Keys are the names and values the the data.
|
resources: A dictionary of resources. Keys are the names and values the the data.
|
||||||
"""
|
"""
|
||||||
egg = imp.new_module(name)
|
egg = imp.new_module(name)
|
||||||
@ -49,7 +51,6 @@ def create_egg(name, resources):
|
|||||||
egg._resources = resources
|
egg._resources = resources
|
||||||
sys.modules[name] = egg
|
sys.modules[name] = egg
|
||||||
|
|
||||||
|
|
||||||
class EggLoader(unittest.TestCase):
|
class EggLoader(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
pkg_resources._provider_factories[MockLoader] = MockProvider
|
pkg_resources._provider_factories[MockLoader] = MockProvider
|
||||||
@ -87,6 +88,5 @@ class EggLoader(unittest.TestCase):
|
|||||||
settings.INSTALLED_APPS = []
|
settings.INSTALLED_APPS = []
|
||||||
self.assertRaises(TemplateDoesNotExist, lts_egg, "y.html")
|
self.assertRaises(TemplateDoesNotExist, lts_egg, "y.html")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -20,7 +20,10 @@ from django.utils.tzinfo import LocalTimezone
|
|||||||
from unicode import unicode_tests
|
from unicode import unicode_tests
|
||||||
from context import context_tests
|
from context import context_tests
|
||||||
|
|
||||||
|
try:
|
||||||
from loaders import *
|
from loaders import *
|
||||||
|
except ImportError:
|
||||||
|
pass # If setuptools isn't installed, that's fine. Just move on.
|
||||||
|
|
||||||
import filters
|
import filters
|
||||||
|
|
||||||
@ -132,8 +135,7 @@ class Templates(unittest.TestCase):
|
|||||||
|
|
||||||
# Quickly check that we aren't accidentally using a name in both
|
# Quickly check that we aren't accidentally using a name in both
|
||||||
# template and filter tests.
|
# template and filter tests.
|
||||||
overlapping_names = [name for name in filter_tests if name in
|
overlapping_names = [name for name in filter_tests if name in template_tests]
|
||||||
template_tests]
|
|
||||||
assert not overlapping_names, 'Duplicate test name(s): %s' % ', '.join(overlapping_names)
|
assert not overlapping_names, 'Duplicate test name(s): %s' % ', '.join(overlapping_names)
|
||||||
|
|
||||||
template_tests.update(filter_tests)
|
template_tests.update(filter_tests)
|
||||||
@ -156,7 +158,7 @@ class Templates(unittest.TestCase):
|
|||||||
# Turn TEMPLATE_DEBUG off, because tests assume that.
|
# Turn TEMPLATE_DEBUG off, because tests assume that.
|
||||||
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
|
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
|
||||||
|
|
||||||
# Set TEMPLATE_STRING_IF_INVALID to a known string
|
# Set TEMPLATE_STRING_IF_INVALID to a known string.
|
||||||
old_invalid = settings.TEMPLATE_STRING_IF_INVALID
|
old_invalid = settings.TEMPLATE_STRING_IF_INVALID
|
||||||
expected_invalid_str = 'INVALID'
|
expected_invalid_str = 'INVALID'
|
||||||
|
|
||||||
@ -546,6 +548,7 @@ class Templates(unittest.TestCase):
|
|||||||
'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'),
|
'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'),
|
||||||
'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'),
|
'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'),
|
||||||
'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'),
|
'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', {'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'),
|
||||||
|
'ifchanged08': ('{% for data in datalist %}{% for c,d in data %}{% if c %}{% ifchanged %}{{ d }}{% endifchanged %}{% endif %}{% endfor %}{% endfor %}', {'datalist': [[(1, 'a'), (1, 'a'), (0, 'b'), (1, 'c')], [(0, 'a'), (1, 'c'), (1, 'd'), (1, 'd'), (0, 'e')]]}, 'accd'),
|
||||||
|
|
||||||
# Test one parameter given to ifchanged.
|
# Test one parameter given to ifchanged.
|
||||||
'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),
|
'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),
|
||||||
@ -873,8 +876,7 @@ class Templates(unittest.TestCase):
|
|||||||
'url02': ('{% url regressiontests.templates.views.client_action client.id, action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
|
'url02': ('{% url regressiontests.templates.views.client_action client.id, action="update" %}', {'client': {'id': 1}}, '/url_tag/client/1/update/'),
|
||||||
'url03': ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
|
'url03': ('{% url regressiontests.templates.views.index %}', {}, '/url_tag/'),
|
||||||
'url04': ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
|
'url04': ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
|
||||||
'url05' : (u'{% url метка_оператора v %}', {'v': u'Ω'},
|
'url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
|
||||||
'/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
|
|
||||||
|
|
||||||
# Failures
|
# Failures
|
||||||
'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
|
'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
|
||||||
@ -888,12 +890,19 @@ class Templates(unittest.TestCase):
|
|||||||
'cache04': ('{% load cache %}{% cache 2 test %}cache04{% endcache %}', {}, 'cache03'),
|
'cache04': ('{% load cache %}{% cache 2 test %}cache04{% endcache %}', {}, 'cache03'),
|
||||||
'cache05': ('{% load cache %}{% cache 2 test foo %}cache05{% endcache %}', {'foo': 1}, 'cache05'),
|
'cache05': ('{% load cache %}{% cache 2 test foo %}cache05{% endcache %}', {'foo': 1}, 'cache05'),
|
||||||
'cache06': ('{% load cache %}{% cache 2 test foo %}cache06{% endcache %}', {'foo': 2}, 'cache06'),
|
'cache06': ('{% load cache %}{% cache 2 test foo %}cache06{% endcache %}', {'foo': 2}, 'cache06'),
|
||||||
'cache07' : ('{% load cache %}{% cache 2 test foo %}cache06{% endcache %}', {'foo': 1}, 'cache05'),
|
'cache07': ('{% load cache %}{% cache 2 test foo %}cache07{% endcache %}', {'foo': 1}, 'cache05'),
|
||||||
|
|
||||||
# Raise exception if we dont have at least 2 args, first one integer.
|
# Allow first argument to be a variable.
|
||||||
'cache08' : ('{% load cache %}{% cache %}{% endcache %}', {}, template.TemplateSyntaxError),
|
'cache08': ('{% load cache %}{% cache time test foo %}cache08{% endcache %}', {'foo': 2, 'time': 2}, 'cache06'),
|
||||||
'cache09' : ('{% load cache %}{% cache 1 %}{% endcache %}', {}, template.TemplateSyntaxError),
|
'cache09': ('{% load cache %}{% cache time test foo %}cache09{% endcache %}', {'foo': 3, 'time': -1}, 'cache09'),
|
||||||
'cache10' : ('{% load cache %}{% cache foo bar %}{% endcache %}', {}, template.TemplateSyntaxError),
|
'cache10': ('{% load cache %}{% cache time test foo %}cache10{% endcache %}', {'foo': 3, 'time': -1}, 'cache10'),
|
||||||
|
|
||||||
|
# Raise exception if we don't have at least 2 args, first one integer.
|
||||||
|
'cache11': ('{% load cache %}{% cache %}{% endcache %}', {}, template.TemplateSyntaxError),
|
||||||
|
'cache12': ('{% load cache %}{% cache 1 %}{% endcache %}', {}, template.TemplateSyntaxError),
|
||||||
|
'cache13': ('{% load cache %}{% cache foo bar %}{% endcache %}', {}, template.TemplateSyntaxError),
|
||||||
|
'cache14': ('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': 'fail'}, template.TemplateSyntaxError),
|
||||||
|
'cache15': ('{% load cache %}{% cache foo bar %}{% endcache %}', {'foo': []}, template.TemplateSyntaxError),
|
||||||
|
|
||||||
### AUTOESCAPE TAG ##############################################
|
### AUTOESCAPE TAG ##############################################
|
||||||
'autoescape-tag01': ("{% autoescape off %}hello{% endautoescape %}", {}, "hello"),
|
'autoescape-tag01': ("{% autoescape off %}hello{% endautoescape %}", {}, "hello"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user