mirror of
https://github.com/django/django.git
synced 2025-07-03 17:29:12 +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>
|
||||
Filip Wasilewski <filip.wasilewski@gmail.com>
|
||||
Dan Watson <http://theidioteque.net/>
|
||||
Joel Watts <joel@joelwatts.com>
|
||||
Chris Wesseling <Chris.Wesseling@cwi.nl>
|
||||
James Wheare <django@sparemint.com>
|
||||
charly.wilhelm@gmail.com
|
||||
|
Binary file not shown.
@ -5,9 +5,9 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Django\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"
|
||||
"Last-Translator: Piotr Lewandowski <django@icomputing.pl>\n"
|
||||
"Last-Translator: Jarek Zgoda <jarek.zgoda@gmail.com>\n"
|
||||
"Language-Team: Polish <pl@li.org>\n"
|
||||
"MIME-Version: 1.0\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%"
|
||||
"100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
|
||||
#: conf/global_settings.py:39
|
||||
#: conf/global_settings.py:44
|
||||
msgid "Arabic"
|
||||
msgstr "Arabski"
|
||||
|
||||
#: conf/global_settings.py:40
|
||||
#: conf/global_settings.py:45
|
||||
msgid "Bengali"
|
||||
msgstr "Bengalski"
|
||||
|
||||
#: conf/global_settings.py:41
|
||||
#: conf/global_settings.py:46
|
||||
msgid "Bulgarian"
|
||||
msgstr "Bułgarski"
|
||||
|
||||
#: conf/global_settings.py:42
|
||||
#: conf/global_settings.py:47
|
||||
msgid "Catalan"
|
||||
msgstr "Kataloński"
|
||||
|
||||
#: conf/global_settings.py:43
|
||||
#: conf/global_settings.py:48
|
||||
msgid "Czech"
|
||||
msgstr "Czeski"
|
||||
|
||||
#: conf/global_settings.py:44
|
||||
#: conf/global_settings.py:49
|
||||
msgid "Welsh"
|
||||
msgstr "Walijski"
|
||||
|
||||
#: conf/global_settings.py:45
|
||||
#: conf/global_settings.py:50
|
||||
msgid "Danish"
|
||||
msgstr "Duński"
|
||||
|
||||
#: conf/global_settings.py:46
|
||||
#: conf/global_settings.py:51
|
||||
msgid "German"
|
||||
msgstr "Niemiecki"
|
||||
|
||||
#: conf/global_settings.py:47
|
||||
#: conf/global_settings.py:52
|
||||
msgid "Greek"
|
||||
msgstr "Grecki"
|
||||
|
||||
#: conf/global_settings.py:48
|
||||
#: conf/global_settings.py:53
|
||||
msgid "English"
|
||||
msgstr "Angielski"
|
||||
|
||||
#: conf/global_settings.py:49
|
||||
#: conf/global_settings.py:54
|
||||
msgid "Spanish"
|
||||
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"
|
||||
msgstr "Hiszpański argentyński"
|
||||
|
||||
#: conf/global_settings.py:51
|
||||
#: conf/global_settings.py:57
|
||||
msgid "Basque"
|
||||
msgstr "Baskijski"
|
||||
|
||||
#: conf/global_settings.py:52
|
||||
#: conf/global_settings.py:58
|
||||
msgid "Persian"
|
||||
msgstr "Perski"
|
||||
|
||||
#: conf/global_settings.py:53
|
||||
#: conf/global_settings.py:59
|
||||
msgid "Finnish"
|
||||
msgstr "Fiński"
|
||||
|
||||
#: conf/global_settings.py:54
|
||||
#: conf/global_settings.py:60
|
||||
msgid "French"
|
||||
msgstr "Francuski"
|
||||
|
||||
#: conf/global_settings.py:55
|
||||
#: conf/global_settings.py:61
|
||||
msgid "Irish"
|
||||
msgstr "Irlandzki"
|
||||
|
||||
#: conf/global_settings.py:56
|
||||
#: conf/global_settings.py:62
|
||||
msgid "Galician"
|
||||
msgstr "Galicyjski"
|
||||
|
||||
#: conf/global_settings.py:57
|
||||
#: conf/global_settings.py:63
|
||||
msgid "Hungarian"
|
||||
msgstr "Węgierski"
|
||||
|
||||
#: conf/global_settings.py:58
|
||||
#: conf/global_settings.py:64
|
||||
msgid "Hebrew"
|
||||
msgstr "Hebrajski"
|
||||
|
||||
#: conf/global_settings.py:59
|
||||
#: conf/global_settings.py:65
|
||||
msgid "Croatian"
|
||||
msgstr "Chorwacki"
|
||||
|
||||
#: conf/global_settings.py:60
|
||||
#: conf/global_settings.py:66
|
||||
msgid "Icelandic"
|
||||
msgstr "Islandzki"
|
||||
|
||||
#: conf/global_settings.py:61
|
||||
#: conf/global_settings.py:67
|
||||
msgid "Italian"
|
||||
msgstr "Włoski"
|
||||
|
||||
#: conf/global_settings.py:62
|
||||
#: conf/global_settings.py:68
|
||||
msgid "Japanese"
|
||||
msgstr "Japoński"
|
||||
|
||||
#: conf/global_settings.py:63
|
||||
#: conf/global_settings.py:69
|
||||
msgid "Georgian"
|
||||
msgstr "Gruziński"
|
||||
|
||||
#: conf/global_settings.py:64
|
||||
#: conf/global_settings.py:70
|
||||
msgid "Korean"
|
||||
msgstr "Koreański"
|
||||
|
||||
#: conf/global_settings.py:65
|
||||
#: conf/global_settings.py:71
|
||||
msgid "Khmer"
|
||||
msgstr "Khmerski"
|
||||
|
||||
#: conf/global_settings.py:66
|
||||
#: conf/global_settings.py:72
|
||||
msgid "Kannada"
|
||||
msgstr "Kannada"
|
||||
|
||||
#: conf/global_settings.py:67
|
||||
#: conf/global_settings.py:73
|
||||
msgid "Latvian"
|
||||
msgstr "Łotewski"
|
||||
|
||||
#: conf/global_settings.py:68
|
||||
#: conf/global_settings.py:74
|
||||
msgid "Lithuanian"
|
||||
msgstr "Litewski"
|
||||
|
||||
#: conf/global_settings.py:75
|
||||
msgid "Macedonian"
|
||||
msgstr "Macedoński"
|
||||
|
||||
#: conf/global_settings.py:69
|
||||
#: conf/global_settings.py:76
|
||||
msgid "Dutch"
|
||||
msgstr "Holenderski"
|
||||
|
||||
#: conf/global_settings.py:70
|
||||
#: conf/global_settings.py:77
|
||||
msgid "Norwegian"
|
||||
msgstr "Norweski"
|
||||
|
||||
#: conf/global_settings.py:71
|
||||
#: conf/global_settings.py:78
|
||||
msgid "Polish"
|
||||
msgstr "Polski"
|
||||
|
||||
#: conf/global_settings.py:72
|
||||
#: conf/global_settings.py:79
|
||||
msgid "Portugese"
|
||||
msgstr "Portugalski"
|
||||
|
||||
#: conf/global_settings.py:73
|
||||
#: conf/global_settings.py:80
|
||||
msgid "Brazilian Portuguese"
|
||||
msgstr "Brazylijski portugalski"
|
||||
|
||||
#: conf/global_settings.py:74
|
||||
#: conf/global_settings.py:81
|
||||
msgid "Romanian"
|
||||
msgstr "Rumuński"
|
||||
|
||||
#: conf/global_settings.py:75
|
||||
#: conf/global_settings.py:82
|
||||
msgid "Russian"
|
||||
msgstr "Rosyjski"
|
||||
|
||||
#: conf/global_settings.py:76
|
||||
#: conf/global_settings.py:83
|
||||
msgid "Slovak"
|
||||
msgstr "Słowacki"
|
||||
|
||||
#: conf/global_settings.py:77
|
||||
#: conf/global_settings.py:84
|
||||
msgid "Slovenian"
|
||||
msgstr "Słoweński"
|
||||
|
||||
#: conf/global_settings.py:78
|
||||
#: conf/global_settings.py:85
|
||||
msgid "Serbian"
|
||||
msgstr "Serbski"
|
||||
|
||||
#: conf/global_settings.py:79
|
||||
#: conf/global_settings.py:86
|
||||
msgid "Swedish"
|
||||
msgstr "Szwedzki"
|
||||
|
||||
#: conf/global_settings.py:80
|
||||
#: conf/global_settings.py:87
|
||||
msgid "Tamil"
|
||||
msgstr "Tamilski"
|
||||
|
||||
#: conf/global_settings.py:81
|
||||
#: conf/global_settings.py:88
|
||||
msgid "Telugu"
|
||||
msgstr "Telugu"
|
||||
|
||||
#: conf/global_settings.py:82
|
||||
#: conf/global_settings.py:89
|
||||
msgid "Turkish"
|
||||
msgstr "Turecki"
|
||||
|
||||
#: conf/global_settings.py:83
|
||||
#: conf/global_settings.py:90
|
||||
msgid "Ukrainian"
|
||||
msgstr "Ukraiński"
|
||||
|
||||
#: conf/global_settings.py:84
|
||||
#: conf/global_settings.py:91
|
||||
msgid "Simplified Chinese"
|
||||
msgstr "Uproszczony chiński"
|
||||
|
||||
#: conf/global_settings.py:85
|
||||
#: conf/global_settings.py:92
|
||||
msgid "Traditional Chinese"
|
||||
msgstr "Chiński tradycyjny"
|
||||
|
||||
@ -417,7 +425,7 @@ msgstr ""
|
||||
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:25
|
||||
msgid "Yes, I'm sure"
|
||||
msgstr "Tak, usuń"
|
||||
msgstr "Tak, na pewno"
|
||||
|
||||
#: contrib/admin/templates/admin/filter.html:2
|
||||
#, python-format
|
||||
@ -824,15 +832,15 @@ msgstr ""
|
||||
"Twoja przeglądarka nie chce akceptować ciasteczek. Zmień jej ustawienia i "
|
||||
"spróbuj ponownie."
|
||||
|
||||
#: contrib/admin/views/decorators.py:90
|
||||
msgid "Usernames cannot contain the '@' character."
|
||||
msgstr "Nazwy użytkowników nie mogą zawierać znaków '@'."
|
||||
|
||||
#: contrib/admin/views/decorators.py:92
|
||||
#: contrib/admin/views/decorators.py:89
|
||||
#, python-format
|
||||
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'."
|
||||
|
||||
#: 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:52
|
||||
msgid "tag:"
|
||||
@ -1063,7 +1071,7 @@ msgstr "Zaznacz %s"
|
||||
msgid "Select %s to change"
|
||||
msgstr "Zaznacz %s aby zmienić"
|
||||
|
||||
#: contrib/admin/views/main.py:784
|
||||
#: contrib/admin/views/main.py:765
|
||||
msgid "Database error"
|
||||
msgstr "Błąd bazy danych"
|
||||
|
||||
@ -1128,15 +1136,15 @@ msgstr "uprawnienia"
|
||||
msgid "group"
|
||||
msgstr "grupa"
|
||||
|
||||
#: contrib/auth/models.py:98 contrib/auth/models.py:141
|
||||
#: contrib/auth/models.py:98 contrib/auth/models.py:148
|
||||
msgid "groups"
|
||||
msgstr "grupy"
|
||||
|
||||
#: contrib/auth/models.py:131
|
||||
#: contrib/auth/models.py:138
|
||||
msgid "username"
|
||||
msgstr "użytkownik"
|
||||
|
||||
#: contrib/auth/models.py:131
|
||||
#: contrib/auth/models.py:138
|
||||
msgid ""
|
||||
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
||||
"digits and underscores)."
|
||||
@ -1144,23 +1152,23 @@ msgstr ""
|
||||
"Wymagane. 30 znaków lub mniej. Tylko znaki alfanumeryczne (litery, cyfry i "
|
||||
"podkreślenia)."
|
||||
|
||||
#: contrib/auth/models.py:132
|
||||
#: contrib/auth/models.py:139
|
||||
msgid "first name"
|
||||
msgstr "Imię"
|
||||
|
||||
#: contrib/auth/models.py:133
|
||||
#: contrib/auth/models.py:140
|
||||
msgid "last name"
|
||||
msgstr "Nazwisko"
|
||||
|
||||
#: contrib/auth/models.py:134
|
||||
#: contrib/auth/models.py:141
|
||||
msgid "e-mail address"
|
||||
msgstr "adres e-mail"
|
||||
|
||||
#: contrib/auth/models.py:135
|
||||
#: contrib/auth/models.py:142
|
||||
msgid "password"
|
||||
msgstr "hasło"
|
||||
|
||||
#: contrib/auth/models.py:135
|
||||
#: contrib/auth/models.py:142
|
||||
msgid ""
|
||||
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
|
||||
"password form</a>."
|
||||
@ -1168,19 +1176,19 @@ msgstr ""
|
||||
"Użyj '[algo]$[salt]$[hexdigest]' lub <a href=\"password/\">formularza zmiany "
|
||||
"hasła</a>."
|
||||
|
||||
#: contrib/auth/models.py:136
|
||||
#: contrib/auth/models.py:143
|
||||
msgid "staff status"
|
||||
msgstr "w zespole"
|
||||
|
||||
#: contrib/auth/models.py:136
|
||||
#: contrib/auth/models.py:143
|
||||
msgid "Designates whether the user can log into this admin site."
|
||||
msgstr "Oznacza czy użytkownik może zalogować się do panelu admina."
|
||||
|
||||
#: contrib/auth/models.py:137
|
||||
#: contrib/auth/models.py:144
|
||||
msgid "active"
|
||||
msgstr "aktywny"
|
||||
|
||||
#: contrib/auth/models.py:137
|
||||
#: contrib/auth/models.py:144
|
||||
msgid ""
|
||||
"Designates whether this user should be treated as active. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
@ -1188,11 +1196,11 @@ msgstr ""
|
||||
"Oznacza czy użytkownika należy uważać za aktywnego. Odznacz tozamiast usuwać "
|
||||
"konta."
|
||||
|
||||
#: contrib/auth/models.py:138
|
||||
#: contrib/auth/models.py:145
|
||||
msgid "superuser status"
|
||||
msgstr "Główny Administrator"
|
||||
|
||||
#: contrib/auth/models.py:138
|
||||
#: contrib/auth/models.py:145
|
||||
msgid ""
|
||||
"Designates that this user has all permissions without explicitly assigning "
|
||||
"them."
|
||||
@ -1200,15 +1208,15 @@ msgstr ""
|
||||
"Oznacza, że ten użytkownik ma wszystkie uprawnienia bez jawnego "
|
||||
"przypisywania ich."
|
||||
|
||||
#: contrib/auth/models.py:139
|
||||
#: contrib/auth/models.py:146
|
||||
msgid "last login"
|
||||
msgstr "ostatnio zalogowany"
|
||||
|
||||
#: contrib/auth/models.py:140
|
||||
#: contrib/auth/models.py:147
|
||||
msgid "date joined"
|
||||
msgstr "data przyłączenia"
|
||||
|
||||
#: contrib/auth/models.py:142
|
||||
#: contrib/auth/models.py:149
|
||||
msgid ""
|
||||
"In addition to the permissions manually assigned, this user will also get "
|
||||
"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 "
|
||||
"uprawnienia grup, do których należy."
|
||||
|
||||
#: contrib/auth/models.py:143
|
||||
#: contrib/auth/models.py:150
|
||||
msgid "user permissions"
|
||||
msgstr "uprawnienia użytkownika"
|
||||
|
||||
#: contrib/auth/models.py:147
|
||||
#: contrib/auth/models.py:154
|
||||
msgid "user"
|
||||
msgstr "użytkownik"
|
||||
|
||||
#: contrib/auth/models.py:148
|
||||
#: contrib/auth/models.py:155
|
||||
msgid "users"
|
||||
msgstr "użytkownicy"
|
||||
|
||||
#: contrib/auth/models.py:154
|
||||
#: contrib/auth/models.py:161
|
||||
msgid "Personal info"
|
||||
msgstr "Dane osobowe"
|
||||
|
||||
#: contrib/auth/models.py:155
|
||||
#: contrib/auth/models.py:162
|
||||
msgid "Permissions"
|
||||
msgstr "Uprawnienia"
|
||||
|
||||
#: contrib/auth/models.py:156
|
||||
#: contrib/auth/models.py:163
|
||||
msgid "Important dates"
|
||||
msgstr "Ważne daty"
|
||||
|
||||
#: contrib/auth/models.py:157
|
||||
#: contrib/auth/models.py:164
|
||||
msgid "Groups"
|
||||
msgstr "Grupy"
|
||||
|
||||
#: contrib/auth/models.py:316
|
||||
#: contrib/auth/models.py:323
|
||||
msgid "message"
|
||||
msgstr "wiadomość"
|
||||
|
||||
#: contrib/auth/views.py:47
|
||||
#: contrib/auth/views.py:48
|
||||
msgid "Logged out"
|
||||
msgstr "Wylogowany"
|
||||
|
||||
@ -3516,23 +3524,23 @@ msgstr "przekieruj"
|
||||
msgid "redirects"
|
||||
msgstr "przekierowania"
|
||||
|
||||
#: contrib/sessions/models.py:41
|
||||
#: contrib/sessions/models.py:45
|
||||
msgid "session key"
|
||||
msgstr "klucz sesji"
|
||||
|
||||
#: contrib/sessions/models.py:42
|
||||
#: contrib/sessions/models.py:47
|
||||
msgid "session data"
|
||||
msgstr "data sesji"
|
||||
|
||||
#: contrib/sessions/models.py:43
|
||||
#: contrib/sessions/models.py:48
|
||||
msgid "expire date"
|
||||
msgstr "data wygaśnięcia sesji"
|
||||
|
||||
#: contrib/sessions/models.py:48
|
||||
#: contrib/sessions/models.py:53
|
||||
msgid "session"
|
||||
msgstr "sesja"
|
||||
|
||||
#: contrib/sessions/models.py:49
|
||||
#: contrib/sessions/models.py:54
|
||||
msgid "sessions"
|
||||
msgstr "sesje"
|
||||
|
||||
@ -3617,7 +3625,7 @@ msgstr "Rok nie może być wcześniejszy niż 1900."
|
||||
msgid "Invalid date: %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."
|
||||
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."
|
||||
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."
|
||||
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."
|
||||
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
|
||||
msgid "%(optname)s with this %(fieldname)s already exists."
|
||||
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:759 db/models/fields/__init__.py:770
|
||||
#: db/models/fields/__init__.py:176 db/models/fields/__init__.py:348
|
||||
#: db/models/fields/__init__.py:780 db/models/fields/__init__.py:791
|
||||
#: newforms/fields.py:46 oldforms/__init__.py:374
|
||||
msgid "This field is required."
|
||||
msgstr "To pole jest wymagane."
|
||||
|
||||
#: db/models/fields/__init__.py:427
|
||||
#: db/models/fields/__init__.py:448
|
||||
msgid "This value must be an integer."
|
||||
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."
|
||||
msgstr ""
|
||||
"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."
|
||||
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."
|
||||
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."
|
||||
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."
|
||||
msgstr ""
|
||||
"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
|
||||
msgid "Please enter a valid %s."
|
||||
msgstr "Proszę wpisać poprawne %s."
|
||||
|
||||
#: db/models/fields/related.py:701
|
||||
#: db/models/fields/related.py:746
|
||||
msgid "Separate multiple IDs with commas."
|
||||
msgstr "Oddziel identyfikatory przecinkami."
|
||||
|
||||
#: db/models/fields/related.py:703
|
||||
#: db/models/fields/related.py:748
|
||||
msgid ""
|
||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr ""
|
||||
"Przytrzymaj wciśnięty klawisz \"Ctrl\" lub \"Command\" na Mac'u aby "
|
||||
"zaznaczyć więcej niż jeden wybór."
|
||||
|
||||
#: db/models/fields/related.py:750
|
||||
#: db/models/fields/related.py:795
|
||||
#, python-format
|
||||
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
||||
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."
|
||||
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."
|
||||
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."
|
||||
msgstr "Wpisz poprawną godzinę."
|
||||
|
||||
@ -4031,25 +4039,25 @@ msgstr "Wpisz poprawny URL."
|
||||
msgid "This URL appears to be a broken link."
|
||||
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."
|
||||
msgstr "Wybierz poprawną wartość. Podana nie jest jednym z dostępnych wyborów."
|
||||
|
||||
#: newforms/fields.py:599
|
||||
#: newforms/fields.py:598
|
||||
#, python-format
|
||||
msgid "Select a valid choice. %(value)s is not one of the available choices."
|
||||
msgstr ""
|
||||
"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."
|
||||
msgstr "Podaj listę wartości."
|
||||
|
||||
#: newforms/fields.py:780
|
||||
#: newforms/fields.py:779
|
||||
msgid "Enter a valid IPv4 address."
|
||||
msgstr "Wprowadź poprawny adres IPv4."
|
||||
|
||||
#: newforms/models.py:372
|
||||
#: newforms/models.py:373
|
||||
#, python-format
|
||||
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."
|
||||
|
@ -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 PasswordResetForm, PasswordChangeForm, AdminPasswordChangeForm
|
||||
from django.core.exceptions import PermissionDenied
|
||||
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.http import HttpResponseRedirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||
from django.template import RequestContext
|
||||
from django.utils.http import urlquote
|
||||
from django.utils.html import escape
|
||||
from django.utils.translation import ugettext as _
|
||||
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:
|
||||
from django.conf import settings
|
||||
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',
|
||||
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:
|
||||
form.save(domain_override=request.META['HTTP_HOST'])
|
||||
else:
|
||||
if Site._meta.installed:
|
||||
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)
|
||||
else:
|
||||
form = password_reset_form()
|
||||
|
@ -2,8 +2,8 @@
|
||||
>>> # Make sure that get_current() does not return a deleted Site object.
|
||||
>>> from django.contrib.sites.models import Site
|
||||
>>> s = Site.objects.get_current()
|
||||
>>> s
|
||||
<Site: example.com>
|
||||
>>> isinstance(s, Site)
|
||||
True
|
||||
|
||||
>>> s.delete()
|
||||
>>> Site.objects.get_current()
|
||||
|
@ -17,7 +17,7 @@ import urllib
|
||||
from django.utils.http import http_date
|
||||
|
||||
__version__ = "0.1"
|
||||
__all__ = ['WSGIServer','WSGIRequestHandler','demo_app']
|
||||
__all__ = ['WSGIServer','WSGIRequestHandler']
|
||||
|
||||
server_version = "WSGIServer/" + __version__
|
||||
sys_version = "Python/" + sys.version.split()[0]
|
||||
|
@ -45,7 +45,6 @@ class BaseDatabaseFeatures(object):
|
||||
autoindexes_primary_keys = True
|
||||
inline_fk_references = True
|
||||
needs_datetime_string_cast = True
|
||||
needs_upper_for_iops = False
|
||||
supports_constraints = True
|
||||
supports_tablespaces = 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)
|
||||
empty_fetchmany_value = ()
|
||||
needs_datetime_string_cast = False
|
||||
needs_upper_for_iops = True
|
||||
supports_tablespaces = True
|
||||
uses_case_insensitive_names = 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
|
||||
# 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.
|
||||
#
|
||||
# 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 = {
|
||||
'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)',
|
||||
'CommaSeparatedIntegerField': 'VARCHAR2(%(max_length)s)',
|
||||
'DateField': 'DATE',
|
||||
@ -19,11 +23,11 @@ DATA_TYPES = {
|
||||
'ImageField': 'NVARCHAR2(%(max_length)s)',
|
||||
'IntegerField': 'NUMBER(11)',
|
||||
'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)',
|
||||
'PhoneNumberField': 'VARCHAR2(20)',
|
||||
'PositiveIntegerField': 'NUMBER(11) CHECK (%(column)s >= 0)',
|
||||
'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(column)s >= 0)',
|
||||
'PositiveIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)',
|
||||
'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(qn_column)s >= 0)',
|
||||
'SlugField': 'NVARCHAR2(50)',
|
||||
'SmallIntegerField': 'NUMBER(11)',
|
||||
'TextField': 'NCLOB',
|
||||
|
@ -16,6 +16,7 @@ from django.core import validators
|
||||
from django import oldforms
|
||||
from django import newforms as forms
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.utils.datastructures import DictWrapper
|
||||
from django.utils.functional import curry
|
||||
from django.utils.itercompat import tee
|
||||
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
|
||||
# can implement db_type() instead of get_internal_type() to specify
|
||||
# exactly which wacky database column type you want to use.
|
||||
data = DictWrapper(self.__dict__, connection.ops.quote_name, "qn_")
|
||||
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:
|
||||
return None
|
||||
|
||||
|
@ -103,13 +103,15 @@ class RelatedField(object):
|
||||
|
||||
if hasattr(sup, 'contribute_to_class'):
|
||||
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
|
||||
if isinstance(other, basestring):
|
||||
add_lazy_relation(cls, self, other)
|
||||
else:
|
||||
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):
|
||||
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):
|
||||
self.set_attributes_from_rel()
|
||||
related = RelatedObject(other, cls, self)
|
||||
if not cls._meta.abstract:
|
||||
self.contribute_to_related_class(other, related)
|
||||
|
||||
def get_db_prep_lookup(self, lookup_type, value):
|
||||
|
@ -273,14 +273,17 @@ class Options(object):
|
||||
"""
|
||||
Initialises the field name -> field object mapping.
|
||||
"""
|
||||
cache = dict([(f.name, (f, m, True, False)) for f, m in
|
||||
self.get_fields_with_model()])
|
||||
for f, model in self.get_m2m_with_model():
|
||||
cache[f.name] = (f, model, True, True)
|
||||
cache = {}
|
||||
# We intentionally handle related m2m objects first so that symmetrical
|
||||
# m2m accessor names can be overridden, if necessary.
|
||||
for f, model in self.get_all_related_m2m_objects_with_model():
|
||||
cache[f.field.related_query_name()] = (f, model, False, True)
|
||||
for f, model in self.get_all_related_objects_with_model():
|
||||
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:
|
||||
cache['_order'] = OrderWrt(), None, True, False
|
||||
if app_cache_ready():
|
||||
|
@ -218,6 +218,8 @@ class QuerySet(object):
|
||||
|
||||
def __and__(self, other):
|
||||
self._merge_sanity_check(other)
|
||||
if isinstance(other, EmptyQuerySet):
|
||||
return other._clone()
|
||||
combined = self._clone()
|
||||
combined.query.combine(other.query, sql.AND)
|
||||
return combined
|
||||
@ -225,6 +227,8 @@ class QuerySet(object):
|
||||
def __or__(self, other):
|
||||
self._merge_sanity_check(other)
|
||||
combined = self._clone()
|
||||
if isinstance(other, EmptyQuerySet):
|
||||
return combined
|
||||
combined.query.combine(other.query, sql.OR)
|
||||
return combined
|
||||
|
||||
@ -488,7 +492,9 @@ class QuerySet(object):
|
||||
and usually it will be more natural to use other methods.
|
||||
"""
|
||||
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:
|
||||
return self._filter_or_exclude(None, **filter_obj)
|
||||
|
||||
@ -583,11 +589,11 @@ class QuerySet(object):
|
||||
|
||||
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__:
|
||||
raise TypeError("Cannot merge querysets of different types ('%s' and '%s'."
|
||||
% (self.__class__.__name__, other.__class__.__name__))
|
||||
pass
|
||||
|
||||
class ValuesQuerySet(QuerySet):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -688,9 +694,9 @@ class DateQuerySet(QuerySet):
|
||||
"""
|
||||
self.query = self.query.clone(klass=sql.DateQuery, setup=True)
|
||||
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:
|
||||
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):
|
||||
c = super(DateQuerySet, self)._clone(klass, False, **kwargs)
|
||||
@ -705,6 +711,12 @@ class EmptyQuerySet(QuerySet):
|
||||
super(EmptyQuerySet, self).__init__(model, query)
|
||||
self._result_cache = []
|
||||
|
||||
def __and__(self, other):
|
||||
return self._clone()
|
||||
|
||||
def __or__(self, other):
|
||||
return other._clone()
|
||||
|
||||
def count(self):
|
||||
return 0
|
||||
|
||||
|
@ -610,6 +610,10 @@ class Query(object):
|
||||
alias = joins[-1]
|
||||
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,
|
||||
# append the default ordering for that model.
|
||||
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
|
||||
# add_filter, since the final column might not otherwise be part of
|
||||
# the select set (so we can't order on it).
|
||||
while 1:
|
||||
join = self.alias_map[alias]
|
||||
if col == join[RHS_JOIN_COL]:
|
||||
if col != join[RHS_JOIN_COL]:
|
||||
break
|
||||
self.unref_alias(alias)
|
||||
alias = join[LHS_ALIAS]
|
||||
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
|
||||
False, the join is only promoted if it is nullable, otherwise it is
|
||||
always promoted.
|
||||
|
||||
Returns True if the join was promoted.
|
||||
"""
|
||||
if ((unconditional or self.alias_map[alias][NULLABLE]) and
|
||||
self.alias_map[alias] != self.LOUTER):
|
||||
data = list(self.alias_map[alias])
|
||||
data[JOIN_TYPE] = self.LOUTER
|
||||
self.alias_map[alias] = tuple(data)
|
||||
return True
|
||||
return False
|
||||
|
||||
def change_aliases(self, change_map):
|
||||
"""
|
||||
@ -826,6 +836,10 @@ class Query(object):
|
||||
if not always_create:
|
||||
for alias in self.join_map.get(t_ident, ()):
|
||||
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)
|
||||
if promote:
|
||||
self.promote_alias(alias)
|
||||
@ -985,13 +999,15 @@ class Query(object):
|
||||
col = target.column
|
||||
alias = join_list[-1]
|
||||
|
||||
if final > 1:
|
||||
while final > 1:
|
||||
# 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
|
||||
# chain and compare against the lhs of the join instead. The result
|
||||
# (potentially) involves one less table join.
|
||||
# chain and compare against the lhs of the join instead (and then
|
||||
# repeat the optimization). The result, potentially, involves less
|
||||
# table joins.
|
||||
join = self.alias_map[alias]
|
||||
if col == join[RHS_JOIN_COL]:
|
||||
if col != join[RHS_JOIN_COL]:
|
||||
break
|
||||
self.unref_alias(alias)
|
||||
alias = join[LHS_ALIAS]
|
||||
col = join[LHS_JOIN_COL]
|
||||
@ -1033,17 +1049,27 @@ class Query(object):
|
||||
self.promote_alias(table)
|
||||
|
||||
self.where.add((alias, col, field, lookup_type, value), connector)
|
||||
|
||||
if negate:
|
||||
for alias in join_list:
|
||||
self.promote_alias(alias)
|
||||
if final > 1 and lookup_type != 'isnull':
|
||||
if lookup_type != 'isnull':
|
||||
if final > 1:
|
||||
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]
|
||||
entry = Node([(alias, j_col, None, 'isnull', True)])
|
||||
entry.negate()
|
||||
self.where.add(entry, AND)
|
||||
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:
|
||||
can_reuse.update(join_list)
|
||||
|
||||
@ -1294,10 +1320,12 @@ class Query(object):
|
||||
final_alias = join[LHS_ALIAS]
|
||||
col = join[LHS_JOIN_COL]
|
||||
joins = joins[:-1]
|
||||
promote = False
|
||||
for join in joins[1:]:
|
||||
# Only nullable aliases are promoted, so we don't end up
|
||||
# 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_fields.append(field)
|
||||
except MultiJoin:
|
||||
|
@ -357,12 +357,14 @@ class DateQuery(Query):
|
||||
date = typecast_timestamp(str(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.
|
||||
"""
|
||||
alias = self.join((None, self.model._meta.db_table, None, None))
|
||||
select = Date((alias, column), lookup_type,
|
||||
result = self.setup_joins([field.name], self.get_meta(),
|
||||
self.get_initial_alias(), False)
|
||||
alias = result[3][-1]
|
||||
select = Date((alias, field.column), lookup_type,
|
||||
self.connection.ops.date_trunc_sql)
|
||||
self.select = [select]
|
||||
self.select_fields = [None]
|
||||
|
@ -39,12 +39,11 @@ class CommentNode(Node):
|
||||
|
||||
class CycleNode(Node):
|
||||
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
|
||||
|
||||
def render(self, context):
|
||||
value = self.cycle_iter.next()
|
||||
value = Variable(value).resolve(context)
|
||||
value = self.cycle_iter.next().resolve(context)
|
||||
if self.variable_name:
|
||||
context[self.variable_name] = value
|
||||
return value
|
||||
@ -162,10 +161,12 @@ class IfChangedNode(Node):
|
||||
self.nodelist = nodelist
|
||||
self._last_seen = None
|
||||
self._varlist = map(Variable, varlist)
|
||||
self._id = str(id(self))
|
||||
|
||||
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
|
||||
context['forloop'][self._id] = 1
|
||||
try:
|
||||
if self._varlist:
|
||||
# Consider multiple parameters. This automatically behaves
|
||||
@ -452,7 +453,7 @@ def cycle(parser, token):
|
||||
<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
|
||||
interpreted as literal strings.
|
||||
"""
|
||||
@ -462,7 +463,7 @@ def cycle(parser, token):
|
||||
# one returned from {% cycle name %} are the exact same object. This
|
||||
# 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
|
||||
# a global variable, which would make cycle names have to be unique across
|
||||
# *all* templates.
|
||||
@ -481,8 +482,7 @@ def cycle(parser, token):
|
||||
# {% cycle foo %} case.
|
||||
name = args[1]
|
||||
if not hasattr(parser, '_namedCycleNodes'):
|
||||
raise TemplateSyntaxError("No named cycles in template."
|
||||
" '%s' is not defined" % name)
|
||||
raise TemplateSyntaxError("No named cycles in template. '%s' is not defined" % name)
|
||||
if not name in parser._namedCycleNodes:
|
||||
raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
|
||||
return parser._namedCycleNodes[name]
|
||||
@ -682,8 +682,10 @@ ifnotequal = register.tag(ifnotequal)
|
||||
def do_if(parser, token):
|
||||
"""
|
||||
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
|
||||
of the block are output::
|
||||
(i.e., exists, is not empty, and is not a false boolean value), the
|
||||
contents of the block are output:
|
||||
|
||||
::
|
||||
|
||||
{% if athlete_list %}
|
||||
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.core.cache import cache
|
||||
from django.utils.encoding import force_unicode
|
||||
@ -6,20 +6,27 @@ from django.utils.encoding import force_unicode
|
||||
register = Library()
|
||||
|
||||
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.expire_time = expire_time
|
||||
self.expire_time_var = Variable(expire_time_var)
|
||||
self.fragment_name = fragment_name
|
||||
self.vary_on = vary_on
|
||||
|
||||
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.
|
||||
cache_key = u':'.join([self.fragment_name] + \
|
||||
[force_unicode(resolve_variable(var, context)) for var in self.vary_on])
|
||||
cache_key = u':'.join([self.fragment_name] + [force_unicode(resolve_variable(var, context)) for var in self.vary_on])
|
||||
value = cache.get(cache_key)
|
||||
if value is None:
|
||||
value = self.nodelist.render(context)
|
||||
cache.set(cache_key, value, self.expire_time)
|
||||
cache.set(cache_key, value, expire_time)
|
||||
return value
|
||||
|
||||
def do_cache(parser, token):
|
||||
@ -48,10 +55,6 @@ def do_cache(parser, token):
|
||||
tokens = token.contents.split()
|
||||
if len(tokens) < 3:
|
||||
raise TemplateSyntaxError(u"'%r' tag requires at least 2 arguments." % tokens[0])
|
||||
try:
|
||||
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:])
|
||||
return CacheNode(nodelist, tokens[1], tokens[2], tokens[3:])
|
||||
|
||||
register.tag('cache', do_cache)
|
||||
|
@ -343,3 +343,34 @@ class FileDict(dict):
|
||||
d = dict(self, content='<omitted>')
|
||||
return dict.__repr__(d)
|
||||
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.
|
||||
|
||||
Works on http://, https://, and www. links. Links can have trailing
|
||||
punctuation (periods, commas, close-parens) and leading punctuation
|
||||
(opening parens) and it'll still do the right thing.
|
||||
Works on http://, https://, www. links and links ending in .org, .net or
|
||||
.com. Links can have trailing punctuation (periods, commas, close-parens)
|
||||
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
|
||||
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"
|
||||
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
|
||||
safe_input = isinstance(text, SafeData)
|
||||
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)
|
||||
if match:
|
||||
lead, middle, trail = match.groups()
|
||||
if safe_input:
|
||||
middle = mark_safe(middle)
|
||||
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
|
||||
# Make URL we want to point to.
|
||||
url = None
|
||||
if middle.startswith('http://') or middle.startswith('https://'):
|
||||
url = urlquote(middle, safe='/&=:;#?+*')
|
||||
if autoescape and not safe_input:
|
||||
url = escape(url)
|
||||
trimmed_url = trim_url(middle)
|
||||
middle = '<a href="%s"%s>%s</a>' % (url, nofollow_attr,
|
||||
trimmed_url)
|
||||
elif '@' in middle and not middle.startswith('www.') and \
|
||||
not ':' in middle and simple_email_re.match(middle):
|
||||
if autoescape:
|
||||
middle = conditional_escape(middle)
|
||||
middle = '<a href="mailto:%s">%s</a>' % (middle, middle)
|
||||
if lead + middle + trail != word:
|
||||
elif middle.startswith('www.') or ('@' not in middle 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'))):
|
||||
url = urlquote('http://%s' % middle, safe='/&=:;#?+*')
|
||||
elif '@' in middle and not ':' in middle and simple_email_re.match(middle):
|
||||
url = 'mailto:%s' % middle
|
||||
nofollow_attr = ''
|
||||
# Make link.
|
||||
if url:
|
||||
trimmed = trim_url(middle)
|
||||
if autoescape and not safe_input:
|
||||
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))
|
||||
elif autoescape and not safe_input:
|
||||
else:
|
||||
if safe_input:
|
||||
words[i] = mark_safe(word)
|
||||
elif autoescape:
|
||||
words[i] = escape(word)
|
||||
elif safe_input:
|
||||
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.
|
||||
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
|
||||
=======================
|
||||
|
||||
|
@ -332,50 +332,49 @@ reopen tickets that have been marked as "wontfix" by core developers.
|
||||
Triage by the general community
|
||||
-------------------------------
|
||||
|
||||
Although the Core Developers and Ticket Triagers make the big decisions in
|
||||
the ticket triage process, there is also a lot that general community
|
||||
Although the core developers and ticket triagers make the big decisions in
|
||||
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:
|
||||
|
||||
* 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
|
||||
is a design decision that needs to be made, or "Accepted" if they are
|
||||
an obvious bug.
|
||||
* Promoting "Unreviewed" tickets to "Design decision needed" if a design
|
||||
decision needs to be made, or "Accepted" in case of obvious bugs.
|
||||
|
||||
* 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.
|
||||
|
||||
* 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
|
||||
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,
|
||||
remove the owner's claim on the ticket.
|
||||
|
||||
* 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
|
||||
to consider refactoring that part of the code. If a trend is emerging,
|
||||
you should raise it for discussion (referencing the relevant tickets)
|
||||
on `django-developers`_.
|
||||
about a particular part of Django, it may indicate we should consider
|
||||
refactoring that part of the code. If a trend is emerging, you should
|
||||
raise it for discussion (referencing the relevant tickets) on
|
||||
`django-developers`_.
|
||||
|
||||
However, we do ask that as a general community member working in the
|
||||
ticket database:
|
||||
However, we do ask the following of all general community members working in
|
||||
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
|
||||
consultation with the community.
|
||||
|
||||
* Please **don't** promote tickets to "Ready for checkin" unless they are
|
||||
*trivial* changes - for example, spelling mistakes or
|
||||
broken links in documentation.
|
||||
*trivial* changes -- for example, spelling mistakes or broken links in
|
||||
documentation.
|
||||
|
||||
* Please **don't** reverse a decision that has been made by a core
|
||||
developer. If you disagree with a discussion that has been made,
|
||||
please post a message to `django-developers`_.
|
||||
|
||||
* 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`_.
|
||||
|
||||
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
|
||||
permission to execute ``CREATE DATABASE``.
|
||||
|
||||
If you want to run the full suite of tests, there are a number of dependencies that
|
||||
you should install:
|
||||
If you want to run the full suite of tests, you'll need to install a number of
|
||||
dependencies:
|
||||
|
||||
* PyYAML_
|
||||
* Markdown_
|
||||
@ -748,10 +747,8 @@ you should install:
|
||||
* Docutils_
|
||||
* setuptools_
|
||||
|
||||
Of these dependencies, setuptools_ is the only dependency that is required - if
|
||||
setuptools_ is not installed, you will get import errors when running one of
|
||||
the template tests. The tests using the other libraries will be skipped if the
|
||||
dependency can't be found.
|
||||
Each of these dependencies is optional. If you're missing any of them, the
|
||||
associated tests will be skipped.
|
||||
|
||||
.. _PyYAML: http://pyyaml.org/wiki/PyYAML
|
||||
.. _Markdown: http://pypi.python.org/pypi/Markdown/1.7
|
||||
@ -773,13 +770,13 @@ for generic relations and internationalization, type::
|
||||
Contrib apps
|
||||
------------
|
||||
|
||||
Tests for apps in ``django/contrib/`` go in their respective directories,
|
||||
in a ``tests.py`` file. (You can split the tests over multiple modules
|
||||
by using a ``tests`` folder in the normal Python way).
|
||||
Tests for apps in ``django/contrib/`` go in their respective directories under
|
||||
``django/contrib/``, in a ``tests.py`` file. (You can split the tests over
|
||||
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
|
||||
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
|
||||
method as above::
|
||||
|
@ -382,7 +382,7 @@ Pickling QuerySets
|
||||
|
||||
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
|
||||
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
|
||||
``QuerySet``, it contains the results at the moment it was pickled, rather
|
||||
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 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
|
||||
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.entry # Returns the related Entry object.
|
||||
|
||||
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``
|
||||
The difference comes in "reverse" queries. The related model in a one-to-one
|
||||
relationship also has access to a ``Manager`` object, but that ``Manager``
|
||||
represents a single object, rather than a collection of objects::
|
||||
|
||||
e = Entry.objects.get(id=2)
|
||||
|
@ -1544,7 +1544,7 @@ the ``url`` function)::
|
||||
'django.views.generic.list_detail.object_detail',
|
||||
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::
|
||||
|
||||
from django.db.models import permalink
|
||||
@ -1553,7 +1553,7 @@ of the view name::
|
||||
return ('people_view', [str(self.id)])
|
||||
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
|
||||
|
||||
|
@ -38,6 +38,29 @@ class Student(CommonInfo):
|
||||
class Meta:
|
||||
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
|
||||
#
|
||||
@ -128,9 +151,25 @@ Traceback (most recent call last):
|
||||
...
|
||||
AttributeError: type object 'CommonInfo' has no attribute 'objects'
|
||||
|
||||
# The Place/Restaurant/ItalianRestaurant models, on the other hand, all exist
|
||||
# as independent models. However, the subclasses also have transparent access
|
||||
# to the fields of their ancestors.
|
||||
# Create a Post
|
||||
>>> post = Post(title='Lorem Ipsum')
|
||||
>>> 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.
|
||||
>>> 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...'})
|
||||
>>> repr(d)
|
||||
"{'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>'
|
||||
|
||||
>>> 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)
|
||||
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>'
|
||||
|
||||
>>> 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')
|
||||
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')
|
||||
u'<a href="mailto:info@djangoproject.org">info@djangoproject.org</a>'
|
||||
|
@ -2,6 +2,8 @@
|
||||
Regression tests for Model inheritance behaviour.
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
from django.db import models
|
||||
|
||||
class Place(models.Model):
|
||||
@ -35,11 +37,17 @@ class ParkingLot(Place):
|
||||
def __unicode__(self):
|
||||
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':"""
|
||||
# Regression for #7350, #7202
|
||||
# Check that when you create a Parent object with a specific reference to an existent
|
||||
# child instance, saving the Parent doesn't duplicate the child.
|
||||
# This behaviour is only activated during a raw save - it is mostly relevant to
|
||||
# Check that when you create a Parent object with a specific reference to an
|
||||
# existent child instance, saving the Parent doesn't duplicate the child. This
|
||||
# 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
|
||||
# similar approach.
|
||||
|
||||
@ -117,4 +125,10 @@ __test__ = {'API_TESTS':"""
|
||||
>>> [sorted(d.items()) for d in dicts]
|
||||
[[('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):
|
||||
name = models.CharField(max_length=10)
|
||||
created = models.DateTimeField()
|
||||
modified = models.DateTimeField(blank=True, null=True)
|
||||
tags = models.ManyToManyField(Tag, blank=True, null=True)
|
||||
creator = models.ForeignKey(Author)
|
||||
note = models.ForeignKey(Note)
|
||||
@ -57,7 +58,7 @@ class Item(models.Model):
|
||||
|
||||
class Report(models.Model):
|
||||
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):
|
||||
return self.name
|
||||
@ -89,6 +90,15 @@ class Number(models.Model):
|
||||
def __unicode__(self):
|
||||
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
|
||||
# cases.
|
||||
class X(models.Model):
|
||||
@ -121,12 +131,12 @@ class LoopZ(models.Model):
|
||||
class CustomManager(models.Manager):
|
||||
def get_query_set(self):
|
||||
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):
|
||||
data = models.CharField(max_length=10)
|
||||
tag = models.ForeignKey(Tag)
|
||||
is_public = models.BooleanField(default=True)
|
||||
public = models.BooleanField(default=True)
|
||||
|
||||
objects = CustomManager()
|
||||
normal_manager = models.Manager()
|
||||
@ -134,6 +144,24 @@ class ManagedModel(models.Model):
|
||||
def __unicode__(self):
|
||||
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':"""
|
||||
>>> t1 = Tag(name='t1')
|
||||
@ -174,7 +202,7 @@ by 'info'. Helps detect some problems later.
|
||||
>>> time2 = datetime.datetime(2007, 12, 19, 21, 0, 0)
|
||||
>>> time3 = datetime.datetime(2007, 12, 20, 22, 25, 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.tags = [t1, t2]
|
||||
>>> i2 = Item(name='two', created=time2, creator=a2, note=n2)
|
||||
@ -190,6 +218,8 @@ by 'info'. Helps detect some problems later.
|
||||
>>> r1.save()
|
||||
>>> r2 = Report(name='r2', creator=a3)
|
||||
>>> r2.save()
|
||||
>>> r3 = Report(name='r3')
|
||||
>>> r3.save()
|
||||
|
||||
Ordering by 'rank' gives us rank2, rank1, rank3. Ordering by the Meta.ordering
|
||||
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
|
||||
# ForeignKey) is legal, but the results might not make sense. That isn't
|
||||
# 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>]
|
||||
|
||||
# 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})
|
||||
[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.
|
||||
|
||||
>>> qs = Tag.objects.all()
|
||||
@ -705,8 +739,57 @@ More twisted cases, involving nested negations.
|
||||
Bug #7095
|
||||
Updates that are filtered on the model being updated are somewhat tricky to get
|
||||
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')
|
||||
|
||||
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
|
||||
|
||||
Note: This test requires setuptools!
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
@ -17,7 +18,7 @@ import StringIO
|
||||
from django.template import TemplateDoesNotExist
|
||||
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):
|
||||
def __init__(self, module):
|
||||
pkg_resources.NullProvider.__init__(self, module)
|
||||
@ -35,13 +36,14 @@ class MockProvider(pkg_resources.NullProvider):
|
||||
def _get(self, path):
|
||||
return self.module._resources[path].read()
|
||||
|
||||
class MockLoader(object): pass
|
||||
class MockLoader(object):
|
||||
pass
|
||||
|
||||
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.
|
||||
"""
|
||||
egg = imp.new_module(name)
|
||||
@ -49,7 +51,6 @@ def create_egg(name, resources):
|
||||
egg._resources = resources
|
||||
sys.modules[name] = egg
|
||||
|
||||
|
||||
class EggLoader(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pkg_resources._provider_factories[MockLoader] = MockProvider
|
||||
@ -87,6 +88,5 @@ class EggLoader(unittest.TestCase):
|
||||
settings.INSTALLED_APPS = []
|
||||
self.assertRaises(TemplateDoesNotExist, lts_egg, "y.html")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
@ -20,7 +20,10 @@ from django.utils.tzinfo import LocalTimezone
|
||||
from unicode import unicode_tests
|
||||
from context import context_tests
|
||||
|
||||
from loaders import *
|
||||
try:
|
||||
from loaders import *
|
||||
except ImportError:
|
||||
pass # If setuptools isn't installed, that's fine. Just move on.
|
||||
|
||||
import filters
|
||||
|
||||
@ -132,8 +135,7 @@ class Templates(unittest.TestCase):
|
||||
|
||||
# Quickly check that we aren't accidentally using a name in both
|
||||
# template and filter tests.
|
||||
overlapping_names = [name for name in filter_tests if name in
|
||||
template_tests]
|
||||
overlapping_names = [name for name in filter_tests if name in template_tests]
|
||||
assert not overlapping_names, 'Duplicate test name(s): %s' % ', '.join(overlapping_names)
|
||||
|
||||
template_tests.update(filter_tests)
|
||||
@ -156,7 +158,7 @@ class Templates(unittest.TestCase):
|
||||
# Turn TEMPLATE_DEBUG off, because tests assume that.
|
||||
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
|
||||
expected_invalid_str = 'INVALID'
|
||||
|
||||
@ -539,13 +541,14 @@ class Templates(unittest.TestCase):
|
||||
'if-tag-error05': ("{% if not foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
|
||||
|
||||
### IFCHANGED TAG #########################################################
|
||||
'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,2,3) }, '123'),
|
||||
'ifchanged02': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,3) }, '13'),
|
||||
'ifchanged03': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,1) }, '1'),
|
||||
'ifchanged04': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 2, 3), 'numx': (2, 2, 2)}, '122232'),
|
||||
'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'),
|
||||
'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'),
|
||||
'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,2,3)}, '123'),
|
||||
'ifchanged02': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,1,3)}, '13'),
|
||||
'ifchanged03': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', {'num': (1,1,1)}, '1'),
|
||||
'ifchanged04': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', {'num': (1, 2, 3), 'numx': (2, 2, 2)}, '122232'),
|
||||
'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'),
|
||||
'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.
|
||||
'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),
|
||||
@ -860,40 +863,46 @@ class Templates(unittest.TestCase):
|
||||
|
||||
### NOW TAG ########################################################
|
||||
# Simple case
|
||||
'now01' : ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),
|
||||
'now01': ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),
|
||||
|
||||
# Check parsing of escaped and special characters
|
||||
'now02' : ('{% now "j "n" Y"%}', {}, template.TemplateSyntaxError),
|
||||
# 'now03' : ('{% now "j \"n\" Y"%}', {}, str(datetime.now().day) + '"' + str(datetime.now().month) + '"' + str(datetime.now().year)),
|
||||
# 'now04' : ('{% now "j \nn\n Y"%}', {}, str(datetime.now().day) + '\n' + str(datetime.now().month) + '\n' + str(datetime.now().year))
|
||||
'now02': ('{% now "j "n" Y"%}', {}, template.TemplateSyntaxError),
|
||||
# 'now03': ('{% now "j \"n\" Y"%}', {}, str(datetime.now().day) + '"' + str(datetime.now().month) + '"' + str(datetime.now().year)),
|
||||
# 'now04': ('{% now "j \nn\n Y"%}', {}, str(datetime.now().day) + '\n' + str(datetime.now().month) + '\n' + str(datetime.now().year))
|
||||
|
||||
### URL TAG ########################################################
|
||||
# Successes
|
||||
'url01' : ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
|
||||
'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/'),
|
||||
'url04' : ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
|
||||
'url05' : (u'{% url метка_оператора v %}', {'v': u'Ω'},
|
||||
'/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
|
||||
'url01': ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
|
||||
'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/'),
|
||||
'url04': ('{% url named.client client.id %}', {'client': {'id': 1}}, '/url_tag/named-client/1/'),
|
||||
'url05': (u'{% url метка_оператора v %}', {'v': u'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
|
||||
|
||||
# Failures
|
||||
'url-fail01' : ('{% url %}', {}, template.TemplateSyntaxError),
|
||||
'url-fail02' : ('{% url no_such_view %}', {}, ''),
|
||||
'url-fail03' : ('{% url regressiontests.templates.views.client no_such_param="value" %}', {}, ''),
|
||||
'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
|
||||
'url-fail02': ('{% url no_such_view %}', {}, ''),
|
||||
'url-fail03': ('{% url regressiontests.templates.views.client no_such_param="value" %}', {}, ''),
|
||||
|
||||
### CACHE TAG ######################################################
|
||||
'cache01' : ('{% load cache %}{% cache -1 test %}cache01{% endcache %}', {}, 'cache01'),
|
||||
'cache02' : ('{% load cache %}{% cache -1 test %}cache02{% endcache %}', {}, 'cache02'),
|
||||
'cache03' : ('{% load cache %}{% cache 2 test %}cache03{% endcache %}', {}, 'cache03'),
|
||||
'cache04' : ('{% load cache %}{% cache 2 test %}cache04{% endcache %}', {}, 'cache03'),
|
||||
'cache05' : ('{% load cache %}{% cache 2 test foo %}cache05{% endcache %}', {'foo': 1}, 'cache05'),
|
||||
'cache06' : ('{% load cache %}{% cache 2 test foo %}cache06{% endcache %}', {'foo': 2}, 'cache06'),
|
||||
'cache07' : ('{% load cache %}{% cache 2 test foo %}cache06{% endcache %}', {'foo': 1}, 'cache05'),
|
||||
'cache01': ('{% load cache %}{% cache -1 test %}cache01{% endcache %}', {}, 'cache01'),
|
||||
'cache02': ('{% load cache %}{% cache -1 test %}cache02{% endcache %}', {}, 'cache02'),
|
||||
'cache03': ('{% load cache %}{% cache 2 test %}cache03{% endcache %}', {}, 'cache03'),
|
||||
'cache04': ('{% load cache %}{% cache 2 test %}cache04{% endcache %}', {}, 'cache03'),
|
||||
'cache05': ('{% load cache %}{% cache 2 test foo %}cache05{% endcache %}', {'foo': 1}, 'cache05'),
|
||||
'cache06': ('{% load cache %}{% cache 2 test foo %}cache06{% endcache %}', {'foo': 2}, 'cache06'),
|
||||
'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.
|
||||
'cache08' : ('{% load cache %}{% cache %}{% endcache %}', {}, template.TemplateSyntaxError),
|
||||
'cache09' : ('{% load cache %}{% cache 1 %}{% endcache %}', {}, template.TemplateSyntaxError),
|
||||
'cache10' : ('{% load cache %}{% cache foo bar %}{% endcache %}', {}, template.TemplateSyntaxError),
|
||||
# Allow first argument to be a variable.
|
||||
'cache08': ('{% load cache %}{% cache time test foo %}cache08{% endcache %}', {'foo': 2, 'time': 2}, 'cache06'),
|
||||
'cache09': ('{% load cache %}{% cache time test foo %}cache09{% endcache %}', {'foo': 3, 'time': -1}, 'cache09'),
|
||||
'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-tag01': ("{% autoescape off %}hello{% endautoescape %}", {}, "hello"),
|
||||
|
Loading…
x
Reference in New Issue
Block a user