1
0
mirror of https://github.com/django/django.git synced 2025-07-04 17:59:13 +00:00

newforms-admin: Merged from trunk up to [7021].

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7022 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Joseph Kocherhans 2008-01-17 18:12:24 +00:00
parent c080e441f3
commit daa467d79e
49 changed files with 5384 additions and 2865 deletions

View File

@ -70,6 +70,7 @@ answer newbie questions, and generally made Django that much better:
Andrew Brehaut <http://brehaut.net/blog> Andrew Brehaut <http://brehaut.net/blog>
brut.alll@gmail.com brut.alll@gmail.com
Jonathan Buchanan <jonathan.buchanan@gmail.com> Jonathan Buchanan <jonathan.buchanan@gmail.com>
Can Burak Çilingir <canburak@cs.bilgi.edu.tr>
Trevor Caira <trevor@caira.com> Trevor Caira <trevor@caira.com>
Ricardo Javier Cárdenes Medina <ricardo.cardenes@gmail.com> Ricardo Javier Cárdenes Medina <ricardo.cardenes@gmail.com>
Graham Carlyle <graham.carlyle@maplecroft.net> Graham Carlyle <graham.carlyle@maplecroft.net>
@ -175,6 +176,7 @@ answer newbie questions, and generally made Django that much better:
jpellerin@gmail.com jpellerin@gmail.com
junzhang.jn@gmail.com junzhang.jn@gmail.com
Antti Kaihola <http://akaihola.blogspot.com/> Antti Kaihola <http://akaihola.blogspot.com/>
Bahadır Kandemir <bahadir@pardus.org.tr>
Nagy Károly <charlie@rendszergazda.com> Nagy Károly <charlie@rendszergazda.com>
Erik Karulf <erik@karulf.com> Erik Karulf <erik@karulf.com>
Ben Dean Kawamura <ben.dean.kawamura@gmail.com> Ben Dean Kawamura <ben.dean.kawamura@gmail.com>

View File

@ -5,8 +5,8 @@ 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: 2007-12-02 22:26+0100\n" "POT-Creation-Date: 2007-12-29 21:28+0100\n"
"PO-Revision-Date: 2007-12-02 22:32+0100\n" "PO-Revision-Date: 2007-12-30 11:38+0100\n"
"Last-Translator: Marc Fargas <telenieko@telenieko.com>\n" "Last-Translator: Marc Fargas <telenieko@telenieko.com>\n"
"Language-Team: <es@li.org>\n" "Language-Team: <es@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -1691,41 +1691,42 @@ msgstr "demà"
msgid "yesterday" msgid "yesterday"
msgstr "ahir" msgstr "ahir"
#: contrib/localflavor/ar/forms.py:30 contrib/localflavor/ar/forms.py:38 #: contrib/localflavor/ar/forms.py:28
msgid "Enter a postal code in the format NNNN or ANNNNAAA." msgid "Enter a postal code in the format NNNN or ANNNNAAA."
msgstr "Introdueixi un codi postal en el format NNNN or ANNNNAAA." msgstr "Introdueixi un codi postal en el format NNNN o ANNNNAAA."
#: contrib/localflavor/ar/forms.py:61 contrib/localflavor/br/forms.py:103 #: contrib/localflavor/ar/forms.py:50 contrib/localflavor/br/forms.py:96
#: contrib/localflavor/pe/forms.py:34 contrib/localflavor/pe/forms.py:57 #: contrib/localflavor/br/forms.py:135 contrib/localflavor/pe/forms.py:23
#: contrib/localflavor/pe/forms.py:51
msgid "This field requires only numbers." msgid "This field requires only numbers."
msgstr "Aquest camps requereix només números." msgstr "Aquest camps requereix només números."
#: contrib/localflavor/ar/forms.py:64 #: contrib/localflavor/ar/forms.py:51
msgid "This field requires 7 or 8 digits." msgid "This field requires 7 or 8 digits."
msgstr "Aquest camp requereix 7 o 8 dígits." msgstr "Aquest camp requereix 7 o 8 dígits."
#: contrib/localflavor/ar/forms.py:75 #: contrib/localflavor/ar/forms.py:80
msgid "Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format." msgid "Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format."
msgstr "" msgstr ""
"Introdueixi un número CUIT vàlid en el format XX-XXXXXXXX-X o XXXXXXXXXXXX." "Introdueixi un número CUIT vàlid en el format XX-XXXXXXXX-X o XXXXXXXXXXXX."
#: contrib/localflavor/ar/forms.py:88 #: contrib/localflavor/ar/forms.py:81
msgid "Invalid CUIT." msgid "Invalid CUIT."
msgstr "Invàlid CUIT." msgstr "Invàlid CUIT."
#: contrib/localflavor/au/forms.py:18 #: contrib/localflavor/au/forms.py:16
msgid "Enter a 4 digit post code." msgid "Enter a 4 digit post code."
msgstr "Introdueixi un codi postal de 4 dígits." msgstr "Introdueixi un codi postal de 4 dígits."
#: contrib/localflavor/br/forms.py:23 #: contrib/localflavor/br/forms.py:21
msgid "Enter a zip code in the format XXXXX-XXX." msgid "Enter a zip code in the format XXXXX-XXX."
msgstr "Introdueixi un codi zip en el format XXXXX-XXX." msgstr "Introdueixi un codi zip en el format XXXXX-XXX."
#: contrib/localflavor/br/forms.py:35 #: contrib/localflavor/br/forms.py:30
msgid "Phone numbers must be in XX-XXXX-XXXX format." msgid "Phone numbers must be in XX-XXXX-XXXX format."
msgstr "El número de telèfon ha de ser en el format XX-XXXX-XXXX." msgstr "El número de telèfon ha de ser en el format XX-XXXX-XXXX."
#: contrib/localflavor/br/forms.py:68 #: contrib/localflavor/br/forms.py:58
msgid "" msgid ""
"Select a valid brazilian state. That state is not one of the available " "Select a valid brazilian state. That state is not one of the available "
"states." "states."
@ -1733,30 +1734,30 @@ msgstr ""
"Seleccioni un estat brasiler vàlid. Aquest estat no és un dels estats " "Seleccioni un estat brasiler vàlid. Aquest estat no és un dels estats "
"disponibles." "disponibles."
#: contrib/localflavor/br/forms.py:105 #: contrib/localflavor/br/forms.py:94
msgid "This field requires at most 11 digits or 14 characters."
msgstr "Aquest camp requereix com a màxim 11 dígits o 14 caracters."
#: contrib/localflavor/br/forms.py:115
msgid "Invalid CPF number." msgid "Invalid CPF number."
msgstr "Número CPF invàlid." msgstr "Número CPF invàlid."
#: contrib/localflavor/br/forms.py:137 #: contrib/localflavor/br/forms.py:95
msgid "This field requires at least 14 digits" msgid "This field requires at most 11 digits or 14 characters."
msgstr "Aquest camp requereix almenys 14 dígits." msgstr "Aquest camp requereix com a màxim 11 dígits o 14 caracters."
#: contrib/localflavor/br/forms.py:147 #: contrib/localflavor/br/forms.py:134
msgid "Invalid CNPJ number." msgid "Invalid CNPJ number."
msgstr "Número CNPJ invàlid." msgstr "Número CNPJ invàlid."
#: contrib/localflavor/ca/forms.py:19 #: contrib/localflavor/br/forms.py:136
msgid "This field requires at least 14 digits"
msgstr "Aquest camp requereix almenys 14 dígits."
#: contrib/localflavor/ca/forms.py:17
msgid "Enter a postal code in the format XXX XXX." msgid "Enter a postal code in the format XXX XXX."
msgstr "Introdueixi un codi postal en el format XXX XXX." msgstr "Introdueixi un codi postal en el format XXX XXX."
#: contrib/localflavor/ca/forms.py:81 #: contrib/localflavor/ca/forms.py:88
msgid "Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format." msgid "Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format."
msgstr "" msgstr ""
"Introdueixi un número vàlid de la Seguretat Social de Canada en el format " "Introdueixi un número vàlid de la Seguretat Social de Canadà en el format "
"XXX-XXX-XXXX." "XXX-XXX-XXXX."
#: contrib/localflavor/ch/ch_states.py:5 #: contrib/localflavor/ch/ch_states.py:5
@ -1863,11 +1864,11 @@ msgstr "Zug"
msgid "Zurich" msgid "Zurich"
msgstr "Zurich" msgstr "Zurich"
#: contrib/localflavor/ch/forms.py:18 contrib/localflavor/no/forms.py:14 #: contrib/localflavor/ch/forms.py:16 contrib/localflavor/no/forms.py:12
msgid "Enter a zip code in the format XXXX." msgid "Enter a zip code in the format XXXX."
msgstr "Introdueixi un codi zip en el format XXXX." msgstr "Introdueixi un codi zip en el format XXXX."
#: contrib/localflavor/ch/forms.py:90 #: contrib/localflavor/ch/forms.py:64
msgid "" msgid ""
"Enter a valid Swiss identity or passport card number in X1234567<0 or " "Enter a valid Swiss identity or passport card number in X1234567<0 or "
"1234567890 format." "1234567890 format."
@ -1875,13 +1876,17 @@ msgstr ""
"Introdueixi un número de identificació o de passaport Suïssos en els formats " "Introdueixi un número de identificació o de passaport Suïssos en els formats "
"1234567890 o X1234567<0." "1234567890 o X1234567<0."
#: contrib/localflavor/cl/forms.py:32 #: contrib/localflavor/cl/forms.py:29
msgid "Enter valid a Chilean RUT. The format is XX.XXX.XXX-X." msgid "Enter a valid Chilean RUT."
msgstr "Introdueixi un RUT Xilè vàlid."
#: contrib/localflavor/cl/forms.py:30
msgid "Enter a valid Chilean RUT. The format is XX.XXX.XXX-X."
msgstr "Introdueixi un RUT Xilè vàlid. El format és XX.XXX.XXX-X" msgstr "Introdueixi un RUT Xilè vàlid. El format és XX.XXX.XXX-X"
#: contrib/localflavor/cl/forms.py:37 #: contrib/localflavor/cl/forms.py:31
msgid "Enter valid a Chilean RUT" msgid "The Chilean RUT is not valid."
msgstr "Introdueixi un RUT Xilè vàlid." msgstr "El RUT Xilè no és vàlid."
#: contrib/localflavor/de/de_states.py:5 #: contrib/localflavor/de/de_states.py:5
msgid "Baden-Wuerttemberg" msgid "Baden-Wuerttemberg"
@ -1947,12 +1952,12 @@ msgstr "Schleswig-Holstein"
msgid "Thuringia" msgid "Thuringia"
msgstr "Thuringia" msgstr "Thuringia"
#: contrib/localflavor/de/forms.py:16 contrib/localflavor/fi/forms.py:14 #: contrib/localflavor/de/forms.py:14 contrib/localflavor/fi/forms.py:12
#: contrib/localflavor/fr/forms.py:17 #: contrib/localflavor/fr/forms.py:15
msgid "Enter a zip code in the format XXXXX." msgid "Enter a zip code in the format XXXXX."
msgstr "Introdueixi un codi zip en el format XXXXX." msgstr "Introdueixi un codi zip en el format XXXXX."
#: contrib/localflavor/de/forms.py:60 #: contrib/localflavor/de/forms.py:41
msgid "" msgid ""
"Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X " "Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X "
"format." "format."
@ -2227,7 +2232,7 @@ msgstr "Comunitat Foral de Navarra"
msgid "Valencian Community" msgid "Valencian Community"
msgstr "Comunitat Valenciana" msgstr "Comunitat Valenciana"
#: contrib/localflavor/es/forms.py:22 #: contrib/localflavor/es/forms.py:19
msgid "Enter a valid postal code in the range and format 01XXX - 52XXX." msgid "Enter a valid postal code in the range and format 01XXX - 52XXX."
msgstr "Introdueixi un codi postal en rang i format 01XXX - 52XXX." msgstr "Introdueixi un codi postal en rang i format 01XXX - 52XXX."
@ -2239,40 +2244,42 @@ msgstr ""
"Introdueixi un número de telèfon vàlid en un dels formats 6XXXXXXXX, " "Introdueixi un número de telèfon vàlid en un dels formats 6XXXXXXXX, "
"8XXXXXXXX o 9XXXXXXXX." "8XXXXXXXX o 9XXXXXXXX."
#: contrib/localflavor/es/forms.py:73 contrib/localflavor/es/forms.py:108 #: contrib/localflavor/es/forms.py:66
#: db/models/fields/related.py:55 msgid "Please enter a valid NIF, NIE, or CIF."
#, python-format msgstr "Si us plau, introdueixi un NIF, NIE o CIF vàlid."
msgid "Please enter a valid %s."
msgstr "Si us plau, introdueixi un %s vàlid."
#: contrib/localflavor/es/forms.py:91 #: contrib/localflavor/es/forms.py:67
msgid "Please enter a valid NIF or NIE."
msgstr "Si us plau, introdueixi un NIF o NIE vàlid."
#: contrib/localflavor/es/forms.py:68
msgid "Invalid checksum for NIF." msgid "Invalid checksum for NIF."
msgstr "Validació invàlida del NIF." msgstr "Validació invàlida del NIF."
#: contrib/localflavor/es/forms.py:97 #: contrib/localflavor/es/forms.py:69
msgid "Invalid checksum for NIE." msgid "Invalid checksum for NIE."
msgstr "Validació invàlida del NIE." msgstr "Validació invàlida del NIE."
#: contrib/localflavor/es/forms.py:106 #: contrib/localflavor/es/forms.py:70
msgid "Invalid checksum for CIF." msgid "Invalid checksum for CIF."
msgstr "Validació invàlida del CIF." msgstr "Validació invàlida del CIF."
#: contrib/localflavor/es/forms.py:136 #: contrib/localflavor/es/forms.py:142
msgid "" msgid ""
"Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX." "Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX."
msgstr "" msgstr ""
"Introdueixi un número de compte bancari vàlid en el format XXXX-XXXX-XX-" "Introdueixi un número de compte bancari vàlid en el format XXXX-XXXX-XX-"
"XXXXXXXXXX." "XXXXXXXXXX."
#: contrib/localflavor/es/forms.py:150 #: contrib/localflavor/es/forms.py:143
msgid "Invalid checksum for bank account number." msgid "Invalid checksum for bank account number."
msgstr "Validació invàlida del número de compte bancari." msgstr "Validació invàlida del número de compte bancari."
#: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:45 #: contrib/localflavor/fi/forms.py:28
msgid "Enter a valid Finnish social security number." msgid "Enter a valid Finnish social security number."
msgstr "Introdueixi un número vàlid de la seguretat social finlandesa." msgstr "Introdueixi un número vàlid de la seguretat social finlandesa."
#: contrib/localflavor/in_/forms.py:16 #: contrib/localflavor/in_/forms.py:14
msgid "Enter a zip code in the format XXXXXXX." msgid "Enter a zip code in the format XXXXXXX."
msgstr "Introdueixi un codi zip en el format XXXXXXX." msgstr "Introdueixi un codi zip en el format XXXXXXX."
@ -2282,15 +2289,15 @@ msgid ""
msgstr "" msgstr ""
"Introdueixi un número de identificació d'Islàndia. El format és XXXXXX-XXXX." "Introdueixi un número de identificació d'Islàndia. El format és XXXXXX-XXXX."
#: contrib/localflavor/is_/forms.py:31 #: contrib/localflavor/is_/forms.py:18
msgid "The Icelandic identification number is not valid." msgid "The Icelandic identification number is not valid."
msgstr "El número de identificació d'Islàndia no és vàlid." msgstr "El número de identificació d'Islàndia no és vàlid."
#: contrib/localflavor/it/forms.py:16 #: contrib/localflavor/it/forms.py:14
msgid "Enter a valid zip code." msgid "Enter a valid zip code."
msgstr "Introdueixi un codi zip vàlid." msgstr "Introdueixi un codi zip vàlid."
#: contrib/localflavor/it/forms.py:41 #: contrib/localflavor/it/forms.py:43
msgid "Enter a valid Social Security number." msgid "Enter a valid Social Security number."
msgstr "Introdueixi un número valid de la Seguretat Social." msgstr "Introdueixi un número valid de la Seguretat Social."
@ -2298,7 +2305,7 @@ msgstr "Introdueixi un número valid de la Seguretat Social."
msgid "Enter a valid VAT number." msgid "Enter a valid VAT number."
msgstr "Introdueixi un número de IVA (VAT) vàlid." msgstr "Introdueixi un número de IVA (VAT) vàlid."
#: contrib/localflavor/jp/forms.py:21 #: contrib/localflavor/jp/forms.py:19
msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX." msgid "Enter a postal code in the format XXXXXXX or XXX-XXXX."
msgstr "Introdueixi un codi postal en el format XXXXXXX o XX-XXXX." msgstr "Introdueixi un codi postal en el format XXXXXXX o XX-XXXX."
@ -2490,15 +2497,143 @@ msgstr "Kagoshima"
msgid "Okinawa" msgid "Okinawa"
msgstr "Okinawa" msgstr "Okinawa"
#: contrib/localflavor/nl/forms.py:25 #: contrib/localflavor/mx/mx_states.py:12
msgid "Aguascalientes"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:13
msgid "Baja California"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:14
msgid "Baja California Sur"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:15
msgid "Campeche"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:16
msgid "Chihuahua"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:17
msgid "Chiapas"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:18
msgid "Coahuila"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:19
msgid "Colima"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:20
msgid "Distrito Federal"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:21
msgid "Durango"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:22
msgid "Guerrero"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:23
msgid "Guanajuato"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:24
msgid "Hidalgo"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:25
msgid "Jalisco"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:26
msgid "Estado de México"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:27
msgid "Michoacán"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:28
msgid "Morelos"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:29
msgid "Nayarit"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:30
msgid "Nuevo León"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:31
msgid "Oaxaca"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:32
msgid "Puebla"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:33
msgid "Querétaro"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:34
msgid "Quintana Roo"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:35
msgid "Sinaloa"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:36
msgid "San Luis Potosí"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:37
msgid "Sonora"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:38
msgid "Tabasco"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:39
msgid "Tamaulipas"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:40
msgid "Tlaxcala"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:41
msgid "Veracruz"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:42
msgid "Yucatán"
msgstr ""
#: contrib/localflavor/mx/mx_states.py:43
msgid "Zacatecas"
msgstr ""
#: contrib/localflavor/nl/forms.py:21
msgid "Enter a valid postal code" msgid "Enter a valid postal code"
msgstr "Introdueixi un codi postal vàlid." msgstr "Introdueixi un codi postal vàlid."
#: contrib/localflavor/nl/forms.py:53 #: contrib/localflavor/nl/forms.py:52
msgid "Enter a valid phone number" msgid "Enter a valid phone number"
msgstr "Introdueixi un número de telèfon vàlid." msgstr "Introdueixi un número de telèfon vàlid."
#: contrib/localflavor/nl/forms.py:76 #: contrib/localflavor/nl/forms.py:78
msgid "Enter a valid SoFi number" msgid "Enter a valid SoFi number"
msgstr "Introdueixi un número SoFi vàlid." msgstr "Introdueixi un número SoFi vàlid."
@ -2550,23 +2685,23 @@ msgstr "Zeeland"
msgid "Zuid-Holland" msgid "Zuid-Holland"
msgstr "Zuid-Holland" msgstr "Zuid-Holland"
#: contrib/localflavor/no/forms.py:35 #: contrib/localflavor/no/forms.py:33
msgid "Enter a valid Norwegian social security number." msgid "Enter a valid Norwegian social security number."
msgstr "Introdueixi un número de la seguretat social Noruega vàlid." msgstr "Introdueixi un número de la seguretat social Noruega vàlid."
#: contrib/localflavor/pe/forms.py:36 #: contrib/localflavor/pe/forms.py:24
msgid "This field requires 8 digits." msgid "This field requires 8 digits."
msgstr "Aquest camp requereix 8 dígits." msgstr "Aquest camp requereix 8 dígits."
#: contrib/localflavor/pe/forms.py:59 #: contrib/localflavor/pe/forms.py:52
msgid "This field requires 11 digits." msgid "This field requires 11 digits."
msgstr "Aquest camp requereix 11 dígits." msgstr "Aquest camp requereix 11 dígits."
#: contrib/localflavor/pl/forms.py:41 #: contrib/localflavor/pl/forms.py:39
msgid "National Identification Number consists of 11 digits." msgid "National Identification Number consists of 11 digits."
msgstr "El número d'identidicació nacional està compost de 11 digits." msgstr "El número d'identidicació nacional està compost de 11 digits."
#: contrib/localflavor/pl/forms.py:47 #: contrib/localflavor/pl/forms.py:40
msgid "Wrong checksum for the National Identification Number." msgid "Wrong checksum for the National Identification Number."
msgstr "Validació invàlida del número d'identificació nacional." msgstr "Validació invàlida del número d'identificació nacional."
@ -2575,11 +2710,11 @@ msgid ""
"Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX." "Enter a tax number field (NIP) in the format XXX-XXX-XX-XX or XX-XX-XXX-XXX."
msgstr "Introdueixi un número NIP en el format XXX-XXX-XX-XX o XX-XX-XXX-XXX." msgstr "Introdueixi un número NIP en el format XXX-XXX-XX-XX o XX-XX-XXX-XXX."
#: contrib/localflavor/pl/forms.py:78 #: contrib/localflavor/pl/forms.py:73
msgid "Wrong checksum for the Tax Number (NIP)." msgid "Wrong checksum for the Tax Number (NIP)."
msgstr "Validació invàlida del número tributari (NIP)." msgstr "Validació invàlida del número tributari (NIP)."
#: contrib/localflavor/pl/forms.py:107 #: contrib/localflavor/pl/forms.py:112
msgid "National Business Register Number (REGON) consists of 7 or 9 digits." msgid "National Business Register Number (REGON) consists of 7 or 9 digits."
msgstr "" msgstr ""
"El número nacional de registre de negocis (REGON) consisteix en 7 o 9 dígits." "El número nacional de registre de negocis (REGON) consisteix en 7 o 9 dígits."
@ -2588,7 +2723,7 @@ msgstr ""
msgid "Wrong checksum for the National Business Register Number (REGON)." msgid "Wrong checksum for the National Business Register Number (REGON)."
msgstr "Validació invàlida del número nacional de registre de negocis." msgstr "Validació invàlida del número nacional de registre de negocis."
#: contrib/localflavor/pl/forms.py:148 #: contrib/localflavor/pl/forms.py:156
msgid "Enter a postal code in the format XX-XXX." msgid "Enter a postal code in the format XX-XXX."
msgstr "Introdueixi un codi postal en el format XX-XXX." msgstr "Introdueixi un codi postal en el format XX-XXX."
@ -2656,7 +2791,7 @@ msgstr "Greater Poland"
msgid "West Pomerania" msgid "West Pomerania"
msgstr "West Pomerania" msgstr "West Pomerania"
#: contrib/localflavor/sk/forms.py:32 #: contrib/localflavor/sk/forms.py:30
msgid "Enter a postal code in the format XXXXX or XXX XX." msgid "Enter a postal code in the format XXXXX or XXX XX."
msgstr "Introdueixi un codi postal en el format XXXXX or XXX XX." msgstr "Introdueixi un codi postal en el format XXXXX or XXX XX."
@ -3008,27 +3143,302 @@ msgstr "Regió de Trnava"
msgid "Zilina region" msgid "Zilina region"
msgstr "Regió de Zilina" msgstr "Regió de Zilina"
#: contrib/localflavor/uk/forms.py:18 #: contrib/localflavor/uk/forms.py:21
msgid "Enter a postcode. A space is required between the two postcode parts." msgid "Enter a valid postcode."
msgstr "" msgstr "Introdueixi un codi postal vàlid."
"Introdueixi un codi postal. És necessari un espai entre les dues parts del "
"codi postal."
#: contrib/localflavor/us/forms.py:18 #: contrib/localflavor/uk/uk_regions.py:11
msgid "Bedfordshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:12
msgid "Buckinghamshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:14
msgid "Cheshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:15
msgid "Cornwall and Isles of Scilly"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:16
msgid "Cumbria"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:17
msgid "Derbyshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:18
msgid "Devon"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:19
msgid "Dorset"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:20
msgid "Durham"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:21
msgid "East Sussex"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:22
msgid "Essex"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:23
msgid "Gloucestershire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:24
msgid "Greater London"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:25
msgid "Greater Manchester"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:26
msgid "Hampshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:27
msgid "Hertfordshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:28
msgid "Kent"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:29
msgid "Lancashire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:30
msgid "Leicestershire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:31
msgid "Lincolnshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:32
msgid "Merseyside"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:33
msgid "Norfolk"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:34
msgid "North Yorkshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:35
msgid "Northamptonshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:36
msgid "Northumberland"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:37
msgid "Nottinghamshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:38
msgid "Oxfordshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:39
msgid "Shropshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:40
msgid "Somerset"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:41
msgid "South Yorkshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:42
msgid "Staffordshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:43
msgid "Suffolk"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:44
msgid "Surrey"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:45
msgid "Tyne and Wear"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:46
msgid "Warwickshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:47
msgid "West Midlands"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:48
msgid "West Sussex"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:49
msgid "West Yorkshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:50
msgid "Wiltshire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:51
msgid "Worcestershire"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:55
msgid "County Antrim"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:56
msgid "County Armagh"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:57
#: contrib/localflavor/uk/uk_regions.py:58
msgid "County Down"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:59
msgid "County Londonderry"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:60
msgid "County Tyrone"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:64
msgid "Clwyd"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:65
msgid "Dyfed"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:66
msgid "Gwent"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:67
msgid "Gwynedd"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:68
msgid "Mid Glamorgan"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:69
msgid "Powys"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:70
msgid "South Glamorgan"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:71
msgid "West Glamorgan"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:75
msgid "Borders"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:76
msgid "Central Scotland"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:77
msgid "Dumfries and Galloway"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:78
msgid "Fife"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:79
msgid "Grampian"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:80
msgid "Highland"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:81
msgid "Lothian"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:82
msgid "Orkney Islands"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:83
msgid "Shetland Islands"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:84
msgid "Strathclyde"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:85
msgid "Tayside"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:86
msgid "Western Isles"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:90
msgid "England"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:91
msgid "Northern Ireland"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:92
msgid "Scotland"
msgstr ""
#: contrib/localflavor/uk/uk_regions.py:93
msgid "Wales"
msgstr ""
#: contrib/localflavor/us/forms.py:16
msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX."
msgstr "Introdueixi un codi zip en el format XXXXX o XXXXX-XXXX." msgstr "Introdueixi un codi zip en el format XXXXX o XXXXX-XXXX."
#: contrib/localflavor/us/forms.py:51 #: contrib/localflavor/us/forms.py:54
msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format." msgid "Enter a valid U.S. Social Security number in XXX-XX-XXXX format."
msgstr "" msgstr ""
"Introdueixi un número vàlid de la Seguretat Social dels E.U.A. en el format " "Introdueixi un número vàlid de la Seguretat Social dels E.U.A. en el format "
"XXX-XX-XXXX." "XXX-XX-XXXX."
#: contrib/localflavor/za/forms.py:22 #: contrib/localflavor/za/forms.py:20
msgid "Enter a valid South African ID number" msgid "Enter a valid South African ID number"
msgstr "Introdueixi un número d'Identitat Sud Africà valid" msgstr "Introdueixi un número d'Identitat Sud Africà valid"
#: contrib/localflavor/za/forms.py:57 #: contrib/localflavor/za/forms.py:54
msgid "Enter a valid South African postal code" msgid "Enter a valid South African postal code"
msgstr "Introdueixi un codi postal Sud Africà vàlid." msgstr "Introdueixi un codi postal Sud Africà vàlid."
@ -3503,6 +3913,11 @@ msgstr "Introdueixi un nom de fitxer vàlid."
msgid "This value must be either None, True or False." msgid "This value must be either None, True or False."
msgstr "Aquest valor ha de ser None (Cap), True (Veritat) o False (Fals)" msgstr "Aquest valor ha de ser None (Cap), True (Veritat) o False (Fals)"
#: db/models/fields/related.py:55
#, python-format
msgid "Please enter a valid %s."
msgstr "Si us plau, introdueixi un %s vàlid."
#: db/models/fields/related.py:658 #: db/models/fields/related.py:658
msgid "Separate multiple IDs with commas." msgid "Separate multiple IDs with commas."
msgstr "Separi múltiples IDs amb comes." msgstr "Separi múltiples IDs amb comes."
@ -3599,7 +4014,7 @@ msgstr "Introdueixi una URL vàlida."
msgid "This URL appears to be a broken link." msgid "This URL appears to be a broken link."
msgstr "Aquesta URL sembla ser un enllaç trencat." msgstr "Aquesta URL sembla ser un enllaç trencat."
#: newforms/fields.py:555 newforms/models.py:155 #: newforms/fields.py:555 newforms/models.py:317
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 "" msgstr ""
"Esculli una opció vàlida; Aquesta opció no és una de les opcions disponibles." "Esculli una opció vàlida; Aquesta opció no és una de les opcions disponibles."
@ -3609,7 +4024,7 @@ msgstr ""
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 "Esculli una opció vàlida. %(value)s no és una de les opcions vàlides." msgstr "Esculli una opció vàlida. %(value)s no és una de les opcions vàlides."
#: newforms/fields.py:595 newforms/fields.py:657 newforms/models.py:215 #: newforms/fields.py:595 newforms/fields.py:657 newforms/models.py:377
msgid "Enter a list of values." msgid "Enter a list of values."
msgstr "Introdueixi una llista de valors." msgstr "Introdueixi una llista de valors."
@ -3617,7 +4032,7 @@ msgstr "Introdueixi una llista de valors."
msgid "Enter a valid IPv4 address." msgid "Enter a valid IPv4 address."
msgstr "Introdueixi una adreça IPv4 vàlida." msgstr "Introdueixi una adreça IPv4 vàlida."
#: newforms/models.py:216 #: newforms/models.py:378
#, 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 "Esculli una opció vàlida; %s' no és una de les opcions vàlides." msgstr "Esculli una opció vàlida; %s' no és una de les opcions vàlides."
@ -3650,28 +4065,28 @@ msgstr "Introdueixi un número positiu."
msgid "Enter a whole number between 0 and 32,767." msgid "Enter a whole number between 0 and 32,767."
msgstr "Introdueixi un número entre 0 i 32,767." msgstr "Introdueixi un número entre 0 i 32,767."
#: template/defaultfilters.py:658 #: template/defaultfilters.py:683
msgid "yes,no,maybe" msgid "yes,no,maybe"
msgstr "si,no,potser" msgstr "si,no,potser"
#: template/defaultfilters.py:689 #: template/defaultfilters.py:714
#, python-format #, python-format
msgid "%(size)d byte" msgid "%(size)d byte"
msgid_plural "%(size)d bytes" msgid_plural "%(size)d bytes"
msgstr[0] "%(size)d byte" msgstr[0] "%(size)d byte"
msgstr[1] "%(size)d bytes" msgstr[1] "%(size)d bytes"
#: template/defaultfilters.py:691 #: template/defaultfilters.py:716
#, python-format #, python-format
msgid "%.1f KB" msgid "%.1f KB"
msgstr "%.1f KB" msgstr "%.1f KB"
#: template/defaultfilters.py:693 #: template/defaultfilters.py:718
#, python-format #, python-format
msgid "%.1f MB" msgid "%.1f MB"
msgstr "%.1f MB" msgstr "%.1f MB"
#: template/defaultfilters.py:694 #: template/defaultfilters.py:719
#, python-format #, python-format
msgid "%.1f GB" msgid "%.1f GB"
msgstr "%.1f GB" msgstr "%.1f GB"
@ -3968,3 +4383,9 @@ msgstr "El/La %(verbose_name)s s'ha actualtzat amb èxit."
#, python-format #, python-format
msgid "The %(verbose_name)s was deleted." msgid "The %(verbose_name)s was deleted."
msgstr "El %(verbose_name)s s'ha eliminat." msgstr "El %(verbose_name)s s'ha eliminat."
#~ msgid ""
#~ "Enter a postcode. A space is required between the two postcode parts."
#~ msgstr ""
#~ "Introdueixi un codi postal. És necessari un espai entre les dues parts "
#~ "del codi postal."

File diff suppressed because it is too large Load Diff

View File

@ -1,118 +1,117 @@
# SOME DESCRIPTIVE TITLE. # translation of djangojs.po to Hrvatski jezik
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the Django package.
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
# #
#, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: djangojs\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-08-13 11:13+1000\n" "POT-Creation-Date: 2007-08-13 11:13+1000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: 2008-01-05 01:45+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: Aljosa Mohorovic <aljosa.mohorovic@gmail.com>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: Hrvatski jezik\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"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
#: contrib/admin/media/js/SelectFilter2.js:33 #: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format #, perl-format
msgid "Available %s" msgid "Available %s"
msgstr "" msgstr "Dostupno %s"
#: contrib/admin/media/js/SelectFilter2.js:41 #: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all" msgid "Choose all"
msgstr "" msgstr "Odaberi sve"
#: contrib/admin/media/js/SelectFilter2.js:46 #: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add" msgid "Add"
msgstr "" msgstr "Dodaj"
#: contrib/admin/media/js/SelectFilter2.js:48 #: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove" msgid "Remove"
msgstr "" msgstr "Ukloni"
#: contrib/admin/media/js/SelectFilter2.js:53 #: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format #, perl-format
msgid "Chosen %s" msgid "Chosen %s"
msgstr "" msgstr "Odabrano %s"
#: contrib/admin/media/js/SelectFilter2.js:54 #: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click " msgid "Select your choice(s) and click "
msgstr "" msgstr "Odaberi iz izbora i klikni "
#: contrib/admin/media/js/SelectFilter2.js:59 #: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all" msgid "Clear all"
msgstr "" msgstr "Očisti sve"
#: contrib/admin/media/js/dateparse.js:32 #: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24 #: contrib/admin/media/js/calendar.js:24
msgid "" msgid ""
"January February March April May June July August September October November " "January February March April May June July August September October November "
"December" "December"
msgstr "" msgstr "Siječanj Veljača Ožujak Travanj Svibanj Lipanj Srpanj Kolovoz Rujan Listopad Studeni Prosinac"
#: contrib/admin/media/js/dateparse.js:33 #: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "" msgstr "Nedjelja Ponedjeljak Utorak Srijeda Četvrtak Petak Subota"
#: contrib/admin/media/js/calendar.js:25 #: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S" msgid "S M T W T F S"
msgstr "" msgstr "N P U S Č P S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now" msgid "Now"
msgstr "" msgstr "Sada"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock" msgid "Clock"
msgstr "" msgstr "Sat"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time" msgid "Choose a time"
msgstr "" msgstr "Izaberite vrijeme"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight" msgid "Midnight"
msgstr "" msgstr "Ponoć"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m." msgid "6 a.m."
msgstr "" msgstr "6 ujutro"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon" msgid "Noon"
msgstr "" msgstr "Podne"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr "Odustani"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today" msgid "Today"
msgstr "" msgstr "Danas"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar" msgid "Calendar"
msgstr "" msgstr "Kalendar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday" msgid "Yesterday"
msgstr "" msgstr "Jučer"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow" msgid "Tomorrow"
msgstr "" msgstr "Sutra"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show" msgid "Show"
msgstr "" msgstr "Prikaži"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide" msgid "Hide"
msgstr "" msgstr "Sakri"

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,13 @@
# translation of django.po to Turkish # translation of django.po to Turkish
# Django 0.95
# Copyright (C) 2006 Django
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Can Burak Çilingir <canburak@cs.bilgi.edu.tr>, 2007. (Slight modifications)
# Bahadır Kandemir <bahadir@pardus.org.tr>, 2006.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: django\n" "Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-03-14 01:38+0200\n" "POT-Creation-Date: 2007-03-14 01:38+0200\n"
"PO-Revision-Date: 2007-03-14 02:06+0200\n" "PO-Revision-Date: 2007-12-30 12:15+0200\n"
"Last-Translator: Bahadır Kandemir <bahadir@pardus.org.tr>\n" "Last-Translator: Can Burak Çilingir <canburak@cs.bilgi.edu.tr>\n"
"Language-Team: Turkish <bahadir@pardus.org.tr>\n" "Language-Team: Turkish <bahadir@pardus.org.tr>\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"
@ -157,7 +153,7 @@ msgstr "Bengali Dili"
#: conf/global_settings.py:41 #: conf/global_settings.py:41
msgid "Catalan" msgid "Catalan"
msgstr "" msgstr "Katalanca"
#: conf/global_settings.py:42 #: conf/global_settings.py:42
msgid "Czech" msgid "Czech"
@ -225,15 +221,15 @@ msgstr "Japonca"
#: conf/global_settings.py:58 #: conf/global_settings.py:58
msgid "Kannada" msgid "Kannada"
msgstr "" msgstr "Kannada Dili"
#: conf/global_settings.py:59 #: conf/global_settings.py:59
msgid "Latvian" msgid "Latvian"
msgstr "" msgstr "Leton Dili"
#: conf/global_settings.py:60 #: conf/global_settings.py:60
msgid "Macedonian" msgid "Macedonian"
msgstr "" msgstr "Makedonca"
#: conf/global_settings.py:61 #: conf/global_settings.py:61
msgid "Dutch" msgid "Dutch"
@ -245,7 +241,7 @@ msgstr "Norveç Dili"
#: conf/global_settings.py:63 #: conf/global_settings.py:63
msgid "Polish" msgid "Polish"
msgstr "" msgstr "Lehçe"
#: conf/global_settings.py:64 #: conf/global_settings.py:64
msgid "Brazilian" msgid "Brazilian"
@ -281,7 +277,7 @@ msgstr "Tamilce"
#: conf/global_settings.py:72 #: conf/global_settings.py:72
msgid "Telugu" msgid "Telugu"
msgstr "" msgstr "Telugu Dili"
#: conf/global_settings.py:73 #: conf/global_settings.py:73
msgid "Turkish" msgid "Turkish"
@ -615,7 +611,7 @@ msgstr "Geçerli bir seçimde bulunun; seçiminiz mevcut değerlerden birisi de
#: newforms/models.py:181 newforms/fields.py:378 newforms/fields.py:454 #: newforms/models.py:181 newforms/fields.py:378 newforms/fields.py:454
msgid "Enter a list of values." msgid "Enter a list of values."
msgstr "" msgstr "Değer listesi giriniz."
#: newforms/models.py:187 newforms/fields.py:387 #: newforms/models.py:187 newforms/fields.py:387
#, python-format #, python-format
@ -648,11 +644,11 @@ msgstr "Geçerli bir tarih girin."
#: newforms/fields.py:190 #: newforms/fields.py:190
msgid "Enter a valid time." msgid "Enter a valid time."
msgstr "" msgstr "Geçerli bir zaman giriniz."
#: newforms/fields.py:226 #: newforms/fields.py:226
msgid "Enter a valid date/time." msgid "Enter a valid date/time."
msgstr "" msgstr "Geçerli bir tarih/zaman giriniz."
#: newforms/fields.py:240 #: newforms/fields.py:240
msgid "Enter a valid value." msgid "Enter a valid value."
@ -668,40 +664,40 @@ msgstr "Bu URL kırık bir link gibi duruyor."
#: contrib/humanize/templatetags/humanize.py:17 #: contrib/humanize/templatetags/humanize.py:17
msgid "th" msgid "th"
msgstr "" msgstr "."
#: contrib/humanize/templatetags/humanize.py:17 #: contrib/humanize/templatetags/humanize.py:17
msgid "st" msgid "st"
msgstr "" msgstr "."
#: contrib/humanize/templatetags/humanize.py:17 #: contrib/humanize/templatetags/humanize.py:17
msgid "nd" msgid "nd"
msgstr "" msgstr "."
#: contrib/humanize/templatetags/humanize.py:17 #: contrib/humanize/templatetags/humanize.py:17
msgid "rd" msgid "rd"
msgstr "" msgstr "."
#: contrib/humanize/templatetags/humanize.py:47 #: contrib/humanize/templatetags/humanize.py:47
#, python-format #, python-format
msgid "%(value).1f million" msgid "%(value).1f million"
msgid_plural "%(value).1f million" msgid_plural "%(value).1f million"
msgstr[0] "" msgstr[0] "%(value).1f milyon"
msgstr[1] "" msgstr[1] "%(value).1f milyon"
#: contrib/humanize/templatetags/humanize.py:50 #: contrib/humanize/templatetags/humanize.py:50
#, python-format #, python-format
msgid "%(value).1f billion" msgid "%(value).1f billion"
msgid_plural "%(value).1f billion" msgid_plural "%(value).1f billion"
msgstr[0] "" msgstr[0] "%(value).1f milyar"
msgstr[1] "" msgstr[1] "%(value).1f milyar"
#: contrib/humanize/templatetags/humanize.py:53 #: contrib/humanize/templatetags/humanize.py:53
#, python-format #, python-format
msgid "%(value).1f trillion" msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion" msgid_plural "%(value).1f trillion"
msgstr[0] "" msgstr[0] "%(value).1f trilyon"
msgstr[1] "" msgstr[1] "%(value).1f trilyon"
#: contrib/humanize/templatetags/humanize.py:68 #: contrib/humanize/templatetags/humanize.py:68
msgid "one" msgid "one"
@ -2029,6 +2025,8 @@ msgid ""
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change " "Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
"password form</a>." "password form</a>."
msgstr "" msgstr ""
"'[algo]$[salt]$[hexdigest]' yazın ya da <a href=\"password/\">parola\n"
"değiştir formunu kullanın</a>."
#: contrib/auth/models.py:95 #: contrib/auth/models.py:95
msgid "staff status" msgid "staff status"
@ -2152,7 +2150,7 @@ msgstr "Posta kodu girin. Posta kodunun iki kısmı arasında bir boşluk bırak
#: contrib/localflavor/usa/forms.py:17 #: contrib/localflavor/usa/forms.py:17
msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX."
msgstr "" msgstr "XXXXX ya da XXXXX-XXXX biçiminde bir posta kodu yazın."
#: contrib/sessions/models.py:51 #: contrib/sessions/models.py:51
msgid "session key" msgid "session key"
@ -2411,27 +2409,27 @@ msgstr[1] "dakika"
#: utils/dateformat.py:40 #: utils/dateformat.py:40
msgid "p.m." msgid "p.m."
msgstr "" msgstr "ö.s."
#: utils/dateformat.py:41 #: utils/dateformat.py:41
msgid "a.m." msgid "a.m."
msgstr "" msgstr "ö.ö."
#: utils/dateformat.py:46 #: utils/dateformat.py:46
msgid "PM" msgid "PM"
msgstr "" msgstr "ÖS"
#: utils/dateformat.py:47 #: utils/dateformat.py:47
msgid "AM" msgid "AM"
msgstr "" msgstr "ÖÖ"
#: utils/dateformat.py:95 #: utils/dateformat.py:95
msgid "midnight" msgid "midnight"
msgstr "" msgstr "gece yarısı"
#: utils/dateformat.py:97 #: utils/dateformat.py:97
msgid "noon" msgid "noon"
msgstr "" msgstr "öğlen"
#: utils/translation/trans_real.py:362 #: utils/translation/trans_real.py:362
msgid "DATE_FORMAT" msgid "DATE_FORMAT"

View File

@ -1,7 +1,4 @@
# Django 0.95
# Copyright (C) 2006 Django
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# Bahadır Kandemir <bahadir@pardus.org.tr>, 2006.
# #
msgid "" msgid ""
msgstr "" msgstr ""

View File

@ -5,7 +5,7 @@ var LATIN_MAP = {
'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U', 'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä': 'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'o', 'ñ': 'n', 'ò': 'o', 'ó': 'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó':
'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y' 'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
} }

View File

@ -10,6 +10,9 @@ from django.contrib.auth.models import User
import getpass import getpass
import os import os
import sys import sys
import re
RE_VALID_USERNAME = re.compile('\w+$')
def createsuperuser(username=None, email=None, password=None): def createsuperuser(username=None, email=None, password=None):
""" """
@ -43,7 +46,7 @@ def createsuperuser(username=None, email=None, password=None):
username = raw_input(input_msg + ': ') username = raw_input(input_msg + ': ')
if default_username and username == '': if default_username and username == '':
username = default_username username = default_username
if not username.isalnum(): if not RE_VALID_USERNAME.match(username):
sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n") sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n")
username = None username = None
continue continue

View File

@ -80,12 +80,12 @@ class CASocialInsuranceNumberField(Field):
Checks the following rules to determine whether the number is valid: Checks the following rules to determine whether the number is valid:
* Conforms to the XXX-XXX-XXXX format. * Conforms to the XXX-XXX-XXX format.
* Passes the check digit process "Luhn Algorithm" * Passes the check digit process "Luhn Algorithm"
See: http://en.wikipedia.org/wiki/Social_Insurance_Number See: http://en.wikipedia.org/wiki/Social_Insurance_Number
""" """
default_error_messages = { default_error_messages = {
'invalid': ugettext('Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'), 'invalid': ugettext('Enter a valid Canadian Social Insurance number in XXX-XXX-XXX format.'),
} }
def clean(self, value): def clean(self, value):

View File

@ -85,7 +85,7 @@ PROVINCE_CHOICES = (
('RC', 'Reggio Calabria'), ('RC', 'Reggio Calabria'),
('RE', 'Reggio Emilia'), ('RE', 'Reggio Emilia'),
('RI', 'Rieti'), ('RI', 'Rieti'),
('RN', 'Rimini') ('RN', 'Rimini'),
('RM', 'Roma'), ('RM', 'Roma'),
('RO', 'Rovigo'), ('RO', 'Rovigo'),
('SA', 'Salerno'), ('SA', 'Salerno'),

View File

@ -26,6 +26,8 @@ class SessionStore(SessionBase):
# Save immediately to minimize collision # Save immediately to minimize collision
self.save() self.save()
# Ensure the user is notified via a new cookie.
self.modified = True
return {} return {}
def exists(self, session_key): def exists(self, session_key):

View File

@ -46,6 +46,8 @@ class SessionStore(SessionBase):
self._session_key = self._get_new_session_key() self._session_key = self._get_new_session_key()
self._session_cache = {} self._session_cache = {}
self.save() self.save()
# Ensure the user is notified via a new cookie.
self.modified = True
finally: finally:
session_file.close() session_file.close()
except(IOError): except(IOError):

View File

@ -67,11 +67,10 @@ def make_msgid(idstring=None):
class BadHeaderError(ValueError): class BadHeaderError(ValueError):
pass pass
class SafeMIMEText(MIMEText): def forbid_multi_line_headers(name, val):
def __setitem__(self, name, val):
"Forbids multi-line headers, to prevent header injection." "Forbids multi-line headers, to prevent header injection."
if '\n' in val or '\r' in val: if '\n' in val or '\r' in val:
raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name) raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" % (val, name))
try: try:
val = force_unicode(val).encode('ascii') val = force_unicode(val).encode('ascii')
except UnicodeEncodeError: except UnicodeEncodeError:
@ -84,25 +83,16 @@ class SafeMIMEText(MIMEText):
val = ', '.join(result) val = ', '.join(result)
else: else:
val = Header(force_unicode(val), settings.DEFAULT_CHARSET) val = Header(force_unicode(val), settings.DEFAULT_CHARSET)
return name, val
class SafeMIMEText(MIMEText):
def __setitem__(self, name, val):
name, val = forbid_multi_line_headers(name, val)
MIMEText.__setitem__(self, name, val) MIMEText.__setitem__(self, name, val)
class SafeMIMEMultipart(MIMEMultipart): class SafeMIMEMultipart(MIMEMultipart):
def __setitem__(self, name, val): def __setitem__(self, name, val):
"Forbids multi-line headers, to prevent header injection." name, val = forbid_multi_line_headers(name, val)
if '\n' in val or '\r' in val:
raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name)
try:
val = force_unicode(val).encode('ascii')
except UnicodeEncodeError:
if name.lower() in ('to', 'from', 'cc'):
result = []
for item in val.split(', '):
nm, addr = parseaddr(item)
nm = str(Header(nm, settings.DEFAULT_CHARSET))
result.append(formataddr((nm, str(addr))))
val = ', '.join(result)
else:
val = Header(force_unicode(val), settings.DEFAULT_CHARSET)
MIMEMultipart.__setitem__(self, name, val) MIMEMultipart.__setitem__(self, name, val)
class SMTPConnection(object): class SMTPConnection(object):
@ -209,8 +199,14 @@ class EmailMessage(object):
bytestrings). The SafeMIMEText class will handle any necessary encoding bytestrings). The SafeMIMEText class will handle any necessary encoding
conversions. conversions.
""" """
self.to = to or [] if to:
self.bcc = bcc or [] self.to = list(to)
else:
self.to = []
if bcc:
self.bcc = list(bcc)
else:
self.bcc = []
self.from_email = from_email or settings.DEFAULT_FROM_EMAIL self.from_email = from_email or settings.DEFAULT_FROM_EMAIL
self.subject = subject self.subject = subject
self.body = body self.body = body

View File

@ -293,7 +293,7 @@ def sql_model_create(model, style, known_models=set()):
style.SQL_KEYWORD('NULL')) style.SQL_KEYWORD('NULL'))
for field_constraints in opts.unique_together: for field_constraints in opts.unique_together:
table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \ table_output.append(style.SQL_KEYWORD('UNIQUE') + ' (%s)' % \
", ".join([qn(style.SQL_FIELD(opts.get_field(f).column)) for f in field_constraints])) ", ".join([style.SQL_FIELD(qn(opts.get_field(f).column)) for f in field_constraints]))
full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(qn(opts.db_table)) + ' ('] full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(qn(opts.db_table)) + ' (']
for i, line in enumerate(table_output): # Combine and add commas. for i, line in enumerate(table_output): # Combine and add commas.

View File

@ -413,6 +413,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
return self.connection is not None return self.connection is not None
def _cursor(self, settings): def _cursor(self, settings):
cursor = None
if not self._valid_connection(): if not self._valid_connection():
if len(settings.DATABASE_HOST.strip()) == 0: if len(settings.DATABASE_HOST.strip()) == 0:
settings.DATABASE_HOST = 'localhost' settings.DATABASE_HOST = 'localhost'
@ -422,16 +423,25 @@ class DatabaseWrapper(BaseDatabaseWrapper):
else: else:
conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME) conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)
self.connection = Database.connect(conn_string, **self.options) self.connection = Database.connect(conn_string, **self.options)
cursor = FormatStylePlaceholderCursor(self.connection)
# Set oracle date to ansi date format. This only needs to execute
# once when we create a new connection.
cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD' "
"NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'")
try: try:
self.oracle_version = int(self.connection.version.split('.')[0]) self.oracle_version = int(self.connection.version.split('.')[0])
except ValueError: except ValueError:
pass pass
try:
self.connection.stmtcachesize = 20
except:
# Django docs specify cx_Oracle version 4.3.1 or higher, but
# stmtcachesize is available only in 4.3.2 and up.
pass
if not cursor:
cursor = FormatStylePlaceholderCursor(self.connection) cursor = FormatStylePlaceholderCursor(self.connection)
# Default arraysize of 1 is highly sub-optimal. # Default arraysize of 1 is highly sub-optimal.
cursor.arraysize = 100 cursor.arraysize = 100
# Set oracle date to ansi date format.
cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'")
cursor.execute("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'")
return cursor return cursor
class FormatStylePlaceholderCursor(Database.Cursor): class FormatStylePlaceholderCursor(Database.Cursor):
@ -506,7 +516,10 @@ class FormatStylePlaceholderCursor(Database.Cursor):
return Database.Cursor.executemany(self, query, new_param_list) return Database.Cursor.executemany(self, query, new_param_list)
def fetchone(self): def fetchone(self):
return to_unicode(Database.Cursor.fetchone(self)) row = Database.Cursor.fetchone(self)
if row is None:
return row
return tuple([to_unicode(e) for e in row])
def fetchmany(self, size=None): def fetchmany(self, size=None):
if size is None: if size is None:

View File

@ -795,13 +795,17 @@ class FileField(Field):
return os.path.normpath(f) return os.path.normpath(f)
def save_form_data(self, instance, data): def save_form_data(self, instance, data):
if data: from django.newforms.fields import UploadedFile
if data and isinstance(data, UploadedFile):
getattr(instance, "save_%s_file" % self.name)(data.filename, data.content, save=False) getattr(instance, "save_%s_file" % self.name)(data.filename, data.content, save=False)
def formfield(self, **kwargs): def formfield(self, **kwargs):
defaults = {'form_class': forms.FileField} defaults = {'form_class': forms.FileField}
# If a file has been provided previously, then the form doesn't require # If a file has been provided previously, then the form doesn't require
# that a new file is provided this time. # that a new file is provided this time.
# The code to mark the form field as not required is used by
# form_for_instance, but can probably be removed once form_for_instance
# is gone. ModelForm uses a different method to check for an existing file.
if 'initial' in kwargs: if 'initial' in kwargs:
defaults['required'] = False defaults['required'] = False
defaults.update(kwargs) defaults.update(kwargs)

View File

@ -437,10 +437,12 @@ class FileField(Field):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(FileField, self).__init__(*args, **kwargs) super(FileField, self).__init__(*args, **kwargs)
def clean(self, data): def clean(self, data, initial=None):
super(FileField, self).clean(data) super(FileField, self).clean(initial or data)
if not self.required and data in EMPTY_VALUES: if not self.required and data in EMPTY_VALUES:
return None return None
elif not data and initial:
return initial
try: try:
f = UploadedFile(data['filename'], data['content']) f = UploadedFile(data['filename'], data['content'])
except TypeError: except TypeError:
@ -456,12 +458,12 @@ class ImageField(FileField):
'invalid_image': _(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."), 'invalid_image': _(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."),
} }
def clean(self, data): def clean(self, data, initial=None):
""" """
Checks that the file-upload field data contains a valid image (GIF, JPG, Checks that the file-upload field data contains a valid image (GIF, JPG,
PNG, possibly others -- whatever the Python Imaging Library supports). PNG, possibly others -- whatever the Python Imaging Library supports).
""" """
f = super(ImageField, self).clean(data) f = super(ImageField, self).clean(data, initial)
if f is None: if f is None:
return None return None
from PIL import Image from PIL import Image

View File

@ -9,7 +9,7 @@ from django.utils.html import escape
from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from fields import Field from fields import Field, FileField
from widgets import Media, media_property, TextInput, Textarea from widgets import Media, media_property, TextInput, Textarea
from util import flatatt, ErrorDict, ErrorList, ValidationError from util import flatatt, ErrorDict, ErrorList, ValidationError
@ -205,6 +205,10 @@ class BaseForm(StrAndUnicode):
# widgets split data over several HTML fields. # widgets split data over several HTML fields.
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try: try:
if isinstance(field, FileField):
initial = self.initial.get(name, field.initial)
value = field.clean(value, initial)
else:
value = field.clean(value) value = field.clean(value)
self.cleaned_data[name] = value self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name): if hasattr(self, 'clean_%s' % name):

View File

@ -154,15 +154,12 @@ class StringOrigin(Origin):
class Template(object): class Template(object):
def __init__(self, template_string, origin=None, name='<Unknown Template>'): def __init__(self, template_string, origin=None, name='<Unknown Template>'):
"Compilation stage"
try: try:
template_string = smart_unicode(template_string) template_string = smart_unicode(template_string)
except UnicodeDecodeError: except UnicodeDecodeError:
raise TemplateEncodingError("Templates can only be constructed from unicode or UTF-8 strings.") raise TemplateEncodingError("Templates can only be constructed from unicode or UTF-8 strings.")
if settings.TEMPLATE_DEBUG and origin == None: if settings.TEMPLATE_DEBUG and origin is None:
origin = StringOrigin(template_string) origin = StringOrigin(template_string)
# Could do some crazy stack-frame stuff to record where this string
# came from...
self.nodelist = compile_string(template_string, origin) self.nodelist = compile_string(template_string, origin)
self.name = name self.name = name
@ -177,13 +174,18 @@ class Template(object):
def compile_string(template_string, origin): def compile_string(template_string, origin):
"Compiles template_string into NodeList ready for rendering" "Compiles template_string into NodeList ready for rendering"
lexer = lexer_factory(template_string, origin) if settings.TEMPLATE_DEBUG:
parser = parser_factory(lexer.tokenize()) from debug import DebugLexer, DebugParser
lexer_class, parser_class = DebugLexer, DebugParser
else:
lexer_class, parser_class = Lexer, Parser
lexer = lexer_class(template_string, origin)
parser = parser_class(lexer.tokenize())
return parser.parse() return parser.parse()
class Token(object): class Token(object):
def __init__(self, token_type, contents): def __init__(self, token_type, contents):
"The token_type must be TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK or TOKEN_COMMENT" # token_type must be TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK or TOKEN_COMMENT.
self.token_type, self.contents = token_type, contents self.token_type, self.contents = token_type, contents
def __str__(self): def __str__(self):
@ -200,7 +202,7 @@ class Lexer(object):
self.origin = origin self.origin = origin
def tokenize(self): def tokenize(self):
"Return a list of tokens from a given template_string" "Return a list of tokens from a given template_string."
in_tag = False in_tag = False
result = [] result = []
for bit in tag_re.split(self.template_string): for bit in tag_re.split(self.template_string):
@ -226,30 +228,6 @@ class Lexer(object):
token = Token(TOKEN_TEXT, token_string) token = Token(TOKEN_TEXT, token_string)
return token return token
class DebugLexer(Lexer):
def __init__(self, template_string, origin):
super(DebugLexer, self).__init__(template_string, origin)
def tokenize(self):
"Return a list of tokens from a given template_string"
result, upto = [], 0
for match in tag_re.finditer(self.template_string):
start, end = match.span()
if start > upto:
result.append(self.create_token(self.template_string[upto:start], (upto, start), False))
upto = start
result.append(self.create_token(self.template_string[start:end], (start, end), True))
upto = end
last_bit = self.template_string[upto:]
if last_bit:
result.append(self.create_token(last_bit, (upto, upto + len(last_bit)), False))
return result
def create_token(self, token_string, source, in_tag):
token = super(DebugLexer, self).create_token(token_string, in_tag)
token.source = self.origin, source
return token
class Parser(object): class Parser(object):
def __init__(self, tokens): def __init__(self, tokens):
self.tokens = tokens self.tokens = tokens
@ -358,57 +336,7 @@ class Parser(object):
if filter_name in self.filters: if filter_name in self.filters:
return self.filters[filter_name] return self.filters[filter_name]
else: else:
raise TemplateSyntaxError, "Invalid filter: '%s'" % filter_name raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name)
class DebugParser(Parser):
def __init__(self, lexer):
super(DebugParser, self).__init__(lexer)
self.command_stack = []
def enter_command(self, command, token):
self.command_stack.append( (command, token.source) )
def exit_command(self):
self.command_stack.pop()
def error(self, token, msg):
return self.source_error(token.source, msg)
def source_error(self, source,msg):
e = TemplateSyntaxError(msg)
e.source = source
return e
def create_nodelist(self):
return DebugNodeList()
def create_variable_node(self, contents):
return DebugVariableNode(contents)
def extend_nodelist(self, nodelist, node, token):
node.source = token.source
super(DebugParser, self).extend_nodelist(nodelist, node, token)
def unclosed_block_tag(self, parse_until):
command, source = self.command_stack.pop()
msg = "Unclosed tag '%s'. Looking for one of: %s " % (command, ', '.join(parse_until))
raise self.source_error( source, msg)
def compile_function_error(self, token, e):
if not hasattr(e, 'source'):
e.source = token.source
def lexer_factory(*args, **kwargs):
if settings.TEMPLATE_DEBUG:
return DebugLexer(*args, **kwargs)
else:
return Lexer(*args, **kwargs)
def parser_factory(*args, **kwargs):
if settings.TEMPLATE_DEBUG:
return DebugParser(*args, **kwargs)
else:
return Parser(*args, **kwargs)
class TokenParser(object): class TokenParser(object):
""" """
@ -426,7 +354,7 @@ class TokenParser(object):
def top(self): def top(self):
"Overload this method to do the actual parsing and return the result." "Overload this method to do the actual parsing and return the result."
raise NotImplemented raise NotImplementedError()
def more(self): def more(self):
"Returns True if there is more stuff in the tag." "Returns True if there is more stuff in the tag."
@ -435,7 +363,7 @@ class TokenParser(object):
def back(self): def back(self):
"Undoes the last microparser. Use this for lookahead and backtracking." "Undoes the last microparser. Use this for lookahead and backtracking."
if not len(self.backout): if not len(self.backout):
raise TemplateSyntaxError, "back called without some previous parsing" raise TemplateSyntaxError("back called without some previous parsing")
self.pointer = self.backout.pop() self.pointer = self.backout.pop()
def tag(self): def tag(self):
@ -443,7 +371,7 @@ class TokenParser(object):
subject = self.subject subject = self.subject
i = self.pointer i = self.pointer
if i >= len(subject): if i >= len(subject):
raise TemplateSyntaxError, "expected another tag, found end of string: %s" % subject raise TemplateSyntaxError("expected another tag, found end of string: %s" % subject)
p = i p = i
while i < len(subject) and subject[i] not in (' ', '\t'): while i < len(subject) and subject[i] not in (' ', '\t'):
i += 1 i += 1
@ -459,14 +387,14 @@ class TokenParser(object):
subject = self.subject subject = self.subject
i = self.pointer i = self.pointer
if i >= len(subject): if i >= len(subject):
raise TemplateSyntaxError, "Searching for value. Expected another value but found end of string: %s" % subject raise TemplateSyntaxError("Searching for value. Expected another value but found end of string: %s" % subject)
if subject[i] in ('"', "'"): if subject[i] in ('"', "'"):
p = i p = i
i += 1 i += 1
while i < len(subject) and subject[i] != subject[p]: while i < len(subject) and subject[i] != subject[p]:
i += 1 i += 1
if i >= len(subject): if i >= len(subject):
raise TemplateSyntaxError, "Searching for value. Unexpected end of string in column %d: %s" % (i, subject) raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject))
i += 1 i += 1
res = subject[p:i] res = subject[p:i]
while i < len(subject) and subject[i] in (' ', '\t'): while i < len(subject) and subject[i] in (' ', '\t'):
@ -483,7 +411,7 @@ class TokenParser(object):
while i < len(subject) and subject[i] != c: while i < len(subject) and subject[i] != c:
i += 1 i += 1
if i >= len(subject): if i >= len(subject):
raise TemplateSyntaxError, "Searching for value. Unexpected end of string in column %d: %s" % (i, subject) raise TemplateSyntaxError("Searching for value. Unexpected end of string in column %d: %s" % (i, subject))
i += 1 i += 1
s = subject[p:i] s = subject[p:i]
while i < len(subject) and subject[i] in (' ', '\t'): while i < len(subject) and subject[i] in (' ', '\t'):
@ -542,8 +470,8 @@ class FilterExpression(object):
for match in matches: for match in matches:
start = match.start() start = match.start()
if upto != start: if upto != start:
raise TemplateSyntaxError, "Could not parse some characters: %s|%s|%s" % \ raise TemplateSyntaxError("Could not parse some characters: %s|%s|%s" % \
(token[:upto], token[upto:start], token[start:]) (token[:upto], token[upto:start], token[start:]))
if var == None: if var == None:
var, constant, i18n_constant = match.group("var", "constant", "i18n_constant") var, constant, i18n_constant = match.group("var", "constant", "i18n_constant")
if i18n_constant: if i18n_constant:
@ -552,9 +480,9 @@ class FilterExpression(object):
var = '"%s"' % constant.replace(r'\"', '"') var = '"%s"' % constant.replace(r'\"', '"')
upto = match.end() upto = match.end()
if var == None: if var == None:
raise TemplateSyntaxError, "Could not find variable at start of %s" % token raise TemplateSyntaxError("Could not find variable at start of %s" % token)
elif var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_': elif var.find(VARIABLE_ATTRIBUTE_SEPARATOR + '_') > -1 or var[0] == '_':
raise TemplateSyntaxError, "Variables and attributes may not begin with underscores: '%s'" % var raise TemplateSyntaxError("Variables and attributes may not begin with underscores: '%s'" % var)
else: else:
filter_name = match.group("filter_name") filter_name = match.group("filter_name")
args = [] args = []
@ -570,7 +498,7 @@ class FilterExpression(object):
filters.append( (filter_func,args)) filters.append( (filter_func,args))
upto = match.end() upto = match.end()
if upto != len(token): if upto != len(token):
raise TemplateSyntaxError, "Could not parse the remainder: '%s' from '%s'" % (token[upto:], token) raise TemplateSyntaxError("Could not parse the remainder: '%s' from '%s'" % (token[upto:], token))
self.filters = filters self.filters = filters
self.var = Variable(var) self.var = Variable(var)
@ -627,7 +555,7 @@ class FilterExpression(object):
provided.pop(0) provided.pop(0)
except IndexError: except IndexError:
# Not enough # Not enough
raise TemplateSyntaxError, "%s requires %d arguments, %d provided" % (name, len(nondefs), plen) raise TemplateSyntaxError("%s requires %d arguments, %d provided" % (name, len(nondefs), plen))
# Defaults can be overridden. # Defaults can be overridden.
defaults = defaults and list(defaults) or [] defaults = defaults and list(defaults) or []
@ -636,7 +564,7 @@ class FilterExpression(object):
defaults.pop(0) defaults.pop(0)
except IndexError: except IndexError:
# Too many. # Too many.
raise TemplateSyntaxError, "%s requires %d arguments, %d provided" % (name, len(nondefs), plen) raise TemplateSyntaxError("%s requires %d arguments, %d provided" % (name, len(nondefs), plen))
return True return True
args_check = staticmethod(args_check) args_check = staticmethod(args_check)
@ -816,22 +744,6 @@ class NodeList(list):
def render_node(self, node, context): def render_node(self, node, context):
return node.render(context) return node.render(context)
class DebugNodeList(NodeList):
def render_node(self, node, context):
try:
result = node.render(context)
except TemplateSyntaxError, e:
if not hasattr(e, 'source'):
e.source = node.source
raise
except Exception, e:
from sys import exc_info
wrapped = TemplateSyntaxError('Caught an exception while rendering: %s' % e)
wrapped.source = node.source
wrapped.exc_info = exc_info()
raise wrapped
return result
class TextNode(Node): class TextNode(Node):
def __init__(self, s): def __init__(self, s):
self.s = s self.s = s
@ -861,21 +773,6 @@ class VariableNode(Node):
else: else:
return force_unicode(output) return force_unicode(output)
class DebugVariableNode(VariableNode):
def render(self, context):
try:
output = force_unicode(self.filter_expression.resolve(context))
except TemplateSyntaxError, e:
if not hasattr(e, 'source'):
e.source = self.source
raise
except UnicodeDecodeError:
return ''
if (context.autoescape and not isinstance(output, SafeData)) or isinstance(output, EscapeData):
return escape(output)
else:
return output
def generic_tag_compiler(params, defaults, name, node_class, parser, token): def generic_tag_compiler(params, defaults, name, node_class, parser, token):
"Returns a template.Node subclass." "Returns a template.Node subclass."
bits = token.split_contents()[1:] bits = token.split_contents()[1:]
@ -887,7 +784,7 @@ def generic_tag_compiler(params, defaults, name, node_class, parser, token):
message = "%s takes %s arguments" % (name, bmin) message = "%s takes %s arguments" % (name, bmin)
else: else:
message = "%s takes between %s and %s arguments" % (name, bmin, bmax) message = "%s takes between %s and %s arguments" % (name, bmin, bmax)
raise TemplateSyntaxError, message raise TemplateSyntaxError(message)
return node_class(bits) return node_class(bits)
class Library(object): class Library(object):
@ -913,7 +810,7 @@ class Library(object):
self.tags[name] = compile_function self.tags[name] = compile_function
return compile_function return compile_function
else: else:
raise InvalidTemplateLibrary, "Unsupported arguments to Library.tag: (%r, %r)", (name, compile_function) raise InvalidTemplateLibrary("Unsupported arguments to Library.tag: (%r, %r)", (name, compile_function))
def tag_function(self,func): def tag_function(self,func):
self.tags[getattr(func, "_decorated_function", func).__name__] = func self.tags[getattr(func, "_decorated_function", func).__name__] = func
@ -937,7 +834,7 @@ class Library(object):
self.filters[name] = filter_func self.filters[name] = filter_func
return filter_func return filter_func
else: else:
raise InvalidTemplateLibrary, "Unsupported arguments to Library.filter: (%r, %r)", (name, filter_func) raise InvalidTemplateLibrary("Unsupported arguments to Library.filter: (%r, %r)", (name, filter_func))
def filter_function(self, func): def filter_function(self, func):
self.filters[getattr(func, "_decorated_function", func).__name__] = func self.filters[getattr(func, "_decorated_function", func).__name__] = func
@ -966,7 +863,7 @@ class Library(object):
if params[0] == 'context': if params[0] == 'context':
params = params[1:] params = params[1:]
else: else:
raise TemplateSyntaxError, "Any tag function decorated with takes_context=True must have a first argument of 'context'" raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'")
class InclusionNode(Node): class InclusionNode(Node):
def __init__(self, vars_to_resolve): def __init__(self, vars_to_resolve):
@ -1003,12 +900,12 @@ def get_library(module_name):
try: try:
mod = __import__(module_name, {}, {}, ['']) mod = __import__(module_name, {}, {}, [''])
except ImportError, e: except ImportError, e:
raise InvalidTemplateLibrary, "Could not load template library from %s, %s" % (module_name, e) raise InvalidTemplateLibrary("Could not load template library from %s, %s" % (module_name, e))
try: try:
lib = mod.register lib = mod.register
libraries[module_name] = lib libraries[module_name] = lib
except AttributeError: except AttributeError:
raise InvalidTemplateLibrary, "Template library %s does not have a variable named 'register'" % module_name raise InvalidTemplateLibrary("Template library %s does not have a variable named 'register'" % module_name)
return lib return lib
def add_to_builtins(module_name): def add_to_builtins(module_name):

View File

@ -9,7 +9,6 @@ class ContextPopException(Exception):
class Context(object): class Context(object):
"A stack container for variable context" "A stack container for variable context"
def __init__(self, dict_=None, autoescape=True): def __init__(self, dict_=None, autoescape=True):
dict_ = dict_ or {} dict_ = dict_ or {}
self.dicts = [dict_] self.dicts = [dict_]
@ -78,11 +77,11 @@ def get_standard_processors():
try: try:
mod = __import__(module, {}, {}, [attr]) mod = __import__(module, {}, {}, [attr])
except ImportError, e: except ImportError, e:
raise ImproperlyConfigured, 'Error importing request processor module %s: "%s"' % (module, e) raise ImproperlyConfigured('Error importing request processor module %s: "%s"' % (module, e))
try: try:
func = getattr(mod, attr) func = getattr(mod, attr)
except AttributeError: except AttributeError:
raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable request processor' % (module, attr) raise ImproperlyConfigured('Module "%s" does not define a "%s" callable request processor' % (module, attr))
processors.append(func) processors.append(func)
_standard_context_processors = tuple(processors) _standard_context_processors = tuple(processors)
return _standard_context_processors return _standard_context_processors
@ -102,4 +101,3 @@ class RequestContext(Context):
processors = tuple(processors) processors = tuple(processors)
for processor in get_standard_processors() + processors: for processor in get_standard_processors() + processors:
self.update(processor(request)) self.update(processor(request))

97
django/template/debug.py Normal file
View File

@ -0,0 +1,97 @@
from django.template import Lexer, Parser, tag_re, NodeList, VariableNode, TemplateSyntaxError
from django.utils.encoding import force_unicode
from django.utils.html import escape
from django.utils.safestring import SafeData, EscapeData
class DebugLexer(Lexer):
def __init__(self, template_string, origin):
super(DebugLexer, self).__init__(template_string, origin)
def tokenize(self):
"Return a list of tokens from a given template_string"
result, upto = [], 0
for match in tag_re.finditer(self.template_string):
start, end = match.span()
if start > upto:
result.append(self.create_token(self.template_string[upto:start], (upto, start), False))
upto = start
result.append(self.create_token(self.template_string[start:end], (start, end), True))
upto = end
last_bit = self.template_string[upto:]
if last_bit:
result.append(self.create_token(last_bit, (upto, upto + len(last_bit)), False))
return result
def create_token(self, token_string, source, in_tag):
token = super(DebugLexer, self).create_token(token_string, in_tag)
token.source = self.origin, source
return token
class DebugParser(Parser):
def __init__(self, lexer):
super(DebugParser, self).__init__(lexer)
self.command_stack = []
def enter_command(self, command, token):
self.command_stack.append( (command, token.source) )
def exit_command(self):
self.command_stack.pop()
def error(self, token, msg):
return self.source_error(token.source, msg)
def source_error(self, source,msg):
e = TemplateSyntaxError(msg)
e.source = source
return e
def create_nodelist(self):
return DebugNodeList()
def create_variable_node(self, contents):
return DebugVariableNode(contents)
def extend_nodelist(self, nodelist, node, token):
node.source = token.source
super(DebugParser, self).extend_nodelist(nodelist, node, token)
def unclosed_block_tag(self, parse_until):
command, source = self.command_stack.pop()
msg = "Unclosed tag '%s'. Looking for one of: %s " % (command, ', '.join(parse_until))
raise self.source_error(source, msg)
def compile_function_error(self, token, e):
if not hasattr(e, 'source'):
e.source = token.source
class DebugNodeList(NodeList):
def render_node(self, node, context):
try:
result = node.render(context)
except TemplateSyntaxError, e:
if not hasattr(e, 'source'):
e.source = node.source
raise
except Exception, e:
from sys import exc_info
wrapped = TemplateSyntaxError('Caught an exception while rendering: %s' % e)
wrapped.source = node.source
wrapped.exc_info = exc_info()
raise wrapped
return result
class DebugVariableNode(VariableNode):
def render(self, context):
try:
output = force_unicode(self.filter_expression.resolve(context))
except TemplateSyntaxError, e:
if not hasattr(e, 'source'):
e.source = self.source
raise
except UnicodeDecodeError:
return ''
if (context.autoescape and not isinstance(output, SafeData)) or isinstance(output, EscapeData):
return escape(output)
else:
return output

View File

@ -433,7 +433,7 @@ def first(value):
return value[0] return value[0]
except IndexError: except IndexError:
return u'' return u''
first.is_safe = True first.is_safe = False
def join(value, arg): def join(value, arg):
"""Joins a list with a string, like Python's ``str.join(list)``.""" """Joins a list with a string, like Python's ``str.join(list)``."""
@ -449,6 +449,14 @@ def join(value, arg):
return data return data
join.is_safe = True join.is_safe = True
def last(value):
"Returns the last item in a list"
try:
return value[-1]
except IndexError:
return u''
last.is_safe = True
def length(value): def length(value):
"""Returns the length of the value - useful for lists.""" """Returns the length of the value - useful for lists."""
return len(value) return len(value)
@ -800,6 +808,7 @@ register.filter(force_escape)
register.filter(get_digit) register.filter(get_digit)
register.filter(iriencode) register.filter(iriencode)
register.filter(join) register.filter(join)
register.filter(last)
register.filter(length) register.filter(length)
register.filter(length_is) register.filter(length_is)
register.filter(linebreaks) register.filter(linebreaks)

View File

@ -84,19 +84,16 @@ class FirstOfNode(Node):
return u'' return u''
class ForNode(Node): class ForNode(Node):
def __init__(self, loopvars, sequence, reversed, nodelist_loop): def __init__(self, loopvars, sequence, is_reversed, nodelist_loop):
self.loopvars, self.sequence = loopvars, sequence self.loopvars, self.sequence = loopvars, sequence
self.reversed = reversed self.is_reversed = is_reversed
self.nodelist_loop = nodelist_loop self.nodelist_loop = nodelist_loop
def __repr__(self): def __repr__(self):
if self.reversed: reversed_text = self.is_reversed and ' reversed' or ''
reversed = ' reversed'
else:
reversed = ''
return "<For Node: for %s in %s, tail_len: %d%s>" % \ return "<For Node: for %s in %s, tail_len: %d%s>" % \
(', '.join(self.loopvars), self.sequence, len(self.nodelist_loop), (', '.join(self.loopvars), self.sequence, len(self.nodelist_loop),
reversed) reversed_text)
def __iter__(self): def __iter__(self):
for node in self.nodelist_loop: for node in self.nodelist_loop:
@ -125,22 +122,23 @@ class ForNode(Node):
if not hasattr(values, '__len__'): if not hasattr(values, '__len__'):
values = list(values) values = list(values)
len_values = len(values) len_values = len(values)
if self.reversed: if self.is_reversed:
values = reversed(values) values = reversed(values)
unpack = len(self.loopvars) > 1 unpack = len(self.loopvars) > 1
# Create a forloop value in the context. We'll update counters on each
# iteration just below.
loop_dict = context['forloop'] = {'parentloop': parentloop}
for i, item in enumerate(values): for i, item in enumerate(values):
context['forloop'] = {
# Shortcuts for current loop iteration number. # Shortcuts for current loop iteration number.
'counter0': i, loop_dict['counter0'] = i
'counter': i+1, loop_dict['counter'] = i+1
# Reverse counter iteration numbers. # Reverse counter iteration numbers.
'revcounter': len_values - i, loop_dict['revcounter'] = len_values - i
'revcounter0': len_values - i - 1, loop_dict['revcounter0'] = len_values - i - 1
# Boolean values designating first and last times through loop. # Boolean values designating first and last times through loop.
'first': (i == 0), loop_dict['first'] = (i == 0)
'last': (i == len_values - 1), loop_dict['last'] = (i == len_values - 1)
'parentloop': parentloop,
}
if unpack: if unpack:
# If there are multiple loop variables, unpack the item into # If there are multiple loop variables, unpack the item into
# them. # them.
@ -619,8 +617,8 @@ def do_for(parser, token):
raise TemplateSyntaxError("'for' statements should have at least four" raise TemplateSyntaxError("'for' statements should have at least four"
" words: %s" % token.contents) " words: %s" % token.contents)
reversed = bits[-1] == 'reversed' is_reversed = bits[-1] == 'reversed'
in_index = reversed and -3 or -2 in_index = is_reversed and -3 or -2
if bits[in_index] != 'in': if bits[in_index] != 'in':
raise TemplateSyntaxError("'for' statements should use the format" raise TemplateSyntaxError("'for' statements should use the format"
" 'for x in y': %s" % token.contents) " 'for x in y': %s" % token.contents)
@ -634,7 +632,7 @@ def do_for(parser, token):
sequence = parser.compile_filter(bits[in_index+1]) sequence = parser.compile_filter(bits[in_index+1])
nodelist_loop = parser.parse(('endfor',)) nodelist_loop = parser.parse(('endfor',))
parser.delete_first_token() parser.delete_first_token()
return ForNode(loopvars, sequence, reversed, nodelist_loop) return ForNode(loopvars, sequence, is_reversed, nodelist_loop)
do_for = register.tag("for", do_for) do_for = register.tag("for", do_for)
def do_ifequal(parser, token, negate): def do_ifequal(parser, token, negate):

View File

@ -507,7 +507,7 @@ Exception Type: {{ exception_type|escape }} at {{ request.path|escape }}
Exception Value: {{ exception_value|escape }} Exception Value: {{ exception_value|escape }}
</textarea> </textarea>
<br><br> <br><br>
<input type="submit" value="Share this traceback on public Web site"> <input type="submit" value="Share this traceback on a public Web site">
</div> </div>
</form> </form>
</div> </div>

View File

@ -57,7 +57,7 @@ worth using only if it creates a huge convenience unattainable in other ways,
and it isn't implemented in a way that confuses developers who are trying to and it isn't implemented in a way that confuses developers who are trying to
learn how to use the feature. learn how to use the feature.
.. _`core Python principle`: http://www.python.org/doc/Humor.html#zen .. _`core Python principle`: http://www.python.org/dev/peps/pep-0020/
Consistency Consistency
----------- -----------

View File

@ -60,22 +60,22 @@ point to find their preferred version.
Gentoo Gentoo
------ ------
A Django build is available for `Gentoo Linux`_, and is based on Django 0.96. A Django package is available for `Gentoo Linux`_, and is based on Django 0.96.1.
The `current Gentoo build`_ can be installed by typing ``emerge django``. The `current Gentoo package`_ can be installed by typing ``emerge django``.
.. _Gentoo Linux: http://www.gentoo.org/ .. _Gentoo Linux: http://www.gentoo.org/
.. _current Gentoo build: http://packages.gentoo.org/packages/?category=dev-python;name=django .. _current Gentoo package: http://packages.gentoo.org/package/django
Ubuntu Ubuntu
------ ------
The Debian ``python-django`` package is also available for `Ubuntu Linux`_, in The Debian ``python-django`` package is also available for `Ubuntu Linux`_, in
the "universe" repository for Ubuntu 7.04 ("Feisty Fawn"). The `current Ubuntu the "universe" repository for Ubuntu 7.10 ("Gutsy Gibbon"). The `current Ubuntu
package`_ is also based on Django 0.95.1 and can be installed in the same package`_ is based on Django 0.96.1 and can be installed in the same fashion as
fashion as for Debian. for Debian.
.. _Ubuntu Linux: http://www.ubuntu.com/ .. _Ubuntu Linux: http://www.ubuntu.com/
.. _current Ubuntu package: http://packages.ubuntu.com/feisty/python/python-django .. _current Ubuntu package: http://packages.ubuntu.com/gutsy/python/python-django
Mac OS X Mac OS X

View File

@ -716,8 +716,8 @@ in Python package syntax, e.g. ``mysite.settings``. If this isn't provided,
``django-admin.py`` will use the ``DJANGO_SETTINGS_MODULE`` environment ``django-admin.py`` will use the ``DJANGO_SETTINGS_MODULE`` environment
variable. variable.
Note that this option is unnecessary in ``manage.py``, because it takes care of Note that this option is unnecessary in ``manage.py``, because it uses
setting ``DJANGO_SETTINGS_MODULE`` for you. ``settings.py`` from the current project by default.
Extra niceties Extra niceties
============== ==============

View File

@ -100,6 +100,8 @@ any code you'd like to contribute. One thing we ask is that you please use
Unicode objects (``u'mystring'``) for strings, rather than setting the encoding Unicode objects (``u'mystring'``) for strings, rather than setting the encoding
in the file. See any of the existing flavors for examples. in the file. See any of the existing flavors for examples.
.. _create a ticket: http://code.djangoproject.com/simpleticket
Argentina (``django.contrib.localflavor.ar``) Argentina (``django.contrib.localflavor.ar``)
============================================= =============================================
@ -181,7 +183,7 @@ CASocialInsuranceNumberField
---------------------------- ----------------------------
A form field that validates input as a Canadian Social Insurance Number (SIN). A form field that validates input as a Canadian Social Insurance Number (SIN).
A valid number must have the format XXX-XXX-XXXX and pass a `Luhn mod-10 A valid number must have the format XXX-XXX-XXX and pass a `Luhn mod-10
checksum`_. checksum`_.
.. _Luhn mod-10 checksum: http://en.wikipedia.org/wiki/Luhn_algorithm .. _Luhn mod-10 checksum: http://en.wikipedia.org/wiki/Luhn_algorithm

View File

@ -154,6 +154,17 @@ every incoming ``HttpRequest`` object. See `Authentication in Web requests`_.
.. _Authentication in Web requests: ../authentication/#authentication-in-web-requests .. _Authentication in Web requests: ../authentication/#authentication-in-web-requests
django.contrib.csrf.middleware.CsrfMiddleware
---------------------------------------------
**New in Django development version**
Adds protection against Cross Site Request Forgeries by adding hidden form
fields to POST forms and checking requests for the correct value. See the
`Cross Site Request Forgery protection documentation`_.
.. _`Cross Site Request Forgery protection documentation`: ../csrf/
django.middleware.transaction.TransactionMiddleware django.middleware.transaction.TransactionMiddleware
--------------------------------------------------- ---------------------------------------------------

View File

@ -94,7 +94,7 @@ This example is equivalent to::
def my_view(request): def my_view(request):
try: try:
my_object = MyModel.object.get(pk=1) my_object = MyModel.objects.get(pk=1)
except MyModel.DoesNotExist: except MyModel.DoesNotExist:
raise Http404 raise Http404
@ -136,7 +136,7 @@ This example is equivalent to::
from django.http import Http404 from django.http import Http404
def my_view(request): def my_view(request):
my_objects = MyModels.object.filter(published=True) my_objects = MyModel.objects.filter(published=True)
if not my_objects: if not my_objects:
raise Http404 raise Http404

View File

@ -97,7 +97,7 @@ Hooking into the current site from views
---------------------------------------- ----------------------------------------
On a lower level, you can use the sites framework in your Django views to do On a lower level, you can use the sites framework in your Django views to do
particular things based on what site in which the view is being called. particular things based on the site in which the view is being called.
For example:: For example::
from django.conf import settings from django.conf import settings
@ -330,13 +330,13 @@ Here's how Django uses the sites framework:
retrieving flatpages to display. retrieving flatpages to display.
* In the `syndication framework`_, the templates for ``title`` and * In the `syndication framework`_, the templates for ``title`` and
``description`` automatically have access to a variable ``{{{ site }}}``, ``description`` automatically have access to a variable ``{{ site }}``,
which is the ``Site`` object representing the current site. Also, the which is the ``Site`` object representing the current site. Also, the
hook for providing item URLs will use the ``domain`` from the current hook for providing item URLs will use the ``domain`` from the current
``Site`` object if you don't specify a fully-qualified domain. ``Site`` object if you don't specify a fully-qualified domain.
* In the `authentication framework`_, the ``django.contrib.auth.views.login`` * In the `authentication framework`_, the ``django.contrib.auth.views.login``
view passes the current ``Site`` name to the template as ``{{{ site_name }}}``. view passes the current ``Site`` name to the template as ``{{ site_name }}``.
* The shortcut view (``django.views.defaults.shortcut``) uses the domain of * The shortcut view (``django.views.defaults.shortcut``) uses the domain of
the current ``Site`` object when calculating an object's URL. the current ``Site`` object when calculating an object's URL.

View File

@ -201,7 +201,7 @@ the feed.
An example makes this clear. Here's the code for these beat-specific feeds:: An example makes this clear. Here's the code for these beat-specific feeds::
from django.contrib.syndication import FeedDoesNotExist from django.contrib.syndication.feeds import FeedDoesNotExist
class BeatFeed(Feed): class BeatFeed(Feed):
def get_object(self, bits): def get_object(self, bits):

View File

@ -953,7 +953,7 @@ Available format strings:
U Not implemented. U Not implemented.
w Day of the week, digits without ``'0'`` (Sunday) to ``'6'`` (Saturday) w Day of the week, digits without ``'0'`` (Sunday) to ``'6'`` (Saturday)
leading zeros. leading zeros.
W ISO-8601 week number of year, with ``1``, ``23`` W ISO-8601 week number of year, with ``1``, ``53``
weeks starting on Monday. weeks starting on Monday.
y Year, 2 digits. ``'99'`` y Year, 2 digits. ``'99'``
Y Year, 4 digits. ``'1999'`` Y Year, 4 digits. ``'1999'``
@ -1230,7 +1230,7 @@ addslashes
Adds slashes before quotes. Useful for escaping strings in CSV, for example. Adds slashes before quotes. Useful for escaping strings in CSV, for example.
**New in Django development version**: for escaping data in JavaScript strings, **New in Django development version**: for escaping data in JavaScript strings,
use the `escapejs` filter instead. use the `escapejs`_ filter instead.
capfirst capfirst
~~~~~~~~ ~~~~~~~~
@ -1403,6 +1403,11 @@ join
Joins a list with a string, like Python's ``str.join(list)``. Joins a list with a string, like Python's ``str.join(list)``.
last
~~~~
Returns the last item in a list.
length length
~~~~~~ ~~~~~~

View File

@ -823,11 +823,11 @@ Template filter code falls into one of two situations:
can operate in templates where auto-escaping is either on or off in can operate in templates where auto-escaping is either on or off in
order to make things easier for your template authors. order to make things easier for your template authors.
In order for you filter to know the current auto-escaping state, set the In order for your filter to know the current auto-escaping state, set
``needs_autoescape`` attribute to ``True`` on your function. (If you the ``needs_autoescape`` attribute to ``True`` on your function. (If you
don't specify this attribute, it defaults to ``False``). This attribute don't specify this attribute, it defaults to ``False``). This attribute
tells Django that your filter function wants to be passed an extra tells Django that your filter function wants to be passed an extra
keyword argument, called ``autoescape``, that is ``True`` is keyword argument, called ``autoescape``, that is ``True`` if
auto-escaping is in effect and ``False`` otherwise. auto-escaping is in effect and ``False`` otherwise.
For example, let's write a filter that emphasizes the first character of For example, let's write a filter that emphasizes the first character of

View File

@ -14,7 +14,7 @@ from django.db import models
class Category(models.Model): class Category(models.Model):
name = models.CharField(max_length=20) name = models.CharField(max_length=20)
parent = models.ForeignKey('self', null=True, related_name='child_set') parent = models.ForeignKey('self', blank=True, null=True, related_name='child_set')
def __unicode__(self): def __unicode__(self):
return self.name return self.name

View File

@ -7,6 +7,9 @@ examples are probably a poor fit for the ModelForm syntax. In other words,
most of these tests should be rewritten. most of these tests should be rewritten.
""" """
import os
import tempfile
from django.db import models from django.db import models
ARTICLE_STATUS = ( ARTICLE_STATUS = (
@ -55,6 +58,13 @@ class PhoneNumber(models.Model):
def __unicode__(self): def __unicode__(self):
return self.phone return self.phone
class TextFile(models.Model):
description = models.CharField(max_length=20)
file = models.FileField(upload_to=tempfile.gettempdir())
def __unicode__(self):
return self.description
__test__ = {'API_TESTS': """ __test__ = {'API_TESTS': """
>>> from django import newforms as forms >>> from django import newforms as forms
>>> from django.newforms.models import ModelForm >>> from django.newforms.models import ModelForm
@ -701,4 +711,75 @@ ValidationError: [u'Select a valid choice. 4 is not one of the available choices
True True
>>> f.cleaned_data >>> f.cleaned_data
{'phone': u'312-555-1212', 'description': u'Assistance'} {'phone': u'312-555-1212', 'description': u'Assistance'}
# FileField ###################################################################
>>> class TextFileForm(ModelForm):
... class Meta:
... model = TextFile
Test conditions when files is either not given or empty.
>>> f = TextFileForm(data={'description': u'Assistance'})
>>> f.is_valid()
False
>>> f = TextFileForm(data={'description': u'Assistance'}, files={})
>>> f.is_valid()
False
Upload a file and ensure it all works as expected.
>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test1.txt', 'content': 'hello world'}})
>>> f.is_valid()
True
>>> type(f.cleaned_data['file'])
<class 'django.newforms.fields.UploadedFile'>
>>> instance = f.save()
>>> instance.file
u'.../test1.txt'
Edit an instance that already has the file defined in the model. This will not
save the file again, but leave it exactly as it is.
>>> f = TextFileForm(data={'description': u'Assistance'}, instance=instance)
>>> f.is_valid()
True
>>> f.cleaned_data['file']
u'.../test1.txt'
>>> instance = f.save()
>>> instance.file
u'.../test1.txt'
Delete the current file since this is not done by Django.
>>> os.unlink(instance.get_file_filename())
Override the file by uploading a new one.
>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test2.txt', 'content': 'hello world'}}, instance=instance)
>>> f.is_valid()
True
>>> instance = f.save()
>>> instance.file
u'.../test2.txt'
>>> instance.delete()
Test the non-required FileField
>>> f = TextFileForm(data={'description': u'Assistance'})
>>> f.fields['file'].required = False
>>> f.is_valid()
True
>>> instance = f.save()
>>> instance.file
''
>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test3.txt', 'content': 'hello world'}}, instance=instance)
>>> f.is_valid()
True
>>> instance = f.save()
>>> instance.file
u'.../test3.txt'
>>> instance.delete()
"""} """}

View File

@ -8,6 +8,13 @@ class Square(models.Model):
def __unicode__(self): def __unicode__(self):
return "%s ** 2 == %s" % (self.root, self.square) return "%s ** 2 == %s" % (self.root, self.square)
class Person(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
def __unicode__(self):
return u'%s %s' % (self.first_name, self.last_name)
if connection.features.uses_case_insensitive_names: if connection.features.uses_case_insensitive_names:
t_convert = lambda x: x.upper() t_convert = lambda x: x.upper()
else: else:
@ -32,4 +39,25 @@ __test__ = {'API_TESTS': """
>>> Square.objects.count() >>> Square.objects.count()
11 11
#6254: fetchone, fetchmany, fetchall return strings as unicode objects
>>> Person(first_name="John", last_name="Doe").save()
>>> Person(first_name="Jane", last_name="Doe").save()
>>> Person(first_name="Mary", last_name="Agnelline").save()
>>> Person(first_name="Peter", last_name="Parker").save()
>>> Person(first_name="Clark", last_name="Kent").save()
>>> opts2 = Person._meta
>>> f3, f4 = opts2.get_field('first_name'), opts2.get_field('last_name')
>>> query2 = ('SELECT %s, %s FROM %s ORDER BY %s'
... % (qn(f3.column), qn(f4.column), t_convert(opts2.db_table),
... qn(f3.column)))
>>> cursor.execute(query2) and None or None
>>> cursor.fetchone()
(u'Clark', u'Kent')
>>> list(cursor.fetchmany(2))
[(u'Jane', u'Doe'), (u'John', u'Doe')]
>>> list(cursor.fetchall())
[(u'Mary', u'Agnelline'), (u'Peter', u'Parker')]
"""} """}

View File

@ -749,16 +749,40 @@ Traceback (most recent call last):
... ...
ValidationError: [u'This field is required.'] ValidationError: [u'This field is required.']
>>> f.clean('', '')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('', 'files/test1.pdf')
'files/test1.pdf'
>>> f.clean(None) >>> f.clean(None)
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'This field is required.'] ValidationError: [u'This field is required.']
>>> f.clean(None, '')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean(None, 'files/test2.pdf')
'files/test2.pdf'
>>> f.clean({}) >>> f.clean({})
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'No file was submitted.'] ValidationError: [u'No file was submitted.']
>>> f.clean({}, '')
Traceback (most recent call last):
...
ValidationError: [u'No file was submitted.']
>>> f.clean({}, 'files/test3.pdf')
'files/test3.pdf'
>>> f.clean('some content that is not a file') >>> f.clean('some content that is not a file')
Traceback (most recent call last): Traceback (most recent call last):
... ...
@ -777,6 +801,9 @@ ValidationError: [u'The submitted file is empty.']
>>> type(f.clean({'filename': 'name', 'content': 'Some File Content'})) >>> type(f.clean({'filename': 'name', 'content': 'Some File Content'}))
<class 'django.newforms.fields.UploadedFile'> <class 'django.newforms.fields.UploadedFile'>
>>> type(f.clean({'filename': 'name', 'content': 'Some File Content'}, 'files/test4.pdf'))
<class 'django.newforms.fields.UploadedFile'>
# URLField ################################################################## # URLField ##################################################################
>>> f = URLField() >>> f = URLField()

View File

@ -213,13 +213,13 @@ u'046-454-286'
>>> f.clean('046-454-287') >>> f.clean('046-454-287')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'] ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXX format.']
>>> f.clean('046 454 286') >>> f.clean('046 454 286')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'] ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXX format.']
>>> f.clean('046-44-286') >>> f.clean('046-44-286')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format.'] ValidationError: [u'Enter a valid Canadian Social Insurance number in XXX-XXX-XXX format.']
""" """

View File

@ -0,0 +1 @@
# models.py file for tests to run.

View File

@ -1,7 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import unittest
from django.test import TestCase from django.test import TestCase
from django.http import HttpRequest from django.http import HttpRequest
from django.middleware.common import CommonMiddleware from django.middleware.common import CommonMiddleware
@ -19,7 +17,7 @@ class CommonMiddlewareTest(TestCase):
def test_append_slash_have_slash(self): def test_append_slash_have_slash(self):
""" """
tests that urls with slashes go unmolested Tests that URLs with slashes go unmolested.
""" """
settings.APPEND_SLASH = True settings.APPEND_SLASH = True
request = self._get_request('slash/') request = self._get_request('slash/')
@ -27,7 +25,7 @@ class CommonMiddlewareTest(TestCase):
def test_append_slash_slashless_resource(self): def test_append_slash_slashless_resource(self):
""" """
tests that matches to explicit slashless urls go unmolested Tests that matches to explicit slashless URLs go unmolested.
""" """
settings.APPEND_SLASH = True settings.APPEND_SLASH = True
request = self._get_request('noslash') request = self._get_request('noslash')
@ -35,7 +33,7 @@ class CommonMiddlewareTest(TestCase):
def test_append_slash_slashless_unknown(self): def test_append_slash_slashless_unknown(self):
""" """
tests that APPEND_SLASH doesn't redirect to unknown resources Tests that APPEND_SLASH doesn't redirect to unknown resources.
""" """
settings.APPEND_SLASH = True settings.APPEND_SLASH = True
request = self._get_request('unknown') request = self._get_request('unknown')
@ -43,7 +41,7 @@ class CommonMiddlewareTest(TestCase):
def test_append_slash_redirect(self): def test_append_slash_redirect(self):
""" """
tests that APPEND_SLASH redirects slashless urls to a valid pattern Tests that APPEND_SLASH redirects slashless URLs to a valid pattern.
""" """
settings.APPEND_SLASH = True settings.APPEND_SLASH = True
request = self._get_request('slash') request = self._get_request('slash')
@ -53,9 +51,9 @@ class CommonMiddlewareTest(TestCase):
def test_append_slash_no_redirect_on_POST_in_DEBUG(self): def test_append_slash_no_redirect_on_POST_in_DEBUG(self):
""" """
tests that while in debug mode, an exception is raised with a warning Tests that while in debug mode, an exception is raised with a warning
when a failed attempt is made to POST to an url which would normally be when a failed attempt is made to POST to an URL which would normally be
redirected to a slashed version redirected to a slashed version.
""" """
settings.APPEND_SLASH = True settings.APPEND_SLASH = True
settings.DEBUG = True settings.DEBUG = True
@ -68,11 +66,12 @@ class CommonMiddlewareTest(TestCase):
try: try:
CommonMiddleware().process_request(request) CommonMiddleware().process_request(request)
except RuntimeError, e: except RuntimeError, e:
self.assertTrue('end in a slash' in str(e)) self.failUnless('end in a slash' in str(e))
settings.DEBUG = False
def test_append_slash_disabled(self): def test_append_slash_disabled(self):
""" """
tests disabling append slash functionality Tests disabling append slash functionality.
""" """
settings.APPEND_SLASH = False settings.APPEND_SLASH = False
request = self._get_request('slash') request = self._get_request('slash')
@ -80,8 +79,8 @@ class CommonMiddlewareTest(TestCase):
def test_append_slash_quoted(self): def test_append_slash_quoted(self):
""" """
tests that urls which require quoting are redirected to their slash Tests that URLs which require quoting are redirected to their slash
version ok version ok.
""" """
settings.APPEND_SLASH = True settings.APPEND_SLASH = True
request = self._get_request('needsquoting#') request = self._get_request('needsquoting#')
@ -90,4 +89,3 @@ class CommonMiddlewareTest(TestCase):
self.assertEquals( self.assertEquals(
r['Location'], r['Location'],
'http://testserver/middleware/needsquoting%23/') 'http://testserver/middleware/needsquoting%23/')

View File

@ -179,6 +179,9 @@ def get_filter_tests():
'filter-first01': ('{{ a|first }} {{ b|first }}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&amp;b a&b"), 'filter-first01': ('{{ a|first }} {{ b|first }}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&amp;b a&b"),
'filter-first02': ('{% autoescape off %}{{ a|first }} {{ b|first }}{% endautoescape %}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&b a&b"), 'filter-first02': ('{% autoescape off %}{{ a|first }} {{ b|first }}{% endautoescape %}', {"a": ["a&b", "x"], "b": [mark_safe("a&b"), "x"]}, "a&b a&b"),
'filter-last01': ('{{ a|last }} {{ b|last }}', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]}, "a&amp;b a&b"),
'filter-last02': ('{% autoescape off %}{{ a|last }} {{ b|last }}{% endautoescape %}', {"a": ["x", "a&b"], "b": ["x", mark_safe("a&b")]}, "a&b a&b"),
'filter-random01': ('{{ a|random }} {{ b|random }}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&amp;b a&b"), 'filter-random01': ('{{ a|random }} {{ b|random }}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&amp;b a&b"),
'filter-random02': ('{% autoescape off %}{{ a|random }} {{ b|random }}{% endautoescape %}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&b a&b"), 'filter-random02': ('{% autoescape off %}{{ a|random }} {{ b|random }}{% endautoescape %}', {"a": ["a&b", "a&b"], "b": [mark_safe("a&b"), mark_safe("a&b")]}, "a&b a&b"),

View File

@ -441,6 +441,8 @@ class Templates(unittest.TestCase):
'for-tag-vars02': ("{% for val in values %}{{ forloop.counter0 }}{% endfor %}", {"values": [6, 6, 6]}, "012"), 'for-tag-vars02': ("{% for val in values %}{{ forloop.counter0 }}{% endfor %}", {"values": [6, 6, 6]}, "012"),
'for-tag-vars03': ("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"), 'for-tag-vars03': ("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"),
'for-tag-vars04': ("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"), 'for-tag-vars04': ("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"),
'for-tag-vars05': ("{% for val in values %}{% if forloop.first %}f{% else %}x{% endif %}{% endfor %}", {"values": [6, 6, 6]}, "fxx"),
'for-tag-vars06': ("{% for val in values %}{% if forloop.last %}l{% else %}x{% endif %}{% endfor %}", {"values": [6, 6, 6]}, "xxl"),
'for-tag-unpack01': ("{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 'for-tag-unpack01': ("{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"),
'for-tag-unpack03': ("{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 'for-tag-unpack03': ("{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"),
'for-tag-unpack04': ("{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 'for-tag-unpack04': ("{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"),