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

newforms-admin: Merged to [4545]

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@4546 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-02-20 00:41:14 +00:00
parent 649423e81c
commit 67e0248806
55 changed files with 11374 additions and 2745 deletions

View File

@ -104,6 +104,7 @@ answer newbie questions, and generally made Django that much better:
Michael Josephson <http://www.sdjournal.com/>
jpellerin@gmail.com
junzhang.jn@gmail.com
Ben Dean Kawamura <ben.dean.kawamura@gmail.com>
Garth Kidd <http://www.deadlybloodyserious.com/>
kilian <kilian.cavalotti@lip6.fr>
Sune Kirkeby <http://ibofobi.dk/>
@ -153,15 +154,18 @@ answer newbie questions, and generally made Django that much better:
Michael Radziej <mir@noris.de>
ramiro
Brian Ray <http://brianray.chipy.org/>
remco@diji.biz
rhettg@gmail.com
Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
David Schein
scott@staplefish.com
serbaut@gmail.com
Pete Shinners <pete@shinners.org>
SmileyChris <smileychris@gmail.com>
smurf@smurf.noris.de
sopel
Georgi Stanojevski <glisha@gmail.com>
Thomas Steinacher <tom@eggdrop.ch>
nowell strite
Radek Švarz <http://www.svarz.cz/translate/>
@ -175,6 +179,7 @@ answer newbie questions, and generally made Django that much better:
Makoto Tsuyuki <mtsuyuki@gmail.com>
Amit Upadhyay
Geert Vanderkelen
viestards.lists@gmail.com
Milton Waddams
wam-djangobug@wamber.net
Dan Watson <http://theidioteque.net/>

View File

@ -38,6 +38,7 @@ LANGUAGE_CODE = 'en-us'
LANGUAGES = (
('ar', gettext_noop('Arabic')),
('bn', gettext_noop('Bengali')),
('ca', gettext_noop('Catalan')),
('cs', gettext_noop('Czech')),
('cy', gettext_noop('Welsh')),
('da', gettext_noop('Danish')),
@ -54,6 +55,8 @@ LANGUAGES = (
('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')),
('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')),
('nl', gettext_noop('Dutch')),
('no', gettext_noop('Norwegian')),
('pl', gettext_noop('Polish')),

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,121 @@
# translation of djangojs.po to
# Spanish translation for the django-admin JS files.
# Copyright (C)
# This file is distributed under the same license as the PACKAGE package.
#
# Jorge Gajon <gajon@gajon.org>, 2005.
# Marc Fargas <marc@fargas.com>, 2007.
msgid ""
msgstr ""
"Project-Id-Version: djangojs\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-02-15 11:05+1100\n"
"PO-Revision-Date: 2007-01-19 10:30+0100\n"
"Last-Translator: Marc Fargas <marc@fargas.com>\n"
"Language-Team: <es@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ISO-8859-1\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "%s Disponibles"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Seleccionar tots"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Afegir"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Eliminar"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "%s Escollits"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Faci les seves seleccions i faci click a"
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Deseleccionar tots"
#: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Febrer Març Abril Maig Juny Juliol Agost Setembre Octubre Novembre Desembre"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Diumenge Dilluns Dimarts Dimecres Dijous Divendres Dissabte"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "D L M X J V S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "Ara"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "Rellotje"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "Esculli una hora"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "Mitja nit"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "6 a.m."
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Migdia"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "Cancel·lar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "Avui"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "Calendari"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "Ahir"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Demà"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr ""
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@ -107,3 +107,12 @@ msgstr "Gestern"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "Morgen"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr "Anzeigen"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr "Verbergen"

View File

@ -1029,19 +1029,19 @@ msgstr " %(filter_title)s:"
#: contrib/admin/templates/admin/submit_line.html:4
msgid "Save as new"
msgstr "Talleta uutena"
msgstr "Tallenna uutena"
#: contrib/admin/templates/admin/submit_line.html:5
msgid "Save and add another"
msgstr "Talleta ja lisää seuraava"
msgstr "Tallenna ja lisää seuraava"
#: contrib/admin/templates/admin/submit_line.html:6
msgid "Save and continue editing"
msgstr "Talleta välillä ja jatka muokkaamista"
msgstr "Tallenna välillä ja jatka muokkaamista"
#: contrib/admin/templates/admin/submit_line.html:7
msgid "Save"
msgstr "Talleta ja poistu"
msgstr "Tallenna ja poistu"
#: contrib/admin/templates/admin/change_list.html:11
#, python-format

View File

@ -1,13 +1,13 @@
# Translation of django.po to japanese.
# Copyright (C) 2005,2006 THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# makoto tsuyuki <mtsuyuki@gmail.com>, 2005,2006.
# makoto tsuyuki <mtsuyuki@gmail.com>, 2005,2006,2007.
#
msgid ""
msgstr ""
"Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2006-10-21 20:42+0900\n"
"POT-Creation-Date: 2007-02-15 23:43+0900\n"
"PO-Revision-Date: 2006-05-18 00:28+0900\n"
"Last-Translator: makoto tsuyuki <mtsuyuki@gmail.com>\n"
"Language-Team: Japanese <django-ja@googlegroups.com>\n"
@ -24,126 +24,138 @@ msgid "Bengali"
msgstr "ベンガル語"
#: conf/global_settings.py:41
msgid "Catalan"
msgstr "カタロニア語"
#: conf/global_settings.py:42
msgid "Czech"
msgstr "チェコ語"
#: conf/global_settings.py:42
#: conf/global_settings.py:43
msgid "Welsh"
msgstr "ウェールズ語"
#: conf/global_settings.py:43
#: conf/global_settings.py:44
msgid "Danish"
msgstr "デンマーク語"
#: conf/global_settings.py:44
#: conf/global_settings.py:45
msgid "German"
msgstr "ドイツ語"
#: conf/global_settings.py:45
#: conf/global_settings.py:46
msgid "Greek"
msgstr "ギリシャ語"
#: conf/global_settings.py:46
#: conf/global_settings.py:47
msgid "English"
msgstr "英語"
#: conf/global_settings.py:47
#: conf/global_settings.py:48
msgid "Spanish"
msgstr "スペイン語"
#: conf/global_settings.py:48
#: conf/global_settings.py:49
msgid "Argentinean Spanish"
msgstr "アルゼンチンスペイン語"
#: conf/global_settings.py:49
#: conf/global_settings.py:50
msgid "Finnish"
msgstr "フィンランド語"
#: conf/global_settings.py:50
#: conf/global_settings.py:51
msgid "French"
msgstr "フランス語"
#: conf/global_settings.py:51
#: conf/global_settings.py:52
msgid "Galician"
msgstr "ガリシア語"
#: conf/global_settings.py:52
#: conf/global_settings.py:53
msgid "Hungarian"
msgstr "ハンガリー語"
#: conf/global_settings.py:53
#: conf/global_settings.py:54
msgid "Hebrew"
msgstr "ヘブライ語"
#: conf/global_settings.py:54
#: conf/global_settings.py:55
msgid "Icelandic"
msgstr "アイスランド語"
#: conf/global_settings.py:55
#: conf/global_settings.py:56
msgid "Italian"
msgstr "イタリア語"
#: conf/global_settings.py:56
#: conf/global_settings.py:57
msgid "Japanese"
msgstr "日本語"
#: conf/global_settings.py:57
#: conf/global_settings.py:58
msgid "Latvian"
msgstr "ラトビア語"
#: conf/global_settings.py:59
msgid "Macedonian"
msgstr "マケドニア語"
#: conf/global_settings.py:60
msgid "Dutch"
msgstr "オランダ語"
#: conf/global_settings.py:58
#: conf/global_settings.py:61
msgid "Norwegian"
msgstr "ノルウェー語"
#: conf/global_settings.py:59
#: conf/global_settings.py:62
msgid "Polish"
msgstr "ポーランド語"
#: conf/global_settings.py:60
#: conf/global_settings.py:63
msgid "Brazilian"
msgstr "ブラジル語"
#: conf/global_settings.py:61
#: conf/global_settings.py:64
msgid "Romanian"
msgstr "ルーマニア語"
#: conf/global_settings.py:62
#: conf/global_settings.py:65
msgid "Russian"
msgstr "ロシア語"
#: conf/global_settings.py:63
#: conf/global_settings.py:66
msgid "Slovak"
msgstr "スロバキア語"
#: conf/global_settings.py:64
#: conf/global_settings.py:67
msgid "Slovenian"
msgstr "スロヴェニア語"
#: conf/global_settings.py:65
#: conf/global_settings.py:68
msgid "Serbian"
msgstr "セルビア語"
#: conf/global_settings.py:66
#: conf/global_settings.py:69
msgid "Swedish"
msgstr "スウェーデン語"
#: conf/global_settings.py:67
#: conf/global_settings.py:70
msgid "Tamil"
msgstr "タミル語"
#: conf/global_settings.py:68
#: conf/global_settings.py:71
msgid "Turkish"
msgstr "トルコ語"
#: conf/global_settings.py:69
#: conf/global_settings.py:72
msgid "Ukrainian"
msgstr "ウクライナ語"
#: conf/global_settings.py:70
#: conf/global_settings.py:73
msgid "Simplified Chinese"
msgstr "簡体字中国語"
#: conf/global_settings.py:71
#: conf/global_settings.py:74
msgid "Traditional Chinese"
msgstr "繁体字中国語"
@ -181,15 +193,18 @@ msgstr "今月"
msgid "This year"
msgstr "今年"
#: contrib/admin/filterspecs.py:143
#: contrib/admin/filterspecs.py:143 newforms/widgets.py:170
#: oldforms/__init__.py:572
msgid "Yes"
msgstr "はい"
#: contrib/admin/filterspecs.py:143
#: contrib/admin/filterspecs.py:143 newforms/widgets.py:170
#: oldforms/__init__.py:572
msgid "No"
msgstr "いいえ"
#: contrib/admin/filterspecs.py:150
#: contrib/admin/filterspecs.py:150 newforms/widgets.py:170
#: oldforms/__init__.py:572
msgid "Unknown"
msgstr "不明"
@ -237,6 +252,7 @@ msgstr "申し訳ありませんが、お探しのページは見つかりませ
#: contrib/admin/templates/admin/delete_confirmation.html:6
#: contrib/admin/templates/admin/invalid_setup.html:4
#: contrib/admin/templates/admin/object_history.html:5
#: contrib/admin/templates/admin/auth/user/change_password.html:12
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
#: contrib/admin/templates/registration/logged_out.html:4
#: contrib/admin/templates/registration/password_change_done.html:4
@ -275,6 +291,7 @@ msgstr "ようこそ"
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/auth/user/change_password.html:9
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
#: contrib/admin/templates/registration/password_change_done.html:3
#: contrib/admin/templates/registration/password_change_form.html:3
@ -286,6 +303,9 @@ msgstr "ドキュメント"
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/auth/user/change_password.html:9
#: contrib/admin/templates/admin/auth/user/change_password.html:15
#: contrib/admin/templates/admin/auth/user/change_password.html:46
#: contrib/admin/templates/admin_doc/bookmarklets.html:4
#: contrib/admin/templates/admin_doc/index.html:4
#: contrib/admin/templates/admin_doc/missing_docutils.html:4
@ -306,6 +326,7 @@ msgstr "パスワードの変更"
#: contrib/admin/templates/admin/change_list.html:5
#: contrib/admin/templates/admin/delete_confirmation.html:3
#: contrib/admin/templates/admin/object_history.html:3
#: contrib/admin/templates/admin/auth/user/change_password.html:9
#: contrib/admin/templates/admin_doc/bookmarklets.html:4
#: contrib/admin/templates/admin_doc/index.html:4
#: contrib/admin/templates/admin_doc/missing_docutils.html:4
@ -335,30 +356,31 @@ msgstr "Django 管理サイト"
msgid "Add"
msgstr "追加"
#: contrib/admin/templates/admin/change_form.html:20
#: contrib/admin/templates/admin/change_form.html:21
#: contrib/admin/templates/admin/object_history.html:5
msgid "History"
msgstr "履歴"
#: contrib/admin/templates/admin/change_form.html:21
#: contrib/admin/templates/admin/change_form.html:22
msgid "View on site"
msgstr "サイト上で表示"
#: contrib/admin/templates/admin/change_form.html:30
#: contrib/admin/templates/admin/change_form.html:32
#: contrib/admin/templates/admin/auth/user/change_password.html:24
msgid "Please correct the error below."
msgid_plural "Please correct the errors below."
msgstr[0] "下記のエラーを修正してください。"
msgstr[1] "下記のエラーを修正してください。"
#: contrib/admin/templates/admin/change_form.html:48
#: contrib/admin/templates/admin/change_form.html:50
msgid "Ordering"
msgstr "順序"
#: contrib/admin/templates/admin/change_form.html:51
#: contrib/admin/templates/admin/change_form.html:53
msgid "Order:"
msgstr "並び変え:"
#: contrib/admin/templates/admin/change_list.html:11
#: contrib/admin/templates/admin/change_list.html:12
#, python-format
msgid "Add %(name)s"
msgstr "%(name)s を追加"
@ -451,10 +473,6 @@ msgstr "ユーザ名:"
msgid "Password:"
msgstr "パスワード:"
#: contrib/admin/templates/admin/login.html:22
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
msgstr "<a href=\"/password_reset/\">パスワードをお忘れですか</a>"
#: contrib/admin/templates/admin/login.html:25
#: contrib/admin/views/decorators.py:24
msgid "Log in"
@ -533,17 +551,25 @@ msgid "Username"
msgstr "ユーザ名"
#: contrib/admin/templates/admin/auth/user/add_form.html:18
#: contrib/admin/templates/admin/auth/user/change_password.html:34
msgid "Password"
msgstr "パスワード"
#: contrib/admin/templates/admin/auth/user/add_form.html:23
#: contrib/admin/templates/admin/auth/user/change_password.html:39
msgid "Password (again)"
msgstr "パスワード(確認用)"
#: contrib/admin/templates/admin/auth/user/add_form.html:24
#: contrib/admin/templates/admin/auth/user/change_password.html:40
msgid "Enter the same password as above, for verification."
msgstr "確認のため、再度パスワードを入力してください。"
#: contrib/admin/templates/admin/auth/user/change_password.html:28
#, python-format
msgid "Enter a new password for the user <strong>%(username)s</strong>."
msgstr "<strong>%(username)s</strong>さんの新しいパスワードを入力してください。"
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
msgid "Bookmarklets"
msgstr "ブックマークレット"
@ -743,25 +769,34 @@ msgstr "現在:"
msgid "Change:"
msgstr "変更:"
#: contrib/admin/templatetags/admin_list.py:230
#: contrib/admin/templatetags/admin_list.py:238
msgid "All dates"
msgstr "いつでも"
#: contrib/admin/views/auth.py:17 contrib/admin/views/main.py:257
#: contrib/admin/views/auth.py:19 contrib/admin/views/main.py:257
#, python-format
msgid "The %(name)s \"%(obj)s\" was added successfully."
msgstr "%(name)s \"%(obj)s\" を追加しました。"
#: contrib/admin/views/auth.py:22 contrib/admin/views/main.py:261
#: contrib/admin/views/auth.py:24 contrib/admin/views/main.py:261
#: contrib/admin/views/main.py:347
msgid "You may edit it again below."
msgstr "続けて編集できます。"
#: contrib/admin/views/auth.py:28
#: contrib/admin/views/auth.py:30
msgid "Add user"
msgstr "ユーザを追加"
#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:59
#: contrib/admin/views/auth.py:57
msgid "Password changed successfully."
msgstr "パスワードを変更しました"
#: contrib/admin/views/auth.py:64
#, python-format
msgid "Change password: %s"
msgstr "パスワードの変更: %s"
#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:60
msgid ""
"Please enter a correct username and password. Note that both fields are case-"
"sensitive."
@ -949,7 +984,7 @@ msgid "Added %s."
msgstr "%s を追加しました。"
#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
#: contrib/admin/views/main.py:339
#: contrib/admin/views/main.py:339 db/models/manipulators.py:306
msgid "and"
msgstr "と"
@ -1021,15 +1056,15 @@ msgstr "変更する %s を選択"
msgid "Database error"
msgstr "データベースエラー"
#: contrib/auth/forms.py:16
#: contrib/auth/forms.py:17 contrib/auth/forms.py:138
msgid "The two password fields didn't match."
msgstr "確認用パスワードが一致しません。"
#: contrib/auth/forms.py:24
#: contrib/auth/forms.py:25
msgid "A user with that username already exists."
msgstr "同じユーザ名が既に登録済みです。"
#: contrib/auth/forms.py:52
#: contrib/auth/forms.py:53
msgid ""
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
"required for logging in."
@ -1037,21 +1072,21 @@ msgstr ""
"お使いのブラウザはクッキーを有効にしていないようです。ログインにはクッキーが"
"必要です。"
#: contrib/auth/forms.py:61
#: contrib/auth/forms.py:62
msgid "This account is inactive."
msgstr "アカウントが無効です。"
#: contrib/auth/forms.py:84
#: contrib/auth/forms.py:85
msgid ""
"That e-mail address doesn't have an associated user account. Are you sure "
"you've registered?"
msgstr "メールアドレスの一致するユーザはいません。本当に登録しましたか?"
#: contrib/auth/forms.py:116
#: contrib/auth/forms.py:117
msgid "The two 'new password' fields didn't match."
msgstr "新しいパスワード(確認用)が一致しません。"
#: contrib/auth/forms.py:123
#: contrib/auth/forms.py:124
msgid "Your old password was entered incorrectly. Please enter it again."
msgstr "元のパスワードが間違っています。もう一度入力してください。"
@ -1108,8 +1143,12 @@ msgid "password"
msgstr "パスワード"
#: contrib/auth/models.py:94
msgid "Use '[algo]$[salt]$[hexdigest]'"
msgstr "'[アルゴリズム]$[ソルト]$[ダイジェスト(hex)]' 形式を使って下さい"
msgid ""
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
"password form</a>."
msgstr ""
"'[algo]$[salt]$[hexdigest]'形式か、"
"<a href=\"password/\">パスワード変更フォーム</a>を使ってください。"
#: contrib/auth/models.py:95
msgid "staff status"
@ -1478,15 +1517,15 @@ msgstr "コメント ID が不正です"
msgid "No voting for yourself"
msgstr "自分には投票できません。"
#: contrib/contenttypes/models.py:20
#: contrib/contenttypes/models.py:26
msgid "python model class name"
msgstr "Python モデルクラス名"
#: contrib/contenttypes/models.py:23
#: contrib/contenttypes/models.py:29
msgid "content type"
msgstr "コンテンツタイプ"
#: contrib/contenttypes/models.py:24
#: contrib/contenttypes/models.py:30
msgid "content types"
msgstr "コンテンツタイプ"
@ -1536,6 +1575,10 @@ msgstr "フラットページ"
msgid "flat pages"
msgstr "フラットページ"
#: contrib/localflavor/usa/forms.py:13
msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX."
msgstr "XXXXXか、XXXXX-XXXXの形式で郵便番号を入力してください。"
#: contrib/redirects/models.py:7
msgid "redirect from"
msgstr "リダイレクト元"
@ -1600,92 +1643,92 @@ msgstr "サイト"
msgid "sites"
msgstr "サイト"
#: core/validators.py:63
#: core/validators.py:64
msgid "This value must contain only letters, numbers and underscores."
msgstr "半角の英数字およびアンダースコア以外は使用できません。"
#: core/validators.py:67
#: core/validators.py:68
msgid ""
"This value must contain only letters, numbers, underscores, dashes or "
"slashes."
msgstr ""
"半角の英数字、アンダースコア、ダッシュ、スラッシュ以外は使用できません。"
#: core/validators.py:71
#: core/validators.py:72
msgid "This value must contain only letters, numbers, underscores or hyphens."
msgstr "半角の英数字、アンダースコア、ハイフン以外は使用できません。"
#: core/validators.py:75
#: core/validators.py:76
msgid "Uppercase letters are not allowed here."
msgstr "大文字はここでは使用できません。"
#: core/validators.py:79
#: core/validators.py:80
msgid "Lowercase letters are not allowed here."
msgstr "小文字はここでは使用できません。"
#: core/validators.py:86
#: core/validators.py:87
msgid "Enter only digits separated by commas."
msgstr "カンマ区切りの数字だけを入力してください。"
#: core/validators.py:98
#: core/validators.py:99
msgid "Enter valid e-mail addresses separated by commas."
msgstr "カンマ区切りの有効なメールアドレスを入力してください。"
#: core/validators.py:102
#: core/validators.py:103
msgid "Please enter a valid IP address."
msgstr "有効な IP アドレスを入力してください。"
#: core/validators.py:106
#: core/validators.py:107
msgid "Empty values are not allowed here."
msgstr "入力は必須です。"
#: core/validators.py:110
#: core/validators.py:111
msgid "Non-numeric characters aren't allowed here."
msgstr "数値以外は使用できません。"
#: core/validators.py:114
#: core/validators.py:115
msgid "This value can't be comprised solely of digits."
msgstr "数値だけの値にはできません。"
#: core/validators.py:119
#: core/validators.py:120 newforms/fields.py:126
msgid "Enter a whole number."
msgstr "整数を入力してください。"
#: core/validators.py:123
#: core/validators.py:124
msgid "Only alphabetical characters are allowed here."
msgstr "半角アルファベット以外使用できません。"
#: core/validators.py:138
#: core/validators.py:139
msgid "Year must be 1900 or later."
msgstr "1900年以降を指定してください。"
#: core/validators.py:142
#: core/validators.py:143
#, python-format
msgid "Invalid date: %s."
msgstr "無効な日付: %s"
#: core/validators.py:146 db/models/fields/__init__.py:424
#: core/validators.py:147 db/models/fields/__init__.py:454
msgid "Enter a valid date in YYYY-MM-DD format."
msgstr "YYYY-MM-DD形式で日付を入力してください。"
#: core/validators.py:151
#: core/validators.py:152
msgid "Enter a valid time in HH:MM format."
msgstr "HH:MM形式で時刻を入力してください。"
#: core/validators.py:155 db/models/fields/__init__.py:486
#: core/validators.py:156 db/models/fields/__init__.py:521
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
msgstr "YYYY-MM-DD HH:MM形式で日時を入力してください。"
#: core/validators.py:160
#: core/validators.py:161 newforms/fields.py:269
msgid "Enter a valid e-mail address."
msgstr "有効なメールアドレスを入力してください。"
#: core/validators.py:172 core/validators.py:401 forms/__init__.py:662
#: core/validators.py:173 core/validators.py:442 oldforms/__init__.py:667
msgid "No file was submitted. Check the encoding type on the form."
msgstr ""
"ファイルが取得できませんでした。formのencoding typeを確認してください。"
#: core/validators.py:176
#: core/validators.py:177
msgid ""
"Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image."
@ -1693,26 +1736,26 @@ msgstr ""
"画像をアップロードしてください。アップロードした画像は画像でないか、または壊"
"れています。"
#: core/validators.py:183
#: core/validators.py:184
#, python-format
msgid "The URL %s does not point to a valid image."
msgstr "URL ( %s ) は画像ではありません。"
#: core/validators.py:187
#: core/validators.py:188
#, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr "電話番号は XXX-XXX-XXXX 形式で入力してください。\"%s\" は無効です。"
#: core/validators.py:195
#: core/validators.py:196
#, python-format
msgid "The URL %s does not point to a valid QuickTime video."
msgstr "URL ( %s ) は QuickTime ビデオではありません。"
#: core/validators.py:199
#: core/validators.py:200
msgid "A valid URL is required."
msgstr "正しい URL を入力してください。"
#: core/validators.py:213
#: core/validators.py:214
#, python-format
msgid ""
"Valid HTML is required. Specific errors are:\n"
@ -1721,71 +1764,86 @@ msgstr ""
"有効な HTML を入力してください。エラー:\n"
"%s"
#: core/validators.py:220
#: core/validators.py:221
#, python-format
msgid "Badly formed XML: %s"
msgstr "不正な XML です: %s"
#: core/validators.py:230
#: core/validators.py:238
#, python-format
msgid "Invalid URL: %s"
msgstr "無効なURL: %s"
#: core/validators.py:234 core/validators.py:236
#: core/validators.py:243 core/validators.py:245
#, python-format
msgid "The URL %s is a broken link."
msgstr "URL ( %s ) はリンクが壊れています。"
#: core/validators.py:242
#: core/validators.py:251
msgid "Enter a valid U.S. state abbreviation."
msgstr "正しい米州略称を入力してください。"
#: core/validators.py:256
#: core/validators.py:265
#, python-format
msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "言葉使いに気を付けて! %s という言葉は使えません。"
msgstr[1] "言葉使いに気を付けて! %s という言葉は使えません。"
#: core/validators.py:263
#: core/validators.py:272
#, python-format
msgid "This field must match the '%s' field."
msgstr "このフィールドは '%s' フィールドと一致せねばなりません。"
#: core/validators.py:282
#: core/validators.py:291
msgid "Please enter something for at least one field."
msgstr "少なくとも一つのフィールドに何か入力してください。"
#: core/validators.py:291 core/validators.py:302
#: core/validators.py:300 core/validators.py:311
msgid "Please enter both fields or leave them both empty."
msgstr "両方のフィールドに入力するか、両方とも未入力にしてください。"
#: core/validators.py:309
#: core/validators.py:318
#, python-format
msgid "This field must be given if %(field)s is %(value)s"
msgstr ""
"%(field)s を %(value)s にするのなら、このフィールドに必ず入力してください。"
#: core/validators.py:321
#: core/validators.py:330
#, python-format
msgid "This field must be given if %(field)s is not %(value)s"
msgstr ""
"%(field)s を %(value)s にしないのなら、このフィールドに必ず入力してください。"
#: core/validators.py:340
#: core/validators.py:349
msgid "Duplicate values are not allowed."
msgstr "重複する値は認められません。"
#: core/validators.py:363
#: core/validators.py:364
#, python-format
msgid "This value must be between %s and %s."
msgstr "この値は %s から %s の間でなければなりません。"
#: core/validators.py:366
#, python-format
msgid "This value must be at least %s."
msgstr "この値は %s 以上でなければなりません。"
#: core/validators.py:368
#, python-format
msgid "This value must be no more than %s."
msgstr "この値は %s より小さくなければなりません。"
#: core/validators.py:404
#, python-format
msgid "This value must be a power of %s."
msgstr "この値は %s の累乗でなければなりません。"
#: core/validators.py:374
#: core/validators.py:415
msgid "Please enter a valid decimal number."
msgstr "有効な 10 進数を入力してください。"
#: core/validators.py:378
#: core/validators.py:419
#, python-format
msgid "Please enter a valid decimal number with at most %s total digit."
msgid_plural ""
@ -1793,7 +1851,7 @@ msgid_plural ""
msgstr[0] "全体で %s 文字以下の数字を入力してください。"
msgstr[1] "全体で %s 文字以下の数字を入力してください。"
#: core/validators.py:381
#: core/validators.py:422
#, python-format
msgid ""
"Please enter a valid decimal number with a whole part of at most %s digit."
@ -1802,7 +1860,7 @@ msgid_plural ""
msgstr[0] "整数部は %s 文字以下の数字を入力してください。"
msgstr[1] "整数部は %s 文字以下の数字を入力してください。"
#: core/validators.py:384
#: core/validators.py:425
#, python-format
msgid "Please enter a valid decimal number with at most %s decimal place."
msgid_plural ""
@ -1810,37 +1868,37 @@ msgid_plural ""
msgstr[0] "小数部は %s 文字以下の数字を入力してください。"
msgstr[1] "小数部は %s 文字以下の数字を入力してください。"
#: core/validators.py:394
#: core/validators.py:435
#, python-format
msgid "Make sure your uploaded file is at least %s bytes big."
msgstr "アップロードするファイルの大きさは %s バイト以上にしてください。"
#: core/validators.py:395
#: core/validators.py:436
#, python-format
msgid "Make sure your uploaded file is at most %s bytes big."
msgstr "アップロードするファイルの大きさは %s 最大バイトまでです。"
#: core/validators.py:412
#: core/validators.py:453
msgid "The format for this field is wrong."
msgstr "フィールドの形式が正しくありません。"
#: core/validators.py:427
#: core/validators.py:468
msgid "This field is invalid."
msgstr "このフィールドは無効です。"
#: core/validators.py:463
#: core/validators.py:504
#, python-format
msgid "Could not retrieve anything from %s."
msgstr "%s から何も検索できませんでした。"
#: core/validators.py:466
#: core/validators.py:507
#, python-format
msgid ""
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
msgstr ""
"URL %(url)s は無効なコンテンツタイプヘッダ '%(contenttype)s' を返しました。"
#: core/validators.py:499
#: core/validators.py:540
#, python-format
msgid ""
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
@ -1849,7 +1907,7 @@ msgstr ""
"%(line)s 行目から始まる %(tag)s タグを閉じてください (\"%(start)s\" で始まる"
"行です)。"
#: core/validators.py:503
#: core/validators.py:544
#, python-format
msgid ""
"Some text starting on line %(line)s is not allowed in that context. (Line "
@ -1858,7 +1916,7 @@ msgstr ""
"%(line)s 行目から始まるテキストはこのコンテキストでは使えません。 (\"%(start)"
"s\" で始まる行です)。"
#: core/validators.py:508
#: core/validators.py:549
#, python-format
msgid ""
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
@ -1867,7 +1925,7 @@ msgstr ""
"%(line)s 行目の \"%(attr)s\" は無効なアトリビュートです (\"%(start)s\" で始ま"
"る行です)。"
#: core/validators.py:513
#: core/validators.py:554
#, python-format
msgid ""
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
@ -1876,7 +1934,7 @@ msgstr ""
"%(line)s 行目の \"<%(tag)s>\" は無効なタグです( \"%(start)s\" で始まる行で"
"す)。"
#: core/validators.py:517
#: core/validators.py:558
#, python-format
msgid ""
"A tag on line %(line)s is missing one or more required attributes. (Line "
@ -1885,7 +1943,7 @@ msgstr ""
"%(line)s 行目のタグは必須アトリビュートが未入力です( \"%(start)s\" で始まる行"
"です)。"
#: core/validators.py:522
#: core/validators.py:563
#, python-format
msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
@ -1900,50 +1958,51 @@ msgid "%(object)s with this %(type)s already exists for the given %(field)s."
msgstr ""
"%(field)s に入力されたものは、この %(type)s の %(object)s に既に存在します。"
#: db/models/fields/__init__.py:41
#: db/models/fields/__init__.py:42
#, python-format
msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "%(fieldname)s に %(optname)s は既に存在します。"
#: db/models/fields/__init__.py:115 db/models/fields/__init__.py:266
#: db/models/fields/__init__.py:560 db/models/fields/__init__.py:571
#: forms/__init__.py:347
#: db/models/fields/__init__.py:116 db/models/fields/__init__.py:273
#: db/models/fields/__init__.py:605 db/models/fields/__init__.py:616
#: newforms/fields.py:78 newforms/fields.py:373 newforms/fields.py:449
#: newforms/fields.py:460 oldforms/__init__.py:352
msgid "This field is required."
msgstr "このフィールドは必須です。"
#: db/models/fields/__init__.py:349
#: db/models/fields/__init__.py:366
msgid "This value must be an integer."
msgstr "値は整数でなければなりません。"
#: db/models/fields/__init__.py:381
#: db/models/fields/__init__.py:401
msgid "This value must be either True or False."
msgstr "値は真: True または偽: False でなければなりません。"
#: db/models/fields/__init__.py:397
#: db/models/fields/__init__.py:422
msgid "This field cannot be null."
msgstr "このフィールドには NULL を指定できません。"
#: db/models/fields/__init__.py:580
#: db/models/fields/__init__.py:625
msgid "Enter a valid filename."
msgstr "正しいファイル名を入力してください。"
#: db/models/fields/related.py:51
#: db/models/fields/related.py:53
#, python-format
msgid "Please enter a valid %s."
msgstr "正しい %s を入力してください。"
#: db/models/fields/related.py:618
#: db/models/fields/related.py:642
msgid "Separate multiple IDs with commas."
msgstr "複数の ID はカンマで区切ってください。"
#: db/models/fields/related.py:620
#: db/models/fields/related.py:644
msgid ""
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
msgstr ""
"複数選択するときには Control キーを押したまま選択してください。Mac は "
"Command キーを使ってください"
#: db/models/fields/related.py:664
#: db/models/fields/related.py:691
#, python-format
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
msgid_plural ""
@ -1951,39 +2010,96 @@ msgid_plural ""
msgstr[0] "正しい %(self)s IDを入力してください。 %(value)r は無効です。"
msgstr[1] "正しい %(self)s IDを入力してください。 %(value)r は無効です。"
#: forms/__init__.py:382
#: newforms/fields.py:101 newforms/fields.py:254
#, python-format
msgid "Ensure this value has at most %d characters."
msgstr "%d 字以下で入力してください。"
#: newforms/fields.py:103 newforms/fields.py:256
#, python-format
msgid "Ensure this value has at least %d characters."
msgstr "%d 字以上で入力してください。"
#: newforms/fields.py:128
#, python-format
msgid "Ensure this value is less than or equal to %s."
msgstr "この値は %s 以下でなければなりません。"
#: newforms/fields.py:130
#, python-format
msgid "Ensure this value is greater than or equal to %s."
msgstr "この値は %s 以上でなければなりません。"
#: newforms/fields.py:163
msgid "Enter a valid date."
msgstr "日付を正しく入力してください。"
#: newforms/fields.py:190
msgid "Enter a valid time."
msgstr "時間を正しく入力してください。"
#: newforms/fields.py:226
msgid "Enter a valid date/time."
msgstr "日付/時間を正しく入力してください。"
#: newforms/fields.py:240
msgid "Enter a valid value."
msgstr "値を正しく入力してください。"
#: newforms/fields.py:287 newforms/fields.py:309
msgid "Enter a valid URL."
msgstr "URLを正しく入力してください。"
#: newforms/fields.py:311
msgid "This URL appears to be a broken link."
msgstr "このURLはリンクが壊れています。"
#: newforms/fields.py:359
msgid "Select a valid choice. That choice is not one of the available choices."
msgstr "正しく選択してください。選択したものは候補にありません。"
#: newforms/fields.py:377 newforms/fields.py:453
msgid "Enter a list of values."
msgstr "リストを入力してください。"
#: newforms/fields.py:386
#, python-format
msgid "Select a valid choice. %s is not one of the available choices."
msgstr "正しく選択してください。 %s は候補にありません。"
#: oldforms/__init__.py:387
#, python-format
msgid "Ensure your text is less than %s character."
msgid_plural "Ensure your text is less than %s characters."
msgstr[0] "%s 字以下で入力してください。"
msgstr[1] "%s 字以下で入力してください。"
#: forms/__init__.py:387
#: oldforms/__init__.py:392
msgid "Line breaks are not allowed here."
msgstr "改行はできません。"
#: forms/__init__.py:488 forms/__init__.py:561 forms/__init__.py:600
#: oldforms/__init__.py:493 oldforms/__init__.py:566 oldforms/__init__.py:605
#, python-format
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
msgstr "正しく選択してください。; '%(data)s' は %(choices)s にありません。"
#: forms/__init__.py:664
#: oldforms/__init__.py:669
msgid "The submitted file is empty."
msgstr "入力されたファイルは空です。"
#: forms/__init__.py:720
#: oldforms/__init__.py:725
msgid "Enter a whole number between -32,768 and 32,767."
msgstr "-32,768 から 32,767 までの整数を入力してください。"
#: forms/__init__.py:730
#: oldforms/__init__.py:735
msgid "Enter a positive number."
msgstr "正の数を入力してください。"
#: forms/__init__.py:740
#: oldforms/__init__.py:745
msgid "Enter a whole number between 0 and 32,767."
msgstr "0 から 32,767 までの整数を入力してください。"
#: template/defaultfilters.py:401
#: template/defaultfilters.py:436
msgid "yes,no,maybe"
msgstr "はい,いいえ,たぶん"
@ -2209,21 +2325,3 @@ msgstr "%(verbose_name)s を更新しました。"
#, python-format
msgid "The %(verbose_name)s was deleted."
msgstr " %(verbose_name)s を削除しました。"
#~ msgid "String (up to 50)"
#~ msgstr "文字列 (50 字まで)"
#~ msgid "Comment"
#~ msgstr "コメント"
#~ msgid "Comments"
#~ msgstr "コメント"
#~ msgid "label"
#~ msgstr "ラベル"
#~ msgid "package"
#~ msgstr "パッケージ"
#~ msgid "packages"
#~ msgstr "パッケージ"

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,118 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-02-15 10:46+1100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr ""
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr ""
#: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr ""
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr ""
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr ""
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr ""
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr ""

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,118 @@
# translation of djangojs.po to Macedonian
#
# Georgi Stanojevski <glisha@gmail.com>, 2006.
msgid ""
msgstr ""
"Project-Id-Version: djangojs\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-02-15 10:53+1100\n"
"PO-Revision-Date: 2006-12-04 16:18+0100\n"
"Last-Translator: Georgi Stanojevski <glisha@gmail.com>\n"
"Language-Team: Macedonian <ossm-members@hedona.on.net.mk>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Достапно %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Избери ги сите"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Додади"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Отстрани"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Избрано %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Означете го вашиот избор/и и кликнете"
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Исчисти ги сите"
#: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24
msgid ""
"January February March April May June July August September October November "
"December"
msgstr ""
"Јануари Февруари Март Април Мај Јуни Јули Август Септември Октомври Ноември "
"Декември"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Недела Понеделник Вторник Среда Четврток Петок Сабота"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "Н П В С Ч П С"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "Сега"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "Часовник"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "Избери време"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "Полноќ"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "6 наутро"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "Пладне"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "Откажи"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "Денеска"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "Календар"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "Вчера"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "Утре"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr ""
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ function URLify(s, num_chars) {
"with"];
r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
s = s.replace(r, '');
s = s.replace(/[^-A-Z0-9\s]/gi, ''); // remove unneeded chars
s = s.replace(/[^-\w\s]/g, ''); // remove unneeded chars
s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
s = s.replace(/[-\s]+/g, '-'); // convert spaces to hyphens
s = s.toLowerCase(); // convert to lowercase

View File

View File

@ -0,0 +1,19 @@
"""
UK-specific Form helpers
"""
from django.newforms.fields import RegexField
from django.utils.translation import gettext
class UKPostcodeField(RegexField):
"""
A form field that validates its input is a UK postcode.
The regular expression used is sourced from the schema for British Standard
BS7666 address types: http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd
"""
def __init__(self, *args, **kwargs):
super(UKPostcodeField, self).__init__(r'^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW]) [0-9][ABD-HJLNP-UW-Z]{2})$',
max_length=None, min_length=None,
error_message=gettext(u'Enter a postcode. A space is required between the two postcode parts.'),
*args, **kwargs)

View File

@ -0,0 +1,44 @@
"""
USA-specific Form helpers
"""
from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.utils.translation import gettext
class USZipCodeField(RegexField):
def __init__(self, *args, **kwargs):
super(USZipCodeField, self).__init__(r'^\d{5}(?:-\d{4})?$',
max_length=None, min_length=None,
error_message=gettext(u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'),
*args, **kwargs)
class USStateField(Field):
"""
A form field that validates its input is a U.S. state name or abbreviation.
It normalizes the input to the standard two-leter postal service
abbreviation for the given state.
"""
def clean(self, value):
from us_states import STATES_NORMALIZED # relative import
super(USStateField, self).clean(value)
if value in EMPTY_VALUES:
return u''
try:
value = value.strip().lower()
except AttributeError:
pass
else:
try:
return STATES_NORMALIZED[value.strip().lower()].decode('ascii')
except KeyError:
pass
raise ValidationError(u'Enter a U.S. state or territory.')
class USStateSelect(Select):
"""
A Select widget that uses a list of U.S. states/territories as its choices.
"""
def __init__(self, attrs=None):
from us_states import STATE_CHOICES # relative import
super(USStateSelect, self).__init__(attrs, choices=STATE_CHOICES)

View File

@ -0,0 +1,238 @@
"""
A mapping of state misspellings/abbreviations to normalized abbreviations, and
an alphabetical list of states for use as `choices` in a formfield.
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
STATE_CHOICES = (
('AL', 'Alabama'),
('AK', 'Alaska'),
('AS', 'American Samoa'),
('AZ', 'Arizona'),
('AR', 'Arkansas'),
('CA', 'California'),
('CO', 'Colorado'),
('CT', 'Connecticut'),
('DE', 'Deleware'),
('DC', 'District of Columbia'),
('FM', 'Federated States of Micronesia'),
('FL', 'Florida'),
('GA', 'Georgia'),
('GU', 'Guam'),
('HI', 'Hawaii'),
('ID', 'Idaho'),
('IL', 'Illinois'),
('IN', 'Indiana'),
('IA', 'Iowa'),
('KS', 'Kansas'),
('KY', 'Kentucky'),
('LA', 'Louisiana'),
('ME', 'Maine'),
('MH', 'Marshall Islands'),
('MD', 'Maryland'),
('MI', 'Michigan'),
('MN', 'Minnesota'),
('MS', 'Mississippi'),
('MO', 'Missouri'),
('MT', 'Montana'),
('NE', 'Nebraska'),
('NV', 'Nevada'),
('NH', 'New Hampshire'),
('NJ', 'New Jersey'),
('NM', 'New Mexico'),
('NY', 'New York'),
('NC', 'North Carolina'),
('ND', 'North Dakota'),
('MP', 'Northern Mariana Islands'),
('OH', 'Ohio'),
('OK', 'Oklahoma'),
('OR', 'Oregon'),
('PW', 'Palau'),
('PA', 'Pennsylvania'),
('PR', 'Puerto Rico'),
('RI', 'Rhode Island'),
('SC', 'South Carolina'),
('SD', 'South Dakota'),
('TN', 'Tennessee'),
('TX', 'Texas'),
('UT', 'Utah'),
('VT', 'Vermont'),
('VI', 'Virgin Islands'),
('VA', 'Virginia'),
('WA', 'Washington'),
('WV', 'West Virginia'),
('WI', 'Wisconsin'),
('WY', 'Wyoming'),
)
STATES_NORMALIZED = {
'ak': 'AK',
'al': 'AL',
'ala': 'AL',
'alabama': 'AL',
'alaska': 'AK',
'american samao': 'AS',
'american samoa': 'AS',
'ar': 'AR',
'ariz': 'AZ',
'arizona': 'AZ',
'ark': 'AR',
'arkansas': 'AR',
'as': 'AS',
'az': 'AZ',
'ca': 'CA',
'calf': 'CA',
'calif': 'CA',
'california': 'CA',
'co': 'CO',
'colo': 'CO',
'colorado': 'CO',
'conn': 'CT',
'connecticut': 'CT',
'ct': 'CT',
'dc': 'DC',
'de': 'DE',
'del': 'DE',
'delaware': 'DE',
'district of columbia': 'DC',
'federated states of micronesia': 'FM',
'fl': 'FL',
'fla': 'FL',
'florida': 'FL',
'fm': 'FM',
'ga': 'GA',
'georgia': 'GA',
'gu': 'GU',
'guam': 'GU',
'hawaii': 'HI',
'hi': 'HI',
'ia': 'IA',
'id': 'ID',
'idaho': 'ID',
'il': 'IL',
'ill': 'IL',
'illinois': 'IL',
'in': 'IN',
'ind': 'IN',
'indiana': 'IN',
'iowa': 'IA',
'kan': 'KS',
'kans': 'KS',
'kansas': 'KS',
'kentucky': 'KY',
'ks': 'KS',
'ky': 'KY',
'la': 'LA',
'louisiana': 'LA',
'ma': 'MA',
'maine': 'ME',
'marianas islands': 'MP',
'marianas islands of the pacific': 'MP',
'marinas islands of the pacific': 'MP',
'maryland': 'MD',
'mass': 'MA',
'massachusetts': 'MA',
'massachussetts': 'MA',
'md': 'MD',
'me': 'ME',
'mi': 'MI',
'mich': 'MI',
'michigan': 'MI',
'micronesia': 'FM',
'minn': 'MN',
'minnesota': 'MN',
'miss': 'MS',
'mississippi': 'MS',
'missouri': 'MO',
'mn': 'MN',
'mo': 'MO',
'mont': 'MT',
'montana': 'MT',
'mp': 'MP',
'ms': 'MS',
'mt': 'MT',
'n d': 'ND',
'n dak': 'ND',
'n h': 'NH',
'n j': 'NJ',
'n m': 'NM',
'n mex': 'NM',
'nc': 'NC',
'nd': 'ND',
'ne': 'NE',
'neb': 'NE',
'nebr': 'NE',
'nebraska': 'NE',
'nev': 'NV',
'nevada': 'NV',
'new hampshire': 'NH',
'new jersey': 'NJ',
'new mexico': 'NM',
'new york': 'NY',
'nh': 'NH',
'nj': 'NJ',
'nm': 'NM',
'nmex': 'NM',
'north carolina': 'NC',
'north dakota': 'ND',
'northern mariana islands': 'MP',
'nv': 'NV',
'ny': 'NY',
'oh': 'OH',
'ohio': 'OH',
'ok': 'OK',
'okla': 'OK',
'oklahoma': 'OK',
'or': 'OR',
'ore': 'OR',
'oreg': 'OR',
'oregon': 'OR',
'pa': 'PA',
'penn': 'PA',
'pennsylvania': 'PA',
'pr': 'PR',
'puerto rico': 'PR',
'rhode island': 'RI',
'ri': 'RI',
's dak': 'SD',
'sc': 'SC',
'sd': 'SD',
'sdak': 'SD',
'south carolina': 'SC',
'south dakota': 'SD',
'tenn': 'TN',
'tennessee': 'TN',
'territory of hawaii': 'HI',
'tex': 'TX',
'texas': 'TX',
'tn': 'TN',
'tx': 'TX',
'us virgin islands': 'VI',
'usvi': 'VI',
'ut': 'UT',
'utah': 'UT',
'va': 'VA',
'vermont': 'VT',
'vi': 'VI',
'viginia': 'VA',
'virgin islands': 'VI',
'virgina': 'VA',
'virginia': 'VA',
'vt': 'VT',
'w va': 'WV',
'wa': 'WA',
'wash': 'WA',
'washington': 'WA',
'west virginia': 'WV',
'wi': 'WI',
'wis': 'WI',
'wisc': 'WI',
'wisconsin': 'WI',
'wv': 'WV',
'wva': 'WV',
'wy': 'WY',
'wyo': 'WY',
'wyoming': 'WY',
}

View File

@ -8,7 +8,18 @@ import socket
import time
import random
DNS_NAME = socket.getfqdn() # Cache the hostname
# Cache the hostname, but do it lazily: socket.getfqdn() can take a couple of
# seconds, which slows down the restart of the server.
class CachedDnsName(object):
def __str__(self):
return self.get_fqdn()
def get_fqdn(self):
if not hasattr(self, '_fqdn'):
self._fqdn = socket.getfqdn()
return self._fqdn
DNS_NAME = CachedDnsName()
class BadHeaderError(ValueError):
pass

View File

@ -1177,6 +1177,11 @@ createcachetable.args = "[tablename]"
def run_shell(use_plain=False):
"Runs a Python interactive interpreter. Tries to use IPython, if it's available."
# XXX: (Temporary) workaround for ticket #1796: force early loading of all
# models from installed apps.
from django.db.models.loading import get_models
loaded_models = get_models()
try:
if use_plain:
# Don't bother loading IPython, because the user wants plain Python.

View File

@ -161,7 +161,7 @@ class Field(object):
def get_db_prep_lookup(self, lookup_type, value):
"Returns field's value prepared for database lookup."
if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'year', 'month', 'day', 'search'):
if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'):
return [value]
elif lookup_type in ('range', 'in'):
return value
@ -175,7 +175,13 @@ class Field(object):
return ["%%%s" % prep_for_like_query(value)]
elif lookup_type == 'isnull':
return []
raise TypeError, "Field has invalid lookup: %s" % lookup_type
elif lookup_type == 'year':
try:
value = int(value)
except ValueError:
raise ValueError("The __year lookup type requires an integer argument")
return ['%s-01-01 00:00:00' % value, '%s-12-31 23:59:59.999999' % value]
raise TypeError("Field has invalid lookup: %s" % lookup_type)
def has_default(self):
"Returns a boolean of whether this field has a default value."

View File

@ -708,9 +708,9 @@ def get_where_clause(lookup_type, table_prefix, field_name, value):
return '%s%s IN (%s)' % (table_prefix, field_name, in_string)
else:
raise EmptyResultSet
elif lookup_type == 'range':
elif lookup_type in ('range', 'year'):
return '%s%s BETWEEN %%s AND %%s' % (table_prefix, field_name)
elif lookup_type in ('year', 'month', 'day'):
elif lookup_type in ('month', 'day'):
return "%s = %%s" % backend.get_date_extract_sql(lookup_type, table_prefix + field_name)
elif lookup_type == 'isnull':
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))

View File

@ -104,12 +104,12 @@ class RelatedObject(object):
attr = getattr(manipulator.original_object, self.get_accessor_name())
count = attr.count()
count += self.field.rel.num_extra_on_change
if self.field.rel.min_num_in_admin:
count = max(count, self.field.rel.min_num_in_admin)
if self.field.rel.max_num_in_admin:
count = min(count, self.field.rel.max_num_in_admin)
else:
count = self.field.rel.num_in_admin
if self.field.rel.min_num_in_admin:
count = max(count, self.field.rel.min_num_in_admin)
if self.field.rel.max_num_in_admin:
count = min(count, self.field.rel.max_num_in_admin)
else:
count = 1

View File

@ -51,7 +51,7 @@ class Field(object):
if label is not None:
label = smart_unicode(label)
self.required, self.label, self.initial = required, label, initial
self.help_text = help_text
self.help_text = smart_unicode(help_text or '')
widget = widget or self.widget
if isinstance(widget, type):
widget = widget()

View File

@ -7,6 +7,7 @@ from django.utils.html import escape
from fields import Field
from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput
from util import flatatt, StrAndUnicode, ErrorDict, ErrorList, ValidationError
import copy
__all__ = ('BaseForm', 'Form')
@ -27,13 +28,24 @@ class SortedDictFromList(SortedDict):
dict.__init__(self, dict(data))
def copy(self):
return SortedDictFromList(self.items())
return SortedDictFromList([(k, copy.copy(v)) for k, v in self.items()])
class DeclarativeFieldsMetaclass(type):
"Metaclass that converts Field attributes to a dictionary called 'base_fields'."
"""
Metaclass that converts Field attributes to a dictionary called
'base_fields', taking into account parent class 'base_fields' as well.
"""
def __new__(cls, name, bases, attrs):
fields = [(field_name, attrs.pop(field_name)) for field_name, obj in attrs.items() if isinstance(obj, Field)]
fields.sort(lambda x, y: cmp(x[1].creation_counter, y[1].creation_counter))
# If this class is subclassing another Form, add that Form's fields.
# Note that we loop over the bases in *reverse*. This is necessary in
# order to preserve the correct order of fields.
for base in bases[::-1]:
if hasattr(base, 'base_fields'):
fields = base.base_fields.items() + fields
attrs['base_fields'] = SortedDictFromList(fields)
return type.__new__(cls, name, bases, attrs)
@ -49,6 +61,7 @@ class BaseForm(StrAndUnicode):
self.prefix = prefix
self.initial = initial or {}
self.__errors = None # Stores the errors after clean() has been called.
# The base_fields class attribute is the *class-wide* definition of
# fields. Because a particular *instance* of the class might want to
# alter self.fields, we create self.fields here by copying base_fields.
@ -100,7 +113,7 @@ class BaseForm(StrAndUnicode):
output, hidden_fields = [], []
for name, field in self.fields.items():
bf = BoundField(self, field, name)
bf_errors = bf.errors # Cache in local variable.
bf_errors = ErrorList([escape(error) for error in bf.errors]) # Escape and cache in local variable.
if bf.is_hidden:
if bf_errors:
top_errors.extend(['(Hidden field %s) %s' % (name, e) for e in bf_errors])
@ -205,6 +218,7 @@ class BoundField(StrAndUnicode):
self.label = pretty_name(name)
else:
self.label = self.field.label
self.help_text = field.help_text or ''
def __unicode__(self):
"Renders this field as an HTML widget."

View File

@ -7,7 +7,10 @@ flatatt = lambda attrs: u''.join([u' %s="%s"' % (k, escape(v)) for k, v in attrs
def smart_unicode(s):
if not isinstance(s, basestring):
s = unicode(str(s))
if hasattr(s, '__unicode__'):
s = unicode(s)
else:
s = unicode(str(s), settings.DEFAULT_CHARSET)
elif not isinstance(s, unicode):
s = unicode(s, settings.DEFAULT_CHARSET)
return s

View File

@ -81,6 +81,14 @@ class TextInput(Input):
class PasswordInput(Input):
input_type = 'password'
def __init__(self, attrs=None, render_value=True):
self.attrs = attrs or {}
self.render_value = render_value
def render(self, name, value, attrs=None):
if not self.render_value: value=None
return super(PasswordInput, self).render(name, value, attrs)
class HiddenInput(Input):
input_type = 'hidden'
is_hidden = True

View File

@ -1,5 +1,6 @@
import sys
from cStringIO import StringIO
from urlparse import urlparse
from django.conf import settings
from django.core.handlers.base import BaseHandler
from django.core.handlers.wsgi import WSGIRequest
@ -9,6 +10,9 @@ from django.http import urlencode, SimpleCookie
from django.test import signals
from django.utils.functional import curry
BOUNDARY = 'BoUnDaRyStRiNg'
MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
class ClientHandler(BaseHandler):
"""
A HTTP Handler that can be used for testing purposes.
@ -184,19 +188,20 @@ class Client:
return self.request(**r)
def post(self, path, data={}, **extra):
def post(self, path, data={}, content_type=MULTIPART_CONTENT, **extra):
"Request a response from the server using POST."
BOUNDARY = 'BoUnDaRyStRiNg'
if content_type is MULTIPART_CONTENT:
post_data = encode_multipart(BOUNDARY, data)
else:
post_data = data
encoded = encode_multipart(BOUNDARY, data)
stream = StringIO(encoded)
r = {
'CONTENT_LENGTH': len(encoded),
'CONTENT_TYPE': 'multipart/form-data; boundary=%s' % BOUNDARY,
'CONTENT_LENGTH': len(post_data),
'CONTENT_TYPE': content_type,
'PATH_INFO': path,
'REQUEST_METHOD': 'POST',
'wsgi.input': stream,
'wsgi.input': StringIO(post_data),
}
r.update(extra)
@ -218,7 +223,7 @@ class Client:
if response.status_code != 302:
return False
login_path, data = response['Location'].split('?')
_, _, login_path, _, data, _= urlparse(response['Location'])
next = data.split('=')[1]
# Second, GET the login page; required to set up cookies
@ -235,7 +240,8 @@ class Client:
response = self.post(login_path, data=form_data, **extra)
# Login page should 302 redirect to the originally requested page
if response.status_code != 302 or response['Location'] != path:
if (response.status_code != 302 or
urlparse(response['Location'])[2] != path):
return False
# Since we are logged in, request the actual page again

View File

@ -1,6 +1,5 @@
import unittest, doctest
from django.conf import settings
from django.core import management
from django.test.utils import setup_test_environment, teardown_test_environment
from django.test.utils import create_test_db, destroy_test_db
from django.test.testcases import OutputChecker, DocTestRunner
@ -78,7 +77,6 @@ def run_tests(module_list, verbosity=1, extra_tests=[]):
old_name = settings.DATABASE_NAME
create_test_db(verbosity)
management.syncdb(verbosity, interactive=False)
unittest.TextTestRunner(verbosity=verbosity).run(suite)
destroy_test_db(old_name, verbosity)

View File

@ -1,6 +1,7 @@
import sys, time
from django.conf import settings
from django.db import connection, transaction, backend
from django.core import management
from django.dispatch import dispatcher
from django.test import signals
from django.template import Template
@ -84,6 +85,8 @@ def create_test_db(verbosity=1, autoclobber=False):
connection.close()
settings.DATABASE_NAME = TEST_DATABASE_NAME
management.syncdb(verbosity, interactive=False)
# Get a cursor (even though we don't need one yet). This has
# the side effect of initializing the test database.
cursor = connection.cursor()

View File

@ -139,6 +139,15 @@ See the `flatpages documentation`_.
.. _flatpages documentation: ../flatpages/
localflavor
===========
**New in Django development version**
A collection of various Django snippets that are useful only for a particular
country or culture. For example, ``django.contrib.localflavor.usa.forms``
contains a ``USZipCodeField`` that you can use to validate U.S. zip codes.
markup
======

View File

@ -1721,11 +1721,29 @@ But this template code is good::
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
(Yes, we know ``get_absolute_url()`` couples URLs to models, which violates the
DRY principle, because URLs are defined both in a URLconf and in the model.
This is a rare case in which we've intentionally violated that principle for
the sake of convenience. With that said, we're working on an even cleaner way
of specifying URLs in a more DRY fashion.)
The ``permalink`` decorator
~~~~~~~~~~~~~~~~~~~~~~~~~~~
**New in Django development version.**
The problem with the way we wrote ``get_absolute_url()`` above is that it
slightly violates the DRY principle: the URL for this object is defined both
in the URLConf file and in the model.
You can further decouple your models from the URLconf using the ``permalink``
decorator. This decorator is passed the view function and any parameters you
would use for accessing this instance directly. Django then works out the
correct full URL path using the URLconf. For example::
from django.db.models import permalink
def get_absolute_url(self):
return ('people.views.details', str(self.id))
get_absolute_url = permalink(get_absolute_url)
In this way, you're tying the model's absolute URL to the view that is used
to display it, without repeating the URL information anywhere. You can still
use the ``get_absolute_url`` method in templates, as before.
Executing custom SQL
--------------------

View File

@ -51,9 +51,10 @@ too messy. The choice is yours.
Overview
========
As with the ``django.forms`` ("manipulators") system before it, ``django.newforms``
is intended to handle HTML form display, validation and redisplay. It's what
you use if you want to perform server-side validation for an HTML form.
As with the ``django.forms`` ("manipulators") system before it,
``django.newforms`` is intended to handle HTML form display, data processing
(validation) and redisplay. It's what you use if you want to perform
server-side validation for an HTML form.
For example, if your Web site has a contact form that visitors can use to
send you e-mail, you'd use this library to implement the display of the HTML
@ -571,6 +572,46 @@ is a list-like object that is displayed as an HTML ``<ul>`` when printed::
>>> str(f['subject'].errors)
''
Subclassing forms
-----------------
If you subclass a custom ``Form`` class, the resulting ``Form`` class will
include all fields of the parent class(es), followed by the fields you define
in the subclass.
In this example, ``ContactFormWithPriority`` contains all the fields from
``ContactForm``, plus an additional field, ``priority``. The ``ContactForm``
fields are ordered first::
>>> class ContactFormWithPriority(ContactForm):
... priority = forms.CharField()
>>> f = ContactFormWithPriority(auto_id=False)
>>> print f.as_ul()
<li>Subject: <input type="text" name="subject" maxlength="100" /></li>
<li>Message: <input type="text" name="message" /></li>
<li>Sender: <input type="text" name="sender" /></li>
<li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
<li>Priority: <input type="text" name="priority" /></li>
It's possible to subclass multiple forms, treating forms as "mix-ins." In this
example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm``
(in that order), and its field list includes the fields from the parent
classes::
>>> class PersonForm(Form):
... first_name = CharField()
... last_name = CharField()
>>> class InstrumentForm(Form):
... instrument = CharField()
>>> class BeatleForm(PersonForm, InstrumentForm):
... haircut_type = CharField()
>>> b = BeatleForm(auto_id=False)
>>> print b.as_ul()
<li>First name: <input type="text" name="first_name" /></li>
<li>Last name: <input type="text" name="last_name" /></li>
<li>Instrument: <input type="text" name="instrument" /></li>
<li>Haircut type: <input type="text" name="haircut_type" /></li>
Fields
======

View File

@ -432,3 +432,118 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
``HttpResponseServerError``
Acts just like ``HttpResponse`` but uses a 500 status code.
Returning errors
================
Returning HTTP error codes in Django is easy. We've already mentioned the
``HttpResponseNotFound``, ``HttpResponseForbidden``,
``HttpResponseServerError``, etc., subclasses; just return an instance of one
of those subclasses instead of a normal ``HttpResponse`` in order to signify
an error. For example::
def my_view(request):
# ...
if foo:
return HttpResponseNotFound('<h1>Page not found</h1>')
else:
return HttpResponse('<h1>Page was found</h1>')
Because 404 errors are by far the most common HTTP error, there's an easier way
to handle those errors.
The Http404 exception
---------------------
When you return an error such as ``HttpResponseNotFound``, you're responsible
for defining the HTML of the resulting error page::
return HttpResponseNotFound('<h1>Page not found</h1>')
For convenience, and because it's a good idea to have a consistent 404 error page
across your site, Django provides an ``Http404`` exception. If you raise
``Http404`` at any point in a view function, Django will catch it and return the
standard error page for your application, along with an HTTP error code 404.
Example usage::
from django.http import Http404
def detail(request, poll_id):
try:
p = Poll.objects.get(pk=poll_id)
except Poll.DoesNotExist:
raise Http404
return render_to_response('polls/detail.html', {'poll': p})
In order to use the ``Http404`` exception to its fullest, you should create a
template that is displayed when a 404 error is raised. This template should be
called ``404.html`` and located in the top level of your template tree.
Customing error views
---------------------
The 404 (page not found) view
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When you raise an ``Http404`` exception, Django loads a special view devoted
to handling 404 errors. By default, it's the view
``django.views.defaults.page_not_found``, which loads and renders the template
``404.html``.
This means you need to define a ``404.html`` template in your root template
directory. This template will be used for all 404 errors.
This ``page_not_found`` view should suffice for 99% of Web applications, but if
you want to override the 404 view, you can specify ``handler404`` in your
URLconf, like so::
handler404 = 'mysite.views.my_custom_404_view'
Behind the scenes, Django determines the 404 view by looking for ``handler404``.
By default, URLconfs contain the following line::
from django.conf.urls.defaults import *
That takes care of setting ``handler404`` in the current module. As you can see
in ``django/conf/urls/defaults.py``, ``handler404`` is set to
``'django.views.defaults.page_not_found'`` by default.
Three things to note about 404 views:
* The 404 view is also called if Django doesn't find a match after checking
every regular expression in the URLconf.
* If you don't define your own 404 view -- and simply use the default,
which is recommended -- you still have one obligation: To create a
``404.html`` template in the root of your template directory. The default
404 view will use that template for all 404 errors.
* If ``DEBUG`` is set to ``True`` (in your settings module) then your 404
view will never be used, and the traceback will be displayed instead.
The 500 (server error) view
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Similarly, Django executes special-case behavior in the case of runtime errors
in view code. If a view results in an exception, Django will, by default, call
the view ``django.views.defaults.server_error``, which loads and renders the
template ``500.html``.
This means you need to define a ``500.html`` template in your root template
directory. This template will be used for all server errors.
This ``server_error`` view should suffice for 99% of Web applications, but if
you want to override the view, you can specify ``handler500`` in your
URLconf, like so::
handler500 = 'mysite.views.my_custom_error_view'
Behind the scenes, Django determines the error view by looking for ``handler500``.
By default, URLconfs contain the following line::
from django.conf.urls.defaults import *
That takes care of setting ``handler500`` in the current module. As you can see
in ``django/conf/urls/defaults.py``, ``handler500`` is set to
``'django.views.defaults.server_error'`` by default.

View File

@ -217,15 +217,21 @@ can be invoked on the ``Client`` instance.
http://yoursite.com/customers/details/?name=fred&age=7
``post(path, data={})``
Make a POST request on the provided ``path``. The key-value pairs in the
data dictionary will be used to create the POST data payload. This payload
will be transmitted with the mimetype ``multipart/form-data``.
``post(path, data={}, content_type=MULTIPART_CONTENT)``
Make a POST request on the provided ``path``. If you provide a content type
(e.g., ``text/xml`` for an XML payload), the contents of ``data`` will be
sent as-is in the POST request, using the content type in the HTTP
``Content-Type`` header.
However submitting files is a special case. To POST a file, you need only
If you do not provide a value for ``content_type``, the values in
``data`` will be transmitted with a content type of ``multipart/form-data``.
The key-value pairs in the data dictionary will be encoded as a multipart
message and used to create the POST data payload.
Submitting files is a special case. To POST a file, you need only
provide the file field name as a key, and a file handle to the file you wish to
upload as a value. The Test Client will populate the two POST fields (i.e.,
``field`` and ``field_file``) required by FileField. For example::
``field`` and ``field_file``) required by Django's FileField. For example::
c = Client()
f = open('wishlist.doc')
@ -323,6 +329,7 @@ part of a test condition.
``session`` A dictionary-like object containing session information.
See the `session documentation`_ for full details.
=============== ==========================================================
.. _`session documentation`: ../sessions/

View File

@ -319,7 +319,6 @@ AttributeError: Manager isn't accessible via Article instances
>>> Article.objects.filter(id__lte=4).delete()
>>> Article.objects.all()
[<Article: Article 6>, <Article: Default headline>, <Article: Article 7>, <Article: Updated article 8>]
"""}
from django.conf import settings
@ -358,4 +357,11 @@ __test__['API_TESTS'] += """
>>> a10 = Article.objects.create(headline="Article 10", pub_date=datetime(2005, 7, 31, 12, 30, 45))
>>> Article.objects.get(headline="Article 10")
<Article: Article 10>
# Edge-case test: A year lookup should retrieve all objects in the given
year, including Jan. 1 and Dec. 31.
>>> a11 = Article.objects.create(headline='Article 11', pub_date=datetime(2008, 1, 1))
>>> a12 = Article.objects.create(headline='Article 12', pub_date=datetime(2008, 12, 31, 23, 59, 59, 999999))
>>> Article.objects.filter(pub_date__year=2008)
[<Article: Article 11>, <Article: Article 12>]
"""

View File

@ -43,7 +43,7 @@ class ClientTest(unittest.TestCase):
# Check some response details
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template.name, 'Empty POST Template')
self.assertEqual(response.template.name, 'Empty GET Template')
def test_empty_post(self):
"POST an empty dictionary to a view"
@ -53,7 +53,7 @@ class ClientTest(unittest.TestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template.name, 'Empty POST Template')
def test_post_view(self):
def test_post(self):
"POST some data to a view"
post_data = {
'value': 37
@ -66,6 +66,14 @@ class ClientTest(unittest.TestCase):
self.assertEqual(response.template.name, 'POST Template')
self.failUnless('Data received' in response.content)
def test_raw_post(self):
test_doc = """<?xml version="1.0" encoding="utf-8"?><library><book><title>Blink</title><author>Malcolm Gladwell</author></book></library>"""
response = self.client.post("/test_client/raw_post_view/", test_doc,
content_type="text/xml")
self.assertEqual(response.status_code, 200)
self.assertEqual(response.template.name, "Book template")
self.assertEqual(response.content, "Blink - Malcolm Gladwell")
def test_redirect(self):
"GET a URL that redirects elsewhere"
response = self.client.get('/test_client/redirect_view/')

View File

@ -4,6 +4,7 @@ import views
urlpatterns = patterns('',
(r'^get_view/$', views.get_view),
(r'^post_view/$', views.post_view),
(r'^raw_post_view/$', views.raw_post_view),
(r'^redirect_view/$', views.redirect_view),
(r'^login_protected_view/$', views.login_protected_view),
(r'^session_view/$', views.session_view),

View File

@ -1,3 +1,4 @@
from xml.dom.minidom import parseString
from django.template import Context, Template
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth.decorators import login_required
@ -13,11 +14,30 @@ def post_view(request):
"""A view that expects a POST, and returns a different template depending
on whether any POST data is available
"""
if request.POST:
t = Template('Data received: {{ data }} is the value.', name='POST Template')
c = Context({'data': request.POST['value']})
if request.method == 'POST':
if request.POST:
t = Template('Data received: {{ data }} is the value.', name='POST Template')
c = Context({'data': request.POST['value']})
else:
t = Template('Viewing POST page.', name='Empty POST Template')
c = Context()
else:
t = Template('Viewing POST page.', name='Empty POST Template')
t = Template('Viewing GET page.', name='Empty GET Template')
c = Context()
return HttpResponse(t.render(c))
def raw_post_view(request):
"""A view which expects raw XML to be posted and returns content extracted
from the XML"""
if request.method == 'POST':
root = parseString(request.raw_post_data)
first_book = root.firstChild.firstChild
title, author = [n.firstChild.nodeValue for n in first_book.childNodes]
t = Template("{{ title }} - {{ author }}", name="Book template")
c = Context({"title": title, "author": author})
else:
t = Template("GET request.", name="Book GET template")
c = Context()
return HttpResponse(t.render(c))

View File

@ -72,6 +72,22 @@ u'<input type="password" class="special" name="email" />'
>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
u'<input type="password" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />'
The render_value argument lets you specify whether the widget should render
its value. You may want to do this for security reasons.
>>> w = PasswordInput(render_value=True)
>>> w.render('email', 'secret')
u'<input type="password" name="email" value="secret" />'
>>> w = PasswordInput(render_value=False)
>>> w.render('email', '')
u'<input type="password" name="email" />'
>>> w.render('email', None)
u'<input type="password" name="email" />'
>>> w.render('email', 'secret')
u'<input type="password" name="email" />'
>>> w = PasswordInput(attrs={'class': 'fun'}, render_value=False)
>>> w.render('email', 'secret')
u'<input type="password" class="fun" name="email" />'
# HiddenInput Widget ############################################################
>>> w = HiddenInput()
@ -2201,6 +2217,19 @@ returns a list of input.
>>> f.clean_data
{'composers': [u'J', u'P'], 'name': u'Yesterday'}
Validation errors are HTML-escaped when output as HTML.
>>> class EscapingForm(Form):
... special_name = CharField()
... def clean_special_name(self):
... raise ValidationError("Something's wrong with '%s'" % self.clean_data['special_name'])
>>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False)
>>> print f
<tr><th>Special name:</th><td><ul class="errorlist"><li>Something&#39;s wrong with &#39;Nothing to escape&#39;</li></ul><input type="text" name="special_name" value="Nothing to escape" /></td></tr>
>>> f = EscapingForm({'special_name': "Should escape < & > and <script>alert('xss')</script>"}, auto_id=False)
>>> print f
<tr><th>Special name:</th><td><ul class="errorlist"><li>Something&#39;s wrong with &#39;Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;&#39;</li></ul><input type="text" name="special_name" value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;" /></td></tr>
# Validating multiple fields in relation to another ###########################
There are a couple of ways to do multiple-field validation. If you want the
@ -2334,6 +2363,43 @@ the next.
<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
Similarly, changes to field attributes do not persist from one Form instance
to the next.
>>> class Person(Form):
... first_name = CharField(required=False)
... last_name = CharField(required=False)
... def __init__(self, names_required=False, *args, **kwargs):
... super(Person, self).__init__(*args, **kwargs)
... if names_required:
... self.fields['first_name'].required = True
... self.fields['last_name'].required = True
>>> f = Person(names_required=False)
>>> f['first_name'].field.required, f['last_name'].field.required
(False, False)
>>> f = Person(names_required=True)
>>> f['first_name'].field.required, f['last_name'].field.required
(True, True)
>>> f = Person(names_required=False)
>>> f['first_name'].field.required, f['last_name'].field.required
(False, False)
>>> class Person(Form):
... first_name = CharField(max_length=30)
... last_name = CharField(max_length=30)
... def __init__(self, name_max_length=None, *args, **kwargs):
... super(Person, self).__init__(*args, **kwargs)
... if name_max_length:
... self.fields['first_name'].max_length = name_max_length
... self.fields['last_name'].max_length = name_max_length
>>> f = Person(name_max_length=None)
>>> f['first_name'].field.max_length, f['last_name'].field.max_length
(30, 30)
>>> f = Person(name_max_length=20)
>>> f['first_name'].field.max_length, f['last_name'].field.max_length
(20, 20)
>>> f = Person(name_max_length=None)
>>> f['first_name'].field.max_length, f['last_name'].field.max_length
(30, 30)
HiddenInput widgets are displayed differently in the as_table(), as_ul()
and as_p() output of a Form -- their verbose names are not displayed, and a
separate row is not displayed. They're displayed in the last row of the
@ -2645,6 +2711,54 @@ purposes, though.
<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li>
<li>Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li>
Help text can include arbitrary Unicode characters.
>>> class UserRegistration(Form):
... username = CharField(max_length=10, help_text='ŠĐĆŽćžšđ')
>>> p = UserRegistration(auto_id=False)
>>> p.as_ul()
u'<li>Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>'
# Subclassing forms ###########################################################
You can subclass a Form to add fields. The resulting form subclass will have
all of the fields of the parent Form, plus whichever fields you define in the
subclass.
>>> class Person(Form):
... first_name = CharField()
... last_name = CharField()
... birthday = DateField()
>>> class Musician(Person):
... instrument = CharField()
>>> p = Person(auto_id=False)
>>> print p.as_ul()
<li>First name: <input type="text" name="first_name" /></li>
<li>Last name: <input type="text" name="last_name" /></li>
<li>Birthday: <input type="text" name="birthday" /></li>
>>> m = Musician(auto_id=False)
>>> print m.as_ul()
<li>First name: <input type="text" name="first_name" /></li>
<li>Last name: <input type="text" name="last_name" /></li>
<li>Birthday: <input type="text" name="birthday" /></li>
<li>Instrument: <input type="text" name="instrument" /></li>
Yes, you can subclass multiple forms. The fields are added in the order in
which the parent classes are listed.
>>> class Person(Form):
... first_name = CharField()
... last_name = CharField()
... birthday = DateField()
>>> class Instrument(Form):
... instrument = CharField()
>>> class Beatle(Person, Instrument):
... haircut_type = CharField()
>>> b = Beatle(auto_id=False)
>>> print b.as_ul()
<li>First name: <input type="text" name="first_name" /></li>
<li>Last name: <input type="text" name="last_name" /></li>
<li>Birthday: <input type="text" name="birthday" /></li>
<li>Instrument: <input type="text" name="instrument" /></li>
<li>Haircut type: <input type="text" name="haircut_type" /></li>
# Forms with prefixes #########################################################
Sometimes it's necessary to have multiple forms display on the same HTML page,
@ -2858,7 +2972,7 @@ VALID: {'username': u'adrian', 'password1': u'secret', 'password2': u'secret'}
# Some ideas for using templates with forms ###################################
>>> class UserRegistration(Form):
... username = CharField(max_length=10)
... username = CharField(max_length=10, help_text="Good luck picking a username that doesn't already exist.")
... password1 = CharField(widget=PasswordInput)
... password2 = CharField(widget=PasswordInput)
... def clean(self):
@ -2935,6 +3049,24 @@ field an "id" attribute.
<input type="submit" />
</form>
User form.[field].help_text to output a field's help text. If the given field
does not have help text, nothing will be output.
>>> t = Template('''<form action="">
... <p>{{ form.username.label_tag }}: {{ form.username }}<br />{{ form.username.help_text }}</p>
... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p>
... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p>
... <input type="submit" />
... </form>''')
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
<form action="">
<p>Username: <input type="text" name="username" maxlength="10" /><br />Good luck picking a username that doesn't already exist.</p>
<p>Password1: <input type="password" name="password1" /></p>
<p>Password2: <input type="password" name="password2" /></p>
<input type="submit" />
</form>
>>> Template('{{ form.password1.help_text }}').render(Context({'form': UserRegistration(auto_id=False)}))
''
The label_tag() method takes an optional attrs argument: a dictionary of HTML
attributes to add to the <label> tag.
>>> f = UserRegistration(auto_id='id_%s')
@ -2977,12 +3109,12 @@ the list of errors is empty). You can also use it in {% if %} statements.
<input type="submit" />
</form>
#################
# Extra widgets #
#################
###############
# Extra stuff #
###############
The newforms library comes with some extra, higher-level Widget classes that
demonstrate some of the library's abilities.
The newforms library comes with some extra, higher-level Field and Widget
classes that demonstrate some of the library's abilities.
# SelectDateWidget ############################################################
@ -3111,6 +3243,246 @@ True
<option value="2016">2016</option>
</select>
# USZipCodeField ##############################################################
USZipCodeField validates that the data is either a five-digit U.S. zip code or
a zip+4.
>>> from django.contrib.localflavor.usa.forms import USZipCodeField
>>> f = USZipCodeField()
>>> f.clean('60606')
u'60606'
>>> f.clean(60606)
u'60606'
>>> f.clean('04000')
u'04000'
>>> f.clean('4000')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.']
>>> f.clean('60606-1234')
u'60606-1234'
>>> f.clean('6060-1234')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.']
>>> f.clean('60606-')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f = USZipCodeField(required=False)
>>> f.clean('60606')
u'60606'
>>> f.clean(60606)
u'60606'
>>> f.clean('04000')
u'04000'
>>> f.clean('4000')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.']
>>> f.clean('60606-1234')
u'60606-1234'
>>> f.clean('6060-1234')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.']
>>> f.clean('60606-')
Traceback (most recent call last):
...
ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.']
>>> f.clean(None)
u''
>>> f.clean('')
u''
# USStateField ################################################################
USStateField validates that the data is either an abbreviation or name of a
U.S. state.
>>> from django.contrib.localflavor.usa.forms import USStateField
>>> f = USStateField()
>>> f.clean('il')
u'IL'
>>> f.clean('IL')
u'IL'
>>> f.clean('illinois')
u'IL'
>>> f.clean(' illinois ')
u'IL'
>>> f.clean(60606)
Traceback (most recent call last):
...
ValidationError: [u'Enter a U.S. state or territory.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f = USStateField(required=False)
>>> f.clean('il')
u'IL'
>>> f.clean('IL')
u'IL'
>>> f.clean('illinois')
u'IL'
>>> f.clean(' illinois ')
u'IL'
>>> f.clean(60606)
Traceback (most recent call last):
...
ValidationError: [u'Enter a U.S. state or territory.']
>>> f.clean(None)
u''
>>> f.clean('')
u''
# USStateSelect ###############################################################
USStateSelect is a Select widget that uses a list of U.S. states/territories
as its choices.
>>> from django.contrib.localflavor.usa.forms import USStateSelect
>>> w = USStateSelect()
>>> print w.render('state', 'IL')
<select name="state">
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AS">American Samoa</option>
<option value="AZ">Arizona</option>
<option value="AR">Arkansas</option>
<option value="CA">California</option>
<option value="CO">Colorado</option>
<option value="CT">Connecticut</option>
<option value="DE">Deleware</option>
<option value="DC">District of Columbia</option>
<option value="FM">Federated States of Micronesia</option>
<option value="FL">Florida</option>
<option value="GA">Georgia</option>
<option value="GU">Guam</option>
<option value="HI">Hawaii</option>
<option value="ID">Idaho</option>
<option value="IL" selected="selected">Illinois</option>
<option value="IN">Indiana</option>
<option value="IA">Iowa</option>
<option value="KS">Kansas</option>
<option value="KY">Kentucky</option>
<option value="LA">Louisiana</option>
<option value="ME">Maine</option>
<option value="MH">Marshall Islands</option>
<option value="MD">Maryland</option>
<option value="MI">Michigan</option>
<option value="MN">Minnesota</option>
<option value="MS">Mississippi</option>
<option value="MO">Missouri</option>
<option value="MT">Montana</option>
<option value="NE">Nebraska</option>
<option value="NV">Nevada</option>
<option value="NH">New Hampshire</option>
<option value="NJ">New Jersey</option>
<option value="NM">New Mexico</option>
<option value="NY">New York</option>
<option value="NC">North Carolina</option>
<option value="ND">North Dakota</option>
<option value="MP">Northern Mariana Islands</option>
<option value="OH">Ohio</option>
<option value="OK">Oklahoma</option>
<option value="OR">Oregon</option>
<option value="PW">Palau</option>
<option value="PA">Pennsylvania</option>
<option value="PR">Puerto Rico</option>
<option value="RI">Rhode Island</option>
<option value="SC">South Carolina</option>
<option value="SD">South Dakota</option>
<option value="TN">Tennessee</option>
<option value="TX">Texas</option>
<option value="UT">Utah</option>
<option value="VT">Vermont</option>
<option value="VI">Virgin Islands</option>
<option value="VA">Virginia</option>
<option value="WA">Washington</option>
<option value="WV">West Virginia</option>
<option value="WI">Wisconsin</option>
<option value="WY">Wyoming</option>
</select>
# UKPostcodeField #############################################################
UKPostcodeField validates that the data is a valid UK postcode.
>>> from django.contrib.localflavor.uk.forms import UKPostcodeField
>>> f = UKPostcodeField()
>>> f.clean('BT32 4PX')
u'BT32 4PX'
>>> f.clean('GIR 0AA')
u'GIR 0AA'
>>> f.clean('BT324PX')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
>>> f.clean('1NV 4L1D')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
>>> f.clean(None)
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f.clean('')
Traceback (most recent call last):
...
ValidationError: [u'This field is required.']
>>> f = UKPostcodeField(required=False)
>>> f.clean('BT32 4PX')
u'BT32 4PX'
>>> f.clean('GIR 0AA')
u'GIR 0AA'
>>> f.clean('1NV 4L1D')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
>>> f.clean('BT324PX')
Traceback (most recent call last):
...
ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
>>> f.clean(None)
u''
>>> f.clean('')
u''
#################################
# Tests of underlying functions #
#################################
# smart_unicode tests
>>> from django.newforms.util import smart_unicode
>>> class Test:
... def __str__(self):
... return 'ŠĐĆŽćžšđ'
>>> class TestU:
... def __str__(self):
... return 'Foo'
... def __unicode__(self):
... return u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
>>> smart_unicode(Test())
u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
>>> smart_unicode(TestU())
u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
>>> smart_unicode(1)
u'1'
>>> smart_unicode('foo')
u'foo'
"""
if __name__ == "__main__":