1
0
mirror of https://github.com/django/django.git synced 2025-07-06 02:39:12 +00:00

queryset-refactor: Merged from trunk up to [6724].

git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@6726 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-11-28 21:51:17 +00:00
parent 5d85a5147b
commit a97abcffc2
34 changed files with 892 additions and 327 deletions

View File

@ -11,11 +11,10 @@ except NameError:
def compile_messages(locale=None):
basedirs = [os.path.join('conf', 'locale'), 'locale']
basedirs = (os.path.join('conf', 'locale'), 'locale')
if os.environ.get('DJANGO_SETTINGS_MODULE'):
from django.conf import settings
if hasattr(settings, 'LOCALE_PATHS'):
basedirs += settings.LOCALE_PATHS
basedirs += settings.LOCALE_PATHS
# Gather existing directories.
basedirs = set(map(os.path.abspath, filter(os.path.isdir, basedirs)))

View File

@ -90,6 +90,8 @@ LANGUAGES_BIDI = ("he", "ar", "fa")
# to load the internationalization machinery.
USE_I18N = True
LOCALE_PATHS = ()
# Not-necessarily-technical managers of the site. They get broken link
# notifications and other various e-mails.
MANAGERS = ADMINS

View File

@ -5,7 +5,7 @@ msgid ""
msgstr ""
"Project-Id-Version: django\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-11-13 21:55+0100\n"
"POT-Creation-Date: 2007-11-15 15:28+0100\n"
"PO-Revision-Date: 2007-05-08 20:29+0200\n"
"Last-Translator: Jarek Zgoda <jarek.zgoda@gmail.com>\n"
"Language-Team: Polish <pl@li.org>\n"
@ -196,7 +196,7 @@ msgstr "Uproszczony chiński"
msgid "Traditional Chinese"
msgstr "Chiński tradycyjny"
#: contrib/admin/filterspecs.py:42
#: contrib/admin/filterspecs.py:44
#, python-format
msgid ""
"<h3>By %s:</h3>\n"
@ -205,71 +205,71 @@ msgstr ""
"<h3>Przez %s:</h3>\n"
"</ul>\n"
#: contrib/admin/filterspecs.py:72 contrib/admin/filterspecs.py:90
#: contrib/admin/filterspecs.py:145 contrib/admin/filterspecs.py:171
#: contrib/admin/filterspecs.py:74 contrib/admin/filterspecs.py:92
#: contrib/admin/filterspecs.py:147 contrib/admin/filterspecs.py:173
msgid "All"
msgstr "Wszystko"
#: contrib/admin/filterspecs.py:111
#: contrib/admin/filterspecs.py:113
msgid "Any date"
msgstr "Dowolna data"
#: contrib/admin/filterspecs.py:112
#: contrib/admin/filterspecs.py:114
msgid "Today"
msgstr "Dzisiaj"
#: contrib/admin/filterspecs.py:115
#: contrib/admin/filterspecs.py:117
msgid "Past 7 days"
msgstr "Ostatnie 7 dni"
#: contrib/admin/filterspecs.py:117
#: contrib/admin/filterspecs.py:119
msgid "This month"
msgstr "Ten miesiąc"
#: contrib/admin/filterspecs.py:119
#: contrib/admin/filterspecs.py:121
msgid "This year"
msgstr "Ten rok"
#: contrib/admin/filterspecs.py:145 newforms/widgets.py:221
#: oldforms/__init__.py:591
#: contrib/admin/filterspecs.py:147 newforms/widgets.py:229
#: oldforms/__init__.py:592
msgid "Yes"
msgstr "Tak"
#: contrib/admin/filterspecs.py:145 newforms/widgets.py:221
#: oldforms/__init__.py:591
#: contrib/admin/filterspecs.py:147 newforms/widgets.py:229
#: oldforms/__init__.py:592
msgid "No"
msgstr "Nie"
#: contrib/admin/filterspecs.py:152 newforms/widgets.py:221
#: oldforms/__init__.py:591
#: contrib/admin/filterspecs.py:154 newforms/widgets.py:229
#: oldforms/__init__.py:592
msgid "Unknown"
msgstr "Nieznany"
#: contrib/admin/models.py:17
#: contrib/admin/models.py:18
msgid "action time"
msgstr "czas akcji"
#: contrib/admin/models.py:20
#: contrib/admin/models.py:21
msgid "object id"
msgstr "id obiektu"
#: contrib/admin/models.py:21
#: contrib/admin/models.py:22
msgid "object repr"
msgstr "reprezentacj obiektu"
#: contrib/admin/models.py:22
#: contrib/admin/models.py:23
msgid "action flag"
msgstr "flaga akcji"
#: contrib/admin/models.py:23
#: contrib/admin/models.py:24
msgid "change message"
msgstr "zmień wiadomość"
#: contrib/admin/models.py:26
#: contrib/admin/models.py:27
msgid "log entry"
msgstr "log"
#: contrib/admin/models.py:27
#: contrib/admin/models.py:28
msgid "log entries"
msgstr "logi"
@ -472,7 +472,7 @@ msgid "Password:"
msgstr "Hasło:"
#: contrib/admin/templates/admin/login.html:25
#: contrib/admin/views/decorators.py:24
#: contrib/admin/views/decorators.py:25
msgid "Log in"
msgstr "Zaloguj się"
@ -764,17 +764,17 @@ msgstr "Teraz:"
msgid "Change:"
msgstr "Zmień:"
#: contrib/admin/templatetags/admin_list.py:254
#: contrib/admin/templatetags/admin_list.py:255
msgid "All dates"
msgstr "Wszystkie daty"
#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:264
#: contrib/admin/views/auth.py:20 contrib/admin/views/main.py:267
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "%(name)s \"%(obj)s\" dodany pomyślnie."
#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:268
#: contrib/admin/views/main.py:354
#: contrib/admin/views/auth.py:25 contrib/admin/views/main.py:271
#: contrib/admin/views/main.py:357
msgid "You may edit it again below."
msgstr "Możesz ponownie edytować wpis poniżej."
@ -791,7 +791,7 @@ msgstr "Hasło zostało zmienione pomyślnie."
msgid "Change password: %s"
msgstr "Zmień hasło: %s"
#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:60
#: contrib/admin/views/decorators.py:11 contrib/auth/forms.py:60
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
@ -799,7 +799,7 @@ msgstr ""
"Proszę wpisać poprawną nazwę użytkownika i hasło. Uwaga: wielkość liter ma "
"znaczenie."
#: contrib/admin/views/decorators.py:62
#: contrib/admin/views/decorators.py:63
msgid ""
"Please log in again, because your session has expired. Don't worry: Your "
"submission has been saved."
@ -807,7 +807,7 @@ msgstr ""
"Zaloguj się ponownie. Twoja sesja wygasła lecz twoje zgłoszenie zostało "
"zapisane."
#: contrib/admin/views/decorators.py:69
#: contrib/admin/views/decorators.py:70
msgid ""
"Looks like your browser isn't configured to accept cookies. Please enable "
"cookies, reload this page, and try again."
@ -815,246 +815,246 @@ msgstr ""
"Twoja przeglądarka nie chce akceptować ciasteczek. Zmień jej ustawienia i "
"spróbuj ponownie."
#: contrib/admin/views/decorators.py:83
#: contrib/admin/views/decorators.py:84
msgid "Usernames cannot contain the '@' character."
msgstr "Nazwy użytkowników nie mogą zawierać znaków '@'."
#: contrib/admin/views/decorators.py:85
#: contrib/admin/views/decorators.py:86
#, python-format
msgid "Your e-mail address is not your username. Try '%s' instead."
msgstr "Twój adres e-mail to nie jest twój login. Spróbuj '%s'."
#: contrib/admin/views/doc.py:47 contrib/admin/views/doc.py:49
#: contrib/admin/views/doc.py:51
#: contrib/admin/views/doc.py:48 contrib/admin/views/doc.py:50
#: contrib/admin/views/doc.py:52
msgid "tag:"
msgstr "tag:"
#: contrib/admin/views/doc.py:78 contrib/admin/views/doc.py:80
#: contrib/admin/views/doc.py:82
#: contrib/admin/views/doc.py:79 contrib/admin/views/doc.py:81
#: contrib/admin/views/doc.py:83
msgid "filter:"
msgstr "filtr:"
#: contrib/admin/views/doc.py:136 contrib/admin/views/doc.py:138
#: contrib/admin/views/doc.py:140
#: contrib/admin/views/doc.py:137 contrib/admin/views/doc.py:139
#: contrib/admin/views/doc.py:141
msgid "view:"
msgstr "widok:"
#: contrib/admin/views/doc.py:165
#: contrib/admin/views/doc.py:166
#, python-format
msgid "App %r not found"
msgstr "Aplikacja %r nie została znaleziona"
#: contrib/admin/views/doc.py:172
#: contrib/admin/views/doc.py:173
#, python-format
msgid "Model %(name)r not found in app %(label)r"
msgstr "Model %(name)r nie został znaleziony w aplikacji %(label)r"
#: contrib/admin/views/doc.py:184
#: contrib/admin/views/doc.py:185
#, python-format
msgid "the related `%(label)s.%(type)s` object"
msgstr "powiązany obiekt `%(label)s.%(type)s`"
#: contrib/admin/views/doc.py:184 contrib/admin/views/doc.py:206
#: contrib/admin/views/doc.py:220 contrib/admin/views/doc.py:225
#: contrib/admin/views/doc.py:185 contrib/admin/views/doc.py:207
#: contrib/admin/views/doc.py:221 contrib/admin/views/doc.py:226
msgid "model:"
msgstr "model:"
#: contrib/admin/views/doc.py:215
#: contrib/admin/views/doc.py:216
#, python-format
msgid "related `%(label)s.%(name)s` objects"
msgstr "powiązane obiekty `%(label)s.%(name)s`"
#: contrib/admin/views/doc.py:220
#: contrib/admin/views/doc.py:221
#, python-format
msgid "all %s"
msgstr "wszystkie %s"
#: contrib/admin/views/doc.py:225
#: contrib/admin/views/doc.py:226
#, python-format
msgid "number of %s"
msgstr "liczba %s"
#: contrib/admin/views/doc.py:230
#: contrib/admin/views/doc.py:231
#, python-format
msgid "Fields on %s objects"
msgstr "Pola obiektów %s"
#: contrib/admin/views/doc.py:292 contrib/admin/views/doc.py:303
#: contrib/admin/views/doc.py:305 contrib/admin/views/doc.py:311
#: contrib/admin/views/doc.py:312 contrib/admin/views/doc.py:314
#: contrib/admin/views/doc.py:293 contrib/admin/views/doc.py:304
#: contrib/admin/views/doc.py:306 contrib/admin/views/doc.py:312
#: contrib/admin/views/doc.py:313 contrib/admin/views/doc.py:315
msgid "Integer"
msgstr "Liczba całkowita"
#: contrib/admin/views/doc.py:293
#: contrib/admin/views/doc.py:294
msgid "Boolean (Either True or False)"
msgstr "Wartość logiczna (True, False - prawda lub fałsz)"
#: contrib/admin/views/doc.py:294 contrib/admin/views/doc.py:313
#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:314
#, python-format
msgid "String (up to %(max_length)s)"
msgstr "Łańcuch (do %(max_length)s znaków)"
#: contrib/admin/views/doc.py:295
#: contrib/admin/views/doc.py:296
msgid "Comma-separated integers"
msgstr "Liczby całkowite rozdzielone przecinkami"
#: contrib/admin/views/doc.py:296
#: contrib/admin/views/doc.py:297
msgid "Date (without time)"
msgstr "Data (bez godziny)"
#: contrib/admin/views/doc.py:297
#: contrib/admin/views/doc.py:298
msgid "Date (with time)"
msgstr "Data (z godziną)"
#: contrib/admin/views/doc.py:298
#: contrib/admin/views/doc.py:299
msgid "Decimal number"
msgstr "Numer dziesiętny"
#: contrib/admin/views/doc.py:299
#: contrib/admin/views/doc.py:300
msgid "E-mail address"
msgstr "Adres e-mail"
#: contrib/admin/views/doc.py:300 contrib/admin/views/doc.py:301
#: contrib/admin/views/doc.py:304
#: contrib/admin/views/doc.py:301 contrib/admin/views/doc.py:302
#: contrib/admin/views/doc.py:305
msgid "File path"
msgstr "Ścieżka do pliku"
#: contrib/admin/views/doc.py:302
#: contrib/admin/views/doc.py:303
msgid "Floating point number"
msgstr "Liczba zmiennoprzecinkowa"
#: contrib/admin/views/doc.py:306 contrib/comments/models.py:85
#: contrib/admin/views/doc.py:307 contrib/comments/models.py:85
msgid "IP address"
msgstr "Adres IP"
#: contrib/admin/views/doc.py:308
#: contrib/admin/views/doc.py:309
msgid "Boolean (Either True, False or None)"
msgstr "Wartość logiczna (True, False, None - prawda, fałsz lub nic)"
#: contrib/admin/views/doc.py:309
#: contrib/admin/views/doc.py:310
msgid "Relation to parent model"
msgstr "Relacja do modelu rodzica"
#: contrib/admin/views/doc.py:310
#: contrib/admin/views/doc.py:311
msgid "Phone number"
msgstr "Numer telefonu"
#: contrib/admin/views/doc.py:315
#: contrib/admin/views/doc.py:316
msgid "Text"
msgstr "Tekst"
#: contrib/admin/views/doc.py:316
#: contrib/admin/views/doc.py:317
msgid "Time"
msgstr "Czas"
#: contrib/admin/views/doc.py:317 contrib/flatpages/models.py:7
#: contrib/admin/views/doc.py:318 contrib/flatpages/models.py:7
msgid "URL"
msgstr "URL"
#: contrib/admin/views/doc.py:318
#: contrib/admin/views/doc.py:319
msgid "U.S. state (two uppercase letters)"
msgstr "Stan USA (dwie duże litery)"
#: contrib/admin/views/doc.py:319
#: contrib/admin/views/doc.py:320
msgid "XML text"
msgstr "Tekst XML"
#: contrib/admin/views/doc.py:345
#: contrib/admin/views/doc.py:346
#, python-format
msgid "%s does not appear to be a urlpattern object"
msgstr "%s nie jest obiektem urlpattern"
#: contrib/admin/views/main.py:230
#: contrib/admin/views/main.py:233
msgid "Site administration"
msgstr "Administracja stroną"
#: contrib/admin/views/main.py:278 contrib/admin/views/main.py:363
#: contrib/admin/views/main.py:281 contrib/admin/views/main.py:366
#, python-format
msgid "You may add another %s below."
msgstr "Możesz dodać nowy wpis %s poniżej."
#: contrib/admin/views/main.py:296
#: contrib/admin/views/main.py:299
#, python-format
msgid "Add %s"
msgstr "Dodaj %s"
#: contrib/admin/views/main.py:342
#: contrib/admin/views/main.py:345
#, python-format
msgid "Added %s."
msgstr "Dodano %s"
#: contrib/admin/views/main.py:342 contrib/admin/views/main.py:344
#: contrib/admin/views/main.py:346 core/validators.py:283
#: contrib/admin/views/main.py:345 contrib/admin/views/main.py:347
#: contrib/admin/views/main.py:349 core/validators.py:283
#: db/models/manipulators.py:309
msgid "and"
msgstr "i"
#: contrib/admin/views/main.py:344
#: contrib/admin/views/main.py:347
#, python-format
msgid "Changed %s."
msgstr "Zmieniono %s"
#: contrib/admin/views/main.py:346
#: contrib/admin/views/main.py:349
#, python-format
msgid "Deleted %s."
msgstr "Skasowano %s"
#: contrib/admin/views/main.py:349
#: contrib/admin/views/main.py:352
msgid "No fields changed."
msgstr "Żadne pole nie zmienione."
#: contrib/admin/views/main.py:352
#: contrib/admin/views/main.py:355
#, python-format
msgid "The %(name)s \"%(obj)s\" was changed successfully."
msgstr "%(name)s \"%(obj)s\" zostało pomyślnie zmienione."
#: contrib/admin/views/main.py:360
#: contrib/admin/views/main.py:363
#, python-format
msgid ""
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
msgstr ""
"%(name)s \"%(obj)s\" dodane pomyślnie. Możesz edytować ponownie wpis poniżej."
#: contrib/admin/views/main.py:398
#: contrib/admin/views/main.py:401
#, python-format
msgid "Change %s"
msgstr "Zmień %s"
#: contrib/admin/views/main.py:483
#: contrib/admin/views/main.py:488
#, python-format
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
msgstr "Jedno lub więcej %(fieldname)s w %(name)s: %(obj)s"
#: contrib/admin/views/main.py:488
#: contrib/admin/views/main.py:493
#, python-format
msgid "One or more %(fieldname)s in %(name)s:"
msgstr "Jedno lub więcej %(fieldname)s w %(name)s:"
#: contrib/admin/views/main.py:520
#: contrib/admin/views/main.py:525
#, python-format
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
msgstr "%(name)s \"%(obj)s\" usunięty pomyślnie."
#: contrib/admin/views/main.py:523
#: contrib/admin/views/main.py:528
msgid "Are you sure?"
msgstr "Jesteś pewien?"
#: contrib/admin/views/main.py:545
#: contrib/admin/views/main.py:550
#, python-format
msgid "Change history: %s"
msgstr "Historia zmian: %s"
#: contrib/admin/views/main.py:579
#: contrib/admin/views/main.py:584
#, python-format
msgid "Select %s"
msgstr "Zaznacz %s"
#: contrib/admin/views/main.py:579
#: contrib/admin/views/main.py:584
#, python-format
msgid "Select %s to change"
msgstr "Zaznacz %s aby zmienić"
#: contrib/admin/views/main.py:780
#: contrib/admin/views/main.py:785
msgid "Database error"
msgstr "Błąd bazy danych"
@ -1618,7 +1618,7 @@ msgstr "-gi"
msgid "rd"
msgstr "-ci"
#: contrib/humanize/templatetags/humanize.py:50
#: contrib/humanize/templatetags/humanize.py:52
#, python-format
msgid "%(value).1f million"
msgid_plural "%(value).1f million"
@ -1626,7 +1626,7 @@ msgstr[0] "%(value).1f milion"
msgstr[1] "%(value).1f miliony"
msgstr[2] "%(value).1f milionów"
#: contrib/humanize/templatetags/humanize.py:53
#: contrib/humanize/templatetags/humanize.py:55
#, python-format
msgid "%(value).1f billion"
msgid_plural "%(value).1f billion"
@ -1634,7 +1634,7 @@ msgstr[0] "%(value).1f miliard"
msgstr[1] "%(value).1f miliardy"
msgstr[2] "%(value).1f miliardów"
#: contrib/humanize/templatetags/humanize.py:56
#: contrib/humanize/templatetags/humanize.py:58
#, python-format
msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion"
@ -1642,51 +1642,51 @@ msgstr[0] "%(value).1f bilion"
msgstr[1] "%(value).1f biliony"
msgstr[2] "%(value).1f bilionów"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "one"
msgstr "jeden"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "two"
msgstr "dwa"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "three"
msgstr "trzy"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "four"
msgstr "cztery"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "five"
msgstr "pięć"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "six"
msgstr "sześć"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "seven"
msgstr "siedem"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "eight"
msgstr "osiem"
#: contrib/humanize/templatetags/humanize.py:71
#: contrib/humanize/templatetags/humanize.py:74
msgid "nine"
msgstr "dziewięć"
#: contrib/humanize/templatetags/humanize.py:90
#: contrib/humanize/templatetags/humanize.py:94
msgid "today"
msgstr "dzisiaj"
#: contrib/humanize/templatetags/humanize.py:92
#: contrib/humanize/templatetags/humanize.py:96
msgid "tomorrow"
msgstr "jutro"
#: contrib/humanize/templatetags/humanize.py:94
#: contrib/humanize/templatetags/humanize.py:98
msgid "yesterday"
msgstr "wczoraj"
@ -1705,8 +1705,7 @@ msgstr "To pole musi zawierać 7 lub 8 cyfr."
#: contrib/localflavor/ar/forms.py:75
msgid "Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format."
msgstr ""
"Podaj poprawny numer CUIT w formacie XX-XXXXXXXX-X lub XXXXXXXXXXXX."
msgstr "Podaj poprawny numer CUIT w formacie XX-XXXXXXXX-X lub XXXXXXXXXXXX."
#: contrib/localflavor/ar/forms.py:88
msgid "Invalid CUIT."
@ -1725,11 +1724,12 @@ msgid "Phone numbers must be in XX-XXXX-XXXX format."
msgstr "Numery telefoniczne muszą być w formacie XX-XXXX-XXXX."
#: contrib/localflavor/br/forms.py:68
#, fuzzy
msgid ""
"Select a valid brazilian state. That state is not one of the available "
"states."
msgstr "Wybierz poprawną wartość. Podana nie jest jednym z dostępnych wyborów."
msgstr ""
"Wybierz poprawny brazylijski stan. Ten stan nie jest jednym z dostępnych "
"stanów."
#: contrib/localflavor/br/forms.py:105
msgid "This field requires at most 11 digits or 14 characters."
@ -1748,14 +1748,13 @@ msgid "Invalid CNPJ number."
msgstr "Błędny numer CNPJ."
#: contrib/localflavor/ca/forms.py:19
#, fuzzy
msgid "Enter a postal code in the format XXX XXX."
msgstr "Wpisz kod pocztowy w formacie XXXXX."
msgstr "Wpisz kod pocztowy w formacie XXX XXX."
#: contrib/localflavor/ca/forms.py:81
#, fuzzy
msgid "Enter a valid Canadian Social Insurance number in XXX-XXX-XXXX format."
msgstr "Wpisz poprawny numer U.S. Social Security w formacie XXX-XX-XXXX."
msgstr ""
"Wpisz poprawny numer kanadyjskiego ubezpieczenia w formacie XXX-XXX-XXXX."
#: contrib/localflavor/ch/ch_states.py:5
msgid "Aargau"
@ -1870,7 +1869,7 @@ msgid ""
"Enter a valid Swiss identity or passport card number in X1234567<0 or "
"1234567890 format."
msgstr ""
"Podaj poprawny numer szwajarskiego dowodu osobistego lub paszportu w "
"Podaj poprawny numer szwajcarskiego dowodu osobistego lub paszportu w "
"formacie X1234567<0 lub 1234567890."
#: contrib/localflavor/cl/forms.py:32
@ -2237,16 +2236,15 @@ msgid "Valencian Community"
msgstr ""
#: contrib/localflavor/es/forms.py:22
#, fuzzy
msgid "Enter a valid postal code in the range and format 01XXX - 52XXX."
msgstr "Wpisz kod pocztowy w formacie XXXXXXX lub XXX-XXXX."
msgstr "Wpisz kod pocztowy w zakresie i formacie 01XXX - 52XX."
#: contrib/localflavor/es/forms.py:39
#, fuzzy
msgid ""
"Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or "
"9XXXXXXXX."
msgstr "Wpisz kod pocztowy w formacie XXXXXXX lub XXX-XXXX."
msgstr ""
"Wpisz numer telefoniczny w formacie 6XXXXXXXX, 8XXXXXXXX lub 9XXXXXXXX."
#: contrib/localflavor/es/forms.py:73 contrib/localflavor/es/forms.py:108
#: db/models/fields/related.py:55
@ -2256,36 +2254,33 @@ msgstr "Proszę wpisać poprawne %s."
#: contrib/localflavor/es/forms.py:91
msgid "Invalid checksum for NIF."
msgstr ""
msgstr "Niepoprawna suma kontrolna NIF."
#: contrib/localflavor/es/forms.py:97
msgid "Invalid checksum for NIE."
msgstr ""
msgstr "Niepoprawna suma kontrolna NIE."
#: contrib/localflavor/es/forms.py:106
msgid "Invalid checksum for CIF."
msgstr ""
msgstr "Niepoprawna suma kontrolna CIF."
#: contrib/localflavor/es/forms.py:136
#, fuzzy
msgid ""
"Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX."
msgstr ""
"Podaj poprawny niemiecki numer dowodu osobistego w formacie XXXXXXXXXXX-"
"XXXXXXX-XXXXXXX-X."
"Podaj poprawny numer konta bankowego w formacie XXXX-XXXX-XX-XXXXXXXXXX."
#: contrib/localflavor/es/forms.py:150
msgid "Invalid checksum for bank account number."
msgstr ""
msgstr "Niepoprawna suma kontrolna numeru konta bankowego."
#: contrib/localflavor/fi/forms.py:40 contrib/localflavor/fi/forms.py:45
msgid "Enter a valid Finnish social security number."
msgstr "Wpis poprawny numer fińskiego ubezpieczenia socjalnego."
#: contrib/localflavor/in_/forms.py:16
#, fuzzy
msgid "Enter a zip code in the format XXXXXXX."
msgstr "Wpisz kod pocztowy w formacie XXXXX-XXX."
msgstr "Wpisz kod pocztowy w formacie XXXXXXX."
#: contrib/localflavor/is_/forms.py:17
msgid ""
@ -2502,19 +2497,16 @@ msgid "Okinawa"
msgstr ""
#: contrib/localflavor/nl/forms.py:25
#, fuzzy
msgid "Enter a valid postal code"
msgstr "Wpisz poprawny kod pocztowy."
#: contrib/localflavor/nl/forms.py:53
#, fuzzy
msgid "Enter a valid phone number"
msgstr "Wpisz poprawny numer VAT."
msgstr "Wpisz poprawny numer telefonu."
#: contrib/localflavor/nl/forms.py:76
#, fuzzy
msgid "Enter a valid SoFi number"
msgstr "Wpisz poprawny numer VAT."
msgstr "Wpisz poprawny numer SoFi."
#: contrib/localflavor/nl/nl_provinces.py:4
#, fuzzy
@ -2574,13 +2566,12 @@ msgid "Enter a valid Norwegian social security number."
msgstr "Wpis poprawny numer norweskiego ubezpieczenia socjalnego."
#: contrib/localflavor/pe/forms.py:36
#, fuzzy
msgid "This field requires 8 digits."
msgstr "To pole musi zawierać co najmniej 14 cyfr."
msgstr "To pole musi zawierać 8 cyfr."
#: contrib/localflavor/pe/forms.py:59
msgid "This field requires 11 digits."
msgstr "To pole musi zawierać co najmniej 11 cyfr."
msgstr "To pole musi zawierać 11 cyfr."
#: contrib/localflavor/pl/forms.py:41
msgid "National Identification Number consists of 11 digits."
@ -2676,9 +2667,8 @@ msgid "West Pomerania"
msgstr "Zachodniopomorskie"
#: contrib/localflavor/sk/forms.py:32
#, fuzzy
msgid "Enter a postal code in the format XXXXX or XXX XX."
msgstr "Wpisz kod pocztowy w formacie XXXXXXX lub XXX-XXXX."
msgstr "Wpisz kod pocztowy w formacie XXXXX or XXX XX."
#: contrib/localflavor/sk/sk_districts.py:8
msgid "Banska Bystrica"
@ -3198,7 +3188,7 @@ msgid "Enter a valid e-mail address."
msgstr "Wprowadź poprawny adres e-mail."
#: core/validators.py:182 core/validators.py:474 newforms/fields.py:438
#: oldforms/__init__.py:686
#: oldforms/__init__.py:687
msgid "No file was submitted. Check the encoding type on the form."
msgstr "Nie wysłano żadnego pliku. Sprawdź typ kodowania formularza."
@ -3460,7 +3450,7 @@ msgstr "Już istnieje %(optname)s z %(fieldname)s."
#: db/models/fields/__init__.py:161 db/models/fields/__init__.py:318
#: db/models/fields/__init__.py:735 db/models/fields/__init__.py:746
#: newforms/fields.py:45 newforms/models.py:220 oldforms/__init__.py:373
#: newforms/fields.py:45 newforms/models.py:220 oldforms/__init__.py:374
msgid "This field is required."
msgstr "To pole jest wymagane."
@ -3523,15 +3513,15 @@ msgstr "Wpisz poprawną wartość."
#, python-format
msgid "Ensure this value has at most %(max)d characters (it has %(length)d)."
msgstr ""
"Upewnij się, że ta wartość ma co najwyżej %(max)d znaków "
"(ma długość %(length)d)."
"Upewnij się, że ta wartość ma co najwyżej %(max)d znaków (ma długość %"
"(length)d)."
#: newforms/fields.py:130
#, python-format
msgid "Ensure this value has at least %(min)d characters (it has %(length)d)."
msgstr ""
"Upewnij się, że ta wartość ma co najmniej %(min)d znaków "
"(ma długość %(length)d)."
"Upewnij się, że ta wartość ma co najmniej %(min)d znaków (ma długość %"
"(length)d)."
#: newforms/fields.py:158 newforms/fields.py:187 newforms/fields.py:216
#, python-format
@ -3578,7 +3568,7 @@ msgstr "Wpisz poprawną datę/godzinę."
msgid "No file was submitted."
msgstr "Żaden plik nie został przesłany."
#: newforms/fields.py:440 oldforms/__init__.py:688
#: newforms/fields.py:440 oldforms/__init__.py:689
msgid "The submitted file is empty."
msgstr "Wysłany plik jest pusty."
@ -3613,7 +3603,7 @@ msgstr "Wprowadź poprawny adres IPv4."
msgid "Select a valid choice. %s is not one of the available choices."
msgstr "Wybierz poprawną wartość. %s nie jest jednym z dostępnych wyborów."
#: oldforms/__init__.py:408
#: oldforms/__init__.py:409
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
@ -3621,32 +3611,32 @@ msgstr[0] "Upewnij się, że tekst ma mniej niż %s znak."
msgstr[1] "Upewnij się, że tekst ma mniej niż %s znaki."
msgstr[2] "Upewnij się, że tekst ma mniej niż %s znaków."
#: oldforms/__init__.py:413
#: oldforms/__init__.py:414
msgid "Line breaks are not allowed here."
msgstr "Znaki nowej linii są tutaj niedopuszczalne."
#: oldforms/__init__.py:511 oldforms/__init__.py:585 oldforms/__init__.py:624
#: oldforms/__init__.py:512 oldforms/__init__.py:586 oldforms/__init__.py:625
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "Wybierz poprawną opcję; '%(data)s' nie jest wśród %(choices)s."
#: oldforms/__init__.py:744
#: oldforms/__init__.py:745
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "Proszę wpisać liczbę całkowitą z zakresu od -32 768 do 32 767"
#: oldforms/__init__.py:754
#: oldforms/__init__.py:755
msgid "Enter a positive number."
msgstr "Proszę wpisać liczbę dodatnią."
#: oldforms/__init__.py:764
#: oldforms/__init__.py:765
msgid "Enter a whole number between 0 and 32,767."
msgstr "Proszę wpisać liczbę całkowitą z zakresu od 0 do 32 767"
#: template/defaultfilters.py:555
#: template/defaultfilters.py:655
msgid "yes,no,maybe"
msgstr "tak,nie,może"
#: template/defaultfilters.py:585
#: template/defaultfilters.py:686
#, python-format
msgid "%(size)d byte"
msgid_plural "%(size)d bytes"
@ -3654,17 +3644,17 @@ msgstr[0] "%(size)d bajt"
msgstr[1] "%(size)d bajty"
msgstr[2] "%(size)d bajtów"
#: template/defaultfilters.py:587
#: template/defaultfilters.py:688
#, python-format
msgid "%.1f KB"
msgstr "%.1f KB"
#: template/defaultfilters.py:589
#: template/defaultfilters.py:690
#, python-format
msgid "%.1f MB"
msgstr "%.1f MB"
#: template/defaultfilters.py:590
#: template/defaultfilters.py:691
#, python-format
msgid "%.1f GB"
msgstr "%.1f GB"

View File

@ -4,11 +4,11 @@
*/
/* Block IE 5 */
@import "null?\"\{";
@import "null.css?\"\{";
/* Import other styles */
@import url('global.css');
@import url('layout.css');
/* Import patch for IE 6 Windows */
/*\*/ @import "patch-iewin.css"; /**/
/*\*/ @import "patch-iewin.css"; /**/

View File

@ -1,6 +1,16 @@
// Handles related-objects functionality: lookup link for raw_id_admin=True
// and Add Another links.
function html_unescape(text) {
// Unescape a string that was escaped using django.utils.html.escape.
text = text.replace(/&lt;/g, '<');
text = text.replace(/&gt;/g, '>');
text = text.replace(/&quot;/g, '"');
text = text.replace(/&#39;/g, "'");
text = text.replace(/&amp;/g, '&');
return text;
}
function showRelatedObjectLookupPopup(triggeringLink) {
var name = triggeringLink.id.replace(/^lookup_/, '');
// IE doesn't like periods in the window name, so convert temporarily.
@ -42,6 +52,10 @@ function showAddAnotherPopup(triggeringLink) {
}
function dismissAddAnotherPopup(win, newId, newRepr) {
// newId and newRepr are expected to have previously been escaped by
// django.utils.html.escape.
newId = html_unescape(newId);
newRepr = html_unescape(newRepr);
var name = win.name.replace(/___/g, '.');
var elem = document.getElementById(name);
if (elem) {

View File

@ -148,6 +148,8 @@ def items_for_result(cl, result):
# function has an "allow_tags" attribute set to True.
if not allow_tags:
result_repr = escape(result_repr)
else:
result_repr = mark_safe(result_repr)
else:
field_val = getattr(result, f.attname)
@ -185,7 +187,7 @@ def items_for_result(cl, result):
else:
result_repr = escape(field_val)
if force_unicode(result_repr) == '':
result_repr = '&nbsp;'
result_repr = mark_safe('&nbsp;')
# If list_display_links not defined, add the link tag to the first field
if (first and not cl.lookup_opts.admin.list_display_links) or field_name in cl.lookup_opts.admin.list_display_links:
table_tag = {True:'th', False:'td'}[first]

View File

@ -118,7 +118,7 @@ class FieldWrapper(object):
return not isinstance(self.field, models.AutoField)
def header_class_attribute(self):
return self.field.blank and ' class="optional"' or ''
return self.field.blank and mark_safe(' class="optional"') or ''
def use_raw_id_admin(self):
return isinstance(self.field.rel, (models.ManyToOneRel, models.ManyToManyRel)) \

View File

@ -273,10 +273,9 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
post_url_continue += "?_popup=1"
return HttpResponseRedirect(post_url_continue % pk_value)
if "_popup" in request.POST:
if type(pk_value) is str: # Quote if string, so JavaScript doesn't think it's a variable.
pk_value = '"%s"' % pk_value.replace('"', '\\"')
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
(pk_value, force_unicode(new_object).replace('"', '\\"')))
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>' % \
# escape() calls force_unicode.
(escape(pk_value), escape(new_object)))
elif "_addanother" in request.POST:
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name)))
return HttpResponseRedirect(request.path)

View File

@ -16,8 +16,12 @@ class CacheClass(SimpleCacheClass):
def add(self, key, value, timeout=None):
self._lock.writer_enters()
# Python 2.3 and 2.4 don't allow combined try-except-finally blocks.
try:
SimpleCacheClass.add(self, key, value, timeout)
try:
super(CacheClass, self).add(key, pickle.dumps(value), timeout)
except pickle.PickleError:
pass
finally:
self._lock.writer_leaves()
@ -49,6 +53,7 @@ class CacheClass(SimpleCacheClass):
def set(self, key, value, timeout=None):
self._lock.writer_enters()
# Python 2.3 and 2.4 don't allow combined try-except-finally blocks.
try:
try:
super(CacheClass, self).set(key, pickle.dumps(value), timeout)

View File

@ -52,7 +52,7 @@ def load_command_class(app_name, name):
return getattr(__import__('%s.management.commands.%s' % (app_name, name),
{}, {}, ['Command']), 'Command')()
def get_commands(load_user_commands=True, project_directory=None):
def get_commands():
"""
Returns a dictionary of commands against the application in which
those commands can be found. This works by looking for a
@ -60,10 +60,10 @@ def get_commands(load_user_commands=True, project_directory=None):
application -- if a commands package exists, all commands in that
package are registered.
Core commands are always included; user-defined commands will also
be included if ``load_user_commands`` is True. If a project directory
is provided, the startproject command will be disabled, and the
startapp command will be modified to use that directory.
Core commands are always included. If a settings module has been
specified, user-defined commands will also be included, the
startproject command will be disabled, and the startapp command
will be modified to use the directory in which that module appears.
The dictionary is in the format {command_name: app_name}. Key-value
pairs from this dictionary can then be used in calls to
@ -80,16 +80,27 @@ def get_commands(load_user_commands=True, project_directory=None):
if _commands is None:
_commands = dict([(name, 'django.core')
for name in find_commands(__path__[0])])
if load_user_commands:
# Get commands from all installed apps.
# Get commands from all installed apps.
try:
from django.conf import settings
for app_name in settings.INSTALLED_APPS:
try:
path = find_management_module(app_name)
_commands.update(dict([(name, app_name)
for name in find_commands(path)]))
except ImportError:
pass # No management module - ignore this app
apps = settings.INSTALLED_APPS
except (AttributeError, EnvironmentError):
apps = []
for app_name in apps:
try:
path = find_management_module(app_name)
_commands.update(dict([(name, app_name)
for name in find_commands(path)]))
except ImportError:
pass # No management module - ignore this app
# Try to determine the project directory
try:
from django.conf import settings
project_directory = setup_environ(__import__(settings.SETTINGS_MODULE))
except (AttributeError, EnvironmentError, ImportError):
project_directory = None
if project_directory:
# Remove the "startproject" command from self.commands, because
@ -146,8 +157,6 @@ class ManagementUtility(object):
def __init__(self, argv=None):
self.argv = argv or sys.argv[:]
self.prog_name = os.path.basename(self.argv[0])
self.project_directory = None
self.user_commands = False
def main_help_text(self):
"""
@ -159,8 +168,7 @@ class ManagementUtility(object):
usage.append("Type '%s help <subcommand>' for help on a specific"
" subcommand." % self.prog_name)
usage.append('Available subcommands:')
commands = get_commands(self.user_commands,
self.project_directory).keys()
commands = get_commands().keys()
commands.sort()
for cmd in commands:
usage.append(' %s' % cmd)
@ -173,8 +181,7 @@ class ManagementUtility(object):
django-admin.py or manage.py) if it can't be found.
"""
try:
app_name = get_commands(self.user_commands,
self.project_directory)[subcommand]
app_name = get_commands()[subcommand]
if isinstance(app_name, BaseCommand):
# If the command is already loaded, use it directly.
klass = app_name
@ -235,8 +242,6 @@ class ProjectManagementUtility(ManagementUtility):
"""
def __init__(self, argv, project_directory):
super(ProjectManagementUtility, self).__init__(argv)
self.project_directory = project_directory
self.user_commands = True
def setup_environ(settings_mod):
"""

View File

@ -91,7 +91,7 @@ class ObjectPaginator(object):
a template for loop.
"""
if self._page_range is None:
self._page_range = range(1, self._pages + 1)
self._page_range = range(1, self.pages + 1)
return self._page_range
hits = property(_get_hits)

View File

@ -1,4 +1,5 @@
import re
from django.utils.text import compress_string
from django.utils.cache import patch_vary_headers
@ -11,18 +12,21 @@ class GZipMiddleware(object):
on the Accept-Encoding header.
"""
def process_response(self, request, response):
# It's not worth compressing non-OK or really short responses.
if response.status_code != 200 or len(response.content) < 200:
# Not worth compressing really short responses or 304 status
# responses, etc.
return response
patch_vary_headers(response, ('Accept-Encoding',))
# Avoid gzipping if we've already got a content-encoding or if the
# content-type is Javascript and the user's browser is IE.
is_js = ("msie" in request.META.get('HTTP_USER_AGENT', '').lower() and
"javascript" in response.get('Content-Type', '').lower())
if response.has_header('Content-Encoding') or is_js:
# Avoid gzipping if we've already got a content-encoding.
if response.has_header('Content-Encoding'):
return response
# Older versions of IE have issues with gzipped javascript.
# See http://code.djangoproject.com/ticket/2449
is_ie = "msie" in request.META.get('HTTP_USER_AGENT', '').lower()
is_js = "javascript" in response.get('Content-Type', '').lower()
if is_ie and is_js:
return response
ae = request.META.get('HTTP_ACCEPT_ENCODING', '')

View File

@ -6,6 +6,7 @@ import datetime
from django.newforms.widgets import Widget, Select
from django.utils.dates import MONTHS
from django.utils.safestring import mark_safe
__all__ = ('SelectDateWidget',)
@ -51,7 +52,7 @@ class SelectDateWidget(Widget):
select_html = Select(choices=year_choices).render(self.year_field % name, year_val)
output.append(select_html)
return u'\n'.join(output)
return mark_safe(u'\n'.join(output))
def value_from_datadict(self, data, files, name):
y, m, d = data.get(self.year_field % name), data.get(self.month_field % name), data.get(self.day_field % name)

View File

@ -3,13 +3,13 @@ Helper functions for creating Form classes from Django models
and database field objects.
"""
from django.utils.translation import ugettext
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_unicode
from django.utils.datastructures import SortedDict
from util import ValidationError
from forms import BaseForm
from fields import Field, ChoiceField
from fields import Field, ChoiceField, EMPTY_VALUES
from widgets import Select, SelectMultiple, MultipleHiddenInput
__all__ = (
@ -151,15 +151,20 @@ class ModelChoiceField(ChoiceField):
"""A ChoiceField whose choices are a model QuerySet."""
# This class is a subclass of ChoiceField for purity, but it doesn't
# actually use any of ChoiceField's implementation.
default_error_messages = {
'invalid_choice': _(u'Select a valid choice. That choice is not one of'
u' the available choices.'),
}
def __init__(self, queryset, empty_label=u"---------", cache_choices=False,
required=True, widget=Select, label=None, initial=None,
help_text=None):
help_text=None, *args, **kwargs):
self.empty_label = empty_label
self.cache_choices = cache_choices
# Call Field instead of ChoiceField __init__() because we don't need
# ChoiceField.__init__().
Field.__init__(self, required, widget, label, initial, help_text)
Field.__init__(self, required, widget, label, initial, help_text,
*args, **kwargs)
self.queryset = queryset
def _get_queryset(self):
@ -195,41 +200,43 @@ class ModelChoiceField(ChoiceField):
def clean(self, value):
Field.clean(self, value)
if value in ('', None):
if value in EMPTY_VALUES:
return None
try:
value = self.queryset.get(pk=value)
except self.queryset.model.DoesNotExist:
raise ValidationError(ugettext(u'Select a valid choice. That'
u' choice is not one of the'
u' available choices.'))
raise ValidationError(self.error_messages['invalid_choice'])
return value
class ModelMultipleChoiceField(ModelChoiceField):
"""A MultipleChoiceField whose choices are a model QuerySet."""
hidden_widget = MultipleHiddenInput
default_error_messages = {
'list': _(u'Enter a list of values.'),
'invalid_choice': _(u'Select a valid choice. %s is not one of the'
u' available choices.'),
}
def __init__(self, queryset, cache_choices=False, required=True,
widget=SelectMultiple, label=None, initial=None,
help_text=None):
help_text=None, *args, **kwargs):
super(ModelMultipleChoiceField, self).__init__(queryset, None,
cache_choices, required, widget, label, initial, help_text)
cache_choices, required, widget, label, initial, help_text,
*args, **kwargs)
def clean(self, value):
if self.required and not value:
raise ValidationError(ugettext(u'This field is required.'))
raise ValidationError(self.error_messages['required'])
elif not self.required and not value:
return []
if not isinstance(value, (list, tuple)):
raise ValidationError(ugettext(u'Enter a list of values.'))
raise ValidationError(self.error_messages['list'])
final_values = []
for val in value:
try:
obj = self.queryset.get(pk=val)
except self.queryset.model.DoesNotExist:
raise ValidationError(ugettext(u'Select a valid choice. %s is'
u' not one of the available'
u' choices.') % val)
raise ValidationError(self.error_messages['invalid_choice'] % val)
else:
final_values.append(obj)
return final_values

View File

@ -11,7 +11,7 @@ import copy
from itertools import chain
from django.utils.datastructures import MultiValueDict
from django.utils.html import escape
from django.utils.html import escape, conditional_escape
from django.utils.translation import ugettext
from django.utils.encoding import StrAndUnicode, force_unicode
from django.utils.safestring import mark_safe
@ -155,7 +155,7 @@ class Textarea(Widget):
value = force_unicode(value)
final_attrs = self.build_attrs(attrs, name=name)
return mark_safe(u'<textarea%s>%s</textarea>' % (flatatt(final_attrs),
escape(value)))
conditional_escape(force_unicode(value))))
class DateTimeInput(Input):
input_type = 'text'
@ -217,7 +217,9 @@ class Select(Widget):
for option_value, option_label in chain(self.choices, choices):
option_value = force_unicode(option_value)
selected_html = (option_value == str_value) and u' selected="selected"' or ''
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(force_unicode(option_label))))
output.append(u'<option value="%s"%s>%s</option>' % (
escape(option_value), selected_html,
conditional_escape(force_unicode(option_label))))
output.append(u'</select>')
return mark_safe(u'\n'.join(output))
@ -254,7 +256,9 @@ class SelectMultiple(Widget):
for option_value, option_label in chain(self.choices, choices):
option_value = force_unicode(option_value)
selected_html = (option_value in str_values) and ' selected="selected"' or ''
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(force_unicode(option_label))))
output.append(u'<option value="%s"%s>%s</option>' % (
escape(option_value), selected_html,
conditional_escape(force_unicode(option_label))))
output.append(u'</select>')
return mark_safe(u'\n'.join(output))
@ -278,7 +282,7 @@ class RadioInput(StrAndUnicode):
def __unicode__(self):
return mark_safe(u'<label>%s %s</label>' % (self.tag(),
self.choice_label))
conditional_escape(force_unicode(self.choice_label))))
def is_checked(self):
return self.value == self.choice_value
@ -317,11 +321,13 @@ class RadioFieldRenderer(StrAndUnicode):
% force_unicode(w) for w in self]))
class RadioSelect(Select):
renderer = RadioFieldRenderer
def __init__(self, *args, **kwargs):
self.renderer = kwargs.pop('renderer', None)
if not self.renderer:
self.renderer = RadioFieldRenderer
# Override the default renderer if we were passed one.
renderer = kwargs.pop('renderer', None)
if renderer:
self.renderer = renderer
super(RadioSelect, self).__init__(*args, **kwargs)
def get_renderer(self, name, value, attrs=None, choices=()):
@ -361,7 +367,8 @@ class CheckboxSelectMultiple(SelectMultiple):
cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
option_value = force_unicode(option_value)
rendered_cb = cb.render(name, option_value)
output.append(u'<li><label>%s %s</label></li>' % (rendered_cb, escape(force_unicode(option_label))))
output.append(u'<li><label>%s %s</label></li>' % (rendered_cb,
conditional_escape(force_unicode(option_label))))
output.append(u'</ul>')
return mark_safe(u'\n'.join(output))

View File

@ -547,9 +547,9 @@ class FilterExpression(object):
if var == None:
var, constant, i18n_constant = match.group("var", "constant", "i18n_constant")
if i18n_constant:
var = '"%s"' % _(i18n_constant)
var = '"%s"' % _(i18n_constant.replace(r'\"', '"'))
elif constant:
var = '"%s"' % constant
var = '"%s"' % constant.replace(r'\"', '"')
upto = match.end()
if var == None:
raise TemplateSyntaxError, "Could not find variable at start of %s" % token

View File

@ -25,6 +25,8 @@ def stringfilter(func):
if args:
args = list(args)
args[0] = force_unicode(args[0])
if isinstance(args[0], SafeData) and getattr(func, 'is_safe', False):
return mark_safe(func(*args, **kwargs))
return func(*args, **kwargs)
# Include a reference to the real function (used to check original
@ -106,6 +108,7 @@ floatformat.is_safe = True
def iriencode(value):
"""Escapes an IRI value for use in a URL."""
return force_unicode(iri_to_uri(value))
iriencode.is_safe = True
iriencode = stringfilter(iriencode)
def linenumbers(value, autoescape=None):

View File

@ -51,9 +51,9 @@ class TestCase(unittest.TestCase):
def _pre_setup(self):
"""Performs any pre-test setup. This includes:
* If the Test Case class has a 'fixtures' member, clearing the
database and installing the named fixtures at the start of each
test.
* Flushing the database.
* If the Test Case class has a 'fixtures' member, installing the
named fixtures.
* Clearing the mail test outbox.
"""
call_command('flush', verbosity=0, interactive=False)

View File

@ -20,6 +20,10 @@ An example: i18n middleware would need to distinguish caches by the
import md5
import re
import time
try:
set
except NameError:
from sets import Set as set # Python 2.3 fallback
from django.conf import settings
from django.core.cache import cache
@ -70,8 +74,6 @@ def patch_cache_control(response, **kwargs):
cc = ', '.join([dictvalue(el) for el in cc.items()])
response['Cache-Control'] = cc
vary_delim_re = re.compile(r',\s*')
def patch_response_headers(response, cache_timeout=None):
"""
Adds some useful headers to the given HttpResponse object:
@ -109,14 +111,15 @@ def patch_vary_headers(response, newheaders):
# Note that we need to keep the original order intact, because cache
# implementations may rely on the order of the Vary contents in, say,
# computing an MD5 hash.
vary = []
if response.has_header('Vary'):
vary = vary_delim_re.split(response['Vary'])
oldheaders = dict([(el.lower(), 1) for el in vary])
for newheader in newheaders:
if not newheader.lower() in oldheaders:
vary.append(newheader)
response['Vary'] = ', '.join(vary)
vary_headers = cc_delim_re.split(response['Vary'])
else:
vary_headers = []
# Use .lower() here so we treat headers as case-insensitive.
existing_headers = set([header.lower() for header in vary_headers])
additional_headers = [newheader for newheader in newheaders
if newheader.lower() not in existing_headers]
response['Vary'] = ', '.join(vary_headers + additional_headers)
def _generate_cache_key(request, headerlist, key_prefix):
"""Returns a cache key from the headers given in the header list."""
@ -169,7 +172,7 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None):
key_prefix, iri_to_uri(request.path))
if response.has_header('Vary'):
headerlist = ['HTTP_'+header.upper().replace('-', '_')
for header in vary_delim_re.split(response['Vary'])]
for header in cc_delim_re.split(response['Vary'])]
cache.set(cache_key, headerlist, cache_timeout)
return _generate_cache_key(request, headerlist, key_prefix)
else:

View File

@ -7,9 +7,9 @@ class MergeDict(object):
self.dicts = dicts
def __getitem__(self, key):
for dict in self.dicts:
for dict_ in self.dicts:
try:
return dict[key]
return dict_[key]
except KeyError:
pass
raise KeyError
@ -24,22 +24,22 @@ class MergeDict(object):
return default
def getlist(self, key):
for dict in self.dicts:
for dict_ in self.dicts:
try:
return dict.getlist(key)
return dict_.getlist(key)
except KeyError:
pass
raise KeyError
def items(self):
item_list = []
for dict in self.dicts:
item_list.extend(dict.items())
for dict_ in self.dicts:
item_list.extend(dict_.items())
return item_list
def has_key(self, key):
for dict in self.dicts:
if key in dict:
for dict_ in self.dicts:
if key in dict_:
return True
return False
@ -56,7 +56,7 @@ class SortedDict(dict):
def __init__(self, data=None):
if data is None:
data = {}
dict.__init__(self, data)
super(SortedDict, self).__init__(data)
if isinstance(data, dict):
self.keyOrder = data.keys()
else:
@ -68,12 +68,12 @@ class SortedDict(dict):
for key, value in self.iteritems()])
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
super(SortedDict, self).__setitem__(key, value)
if key not in self.keyOrder:
self.keyOrder.append(key)
def __delitem__(self, key):
dict.__delitem__(self, key)
super(SortedDict, self).__delitem__(key)
self.keyOrder.remove(key)
def __iter__(self):
@ -81,7 +81,7 @@ class SortedDict(dict):
yield k
def pop(self, k, *args):
result = dict.pop(self, k, *args)
result = super(SortedDict, self).pop(k, *args)
try:
self.keyOrder.remove(k)
except ValueError:
@ -90,7 +90,7 @@ class SortedDict(dict):
return result
def popitem(self):
result = dict.popitem(self)
result = super(SortedDict, self).popitem()
self.keyOrder.remove(result[0])
return result
@ -99,7 +99,7 @@ class SortedDict(dict):
def iteritems(self):
for key in self.keyOrder:
yield key, dict.__getitem__(self, key)
yield key, super(SortedDict, self).__getitem__(key)
def keys(self):
return self.keyOrder[:]
@ -108,20 +108,20 @@ class SortedDict(dict):
return iter(self.keyOrder)
def values(self):
return [dict.__getitem__(self, k) for k in self.keyOrder]
return [super(SortedDict, self).__getitem__(k) for k in self.keyOrder]
def itervalues(self):
for key in self.keyOrder:
yield dict.__getitem__(self, key)
yield super(SortedDict, self).__getitem__(key)
def update(self, dict):
for k, v in dict.items():
def update(self, dict_):
for k, v in dict_.items():
self.__setitem__(k, v)
def setdefault(self, key, default):
if key not in self.keyOrder:
self.keyOrder.append(key)
return dict.setdefault(self, key, default)
return super(SortedDict, self).setdefault(key, default)
def value_for_index(self, index):
"""Returns the value of the item at the given zero-based index."""
@ -135,7 +135,7 @@ class SortedDict(dict):
if n < index:
index -= 1
self.keyOrder.insert(index, key)
dict.__setitem__(self, key, value)
super(SortedDict, self).__setitem__(key, value)
def copy(self):
"""Returns a copy of this object."""
@ -173,10 +173,11 @@ class MultiValueDict(dict):
single name-value pairs.
"""
def __init__(self, key_to_list_mapping=()):
dict.__init__(self, key_to_list_mapping)
super(MultiValueDict, self).__init__(key_to_list_mapping)
def __repr__(self):
return "<%s: %s>" % (self.__class__.__name__, dict.__repr__(self))
return "<%s: %s>" % (self.__class__.__name__,
super(MultiValueDict, self).__repr__())
def __getitem__(self, key):
"""
@ -184,7 +185,7 @@ class MultiValueDict(dict):
raises KeyError if not found.
"""
try:
list_ = dict.__getitem__(self, key)
list_ = super(MultiValueDict, self).__getitem__(key)
except KeyError:
raise MultiValueDictKeyError, "Key %r not found in %r" % (key, self)
try:
@ -193,10 +194,10 @@ class MultiValueDict(dict):
return []
def __setitem__(self, key, value):
dict.__setitem__(self, key, [value])
super(MultiValueDict, self).__setitem__(key, [value])
def __copy__(self):
return self.__class__(dict.items(self))
return self.__class__(super(MultiValueDict, self).items())
def __deepcopy__(self, memo=None):
import copy
@ -210,7 +211,10 @@ class MultiValueDict(dict):
return result
def get(self, key, default=None):
"""Returns the default value if the requested data doesn't exist."""
"""
Returns the last data value for the passed key. If key doesn't exist
or value is an empty list, then default is returned.
"""
try:
val = self[key]
except KeyError:
@ -220,14 +224,17 @@ class MultiValueDict(dict):
return val
def getlist(self, key):
"""Returns an empty list if the requested data doesn't exist."""
"""
Returns the list of values for the passed key. If key doesn't exist,
then an empty list is returned.
"""
try:
return dict.__getitem__(self, key)
return super(MultiValueDict, self).__getitem__(key)
except KeyError:
return []
def setlist(self, key, list_):
dict.__setitem__(self, key, list_)
super(MultiValueDict, self).__setitem__(key, list_)
def setdefault(self, key, default=None):
if key not in self:
@ -242,7 +249,7 @@ class MultiValueDict(dict):
def appendlist(self, key, value):
"""Appends an item to the internal list associated with key."""
self.setlistdefault(key, [])
dict.__setitem__(self, key, self.getlist(key) + [value])
super(MultiValueDict, self).__setitem__(key, self.getlist(key) + [value])
def items(self):
"""
@ -253,7 +260,7 @@ class MultiValueDict(dict):
def lists(self):
"""Returns a list of (key, list) pairs."""
return dict.items(self)
return super(MultiValueDict, self).items()
def values(self):
"""Returns a list of the last value on every key list."""
@ -315,7 +322,7 @@ class DotExpandedDict(dict):
try:
current[bits[-1]] = v
except TypeError: # Special-case if current isn't a dict.
current = {bits[-1] : v}
current = {bits[-1]: v}
class FileDict(dict):
"""

View File

@ -168,10 +168,9 @@ def translation(language):
res.merge(t)
return res
if hasattr(settings, 'LOCALE_PATHS'):
for localepath in settings.LOCALE_PATHS:
if os.path.isdir(localepath):
res = _merge(localepath)
for localepath in settings.LOCALE_PATHS:
if os.path.isdir(localepath):
res = _merge(localepath)
if projectpath and os.path.isdir(projectpath):
res = _merge(projectpath)

View File

@ -422,11 +422,11 @@ TECHNICAL_500_TEMPLATE = """
{% if frame.context_line %}
<div class="context" id="c{{ frame.id }}">
{% if frame.pre_context %}
<ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">{% for line in frame.pre_context %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line }}</li>{% endfor %}</ol>
<ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">{% for line in frame.pre_context %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line|escape }}</li>{% endfor %}</ol>
{% endif %}
<ol start="{{ frame.lineno }}" class="context-line"><li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ frame.context_line }} <span>...</span></li></ol>
<ol start="{{ frame.lineno }}" class="context-line"><li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ frame.context_line|escape }} <span>...</span></li></ol>
{% if frame.post_context %}
<ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">{% for line in frame.post_context %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line }}</li>{% endfor %}</ol>
<ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">{% for line in frame.post_context %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line|escape }}</li>{% endfor %}</ol>
{% endif %}
</div>
{% endif %}
@ -445,8 +445,8 @@ TECHNICAL_500_TEMPLATE = """
<tbody>
{% for var in frame.vars|dictsort:"0" %}
<tr>
<td>{{ var.0 }}</td>
<td class="code"><div>{{ var.1|pprint }}</div></td>
<td>{{ var.0|escape }}</td>
<td class="code"><div>{{ var.1|pprint|escape }}</div></td>
</tr>
{% endfor %}
</tbody>
@ -466,7 +466,7 @@ Traceback (most recent call last):<br/>
{% for frame in frames %}
File "{{ frame.filename }}" in {{ frame.function }}<br/>
{% if frame.context_line %}
&nbsp;&nbsp;{{ frame.lineno }}. {{ frame.context_line }}<br/>
&nbsp;&nbsp;{{ frame.lineno }}. {{ frame.context_line|escape }}<br/>
{% endif %}
{% endfor %}<br/>
&nbsp;&nbsp;{{ exception_type }} at {{ request.path|escape }}<br/>

View File

@ -658,7 +658,7 @@ message file. The choice is yours.
of the settings file to determine this, and a settings file doesn't exist
if you're manually configuring your settings.)
.. _settings documentation: ../settings/#using-settings-without-the-django-settings-module-environment-variable
.. _settings documentation: ../settings/#using-settings-without-setting-django-settings-module
All message file repositories are structured the same way. They are:

View File

@ -583,7 +583,7 @@ LOCALE_PATHS
Default: ``()`` (Empty tuple)
A list of directories where Django looks for translation files.
A tuple of directories where Django looks for translation files.
See the `internationalization docs section`_ explaining the variable and the
default behavior.

View File

@ -755,61 +755,106 @@ inside the template code:
``EscapeString`` and ``EscapeUnicode``. You will not normally need to worry
about these; they exist for the implementation of the ``escape`` filter.
Inside your filter, you will need to think about three areas in order to be
auto-escaping compliant:
When you are writing a filter, your code will typically fall into one of two
situations:
1. If your filter returns a string that is ready for direct output (it should
be considered a "safe" string), you should call
``django.utils.safestring.mark_safe()`` on the result prior to returning.
This will turn the result into the appropriate ``SafeData`` type. This is
often the case when you are returning raw HTML, for example.
1. Your filter does not introduce any HTML-unsafe characters (``<``, ``>``,
``'``, ``"`` or ``&``) into the result that were not already present. In
this case, you can let Django take care of all the auto-escaping handling
for you. All you need to do is put the ``is_safe`` attribute on your
filter function and set it to ``True``. This attribute tells Django that
is a "safe" string is passed into your filter, the result will still be
"safe" and if a non-safe string is passed in, Django will automatically
escape it, if necessary. The reason ``is_safe`` is necessary is because
there are plenty of normal string operations that will turn a ``SafeData``
object back into a normal ``str`` or ``unicode`` object and, rather than
try to catch them all, which would be very difficult, Django repairs the
damage after the filter has completed.
2. If your filter is given a "safe" string, is it guaranteed to return a
"safe" string? If so, set the ``is_safe`` attribute on the function to be
``True``. For example, a filter that replaced a word consisting only of
digits with the number spelt out in words is going to be
safe-string-preserving, since it cannot introduce any of the five dangerous
characters: <, >, ", ' or &. We can write::
For example, suppose you have a filter that adds the string ``xx`` to the
end of any input. Since this introduces no dangerous HTML characters into
the result (aside from any that were already present), you should mark
your filter with ``is_safe``::
@register.filter
def convert_to_words(value):
# ... implementation here ...
return result
def add_xx(value):
return '%sxx' % value
add_xx.is_safe = True
convert_to_words.is_safe = True
When this filter is used in a template where auto-escaping is enabled,
Django will escape the output whenever the input is not already marked as
"safe".
Note that this filter does not return a universally safe result (it does
not return ``mark_safe(result)``) because if it is handed a raw string such
as '<a>', this will need further escaping in an auto-escape environment.
The ``is_safe`` attribute only talks about the the result when a safe
string is passed into the filter.
By default, ``is_safe`` defaults to ``False`` and you can omit it from
any filters where it isn't required.
3. Will your filter behave differently depending upon whether auto-escaping
is currently in effect or not? This is normally a concern when you are
returning mixed content (HTML elements mixed with user-supplied content).
For example, the ``ordered_list`` filter that ships with Django needs to
know whether to escape its content or not. It will always return a safe
string. Since it returns raw HTML, we cannot apply escaping to the
result -- it needs to be done in-situ.
Be careful when deciding if your filter really does leave safe strings
as safe. Sometimes if you are *removing* characters, you can
inadvertently leave unbalanced HTML tags or entities in the result.
For example, removing a ``>`` from the input might turn ``<a>`` into
``<a``, which would need to be escaped on output to avoid causing
problems. Similarly, removing a semicolon (``;``) can turn ``&amp;``
into ``&amp``, which is no longer a valid entity and thus needs
further escaping. Most cases won't be nearly this tricky, but keep an
eye out for any problems like that when reviewing your code.
For these cases, the filter function needs to be told what the current
auto-escaping setting is. Set the ``needs_autoescape`` attribute on the
filter to ``True`` and have your function take an extra argument called
``autoescape`` with a default value of ``None``. When the filter is called,
the ``autoescape`` keyword argument will be ``True`` if auto-escaping is in
effect. For example, the ``unordered_list`` filter is written as::
2. Alternatively, your filter code can manually take care of any necessary
escaping. This is usually necessary when you are introducing new HTML
markup into the result. You want to mark the output as safe from further
escaping so that your HTML markup isn't escaped further, so you'll need to
handle the input yourself.
def unordered_list(value, autoescape=None):
# ... lots of code here ...
To mark the output as a safe string, use
``django.utils.safestring.mark_safe()``.
return mark_safe(...)
Be careful, though. You need to do more than just mark the output as
safe. You need to ensure it really *is* safe and what you do will often
depend upon whether or not auto-escaping is in effect. The idea is to
write filters than can operate in templates where auto-escaping is either
on or off in order to make things easier for your template authors.
unordered_list.is_safe = True
unordered_list.needs_autoescape = True
In order for you filter to know the current auto-escaping state, set the
``needs_autoescape`` attribute to ``True`` on your function (if you don't
specify this attribute, it defaults to ``False``). This attribute tells
Django that your filter function wants to be passed an extra keyword
argument, called ``autoescape`` that is ``True`` is auto-escaping is in
effect and ``False`` otherwise.
By default, both the ``is_safe`` and ``needs_autoescape`` attributes are
``False``. You do not need to specify them if ``False`` is an acceptable
value.
An example might make this clearer. Let's write a filter that emphasizes
the first character of a string::
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
def initial_letter_filter(text, autoescape=None):
first, other = text[0] ,text[1:]
if autoescape:
esc = conditional_escape
else:
esc = lambda x: x
result = '<strong>%s</strong>%s' % (esc(first), esc(other))
return mark_safe(result)
initial_letter_filter.needs_autoescape = True
The ``needs_autoescape`` attribute on the filter function and the
``autoescape`` keyword argument mean that our function will know whether
or not automatic escaping is in effect when the filter is called. We use
``autoescape`` to decide whether the input data needs to be passed through
``django.utils.html.conditional_escape`` or not (in the latter case, we
just use the identity function as the "escape" function). The
``conditional_escape()`` function is like ``escape()`` except it only
escapes input that is **not** a ``SafeData`` instance. If a ``SafeData``
instance is passed to ``conditional_escape()``, the data is returned
unchanged.
Finally, in the above example, we remember to mark the result as safe
so that our HTML is inserted directly into the template without further
escaping.
There is no need to worry about the ``is_safe`` attribute in this case
(although including it wouldn't hurt anything). Whenever you are manually
handling the auto-escaping issues and returning a safe string, the
``is_safe`` attribute won't change anything either way.
Writing custom template tags
----------------------------
@ -932,7 +977,9 @@ without having to be parsed multiple times.
Auto-escaping considerations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The output from template tags is not automatically run through the
**New in Django development version**
The output from template tags is **not** automatically run through the
auto-escaping filters. However, there are still a couple of things you should
keep in mind when writing a template tag:

View File

@ -78,7 +78,8 @@ True
>>> paginator.pages
2
# The paginator can provide a list of all available pages
# The paginator can provide a list of all available pages.
>>> paginator = ObjectPaginator(Article.objects.all(), 10)
>>> paginator.page_range
[1, 2]
"""}

View File

@ -3,9 +3,12 @@
# Unit tests for cache framework
# Uses whatever cache backend is set in the test settings file.
from django.core.cache import cache
import time, unittest
from django.core.cache import cache
from django.utils.cache import patch_vary_headers
from django.http import HttpResponse
# functions/classes for complex data type tests
def f():
return 42
@ -87,5 +90,30 @@ class Cache(unittest.TestCase):
cache.set(key, value)
self.assertEqual(cache.get(key), value)
class CacheUtils(unittest.TestCase):
"""TestCase for django.utils.cache functions."""
def test_patch_vary_headers(self):
headers = (
# Initial vary, new headers, resulting vary.
(None, ('Accept-Encoding',), 'Accept-Encoding'),
('Accept-Encoding', ('accept-encoding',), 'Accept-Encoding'),
('Accept-Encoding', ('ACCEPT-ENCODING',), 'Accept-Encoding'),
('Cookie', ('Accept-Encoding',), 'Cookie, Accept-Encoding'),
('Cookie, Accept-Encoding', ('Accept-Encoding',), 'Cookie, Accept-Encoding'),
('Cookie, Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'),
(None, ('Accept-Encoding', 'COOKIE'), 'Accept-Encoding, COOKIE'),
('Cookie, Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'),
('Cookie , Accept-Encoding', ('Accept-Encoding', 'cookie'), 'Cookie, Accept-Encoding'),
)
for initial_vary, newheaders, resulting_vary in headers:
response = HttpResponse()
if initial_vary is not None:
response['Vary'] = initial_vary
patch_vary_headers(response, newheaders)
self.assertEqual(response['Vary'], resulting_vary)
if __name__ == '__main__':
unittest.main()

View File

@ -25,11 +25,23 @@
>>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']})
>>> d['name']
'Simon'
>>> d.get('name')
'Simon'
>>> d.getlist('name')
['Adrian', 'Simon']
>>> d['lastname']
Traceback (most recent call last):
...
MultiValueDictKeyError: "Key 'lastname' not found in <MultiValueDict: {'position': ['Developer'], 'name': ['Adrian', 'Simon']}>"
>>> d.get('lastname')
>>> d.get('lastname', 'nonexistent')
'nonexistent'
>>> d.getlist('lastname')
[]
>>> d.setlist('lastname', ['Holovaty', 'Willison'])
>>> d.getlist('lastname')
['Holovaty', 'Willison']
### SortedDict #################################################################

View File

@ -0,0 +1,360 @@
# -*- coding: utf-8 -*-
tests = r"""
>>> from django.newforms import *
# CharField ###################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s'
>>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s'
>>> f = CharField(min_length=5, max_length=10, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('1234')
Traceback (most recent call last):
...
ValidationError: [u'LENGTH 4, MIN LENGTH 5']
>>> f.clean('12345678901')
Traceback (most recent call last):
...
ValidationError: [u'LENGTH 11, MAX LENGTH 10']
# IntegerField ################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['min_value'] = 'MIN VALUE IS %s'
>>> e['max_value'] = 'MAX VALUE IS %s'
>>> f = IntegerField(min_value=5, max_value=10, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abc')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
>>> f.clean('4')
Traceback (most recent call last):
...
ValidationError: [u'MIN VALUE IS 5']
>>> f.clean('11')
Traceback (most recent call last):
...
ValidationError: [u'MAX VALUE IS 10']
# FloatField ##################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['min_value'] = 'MIN VALUE IS %s'
>>> e['max_value'] = 'MAX VALUE IS %s'
>>> f = FloatField(min_value=5, max_value=10, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abc')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
>>> f.clean('4')
Traceback (most recent call last):
...
ValidationError: [u'MIN VALUE IS 5']
>>> f.clean('11')
Traceback (most recent call last):
...
ValidationError: [u'MAX VALUE IS 10']
# DecimalField ################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['min_value'] = 'MIN VALUE IS %s'
>>> e['max_value'] = 'MAX VALUE IS %s'
>>> e['max_digits'] = 'MAX DIGITS IS %s'
>>> e['max_decimal_places'] = 'MAX DP IS %s'
>>> e['max_whole_digits'] = 'MAX DIGITS BEFORE DP IS %s'
>>> f = DecimalField(min_value=5, max_value=10, error_messages=e)
>>> f2 = DecimalField(max_digits=4, decimal_places=2, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abc')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
>>> f.clean('4')
Traceback (most recent call last):
...
ValidationError: [u'MIN VALUE IS 5']
>>> f.clean('11')
Traceback (most recent call last):
...
ValidationError: [u'MAX VALUE IS 10']
>>> f2.clean('123.45')
Traceback (most recent call last):
...
ValidationError: [u'MAX DIGITS IS 4']
>>> f2.clean('1.234')
Traceback (most recent call last):
...
ValidationError: [u'MAX DP IS 2']
>>> f2.clean('123.4')
Traceback (most recent call last):
...
ValidationError: [u'MAX DIGITS BEFORE DP IS 2']
# DateField ###################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> f = DateField(error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abc')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
# TimeField ###################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> f = TimeField(error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abc')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
# DateTimeField ###############################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> f = DateTimeField(error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abc')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
# RegexField ##################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s'
>>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s'
>>> f = RegexField(r'^\d+$', min_length=5, max_length=10, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abcde')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
>>> f.clean('1234')
Traceback (most recent call last):
...
ValidationError: [u'LENGTH 4, MIN LENGTH 5']
>>> f.clean('12345678901')
Traceback (most recent call last):
...
ValidationError: [u'LENGTH 11, MAX LENGTH 10']
# EmailField ##################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['min_length'] = 'LENGTH %(length)s, MIN LENGTH %(min)s'
>>> e['max_length'] = 'LENGTH %(length)s, MAX LENGTH %(max)s'
>>> f = EmailField(min_length=8, max_length=10, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abcdefgh')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
>>> f.clean('a@b.com')
Traceback (most recent call last):
...
ValidationError: [u'LENGTH 7, MIN LENGTH 8']
>>> f.clean('aye@bee.com')
Traceback (most recent call last):
...
ValidationError: [u'LENGTH 11, MAX LENGTH 10']
# FileField ##################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['missing'] = 'MISSING'
>>> e['empty'] = 'EMPTY FILE'
>>> f = FileField(error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abc')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
>>> f.clean({})
Traceback (most recent call last):
...
ValidationError: [u'MISSING']
>>> f.clean({'filename': 'name', 'content':''})
Traceback (most recent call last):
...
ValidationError: [u'EMPTY FILE']
# URLField ##################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID'
>>> e['invalid_link'] = 'INVALID LINK'
>>> f = URLField(verify_exists=True, error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('abc.c')
Traceback (most recent call last):
...
ValidationError: [u'INVALID']
>>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com')
Traceback (most recent call last):
...
ValidationError: [u'INVALID LINK']
# BooleanField ################################################################
>>> e = {'required': 'REQUIRED'}
>>> f = BooleanField(error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
# ChoiceField #################################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid_choice'] = '%(value)s IS INVALID CHOICE'
>>> f = ChoiceField(choices=[('a', 'aye')], error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('b')
Traceback (most recent call last):
...
ValidationError: [u'b IS INVALID CHOICE']
# MultipleChoiceField #########################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid_choice'] = '%(value)s IS INVALID CHOICE'
>>> e['invalid_list'] = 'NOT A LIST'
>>> f = MultipleChoiceField(choices=[('a', 'aye')], error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('b')
Traceback (most recent call last):
...
ValidationError: [u'NOT A LIST']
>>> f.clean(['b'])
Traceback (most recent call last):
...
ValidationError: [u'b IS INVALID CHOICE']
# SplitDateTimeField ##########################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid_date'] = 'INVALID DATE'
>>> e['invalid_time'] = 'INVALID TIME'
>>> f = SplitDateTimeField(error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean(['a', 'b'])
Traceback (most recent call last):
...
ValidationError: [u'INVALID DATE', u'INVALID TIME']
# IPAddressField ##############################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid'] = 'INVALID IP ADDRESS'
>>> f = IPAddressField(error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('127.0.0')
Traceback (most recent call last):
...
ValidationError: [u'INVALID IP ADDRESS']
###############################################################################
# Create choices for the model choice field tests below.
>>> from regressiontests.forms.models import ChoiceModel
>>> ChoiceModel.objects.create(pk=1, name='a')
<ChoiceModel: ChoiceModel object>
>>> ChoiceModel.objects.create(pk=2, name='b')
<ChoiceModel: ChoiceModel object>
>>> ChoiceModel.objects.create(pk=3, name='c')
<ChoiceModel: ChoiceModel object>
# ModelChoiceField ############################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid_choice'] = 'INVALID CHOICE'
>>> f = ModelChoiceField(queryset=ChoiceModel.objects.all(), error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('4')
Traceback (most recent call last):
...
ValidationError: [u'INVALID CHOICE']
# ModelMultipleChoiceField ####################################################
>>> e = {'required': 'REQUIRED'}
>>> e['invalid_choice'] = '%s IS INVALID CHOICE'
>>> e['list'] = 'NOT A LIST OF VALUES'
>>> f = ModelMultipleChoiceField(queryset=ChoiceModel.objects.all(), error_messages=e)
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'REQUIRED']
>>> f.clean('3')
Traceback (most recent call last):
...
ValidationError: [u'NOT A LIST OF VALUES']
>>> f.clean(['4'])
Traceback (most recent call last):
...
ValidationError: [u'4 IS INVALID CHOICE']
"""

View File

@ -10,6 +10,10 @@ class Defaults(models.Model):
def_date = models.DateField(default = datetime.date(1980, 1, 1))
value = models.IntegerField(default=42)
class ChoiceModel(models.Model):
"""For ModelChoiceField and ModelMultipleChoiceField tests."""
name = models.CharField(max_length=10)
__test__ = {'API_TESTS': """
>>> from django.newforms import form_for_model, form_for_instance

View File

@ -2,6 +2,7 @@
tests = r"""
>>> from django.newforms import *
>>> from django.newforms.widgets import RadioFieldRenderer
>>> from django.utils.safestring import mark_safe
>>> import datetime
>>> import time
>>> import re
@ -205,6 +206,8 @@ u'<textarea rows="10" cols="40" name="msg"></textarea>'
u'<textarea rows="10" cols="40" name="msg">value</textarea>'
>>> w.render('msg', 'some "quoted" & ampersanded value')
u'<textarea rows="10" cols="40" name="msg">some &quot;quoted&quot; &amp; ampersanded value</textarea>'
>>> w.render('msg', mark_safe('pre &quot;quoted&quot; value'))
u'<textarea rows="10" cols="40" name="msg">pre &quot;quoted&quot; value</textarea>'
>>> w.render('msg', 'value', attrs={'class': 'pretty', 'rows': 20})
u'<textarea class="pretty" rows="20" cols="40" name="msg">value</textarea>'
@ -375,6 +378,17 @@ If 'choices' is passed to both the constructor and render(), then they'll both b
<option value="5">5</option>
</select>
# Choices are escaped correctly
>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you &gt; me'))))
<select name="escape">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="bad">you &amp; me</option>
<option value="good">you &gt; me</option>
</select>
# Unicode choices are correctly rendered as HTML
>>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
u'<select name="email">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
@ -538,6 +552,17 @@ If 'choices' is passed to both the constructor and render(), then they'll both b
<option value="5">5</option>
</select>
# Choices are escaped correctly
>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you &gt; me'))))
<select multiple="multiple" name="escape">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="bad">you &amp; me</option>
<option value="good">you &gt; me</option>
</select>
# Unicode choices are correctly rendered as HTML
>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
u'<select multiple="multiple" name="nums">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
@ -663,6 +688,16 @@ You can create your own custom renderers for RadioSelect to use.
<label><input checked="checked" type="radio" name="beatle" value="G" /> George</label><br />
<label><input type="radio" name="beatle" value="R" /> Ringo</label>
Or you can use custom RadioSelect fields that use your custom renderer.
>>> class CustomRadioSelect(RadioSelect):
... renderer = MyRenderer
>>> w = CustomRadioSelect()
>>> print w.render('beatle', 'G', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
<label><input type="radio" name="beatle" value="J" /> John</label><br />
<label><input type="radio" name="beatle" value="P" /> Paul</label><br />
<label><input checked="checked" type="radio" name="beatle" value="G" /> George</label><br />
<label><input type="radio" name="beatle" value="R" /> Ringo</label>
A RadioFieldRenderer object also allows index access to individual RadioInput
objects.
>>> w = RadioSelect()
@ -682,6 +717,14 @@ Traceback (most recent call last):
...
IndexError: list index out of range
# Choices are escaped correctly
>>> w = RadioSelect()
>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you &gt; me'))))
<ul>
<li><label><input type="radio" name="escape" value="bad" /> you &amp; me</label></li>
<li><label><input type="radio" name="escape" value="good" /> you &gt; me</label></li>
</ul>
# Unicode choices are correctly rendered as HTML
>>> w = RadioSelect()
>>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]))
@ -811,6 +854,17 @@ If 'choices' is passed to both the constructor and render(), then they'll both b
<li><label><input type="checkbox" name="nums" value="5" /> 5</label></li>
</ul>
# Choices are escaped correctly
>>> print w.render('escape', None, choices=(('bad', 'you & me'), ('good', mark_safe('you &gt; me'))))
<ul>
<li><label><input type="checkbox" name="escape" value="1" /> 1</label></li>
<li><label><input type="checkbox" name="escape" value="2" /> 2</label></li>
<li><label><input type="checkbox" name="escape" value="3" /> 3</label></li>
<li><label><input type="checkbox" name="escape" value="bad" /> you &amp; me</label></li>
<li><label><input type="checkbox" name="escape" value="good" /> you &gt; me</label></li>
</ul>
# Unicode choices are correctly rendered as HTML
>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>'

View File

@ -198,6 +198,12 @@ def get_filter_tests():
'filter-phone2numeric01': ('{{ a|phone2numeric }} {{ b|phone2numeric }}', {"a": "<1-800-call-me>", "b": mark_safe("<1-800-call-me>") }, "&lt;1-800-2255-63&gt; <1-800-2255-63>"),
'filter-phone2numeric02': ('{% autoescape off %}{{ a|phone2numeric }} {{ b|phone2numeric }}{% endautoescape %}', {"a": "<1-800-call-me>", "b": mark_safe("<1-800-call-me>") }, "<1-800-2255-63> <1-800-2255-63>"),
# Ensure iriencode keeps safe strings:
'filter-iriencode01': ('{{ url|iriencode }}', {'url': '?test=1&me=2'}, '?test=1&amp;me=2'),
'filter-iriencode02': ('{% autoescape off %}{{ url|iriencode }}{% endautoescape %}', {'url': '?test=1&me=2'}, '?test=1&me=2'),
'filter-iriencode03': ('{{ url|iriencode }}', {'url': mark_safe('?test=1&me=2')}, '?test=1&me=2'),
'filter-iriencode04': ('{% autoescape off %}{{ url|iriencode }}{% endautoescape %}', {'url': mark_safe('?test=1&me=2')}, '?test=1&me=2'),
# Chaining a bunch of safeness-preserving filters should not alter
# the safe status either way.
'chaining01': ('{{ a|capfirst|center:"7" }}.{{ b|capfirst|center:"7" }}', {"a": "a < b", "b": mark_safe("a < b")}, " A &lt; b . A < b "),

View File

@ -268,6 +268,12 @@ class Templates(unittest.TestCase):
# Embedded newlines make it not-a-tag.
'basic-syntax24': ("{{ moo\n }}", {}, "{{ moo\n }}"),
# Literal strings are permitted inside variables, mostly for i18n
# purposes.
'basic-syntax25': ('{{ "fred" }}', {}, "fred"),
'basic-syntax26': (r'{{ "\"fred\"" }}', {}, "\"fred\""),
'basic-syntax27': (r'{{ _("\"fred\"") }}', {}, "\"fred\""),
# List-index syntax allows a template to access a certain item of a subscriptable object.
'list-index01': ("{{ var.1 }}", {"var": ["first item", "second item"]}, "second item"),