mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
sqlalchemy: Merged revisions 3918 to 4053 from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/sqlalchemy@4054 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0b059aa4ea
commit
dadfca08c0
7
AUTHORS
7
AUTHORS
@ -83,6 +83,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Simon Greenhill <dev@simon.net.nz>
|
||||
Espen Grindhaug <http://grindhaug.org/>
|
||||
Brant Harris
|
||||
Hawkeye
|
||||
heckj@mac.com
|
||||
Joel Heenan <joelh-django@planetjoel.com>
|
||||
hipertracker@gmail.com
|
||||
@ -90,6 +91,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Kieran Holland <http://www.kieranholland.com>
|
||||
Robert Rock Howard <http://djangomojo.com/>
|
||||
Jason Huggins <http://www.jrandolph.com/blog/>
|
||||
Baurzhan Ismagulov <ibr@radix50.net>
|
||||
jcrasta@gmail.com
|
||||
Michael Josephson <http://www.sdjournal.com/>
|
||||
jpellerin@gmail.com
|
||||
@ -105,17 +107,19 @@ answer newbie questions, and generally made Django that much better:
|
||||
lakin.wecker@gmail.com
|
||||
Stuart Langridge <http://www.kryogenix.org/>
|
||||
Eugene Lazutkin <http://lazutkin.com/blog/>
|
||||
Jeong-Min Lee
|
||||
Jeong-Min Lee <falsetru@gmail.com>
|
||||
Christopher Lenz <http://www.cmlenz.net/>
|
||||
lerouxb@gmail.com
|
||||
limodou
|
||||
mattmcc
|
||||
Martin Maney <http://www.chipy.org/Martin_Maney>
|
||||
masonsimon+django@gmail.com
|
||||
Manuzhai
|
||||
Petar Marić
|
||||
mark@junklight.com
|
||||
mattycakes@gmail.com
|
||||
Jason McBrayer <http://www.carcosa.net/jason/>
|
||||
mccutchen@gmail.com
|
||||
michael.mcewan@gmail.com
|
||||
mmarshall
|
||||
Eric Moritz <http://eric.themoritzfamily.com/>
|
||||
@ -157,6 +161,7 @@ answer newbie questions, and generally made Django that much better:
|
||||
Amit Upadhyay
|
||||
Geert Vanderkelen
|
||||
Milton Waddams
|
||||
wam-djangobug@wamber.net
|
||||
Dan Watson <http://theidioteque.net/>
|
||||
Rachel Willmer <http://www.willmer.com/kb/>
|
||||
Gary Wilson <gary.wilson@gmail.com>
|
||||
|
@ -77,7 +77,7 @@ class Settings(object):
|
||||
self.SETTINGS_MODULE = settings_module
|
||||
|
||||
try:
|
||||
mod = __import__(self.SETTINGS_MODULE, '', '', [''])
|
||||
mod = __import__(self.SETTINGS_MODULE, {}, {}, [''])
|
||||
except ImportError, e:
|
||||
raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
|
||||
|
||||
@ -97,7 +97,7 @@ class Settings(object):
|
||||
new_installed_apps = []
|
||||
for app in self.INSTALLED_APPS:
|
||||
if app.endswith('.*'):
|
||||
appdir = os.path.dirname(__import__(app[:-2], '', '', ['']).__file__)
|
||||
appdir = os.path.dirname(__import__(app[:-2], {}, {}, ['']).__file__)
|
||||
for d in os.listdir(appdir):
|
||||
if d.isalpha() and os.path.isdir(os.path.join(appdir, d)):
|
||||
new_installed_apps.append('%s.%s' % (app[:-2], d))
|
||||
|
@ -101,6 +101,7 @@ DATABASE_USER = '' # Not used with sqlite3.
|
||||
DATABASE_PASSWORD = '' # Not used with sqlite3.
|
||||
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
|
||||
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
||||
DATABASE_OPTIONS = {} # Set to empty dictionary for default.
|
||||
|
||||
# Host for sending e-mail.
|
||||
EMAIL_HOST = 'localhost'
|
||||
@ -228,6 +229,10 @@ MONTH_DAY_FORMAT = 'F j'
|
||||
# Hint: you really don't!
|
||||
TRANSACTIONS_MANAGED = False
|
||||
|
||||
# The User-Agent string to use when checking for URL validity through the
|
||||
# isExistingURL validator.
|
||||
URL_VALIDATOR_USER_AGENT = "Django/0.96pre (http://www.djangoproject.com)"
|
||||
|
||||
##############
|
||||
# MIDDLEWARE #
|
||||
##############
|
||||
|
Binary file not shown.
@ -1,14 +1,13 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# 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.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
# makoto tsuyuki <mtsuyuki@gmail.com>, 2005,2006.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Django 1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-10-05 23:35+0900\n"
|
||||
"POT-Creation-Date: 2006-10-21 20:42+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"
|
||||
@ -57,9 +56,8 @@ msgid "Argentinean Spanish"
|
||||
msgstr "アルゼンチンスペイン語"
|
||||
|
||||
#: conf/global_settings.py:49
|
||||
#, fuzzy
|
||||
msgid "Finnish"
|
||||
msgstr "デンマーク語"
|
||||
msgstr "フィンランド語"
|
||||
|
||||
#: conf/global_settings.py:50
|
||||
msgid "French"
|
||||
@ -98,52 +96,54 @@ msgid "Norwegian"
|
||||
msgstr "ノルウェー語"
|
||||
|
||||
#: conf/global_settings.py:59
|
||||
msgid "Polish"
|
||||
msgstr "ポーランド語"
|
||||
|
||||
#: conf/global_settings.py:60
|
||||
msgid "Brazilian"
|
||||
msgstr "ブラジル語"
|
||||
|
||||
#: conf/global_settings.py:60
|
||||
#: conf/global_settings.py:61
|
||||
msgid "Romanian"
|
||||
msgstr "ルーマニア語"
|
||||
|
||||
#: conf/global_settings.py:61
|
||||
#: conf/global_settings.py:62
|
||||
msgid "Russian"
|
||||
msgstr "ロシア語"
|
||||
|
||||
#: conf/global_settings.py:62
|
||||
#: conf/global_settings.py:63
|
||||
msgid "Slovak"
|
||||
msgstr "スロバキア語"
|
||||
|
||||
#: conf/global_settings.py:63
|
||||
#, fuzzy
|
||||
#: conf/global_settings.py:64
|
||||
msgid "Slovenian"
|
||||
msgstr "スロヴェニア語"
|
||||
|
||||
#: conf/global_settings.py:64
|
||||
#: conf/global_settings.py:65
|
||||
msgid "Serbian"
|
||||
msgstr "セルビア語"
|
||||
|
||||
#: conf/global_settings.py:65
|
||||
#: conf/global_settings.py:66
|
||||
msgid "Swedish"
|
||||
msgstr "スウェーデン語"
|
||||
|
||||
#: conf/global_settings.py:66
|
||||
#: conf/global_settings.py:67
|
||||
msgid "Tamil"
|
||||
msgstr "タミル語"
|
||||
|
||||
#: conf/global_settings.py:67
|
||||
#: conf/global_settings.py:68
|
||||
msgid "Turkish"
|
||||
msgstr "トルコ語"
|
||||
|
||||
#: conf/global_settings.py:68
|
||||
#, fuzzy
|
||||
#: conf/global_settings.py:69
|
||||
msgid "Ukrainian"
|
||||
msgstr "ウクライナ語"
|
||||
|
||||
#: conf/global_settings.py:69
|
||||
#: conf/global_settings.py:70
|
||||
msgid "Simplified Chinese"
|
||||
msgstr "簡体字中国語"
|
||||
|
||||
#: conf/global_settings.py:70
|
||||
#: conf/global_settings.py:71
|
||||
msgid "Traditional Chinese"
|
||||
msgstr "繁体字中国語"
|
||||
|
||||
@ -369,33 +369,33 @@ msgid "Delete"
|
||||
msgstr "削除"
|
||||
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:14
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Deleting the %(object_name)s '%(escaped_object)s' would result in deleting "
|
||||
"related objects, but your account doesn't have permission to delete the "
|
||||
"following types of objects:"
|
||||
msgstr ""
|
||||
"%(object_name)s '%(object)s' の削除時に関連づけられたオブジェクトも削除しよう"
|
||||
"としましたが、あなたのアカウントには以下のタイプのオブジェクトを削除するパー"
|
||||
"ミッションがありません:"
|
||||
"%(object_name)s '%(escaped_object)s' の削除時に関連づけられたオブジェクトも削"
|
||||
"除しようとしましたが、あなたのアカウントには以下のタイプのオブジェクトを削除"
|
||||
"するパーミッションがありません:"
|
||||
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:21
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Are you sure you want to delete the %(object_name)s \"%(escaped_object)s\"? "
|
||||
"All of the following related items will be deleted:"
|
||||
msgstr ""
|
||||
"%(object_name)s \"%(object)s\"を削除しますか? 関連づけられている以下のオブ"
|
||||
"ジェクトも全て削除されます:"
|
||||
"%(object_name)s \"%(escaped_object)s\"を削除しますか? 関連づけられている以下"
|
||||
"のオブジェクトも全て削除されます:"
|
||||
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:26
|
||||
msgid "Yes, I'm sure"
|
||||
msgstr "はい。"
|
||||
|
||||
#: contrib/admin/templates/admin/filter.html:2
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid " By %(filter_title)s "
|
||||
msgstr "%(title)s で絞り込む"
|
||||
msgstr "%(filter_title)s で絞り込む"
|
||||
|
||||
#: contrib/admin/templates/admin/filters.html:4
|
||||
msgid "Filter"
|
||||
@ -407,9 +407,9 @@ msgid "Models available in the %(name)s application."
|
||||
msgstr "%(name)s アプリケーションで利用可能なモデル"
|
||||
|
||||
#: contrib/admin/templates/admin/index.html:18
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "%(name)s"
|
||||
msgstr "%(name)s を追加"
|
||||
msgstr "%(name)s"
|
||||
|
||||
#: contrib/admin/templates/admin/index.html:34
|
||||
msgid "Change"
|
||||
@ -436,9 +436,9 @@ msgid ""
|
||||
"Something's wrong with your database installation. Make sure the appropriate "
|
||||
"database tables have been created, and make sure the database is readable by "
|
||||
"the appropriate user."
|
||||
msgstr "データベースの設定に問題があるようです。"
|
||||
"適切なテーブルが作られていること、適切なユーザで"
|
||||
"データベースのデータを読み込めることを確認してください。"
|
||||
msgstr ""
|
||||
"データベースの設定に問題があるようです。適切なテーブルが作られていること、適"
|
||||
"切なユーザでデータベースのデータを読み込めることを確認してください。"
|
||||
|
||||
#: contrib/admin/templates/admin/login.html:17
|
||||
#: contrib/comments/templates/comments/form.html:6
|
||||
@ -525,23 +525,20 @@ msgid ""
|
||||
"First, enter a username and password. Then, you'll be able to edit more user "
|
||||
"options."
|
||||
msgstr ""
|
||||
"まずユーザ名とパスワードを登録してください。"
|
||||
"その後詳細情報が編集可能になります。"
|
||||
"まずユーザ名とパスワードを登録してください。その後詳細情報が編集可能になりま"
|
||||
"す。"
|
||||
|
||||
#: contrib/admin/templates/admin/auth/user/add_form.html:12
|
||||
#, fuzzy
|
||||
msgid "Username"
|
||||
msgstr "ユーザ名:"
|
||||
msgstr "ユーザ名"
|
||||
|
||||
#: contrib/admin/templates/admin/auth/user/add_form.html:18
|
||||
#, fuzzy
|
||||
msgid "Password"
|
||||
msgstr "パスワード:"
|
||||
msgstr "パスワード"
|
||||
|
||||
#: contrib/admin/templates/admin/auth/user/add_form.html:23
|
||||
#, fuzzy
|
||||
msgid "Password (again)"
|
||||
msgstr "パスワードの変更"
|
||||
msgstr "パスワード(確認用)"
|
||||
|
||||
#: contrib/admin/templates/admin/auth/user/add_form.html:24
|
||||
msgid "Enter the same password as above, for verification."
|
||||
@ -761,9 +758,8 @@ msgid "You may edit it again below."
|
||||
msgstr "続けて編集できます。"
|
||||
|
||||
#: contrib/admin/views/auth.py:28
|
||||
#, fuzzy
|
||||
msgid "Add user"
|
||||
msgstr "%s を追加"
|
||||
msgstr "ユーザを追加"
|
||||
|
||||
#: contrib/admin/views/decorators.py:10 contrib/auth/forms.py:59
|
||||
msgid ""
|
||||
@ -813,9 +809,9 @@ msgid "view:"
|
||||
msgstr "ビュー"
|
||||
|
||||
#: contrib/admin/views/doc.py:164
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "App %r not found"
|
||||
msgstr "ページが見つかりません"
|
||||
msgstr "アプリケーション %r が見つかりません"
|
||||
|
||||
#: contrib/admin/views/doc.py:171
|
||||
#, python-format
|
||||
@ -1030,9 +1026,8 @@ msgid "The two password fields didn't match."
|
||||
msgstr "確認用パスワードが一致しません。"
|
||||
|
||||
#: contrib/auth/forms.py:24
|
||||
#, fuzzy
|
||||
msgid "A user with that username already exists."
|
||||
msgstr "%(fieldname)s に %(optname)s は既に存在します。"
|
||||
msgstr "同じユーザ名が既に登録済みです。"
|
||||
|
||||
#: contrib/auth/forms.py:52
|
||||
msgid ""
|
||||
@ -1048,11 +1043,9 @@ msgstr "アカウントが無効です。"
|
||||
|
||||
#: contrib/auth/forms.py:84
|
||||
msgid ""
|
||||
"That e-mail address doesn't have an associated user acount. Are you sure "
|
||||
"That e-mail address doesn't have an associated user account. Are you sure "
|
||||
"you've registered?"
|
||||
msgstr ""
|
||||
"メールアドレスの一致するユーザはいません。"
|
||||
"本当に登録しましたか?"
|
||||
msgstr "メールアドレスの一致するユーザはいません。本当に登録しましたか?"
|
||||
|
||||
#: contrib/auth/forms.py:116
|
||||
msgid "The two 'new password' fields didn't match."
|
||||
@ -1071,22 +1064,18 @@ msgid "codename"
|
||||
msgstr "コード名"
|
||||
|
||||
#: contrib/auth/models.py:42
|
||||
#, fuzzy
|
||||
msgid "permission"
|
||||
msgstr "パーミッション"
|
||||
|
||||
#: contrib/auth/models.py:43 contrib/auth/models.py:58
|
||||
#, fuzzy
|
||||
msgid "permissions"
|
||||
msgstr "パーミッション"
|
||||
|
||||
#: contrib/auth/models.py:60
|
||||
#, fuzzy
|
||||
msgid "group"
|
||||
msgstr "グループ"
|
||||
|
||||
#: contrib/auth/models.py:61 contrib/auth/models.py:100
|
||||
#, fuzzy
|
||||
msgid "groups"
|
||||
msgstr "グループ"
|
||||
|
||||
@ -1099,8 +1088,8 @@ msgid ""
|
||||
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
||||
"digits and underscores)."
|
||||
msgstr ""
|
||||
"この項目は必須です。"
|
||||
"半角アルファベット、半角数字、半角アンダーバーで30文字以下にしてください。"
|
||||
"この項目は必須です。半角アルファベット、半角数字、半角アンダーバーで30文字以"
|
||||
"下にしてください。"
|
||||
|
||||
#: contrib/auth/models.py:91
|
||||
msgid "first name"
|
||||
@ -1138,9 +1127,7 @@ msgstr "有効"
|
||||
msgid ""
|
||||
"Designates whether this user can log into the Django admin. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
msgstr ""
|
||||
"ユーザが管理サイトにログイン可能か"
|
||||
"どうかを示します。"
|
||||
msgstr "ユーザが管理サイトにログイン可能かどうかを示します。"
|
||||
|
||||
#: contrib/auth/models.py:97
|
||||
msgid "superuser status"
|
||||
@ -1169,17 +1156,14 @@ msgstr ""
|
||||
"パーミッションを獲得します。"
|
||||
|
||||
#: contrib/auth/models.py:102
|
||||
#, fuzzy
|
||||
msgid "user permissions"
|
||||
msgstr "ユーザパーミッション"
|
||||
|
||||
#: contrib/auth/models.py:105
|
||||
#, fuzzy
|
||||
msgid "user"
|
||||
msgstr "ユーザ"
|
||||
|
||||
#: contrib/auth/models.py:106
|
||||
#, fuzzy
|
||||
msgid "users"
|
||||
msgstr "ユーザ"
|
||||
|
||||
@ -1188,7 +1172,6 @@ msgid "Personal info"
|
||||
msgstr "個人情報"
|
||||
|
||||
#: contrib/auth/models.py:112
|
||||
#, fuzzy
|
||||
msgid "Permissions"
|
||||
msgstr "パーミッション"
|
||||
|
||||
@ -1201,12 +1184,10 @@ msgid "Groups"
|
||||
msgstr "グループ"
|
||||
|
||||
#: contrib/auth/models.py:258
|
||||
#, fuzzy
|
||||
msgid "message"
|
||||
msgstr "メッセージ"
|
||||
|
||||
#: contrib/auth/views.py:39
|
||||
#, fuzzy
|
||||
msgid "Logged out"
|
||||
msgstr "ログアウト"
|
||||
|
||||
@ -1280,7 +1261,6 @@ msgstr ""
|
||||
"た」と表示されるようになります。"
|
||||
|
||||
#: contrib/comments/models.py:91
|
||||
#, fuzzy
|
||||
msgid "comments"
|
||||
msgstr "コメント"
|
||||
|
||||
@ -1316,12 +1296,10 @@ msgid "approved by staff"
|
||||
msgstr "スタッフの承認済み"
|
||||
|
||||
#: contrib/comments/models.py:176
|
||||
#, fuzzy
|
||||
msgid "free comment"
|
||||
msgstr "フリーコメント"
|
||||
|
||||
#: contrib/comments/models.py:177
|
||||
#, fuzzy
|
||||
msgid "free comments"
|
||||
msgstr "フリーコメント"
|
||||
|
||||
@ -1334,12 +1312,10 @@ msgid "score date"
|
||||
msgstr "スコアされた日"
|
||||
|
||||
#: contrib/comments/models.py:237
|
||||
#, fuzzy
|
||||
msgid "karma score"
|
||||
msgstr "カルマスコア"
|
||||
|
||||
#: contrib/comments/models.py:238
|
||||
#, fuzzy
|
||||
msgid "karma scores"
|
||||
msgstr "カルマスコア"
|
||||
|
||||
@ -1364,12 +1340,10 @@ msgid "flag date"
|
||||
msgstr "フラグ日"
|
||||
|
||||
#: contrib/comments/models.py:268
|
||||
#, fuzzy
|
||||
msgid "user flag"
|
||||
msgstr "ユーザフラグ"
|
||||
|
||||
#: contrib/comments/models.py:269
|
||||
#, fuzzy
|
||||
msgid "user flags"
|
||||
msgstr "ユーザフラグ"
|
||||
|
||||
@ -1383,12 +1357,10 @@ msgid "deletion date"
|
||||
msgstr "削除日"
|
||||
|
||||
#: contrib/comments/models.py:280
|
||||
#, fuzzy
|
||||
msgid "moderator deletion"
|
||||
msgstr "モデレータ削除"
|
||||
|
||||
#: contrib/comments/models.py:281
|
||||
#, fuzzy
|
||||
msgid "moderator deletions"
|
||||
msgstr "モデレータ削除"
|
||||
|
||||
@ -1398,12 +1370,10 @@ msgid "Moderator deletion by %r"
|
||||
msgstr "%r によるモデレータ削除"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:8
|
||||
#, fuzzy
|
||||
msgid "Forgotten your password?"
|
||||
msgstr "パスワードをお忘れですか?"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#, fuzzy
|
||||
msgid "Ratings"
|
||||
msgstr "レーティング"
|
||||
|
||||
@ -1423,18 +1393,15 @@ msgstr "写真を登録"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:28
|
||||
#: contrib/comments/templates/comments/freeform.html:5
|
||||
#, fuzzy
|
||||
msgid "Comment:"
|
||||
msgstr "コメント:"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:35
|
||||
#: contrib/comments/templates/comments/freeform.html:10
|
||||
#, fuzzy
|
||||
msgid "Preview comment"
|
||||
msgstr "コメントをプレビュー"
|
||||
|
||||
#: contrib/comments/templates/comments/freeform.html:4
|
||||
#, fuzzy
|
||||
msgid "Your name:"
|
||||
msgstr "ユーザ名:"
|
||||
|
||||
@ -1512,7 +1479,6 @@ msgid "No voting for yourself"
|
||||
msgstr "自分には投票できません。"
|
||||
|
||||
#: contrib/contenttypes/models.py:20
|
||||
#, fuzzy
|
||||
msgid "python model class name"
|
||||
msgstr "Python モデルクラス名"
|
||||
|
||||
@ -1547,13 +1513,12 @@ msgid "template name"
|
||||
msgstr "テンプレート名"
|
||||
|
||||
#: contrib/flatpages/models.py:13
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
|
||||
"will use 'flatpages/default.html'."
|
||||
msgstr ""
|
||||
"例: 'flatpages/contact_page'. 指定しなければ、デフォルト設定の'flatpages/"
|
||||
"default' を使います。"
|
||||
"例: 'flatpages/contact_page.html'. 指定しなければ、デフォルト設定"
|
||||
"の'flatpages/default.html' を使います。"
|
||||
|
||||
#: contrib/flatpages/models.py:14
|
||||
msgid "registration required"
|
||||
@ -1640,16 +1605,15 @@ msgid "This value must contain only letters, numbers and underscores."
|
||||
msgstr "半角の英数字およびアンダースコア以外は使用できません。"
|
||||
|
||||
#: core/validators.py:67
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"This value must contain only letters, numbers, underscores, dashes or "
|
||||
"slashes."
|
||||
msgstr "半角の英数字、アンダースコア、ダッシュ、ラッシュ以外は使用できません。"
|
||||
msgstr ""
|
||||
"半角の英数字、アンダースコア、ダッシュ、スラッシュ以外は使用できません。"
|
||||
|
||||
#: core/validators.py:71
|
||||
#, fuzzy
|
||||
msgid "This value must contain only letters, numbers, underscores or hyphens."
|
||||
msgstr "半角の英数字、アンダースコア、ダッシュ、ラッシュ以外は使用できません。"
|
||||
msgstr "半角の英数字、アンダースコア、ハイフン以外は使用できません。"
|
||||
|
||||
#: core/validators.py:75
|
||||
msgid "Uppercase letters are not allowed here."
|
||||
@ -1696,9 +1660,9 @@ msgid "Year must be 1900 or later."
|
||||
msgstr "1900年以降を指定してください。"
|
||||
|
||||
#: core/validators.py:142
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "Invalid date: %s."
|
||||
msgstr "無効なURL: %s"
|
||||
msgstr "無効な日付: %s"
|
||||
|
||||
#: core/validators.py:146 db/models/fields/__init__.py:424
|
||||
msgid "Enter a valid date in YYYY-MM-DD format."
|
||||
@ -1718,7 +1682,8 @@ msgstr "有効なメールアドレスを入力してください。"
|
||||
|
||||
#: core/validators.py:172 core/validators.py:401 forms/__init__.py:662
|
||||
msgid "No file was submitted. Check the encoding type on the form."
|
||||
msgstr "ファイルが取得できませんでした。formのencoding typeを確認してください。"
|
||||
msgstr ""
|
||||
"ファイルが取得できませんでした。formのencoding typeを確認してください。"
|
||||
|
||||
#: core/validators.py:176
|
||||
msgid ""
|
||||
@ -1825,25 +1790,25 @@ msgstr "有効な 10 進数を入力してください。"
|
||||
msgid "Please enter a valid decimal number with at most %s total digit."
|
||||
msgid_plural ""
|
||||
"Please enter a valid decimal number with at most %s total digits."
|
||||
msgstr[0] "最大桁数 %s 桁以下の有効な 10 進数を入力してください。"
|
||||
msgstr[1] "最大桁数 %s 桁以下の有効な 10 進数を入力してください。"
|
||||
msgstr[0] "全体で %s 文字以下の数字を入力してください。"
|
||||
msgstr[1] "全体で %s 文字以下の数字を入力してください。"
|
||||
|
||||
#: core/validators.py:381
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Please enter a valid decimal number with a whole part of at most %s digit."
|
||||
msgid_plural ""
|
||||
"Please enter a valid decimal number with a whole part of at most %s digits."
|
||||
msgstr[0] "最大桁数 %s 桁以下の有効な 10 進数を入力してください。"
|
||||
msgstr[1] "最大桁数 %s 桁以下の有効な 10 進数を入力してください。"
|
||||
msgstr[0] "整数部は %s 文字以下の数字を入力してください。"
|
||||
msgstr[1] "整数部は %s 文字以下の数字を入力してください。"
|
||||
|
||||
#: core/validators.py:384
|
||||
#, python-format
|
||||
msgid "Please enter a valid decimal number with at most %s decimal place."
|
||||
msgid_plural ""
|
||||
"Please enter a valid decimal number with at most %s decimal places."
|
||||
msgstr[0] "小数点以下が %s 桁までの有効な 10 進数を入力してください。"
|
||||
msgstr[1] "小数点以下が %s 桁までの有効な 10 進数を入力してください。"
|
||||
msgstr[0] "小数部は %s 文字以下の数字を入力してください。"
|
||||
msgstr[1] "小数部は %s 文字以下の数字を入力してください。"
|
||||
|
||||
#: core/validators.py:394
|
||||
#, python-format
|
||||
@ -1947,17 +1912,14 @@ msgid "This field is required."
|
||||
msgstr "このフィールドは必須です。"
|
||||
|
||||
#: db/models/fields/__init__.py:349
|
||||
#, fuzzy
|
||||
msgid "This value must be an integer."
|
||||
msgstr "値は整数でなければなりません。"
|
||||
|
||||
#: db/models/fields/__init__.py:381
|
||||
#, fuzzy
|
||||
msgid "This value must be either True or False."
|
||||
msgstr "値は真: True または偽: False でなければなりません。"
|
||||
|
||||
#: db/models/fields/__init__.py:397
|
||||
#, fuzzy
|
||||
msgid "This field cannot be null."
|
||||
msgstr "このフィールドには NULL を指定できません。"
|
||||
|
||||
@ -1971,7 +1933,6 @@ msgid "Please enter a valid %s."
|
||||
msgstr "正しい %s を入力してください。"
|
||||
|
||||
#: db/models/fields/related.py:618
|
||||
#, fuzzy
|
||||
msgid "Separate multiple IDs with commas."
|
||||
msgstr "複数の ID はカンマで区切ってください。"
|
||||
|
||||
@ -1979,7 +1940,8 @@ msgstr "複数の ID はカンマで区切ってください。"
|
||||
msgid ""
|
||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr ""
|
||||
"複数選択するときには Control キーを押したまま選択してください。Mac は Command キーを使ってください"
|
||||
"複数選択するときには Control キーを押したまま選択してください。Mac は "
|
||||
"Command キーを使ってください"
|
||||
|
||||
#: db/models/fields/related.py:664
|
||||
#, python-format
|
||||
@ -2102,7 +2064,6 @@ msgid "December"
|
||||
msgstr "12月"
|
||||
|
||||
#: utils/dates.py:19
|
||||
#, fuzzy
|
||||
msgid "jan"
|
||||
msgstr "1月"
|
||||
|
||||
@ -2119,7 +2080,6 @@ msgid "apr"
|
||||
msgstr "4月"
|
||||
|
||||
#: utils/dates.py:19
|
||||
#, fuzzy
|
||||
msgid "may"
|
||||
msgstr "5月"
|
||||
|
||||
@ -2228,29 +2188,27 @@ msgid "TIME_FORMAT"
|
||||
msgstr "H:i"
|
||||
|
||||
#: utils/translation/trans_real.py:380
|
||||
#, fuzzy
|
||||
msgid "YEAR_MONTH_FORMAT"
|
||||
msgstr "Y/m/d"
|
||||
|
||||
#: utils/translation/trans_real.py:381
|
||||
#, fuzzy
|
||||
msgid "MONTH_DAY_FORMAT"
|
||||
msgstr "Y/m/d"
|
||||
msgstr "m/d"
|
||||
|
||||
#: views/generic/create_update.py:43
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "The %(verbose_name)s was created successfully."
|
||||
msgstr "%(name)s \"%(obj)s\" を変更しました。"
|
||||
msgstr "%(verbose_name)s を作成しました。"
|
||||
|
||||
#: views/generic/create_update.py:117
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "The %(verbose_name)s was updated successfully."
|
||||
msgstr "%(name)s \"%(obj)s\" を削除しました。"
|
||||
msgstr "%(verbose_name)s を更新しました。"
|
||||
|
||||
#: views/generic/create_update.py:184
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "The %(verbose_name)s was deleted."
|
||||
msgstr " %(site_name)s チーム"
|
||||
msgstr " %(verbose_name)s を削除しました。"
|
||||
|
||||
#~ msgid "String (up to 50)"
|
||||
#~ msgstr "文字列 (50 字まで)"
|
||||
|
Binary file not shown.
@ -2,14 +2,15 @@
|
||||
# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# João Marcus Christ <joaoma@gmail.com>, 2006.
|
||||
# Carlos Eduardo de Paula <carlosedp@gmail.com>, 2006.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-05-16 10:11+0200\n"
|
||||
"PO-Revision-Date: 2006-01-23 19:54-0200\n"
|
||||
"Last-Translator: João Marcus Christ <joaoma@gmail.com>\n"
|
||||
"PO-Revision-Date: 2006-11-01 17:45-0300\n"
|
||||
"Last-Translator: Carlos Eduardo de Paula <carlosedp@gmail.com>\n"
|
||||
"Language-Team: Português do Brasil <pt-br@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -86,12 +87,12 @@ msgid ""
|
||||
"removed\" message will be displayed instead."
|
||||
msgstr ""
|
||||
"Selecione esta opção se o comentário é inapropriado. Uma mensagem \"Este "
|
||||
"comentário foi removido\" será mostrada no lugar."
|
||||
"comentário foi removido\" a mensagem será mostrada no lugar."
|
||||
|
||||
#: contrib/comments/models.py:91
|
||||
#, fuzzy
|
||||
msgid "comments"
|
||||
msgstr "comentário"
|
||||
msgstr "comentários"
|
||||
|
||||
#: contrib/comments/models.py:131 contrib/comments/models.py:207
|
||||
msgid "Content object"
|
||||
@ -150,7 +151,7 @@ msgstr "Pontuação de Karma"
|
||||
#: contrib/comments/models.py:238
|
||||
#, fuzzy
|
||||
msgid "karma scores"
|
||||
msgstr "Pontuação de Karma"
|
||||
msgstr "Pontuações de Karma"
|
||||
|
||||
#: contrib/comments/models.py:242
|
||||
#, python-format
|
||||
@ -170,17 +171,17 @@ msgstr ""
|
||||
|
||||
#: contrib/comments/models.py:265
|
||||
msgid "flag date"
|
||||
msgstr "marca de data"
|
||||
msgstr "flag de data"
|
||||
|
||||
#: contrib/comments/models.py:268
|
||||
#, fuzzy
|
||||
msgid "user flag"
|
||||
msgstr "Flag de usuário"
|
||||
msgstr "flag de usuário"
|
||||
|
||||
#: contrib/comments/models.py:269
|
||||
#, fuzzy
|
||||
msgid "user flags"
|
||||
msgstr "Flags de usuário"
|
||||
msgstr "flags de usuário"
|
||||
|
||||
#: contrib/comments/models.py:273
|
||||
#, python-format
|
||||
@ -189,22 +190,22 @@ msgstr "Flag por %r"
|
||||
|
||||
#: contrib/comments/models.py:278
|
||||
msgid "deletion date"
|
||||
msgstr "data de apagamento"
|
||||
msgstr "data de exclusão"
|
||||
|
||||
#: contrib/comments/models.py:280
|
||||
#, fuzzy
|
||||
msgid "moderator deletion"
|
||||
msgstr "Apagamento feito por moderador"
|
||||
msgstr "Exclusão feita pelo moderador"
|
||||
|
||||
#: contrib/comments/models.py:281
|
||||
#, fuzzy
|
||||
msgid "moderator deletions"
|
||||
msgstr "Apagamentos feitos por moderador"
|
||||
msgstr "Exclusões feitas pelo moderador"
|
||||
|
||||
#: contrib/comments/models.py:285
|
||||
#, python-format
|
||||
msgid "Moderator deletion by %r"
|
||||
msgstr "Apagamento feito pelo moderador %r"
|
||||
msgstr "Exclusao feita pelo moderador %r"
|
||||
|
||||
#: contrib/comments/views/karma.py:19
|
||||
msgid "Anonymous users cannot vote"
|
||||
@ -237,12 +238,12 @@ msgid_plural ""
|
||||
"\n"
|
||||
"%(text)s"
|
||||
msgstr[0] ""
|
||||
"Este comentário foi feito por um usuário esboço:\n"
|
||||
"\n"
|
||||
"Este comentário foi feito por um usuário que postou menos de %(count)s "
|
||||
"comentário:\n"
|
||||
"%(text)s"
|
||||
msgstr[1] ""
|
||||
"Este comentário foi feito por um usuário esboço:\n"
|
||||
"\n"
|
||||
"Este comentário foi feito por um usuário que postou menos de %(count)s "
|
||||
"comentários:\n"
|
||||
"%(text)s"
|
||||
|
||||
#: contrib/comments/views/comments.py:117
|
||||
@ -252,7 +253,7 @@ msgid ""
|
||||
"\n"
|
||||
"%(text)s"
|
||||
msgstr ""
|
||||
"Este comentário foi feito por um usuário esboço:\n"
|
||||
"Este comentário foi feito por um usuário incompleto:\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
|
||||
@ -299,7 +300,7 @@ msgstr "Senha:"
|
||||
#: contrib/comments/templates/comments/form.html:6
|
||||
#, fuzzy
|
||||
msgid "Forgotten your password?"
|
||||
msgstr "Alterar minha senha"
|
||||
msgstr "Esqueceu sua senha?"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:8
|
||||
#: contrib/admin/templates/admin/object_history.html:3
|
||||
@ -325,21 +326,21 @@ msgstr "Encerrar sessão"
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#, fuzzy
|
||||
msgid "Ratings"
|
||||
msgstr "avaliação #1"
|
||||
msgstr "Avaliações"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Required"
|
||||
msgstr ""
|
||||
msgstr "Requerido"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Optional"
|
||||
msgstr ""
|
||||
msgstr "Opcional"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Post a photo"
|
||||
msgstr ""
|
||||
msgstr "Postar uma foto"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:27
|
||||
#: contrib/comments/templates/comments/freeform.html:5
|
||||
@ -351,12 +352,12 @@ msgstr "Comentário"
|
||||
#: contrib/comments/templates/comments/freeform.html:9
|
||||
#, fuzzy
|
||||
msgid "Preview comment"
|
||||
msgstr "Comentário livre"
|
||||
msgstr "Pré visualizar comentário"
|
||||
|
||||
#: contrib/comments/templates/comments/freeform.html:4
|
||||
#, fuzzy
|
||||
msgid "Your name:"
|
||||
msgstr "usuário"
|
||||
msgstr "Seu nome:"
|
||||
|
||||
#: contrib/admin/filterspecs.py:40
|
||||
#, python-format
|
||||
@ -443,7 +444,7 @@ msgid ""
|
||||
"sensitive."
|
||||
msgstr ""
|
||||
"Por favor entre usuário e senha corretos. Note que ambos os "
|
||||
"camposdiferenciam maiúsculas e minúsculas."
|
||||
"campos diferenciam maiúsculas e minúsculas."
|
||||
|
||||
#: contrib/admin/views/decorators.py:23
|
||||
#: contrib/admin/templates/admin/login.html:25
|
||||
@ -468,7 +469,7 @@ msgstr ""
|
||||
|
||||
#: contrib/admin/views/decorators.py:82
|
||||
msgid "Usernames cannot contain the '@' character."
|
||||
msgstr "Nomes de usuário não podem conter o caracter '@'."
|
||||
msgstr "Nomes de usuário não podem conter o caractere '@'."
|
||||
|
||||
#: contrib/admin/views/decorators.py:84
|
||||
#, python-format
|
||||
@ -553,7 +554,7 @@ msgstr "Um(a) ou mais %(fieldname)s em %(name)s:"
|
||||
#: contrib/admin/views/main.py:508
|
||||
#, python-format
|
||||
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
||||
msgstr "O(A) %(name)s \"%(obj)s\" foi adicionado com sucesso."
|
||||
msgstr "O(A) %(name)s \"%(obj)s\" foi excluído com sucesso."
|
||||
|
||||
#: contrib/admin/views/main.py:511
|
||||
msgid "Are you sure?"
|
||||
@ -746,7 +747,7 @@ msgid ""
|
||||
"mail and should be fixed shortly. Thanks for your patience."
|
||||
msgstr ""
|
||||
"Houve um erro. Este foi reportado aos administradores do site através d e-"
|
||||
"mail e deve ser consertado em breve. Obrigado pela compreensão."
|
||||
"mail e deve ser corrigido em breve. Obrigado pela compreensão."
|
||||
|
||||
#: contrib/admin/templates/admin/404.html:4
|
||||
#: contrib/admin/templates/admin/404.html:8
|
||||
@ -760,7 +761,7 @@ msgstr "Desculpe, mas a página requisitada não pode ser encontrada."
|
||||
#: contrib/admin/templates/admin/index.html:17
|
||||
#, python-format
|
||||
msgid "Models available in the %(name)s application."
|
||||
msgstr ""
|
||||
msgstr "Modelos disponíveis na aplicação %(name)s"
|
||||
|
||||
#: contrib/admin/templates/admin/index.html:28
|
||||
#: contrib/admin/templates/admin/change_form.html:15
|
||||
@ -794,7 +795,7 @@ msgstr "Adicionar %(name)s"
|
||||
|
||||
#: contrib/admin/templates/admin/login.html:22
|
||||
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
|
||||
msgstr "Você <a href=\"/password_reset/\"esqueceu a senha</a>?"
|
||||
msgstr "Você <a href=\"/password_reset/\">esqueceu sua senha</a>?"
|
||||
|
||||
#: contrib/admin/templates/admin/base.html:23
|
||||
msgid "Welcome,"
|
||||
@ -836,7 +837,7 @@ msgstr "Por %(title)s "
|
||||
|
||||
#: contrib/admin/templates/admin/search_form.html:8
|
||||
msgid "Go"
|
||||
msgstr ""
|
||||
msgstr "Ir"
|
||||
|
||||
#: contrib/admin/templates/admin/change_form.html:21
|
||||
msgid "View on site"
|
||||
@ -847,7 +848,7 @@ msgstr "Ver no site"
|
||||
msgid "Please correct the error below."
|
||||
msgid_plural "Please correct the errors below."
|
||||
msgstr[0] "Por favor, corrija o erro abaixo."
|
||||
msgstr[1] "Por favor, corrija o erro abaixo."
|
||||
msgstr[1] "Por favor, corrija os erros abaixo."
|
||||
|
||||
#: contrib/admin/templates/admin/change_form.html:48
|
||||
msgid "Ordering"
|
||||
@ -930,8 +931,8 @@ msgid ""
|
||||
"We've e-mailed a new password to the e-mail address you submitted. You "
|
||||
"should be receiving it shortly."
|
||||
msgstr ""
|
||||
"Nós enviamos uma nova senha para o e-mail que você informou. Você deve estar "
|
||||
"recebendo uma mensagem em breve."
|
||||
"Nós enviamos uma nova senha para o e-mail que você informou. Você deverá "
|
||||
"receber uma mensagem em breve."
|
||||
|
||||
#: contrib/admin/templates/registration/password_change_form.html:12
|
||||
msgid ""
|
||||
@ -973,7 +974,7 @@ msgstr "Sua nova senha é: %(new_password)s"
|
||||
|
||||
#: contrib/admin/templates/registration/password_reset_email.html:7
|
||||
msgid "Feel free to change this password by going to this page:"
|
||||
msgstr "Sinta-se livre para alterar esta senha visitando esta página:"
|
||||
msgstr "Sinta-se a vontade para alterar esta senha visitando esta página:"
|
||||
|
||||
#: contrib/admin/templates/registration/password_reset_email.html:11
|
||||
msgid "Your username, in case you've forgotten:"
|
||||
@ -1040,17 +1041,17 @@ msgstr ""
|
||||
|
||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
|
||||
msgid "Edit this object (current window)"
|
||||
msgstr "Edita este objeto (janela atual)"
|
||||
msgstr "Editar este objeto (janela atual)"
|
||||
|
||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
|
||||
msgid "Jumps to the admin page for pages that represent a single object."
|
||||
msgstr ""
|
||||
"Vai para a página de administração para páginas que representam um objeto "
|
||||
"Vai para a página de administração que representam um objeto "
|
||||
"único."
|
||||
|
||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
|
||||
msgid "Edit this object (new window)"
|
||||
msgstr "Edita este objeto (nova janela)"
|
||||
msgstr "Editar este objeto (nova janela)"
|
||||
|
||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:29
|
||||
msgid "As above, but opens the admin page in a new window."
|
||||
@ -1135,7 +1136,7 @@ msgstr ""
|
||||
|
||||
#: contrib/flatpages/models.py:14
|
||||
msgid "registration required"
|
||||
msgstr "é obrigatório registrar"
|
||||
msgstr "registro obrigatório"
|
||||
|
||||
#: contrib/flatpages/models.py:14
|
||||
msgid "If this is checked, only logged-in users will be able to view the page."
|
||||
@ -1160,22 +1161,22 @@ msgstr "nome código"
|
||||
#: contrib/auth/models.py:17
|
||||
#, fuzzy
|
||||
msgid "permission"
|
||||
msgstr "Permissão"
|
||||
msgstr "permissão"
|
||||
|
||||
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
||||
#, fuzzy
|
||||
msgid "permissions"
|
||||
msgstr "Permissões"
|
||||
msgstr "permissões"
|
||||
|
||||
#: contrib/auth/models.py:29
|
||||
#, fuzzy
|
||||
msgid "group"
|
||||
msgstr "Grupo"
|
||||
msgstr "grupo"
|
||||
|
||||
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
||||
#, fuzzy
|
||||
msgid "groups"
|
||||
msgstr "Grupos"
|
||||
msgstr "grupos"
|
||||
|
||||
#: contrib/auth/models.py:55
|
||||
msgid "username"
|
||||
@ -1236,17 +1237,17 @@ msgstr ""
|
||||
#: contrib/auth/models.py:67
|
||||
#, fuzzy
|
||||
msgid "user permissions"
|
||||
msgstr "Permissões"
|
||||
msgstr "permissões do usuário"
|
||||
|
||||
#: contrib/auth/models.py:70
|
||||
#, fuzzy
|
||||
msgid "user"
|
||||
msgstr "Usuário"
|
||||
msgstr "usuário"
|
||||
|
||||
#: contrib/auth/models.py:71
|
||||
#, fuzzy
|
||||
msgid "users"
|
||||
msgstr "Usuários"
|
||||
msgstr "usuários"
|
||||
|
||||
#: contrib/auth/models.py:76
|
||||
msgid "Personal info"
|
||||
@ -1267,7 +1268,7 @@ msgstr "Grupos"
|
||||
#: contrib/auth/models.py:219
|
||||
#, fuzzy
|
||||
msgid "message"
|
||||
msgstr "Mensagem"
|
||||
msgstr "mensagem"
|
||||
|
||||
#: contrib/auth/forms.py:30
|
||||
msgid ""
|
||||
@ -1275,7 +1276,7 @@ msgid ""
|
||||
"required for logging in."
|
||||
msgstr ""
|
||||
"Seu navegador Web não parece estar com os cookies habilitados. Cookies são "
|
||||
"requeridos para acesssar."
|
||||
"requeridos para acessar."
|
||||
|
||||
#: contrib/contenttypes/models.py:25
|
||||
#, fuzzy
|
||||
@ -1417,52 +1418,52 @@ msgstr "Dezembro"
|
||||
#: utils/dates.py:19
|
||||
#, fuzzy
|
||||
msgid "jan"
|
||||
msgstr "e"
|
||||
msgstr "jan"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "feb"
|
||||
msgstr ""
|
||||
msgstr "fev"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "mar"
|
||||
msgstr ""
|
||||
msgstr "mar"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "apr"
|
||||
msgstr ""
|
||||
msgstr "abr"
|
||||
|
||||
#: utils/dates.py:19
|
||||
#, fuzzy
|
||||
msgid "may"
|
||||
msgstr "dia"
|
||||
msgstr "mai"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "jun"
|
||||
msgstr ""
|
||||
msgstr "jun"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "jul"
|
||||
msgstr ""
|
||||
msgstr "jul"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "aug"
|
||||
msgstr ""
|
||||
msgstr "ago"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "sep"
|
||||
msgstr ""
|
||||
msgstr "set"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "oct"
|
||||
msgstr ""
|
||||
msgstr "out"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "nov"
|
||||
msgstr ""
|
||||
msgstr "nov"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "dec"
|
||||
msgstr ""
|
||||
msgstr "dez"
|
||||
|
||||
#: utils/dates.py:27
|
||||
msgid "Jan."
|
||||
@ -1497,45 +1498,45 @@ msgstr "Dez."
|
||||
msgid "year"
|
||||
msgid_plural "years"
|
||||
msgstr[0] "ano"
|
||||
msgstr[1] "ano"
|
||||
msgstr[1] "anos"
|
||||
|
||||
#: utils/timesince.py:13
|
||||
#, fuzzy
|
||||
msgid "month"
|
||||
msgid_plural "months"
|
||||
msgstr[0] "mês"
|
||||
msgstr[1] "mês"
|
||||
msgstr[1] "meses"
|
||||
|
||||
#: utils/timesince.py:14
|
||||
msgid "week"
|
||||
msgid_plural "weeks"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "semana"
|
||||
msgstr[1] "semanas"
|
||||
|
||||
#: utils/timesince.py:15
|
||||
#, fuzzy
|
||||
msgid "day"
|
||||
msgid_plural "days"
|
||||
msgstr[0] "dia"
|
||||
msgstr[1] "dia"
|
||||
msgstr[1] "dias"
|
||||
|
||||
#: utils/timesince.py:16
|
||||
#, fuzzy
|
||||
msgid "hour"
|
||||
msgid_plural "hours"
|
||||
msgstr[0] "hora"
|
||||
msgstr[1] "hora"
|
||||
msgstr[1] "horas"
|
||||
|
||||
#: utils/timesince.py:17
|
||||
#, fuzzy
|
||||
msgid "minute"
|
||||
msgid_plural "minutes"
|
||||
msgstr[0] "minuto"
|
||||
msgstr[1] "minuto"
|
||||
msgstr[1] "minutos"
|
||||
|
||||
#: conf/global_settings.py:37
|
||||
msgid "Bengali"
|
||||
msgstr ""
|
||||
msgstr "Bengalês"
|
||||
|
||||
#: conf/global_settings.py:38
|
||||
msgid "Czech"
|
||||
@ -1548,7 +1549,7 @@ msgstr ""
|
||||
#: conf/global_settings.py:40
|
||||
#, fuzzy
|
||||
msgid "Danish"
|
||||
msgstr "Espanhol"
|
||||
msgstr "Dinamarquês"
|
||||
|
||||
#: conf/global_settings.py:41
|
||||
msgid "German"
|
||||
@ -1556,7 +1557,7 @@ msgstr "Alemão"
|
||||
|
||||
#: conf/global_settings.py:42
|
||||
msgid "Greek"
|
||||
msgstr ""
|
||||
msgstr "Grego"
|
||||
|
||||
#: conf/global_settings.py:43
|
||||
msgid "English"
|
||||
@ -1576,11 +1577,11 @@ msgstr "Galiciano"
|
||||
|
||||
#: conf/global_settings.py:47
|
||||
msgid "Hungarian"
|
||||
msgstr ""
|
||||
msgstr "Húngaro"
|
||||
|
||||
#: conf/global_settings.py:48
|
||||
msgid "Hebrew"
|
||||
msgstr ""
|
||||
msgstr "Hebraico"
|
||||
|
||||
#: conf/global_settings.py:49
|
||||
msgid "Icelandic"
|
||||
@ -1604,7 +1605,7 @@ msgstr "Norueguês"
|
||||
|
||||
#: conf/global_settings.py:54
|
||||
msgid "Brazilian"
|
||||
msgstr "Brazileiro"
|
||||
msgstr "Brasileiro"
|
||||
|
||||
#: conf/global_settings.py:55
|
||||
msgid "Romanian"
|
||||
@ -1621,7 +1622,7 @@ msgstr "Eslovaco"
|
||||
#: conf/global_settings.py:58
|
||||
#, fuzzy
|
||||
msgid "Slovenian"
|
||||
msgstr "Eslovaco"
|
||||
msgstr "Esloveno"
|
||||
|
||||
#: conf/global_settings.py:59
|
||||
msgid "Serbian"
|
||||
@ -1634,7 +1635,7 @@ msgstr "Sueco"
|
||||
#: conf/global_settings.py:61
|
||||
#, fuzzy
|
||||
msgid "Ukrainian"
|
||||
msgstr "Brazileiro"
|
||||
msgstr "Ucraniano"
|
||||
|
||||
#: conf/global_settings.py:62
|
||||
msgid "Simplified Chinese"
|
||||
@ -1689,7 +1690,7 @@ msgstr "Este valor não pode conter apenas dígitos."
|
||||
|
||||
#: core/validators.py:116
|
||||
msgid "Enter a whole number."
|
||||
msgstr "Informe um número inteiro."
|
||||
msgstr "Informe um número completo."
|
||||
|
||||
#: core/validators.py:120
|
||||
msgid "Only alphabetical characters are allowed here."
|
||||
@ -1772,7 +1773,7 @@ msgstr "Informe uma abreviação válida de nome de um estado dos EUA."
|
||||
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] "Lave sua boca! A palavra %s não é permitida aqui."
|
||||
msgstr[1] "Lave sua boca! A palavra %s não é permitida aqui."
|
||||
msgstr[1] "Lave sua boca! As palavras %s não são permitidas aqui."
|
||||
|
||||
#: core/validators.py:236
|
||||
#, python-format
|
||||
@ -1808,14 +1809,14 @@ msgstr "Este valor deve ser uma potência de %s."
|
||||
|
||||
#: core/validators.py:347
|
||||
msgid "Please enter a valid decimal number."
|
||||
msgstr "Informe um número decimal."
|
||||
msgstr "Informe um número decimal válido."
|
||||
|
||||
#: core/validators.py:349
|
||||
#, fuzzy, python-format
|
||||
msgid "Please enter a valid decimal number with at most %s total digit."
|
||||
msgid_plural ""
|
||||
"Please enter a valid decimal number with at most %s total digits."
|
||||
msgstr[0] "Por favor entre com um número decimal com no máximo %s digitos."
|
||||
msgstr[0] "Por favor entre com um número decimal com no máximo %s digito."
|
||||
msgstr[1] "Por favor entre com um número decimal com no máximo %s digitos."
|
||||
|
||||
#: core/validators.py:352
|
||||
@ -1824,7 +1825,7 @@ msgid "Please enter a valid decimal number with at most %s decimal place."
|
||||
msgid_plural ""
|
||||
"Please enter a valid decimal number with at most %s decimal places."
|
||||
msgstr[0] "Informe um número decimal com no máximo %s casa decimal."
|
||||
msgstr[1] "Informe um número decimal com no máximo %s casa decimal."
|
||||
msgstr[1] "Informe um número decimal com no máximo %s casas decimais."
|
||||
|
||||
#: core/validators.py:362
|
||||
#, python-format
|
||||
@ -1930,17 +1931,17 @@ msgstr "Este campo é requerido."
|
||||
#: db/models/fields/__init__.py:337
|
||||
#, fuzzy
|
||||
msgid "This value must be an integer."
|
||||
msgstr "Este valor deve ser uma potência de %s."
|
||||
msgstr "Este valor deve ser um inteiro."
|
||||
|
||||
#: db/models/fields/__init__.py:369
|
||||
#, fuzzy
|
||||
msgid "This value must be either True or False."
|
||||
msgstr "Este valor deve ser uma potência de %s."
|
||||
msgstr "Este valor deve ser Verdadeiro ou Falso."
|
||||
|
||||
#: db/models/fields/__init__.py:385
|
||||
#, fuzzy
|
||||
msgid "This field cannot be null."
|
||||
msgstr "Este campo é inválido."
|
||||
msgstr "Este campo não pode ser nulo."
|
||||
|
||||
#: db/models/fields/__init__.py:562
|
||||
msgid "Enter a valid filename."
|
||||
@ -1954,14 +1955,14 @@ msgstr "Por favor informe um %s válido."
|
||||
#: db/models/fields/related.py:579
|
||||
#, fuzzy
|
||||
msgid "Separate multiple IDs with commas."
|
||||
msgstr " Separe IDs múltiplos com vírgulas."
|
||||
msgstr "Separe IDs múltiplos com vírgulas."
|
||||
|
||||
#: db/models/fields/related.py:581
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr ""
|
||||
" Mantenha pressionado \"Control\", ou \"Command\" num Mac para selecionar "
|
||||
" Mantenha pressionado \"Control\", ou \"Command\" no Mac para selecionar "
|
||||
"mais de uma opção."
|
||||
|
||||
#: db/models/fields/related.py:625
|
||||
@ -1972,18 +1973,18 @@ msgid_plural ""
|
||||
msgstr[0] ""
|
||||
"Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido."
|
||||
msgstr[1] ""
|
||||
"Por favor, entre IDs válidos para %(self)s. O valor %(value)r é inválido."
|
||||
"Por favor, entre IDs válidos para %(self)s. Os valores %(value)r são inválidos."
|
||||
|
||||
#: forms/__init__.py:380
|
||||
#, fuzzy, python-format
|
||||
msgid "Ensure your text is less than %s character."
|
||||
msgid_plural "Ensure your text is less than %s characters."
|
||||
msgstr[0] "Certifique-se de que seu texto tenha menos que %s caracteres."
|
||||
msgstr[0] "Certifique-se de que seu texto tenha menos que %s caractere."
|
||||
msgstr[1] "Certifique-se de que seu texto tenha menos que %s caracteres."
|
||||
|
||||
#: forms/__init__.py:385
|
||||
msgid "Line breaks are not allowed here."
|
||||
msgstr "Não são permitidas múltiplas linhas aqui."
|
||||
msgstr "Não são permitidas quebras de linha aqui."
|
||||
|
||||
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
|
||||
#, python-format
|
||||
@ -2037,7 +2038,7 @@ msgstr "sim,não,talvez"
|
||||
#~ "\n"
|
||||
#~ "%(text)s"
|
||||
#~ msgstr ""
|
||||
#~ "Este comentário foi envidao por um usuário que enviou menos de %(count)s "
|
||||
#~ "Este comentário foi enviado por um usuário que enviou menos de %(count)s "
|
||||
#~ "comentário:\n"
|
||||
#~ "\n"
|
||||
#~ "%(text)sEste comentário foi enviado por um usuário que enviou menos de %"
|
||||
@ -2047,4 +2048,4 @@ msgstr "sim,não,talvez"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "count"
|
||||
#~ msgstr "conteúdo"
|
||||
#~ msgstr "contagem"
|
||||
|
Binary file not shown.
@ -1,15 +1,15 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# Português do Brasil translation of django.
|
||||
# Copyright (C) 2006 THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
# Carlos Eduardo de Paula <carlosedp@gmail.com>, 2006.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: django\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
|
||||
"PO-Revision-Date: 2006-01-23 19:54-0200\n"
|
||||
"Last-Translator: João Marcus Christ <joaoma@gmail.com>\n"
|
||||
"PO-Revision-Date: 2006-11-01 17:45-0300\n"
|
||||
"Last-Translator: Carlos Eduardo de Paula <carlosedp@gmail.com>\n"
|
||||
"Language-Team: Português do Brasil <pt-br@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -51,7 +51,7 @@ msgid ""
|
||||
"January February March April May June July August September October November "
|
||||
"December"
|
||||
msgstr ""
|
||||
"Janeiro Fevereiro Março Abrio Maio Junho Julho Agosto Setembro Outubro Novembro "
|
||||
"Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro "
|
||||
"Dezembro"
|
||||
#: contrib/admin/media/js/dateparse.js:27
|
||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||
|
@ -169,8 +169,8 @@ var dateParsePatterns = [
|
||||
handler: function(bits) {
|
||||
var d = new Date();
|
||||
d.setYear(parseInt(bits[1]));
|
||||
d.setDate(parseInt(bits[3], 10));
|
||||
d.setMonth(parseInt(bits[2], 10) - 1);
|
||||
d.setDate(parseInt(bits[3], 10));
|
||||
return d;
|
||||
}
|
||||
},
|
||||
|
@ -19,7 +19,7 @@
|
||||
<div class="form-row">
|
||||
<label for="id_password">{% trans 'Password:' %}</label> <input type="password" name="password" id="id_password" />
|
||||
<input type="hidden" name="this_is_the_login_form" value="1" />
|
||||
<input type="hidden" name="post_data" value="{{ post_data }}" /> {% comment %}<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>{% endcomment %}
|
||||
<input type="hidden" name="post_data" value="{{ post_data }}" /> {#<span class="help">{% trans 'Have you <a href="/password_reset/">forgotten your password</a>?' %}</span>#}
|
||||
</div>
|
||||
<div class="submit-row">
|
||||
<label> </label><input type="submit" value="{% trans 'Log in' %}" />
|
||||
|
@ -177,8 +177,8 @@ def output_all(form_fields):
|
||||
output_all = register.simple_tag(output_all)
|
||||
|
||||
def auto_populated_field_script(auto_pop_fields, change = False):
|
||||
t = []
|
||||
for field in auto_pop_fields:
|
||||
t = []
|
||||
if change:
|
||||
t.append('document.getElementById("id_%s")._changed = true;' % field.name)
|
||||
else:
|
||||
@ -197,8 +197,8 @@ def filter_interface_script_maybe(bound_field):
|
||||
f = bound_field.field
|
||||
if f.rel and isinstance(f.rel, models.ManyToManyRel) and f.rel.filter_interface:
|
||||
return '<script type="text/javascript">addEvent(window, "load", function(e) {' \
|
||||
' SelectFilter.init("id_%s", %r, %s, "%s"); });</script>\n' % (
|
||||
f.name, f.verbose_name, f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
|
||||
' SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
|
||||
f.name, f.verbose_name.replace('"', '\\"'), f.rel.filter_interface-1, settings.ADMIN_MEDIA_PREFIX)
|
||||
else:
|
||||
return ''
|
||||
filter_interface_script_maybe = register.simple_tag(filter_interface_script_maybe)
|
||||
|
@ -1,6 +1,7 @@
|
||||
from django.contrib.admin.views.decorators import staff_member_required
|
||||
from django.contrib.auth.forms import UserCreationForm
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django import forms, template
|
||||
from django.shortcuts import render_to_response
|
||||
from django.http import HttpResponseRedirect
|
||||
|
@ -98,13 +98,13 @@ def view_index(request):
|
||||
return missing_docutils_page(request)
|
||||
|
||||
if settings.ADMIN_FOR:
|
||||
settings_modules = [__import__(m, '', '', ['']) for m in settings.ADMIN_FOR]
|
||||
settings_modules = [__import__(m, {}, {}, ['']) for m in settings.ADMIN_FOR]
|
||||
else:
|
||||
settings_modules = [settings]
|
||||
|
||||
views = []
|
||||
for settings_mod in settings_modules:
|
||||
urlconf = __import__(settings_mod.ROOT_URLCONF, '', '', [''])
|
||||
urlconf = __import__(settings_mod.ROOT_URLCONF, {}, {}, [''])
|
||||
view_functions = extract_views_from_urlpatterns(urlconf.urlpatterns)
|
||||
if Site._meta.installed:
|
||||
site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
|
||||
@ -127,7 +127,7 @@ def view_detail(request, view):
|
||||
|
||||
mod, func = urlresolvers.get_mod_func(view)
|
||||
try:
|
||||
view_func = getattr(__import__(mod, '', '', ['']), func)
|
||||
view_func = getattr(__import__(mod, {}, {}, ['']), func)
|
||||
except (ImportError, AttributeError):
|
||||
raise Http404
|
||||
title, body, metadata = utils.parse_docstring(view_func.__doc__)
|
||||
@ -235,7 +235,7 @@ model_detail = staff_member_required(model_detail)
|
||||
def template_detail(request, template):
|
||||
templates = []
|
||||
for site_settings_module in settings.ADMIN_FOR:
|
||||
settings_mod = __import__(site_settings_module, '', '', [''])
|
||||
settings_mod = __import__(site_settings_module, {}, {}, [''])
|
||||
if Site._meta.installed:
|
||||
site_obj = Site.objects.get(pk=settings_mod.SITE_ID)
|
||||
else:
|
||||
|
@ -454,7 +454,7 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
|
||||
if related.opts.admin and has_related_objs:
|
||||
p = '%s.%s' % (related.opts.app_label, related.opts.get_delete_permission())
|
||||
if not user.has_perm(p):
|
||||
perms_needed.add(rel_opts_name)
|
||||
perms_needed.add(related.opts.verbose_name)
|
||||
for related in opts.get_all_related_many_to_many_objects():
|
||||
if related.opts in opts_seen:
|
||||
continue
|
||||
|
@ -14,7 +14,7 @@ def template_validator(request):
|
||||
# get a dict of {site_id : settings_module} for the validator
|
||||
settings_modules = {}
|
||||
for mod in settings.ADMIN_FOR:
|
||||
settings_module = __import__(mod, '', '', [''])
|
||||
settings_module = __import__(mod, {}, {}, [''])
|
||||
settings_modules[settings_module.SITE_ID] = settings_module
|
||||
manipulator = TemplateValidator(settings_modules)
|
||||
new_data, errors = {}, {}
|
||||
|
@ -9,7 +9,7 @@ def load_backend(path):
|
||||
i = path.rfind('.')
|
||||
module, attr = path[:i], path[i+1:]
|
||||
try:
|
||||
mod = __import__(module, '', '', [attr])
|
||||
mod = __import__(module, {}, {}, [attr])
|
||||
except ImportError, e:
|
||||
raise ImproperlyConfigured, 'Error importing authentication backend %s: "%s"' % (module, e)
|
||||
try:
|
||||
|
@ -92,9 +92,9 @@ class User(models.Model):
|
||||
last_name = models.CharField(_('last name'), maxlength=30, blank=True)
|
||||
email = models.EmailField(_('e-mail address'), blank=True)
|
||||
password = models.CharField(_('password'), maxlength=128, help_text=_("Use '[algo]$[salt]$[hexdigest]'"))
|
||||
is_staff = models.BooleanField(_('staff status'), help_text=_("Designates whether the user can log into this admin site."))
|
||||
is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
|
||||
is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts."))
|
||||
is_superuser = models.BooleanField(_('superuser status'), help_text=_("Designates that this user has all permissions without explicitly assigning them."))
|
||||
is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
|
||||
last_login = models.DateTimeField(_('last login'), default=models.LazyDate())
|
||||
date_joined = models.DateTimeField(_('date joined'), default=models.LazyDate())
|
||||
groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
|
||||
@ -126,7 +126,7 @@ class User(models.Model):
|
||||
def is_anonymous(self):
|
||||
"Always returns False. This is a way of comparing User objects to anonymous users."
|
||||
return False
|
||||
|
||||
|
||||
def is_authenticated(self):
|
||||
"""Always return True. This is a way to tell if the user has been authenticated in templates.
|
||||
"""
|
||||
@ -270,6 +270,15 @@ class AnonymousUser(object):
|
||||
def __str__(self):
|
||||
return 'AnonymousUser'
|
||||
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, self.__class__)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self.__eq__(other)
|
||||
|
||||
def __hash__(self):
|
||||
return 1 # instances always return the same hash value
|
||||
|
||||
def save(self):
|
||||
raise NotImplementedError
|
||||
|
||||
@ -301,6 +310,6 @@ class AnonymousUser(object):
|
||||
|
||||
def is_anonymous(self):
|
||||
return True
|
||||
|
||||
|
||||
def is_authenticated(self):
|
||||
return False
|
||||
|
@ -34,7 +34,7 @@ class CommentManager(models.Manager):
|
||||
"""
|
||||
Given a rating_string, this returns a tuple of (rating_range, options).
|
||||
>>> s = "scale:1-10|First_category|Second_category"
|
||||
>>> get_rating_options(s)
|
||||
>>> Comment.objects.get_rating_options(s)
|
||||
([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ['First category', 'Second category'])
|
||||
"""
|
||||
rating_range, options = rating_string.split('|', 1)
|
||||
|
@ -109,7 +109,7 @@ class PublicCommentManipulator(AuthenticationForm):
|
||||
# send the comment to the managers.
|
||||
if self.user_cache.comment_set.count() <= settings.COMMENTS_FIRST_FEW:
|
||||
message = ngettext('This comment was posted by a user who has posted fewer than %(count)s comment:\n\n%(text)s',
|
||||
'This comment was posted by a user who has posted fewer than %(count)s comments:\n\n%(text)s') % \
|
||||
'This comment was posted by a user who has posted fewer than %(count)s comments:\n\n%(text)s', settings.COMMENTS_FIRST_FEW) % \
|
||||
{'count': settings.COMMENTS_FIRST_FEW, 'text': c.get_as_text()}
|
||||
mail_managers("Comment posted by rookie user", message)
|
||||
if settings.COMMENTS_SKETCHY_USERS_GROUP and settings.COMMENTS_SKETCHY_USERS_GROUP in [g.id for g in self.user_cache.get_group_list()]:
|
||||
@ -217,7 +217,7 @@ def post_comment(request):
|
||||
errors = manipulator.get_validation_errors(new_data)
|
||||
# If user gave correct username/password and wasn't already logged in, log them in
|
||||
# so they don't have to enter a username/password again.
|
||||
if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
|
||||
if manipulator.get_user() and not manipulator.get_user().is_authenticated() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']):
|
||||
from django.contrib.auth import login
|
||||
login(request, manipulator.get_user())
|
||||
if errors or request.POST.has_key('preview'):
|
||||
|
2
django/core/cache/__init__.py
vendored
2
django/core/cache/__init__.py
vendored
@ -48,7 +48,7 @@ def get_cache(backend_uri):
|
||||
if host.endswith('/'):
|
||||
host = host[:-1]
|
||||
|
||||
cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], '', '', ['']), 'CacheClass')
|
||||
cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], {}, {}, ['']), 'CacheClass')
|
||||
return cache_class(host, params)
|
||||
|
||||
cache = get_cache(settings.CACHE_BACKEND)
|
||||
|
@ -26,7 +26,7 @@ class BaseHandler(object):
|
||||
raise exceptions.ImproperlyConfigured, '%s isn\'t a middleware module' % middleware_path
|
||||
mw_module, mw_classname = middleware_path[:dot], middleware_path[dot+1:]
|
||||
try:
|
||||
mod = __import__(mw_module, '', '', [''])
|
||||
mod = __import__(mw_module, {}, {}, [''])
|
||||
except ImportError, e:
|
||||
raise exceptions.ImproperlyConfigured, 'Error importing middleware %s: "%s"' % (mw_module, e)
|
||||
try:
|
||||
|
@ -41,6 +41,7 @@ class ModPythonRequest(http.HttpRequest):
|
||||
return '%s%s' % (self.path, self._req.args and ('?' + self._req.args) or '')
|
||||
|
||||
def is_secure(self):
|
||||
# Note: modpython 3.2.10+ has req.is_https(), but we need to support previous versions
|
||||
return self._req.subprocess_env.has_key('HTTPS') and self._req.subprocess_env['HTTPS'] == 'on'
|
||||
|
||||
def _load_post_and_files(self):
|
||||
@ -102,7 +103,7 @@ class ModPythonRequest(http.HttpRequest):
|
||||
'REQUEST_METHOD': self._req.method,
|
||||
'SCRIPT_NAME': None, # Not supported
|
||||
'SERVER_NAME': self._req.server.server_hostname,
|
||||
'SERVER_PORT': str(self._req.connection.local_addr[1]),
|
||||
'SERVER_PORT': self._req.server.port,
|
||||
'SERVER_PROTOCOL': self._req.protocol,
|
||||
'SERVER_SOFTWARE': 'mod_python'
|
||||
}
|
||||
|
@ -4,6 +4,9 @@ from django.conf import settings
|
||||
from email.MIMEText import MIMEText
|
||||
from email.Header import Header
|
||||
import smtplib, rfc822
|
||||
import socket
|
||||
import time
|
||||
import random
|
||||
|
||||
class BadHeaderError(ValueError):
|
||||
pass
|
||||
@ -50,6 +53,7 @@ def send_mass_mail(datatuple, fail_silently=False, auth_user=settings.EMAIL_HOST
|
||||
msg['From'] = from_email
|
||||
msg['To'] = ', '.join(recipient_list)
|
||||
msg['Date'] = rfc822.formatdate()
|
||||
msg['Message-ID'] = "<%d.%d@%s>" % (time.time(), random.getrandbits(64), socket.getfqdn())
|
||||
try:
|
||||
server.sendmail(from_email, recipient_list, msg.as_string())
|
||||
num_sent += 1
|
||||
|
@ -32,6 +32,7 @@ class dummy: pass
|
||||
style = dummy()
|
||||
style.ERROR = termcolors.make_style(fg='red', opts=('bold',))
|
||||
style.ERROR_OUTPUT = termcolors.make_style(fg='red', opts=('bold',))
|
||||
style.NOTICE = termcolors.make_style(fg='red')
|
||||
style.SQL_FIELD = termcolors.make_style(fg='green', opts=('bold',))
|
||||
style.SQL_COLTYPE = termcolors.make_style(fg='green')
|
||||
style.SQL_KEYWORD = termcolors.make_style(fg='yellow')
|
||||
@ -348,6 +349,8 @@ def get_sql_initial_data_for_model(model):
|
||||
if os.path.exists(sql_file):
|
||||
fp = open(sql_file, 'U')
|
||||
for statement in statements.split(fp.read()):
|
||||
# Remove any comments from the file
|
||||
statement = re.sub(r"--.*[\n\Z]", "", statement)
|
||||
if statement.strip():
|
||||
output.append(statement + ";")
|
||||
fp.close()
|
||||
@ -445,7 +448,7 @@ def syncdb(verbosity=1, interactive=True):
|
||||
# dispatcher events.
|
||||
for app_name in settings.INSTALLED_APPS:
|
||||
try:
|
||||
__import__(app_name + '.management', '', '', [''])
|
||||
__import__(app_name + '.management', {}, {}, [''])
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
@ -540,7 +543,7 @@ def syncdb(verbosity=1, interactive=True):
|
||||
transaction.rollback_unless_managed()
|
||||
else:
|
||||
transaction.commit_unless_managed()
|
||||
|
||||
|
||||
syncdb.args = ''
|
||||
|
||||
def get_admin_index(app):
|
||||
@ -627,6 +630,7 @@ install.args = APP_ARGS
|
||||
def reset(app, interactive=True):
|
||||
"Executes the equivalent of 'get_sql_reset' in the current database."
|
||||
from django.db import connection, transaction
|
||||
from django.conf import settings
|
||||
app_name = app.__name__.split('.')[-2]
|
||||
|
||||
disable_termcolors()
|
||||
@ -638,13 +642,14 @@ def reset(app, interactive=True):
|
||||
if interactive:
|
||||
confirm = raw_input("""
|
||||
You have requested a database reset.
|
||||
This will IRREVERSIBLY DESTROY any data in your database.
|
||||
This will IRREVERSIBLY DESTROY any data for
|
||||
the "%s" application in the database "%s".
|
||||
Are you sure you want to do this?
|
||||
|
||||
Type 'yes' to continue, or 'no' to cancel: """)
|
||||
Type 'yes' to continue, or 'no' to cancel: """ % (app_name, settings.DATABASE_NAME))
|
||||
else:
|
||||
confirm = 'yes'
|
||||
|
||||
|
||||
if confirm == 'yes':
|
||||
try:
|
||||
cursor = connection.cursor()
|
||||
@ -694,7 +699,10 @@ def _start_helper(app_or_project, name, directory, other_name=''):
|
||||
fp_new.write(fp_old.read().replace('{{ %s_name }}' % app_or_project, name).replace('{{ %s_name }}' % other, other_name))
|
||||
fp_old.close()
|
||||
fp_new.close()
|
||||
shutil.copymode(path_old, path_new)
|
||||
try:
|
||||
shutil.copymode(path_old, path_new)
|
||||
except OSError:
|
||||
sys.stderr.write(style.NOTICE("Notice: Couldn't set permission bits on %s. You're probably using an uncommon filesystem setup. No problem.\n" % path_new))
|
||||
|
||||
def startproject(project_name, directory):
|
||||
"Creates a Django project for the given project_name in the given directory."
|
||||
@ -1224,7 +1232,7 @@ def test(app_labels, verbosity=1):
|
||||
test_module_name = '.'.join(test_path[:-1])
|
||||
else:
|
||||
test_module_name = '.'
|
||||
test_module = __import__(test_module_name, [],[],test_path[-1])
|
||||
test_module = __import__(test_module_name, {}, {}, test_path[-1])
|
||||
test_runner = getattr(test_module, test_path[-1])
|
||||
|
||||
test_runner(app_list, verbosity)
|
||||
@ -1413,7 +1421,7 @@ def setup_environ(settings_mod):
|
||||
project_directory = os.path.dirname(settings_mod.__file__)
|
||||
project_name = os.path.basename(project_directory)
|
||||
sys.path.append(os.path.join(project_directory, '..'))
|
||||
project_module = __import__(project_name, '', '', [''])
|
||||
project_module = __import__(project_name, {}, {}, [''])
|
||||
sys.path.pop()
|
||||
|
||||
# Set DJANGO_SETTINGS_MODULE appropriately.
|
||||
|
@ -1,54 +1,46 @@
|
||||
from math import ceil
|
||||
|
||||
class InvalidPage(Exception):
|
||||
pass
|
||||
|
||||
class ObjectPaginator(object):
|
||||
"""
|
||||
This class makes pagination easy. Feed it a QuerySet, plus the number of
|
||||
objects you want on each page. Then read the hits and pages properties to
|
||||
This class makes pagination easy. Feed it a QuerySet or list, plus the number
|
||||
of objects you want on each page. Then read the hits and pages properties to
|
||||
see how many pages it involves. Call get_page with a page number (starting
|
||||
at 0) to get back a list of objects for that page.
|
||||
|
||||
Finally, check if a page number has a next/prev page using
|
||||
has_next_page(page_number) and has_previous_page(page_number).
|
||||
|
||||
Use orphans to avoid small final pages. For example:
|
||||
13 records, num_per_page=10, orphans=2 --> pages==2, len(self.get_page(0))==10
|
||||
12 records, num_per_page=10, orphans=2 --> pages==1, len(self.get_page(0))==12
|
||||
"""
|
||||
def __init__(self, query_set, num_per_page):
|
||||
def __init__(self, query_set, num_per_page, orphans=0):
|
||||
self.query_set = query_set
|
||||
self.num_per_page = num_per_page
|
||||
self._hits, self._pages = None, None
|
||||
self._has_next = {} # Caches page_number -> has_next_boolean
|
||||
self.orphans = orphans
|
||||
self._hits = self._pages = None
|
||||
|
||||
def get_page(self, page_number):
|
||||
def validate_page_number(self, page_number):
|
||||
try:
|
||||
page_number = int(page_number)
|
||||
except ValueError:
|
||||
raise InvalidPage
|
||||
if page_number < 0:
|
||||
if page_number < 0 or page_number > self.pages - 1:
|
||||
raise InvalidPage
|
||||
return page_number
|
||||
|
||||
# Retrieve one extra record, and check for the existence of that extra
|
||||
# record to determine whether there's a next page.
|
||||
limit = self.num_per_page + 1
|
||||
offset = page_number * self.num_per_page
|
||||
|
||||
object_list = list(self.query_set[offset:offset+limit])
|
||||
|
||||
if not object_list:
|
||||
raise InvalidPage
|
||||
|
||||
self._has_next[page_number] = (len(object_list) > self.num_per_page)
|
||||
return object_list[:self.num_per_page]
|
||||
def get_page(self, page_number):
|
||||
page_number = self.validate_page_number(page_number)
|
||||
bottom = page_number * self.num_per_page
|
||||
top = bottom + self.num_per_page
|
||||
if top + self.orphans >= self.hits:
|
||||
top = self.hits
|
||||
return self.query_set[bottom:top]
|
||||
|
||||
def has_next_page(self, page_number):
|
||||
"Does page $page_number have a 'next' page?"
|
||||
if not self._has_next.has_key(page_number):
|
||||
if self._pages is None:
|
||||
offset = (page_number + 1) * self.num_per_page
|
||||
self._has_next[page_number] = len(self.query_set[offset:offset+1]) > 0
|
||||
else:
|
||||
self._has_next[page_number] = page_number < (self.pages - 1)
|
||||
return self._has_next[page_number]
|
||||
return page_number < self.pages - 1
|
||||
|
||||
def has_previous_page(self, page_number):
|
||||
return page_number > 0
|
||||
@ -58,8 +50,7 @@ class ObjectPaginator(object):
|
||||
Returns the 1-based index of the first object on the given page,
|
||||
relative to total objects found (hits).
|
||||
"""
|
||||
if page_number == 0:
|
||||
return 1
|
||||
page_number = self.validate_page_number(page_number)
|
||||
return (self.num_per_page * page_number) + 1
|
||||
|
||||
def last_on_page(self, page_number):
|
||||
@ -67,20 +58,30 @@ class ObjectPaginator(object):
|
||||
Returns the 1-based index of the last object on the given page,
|
||||
relative to total objects found (hits).
|
||||
"""
|
||||
if page_number == 0 and self.num_per_page >= self._hits:
|
||||
return self._hits
|
||||
elif page_number == (self._pages - 1) and (page_number + 1) * self.num_per_page > self._hits:
|
||||
return self._hits
|
||||
return (page_number + 1) * self.num_per_page
|
||||
page_number = self.validate_page_number(page_number)
|
||||
page_number += 1 # 1-base
|
||||
if page_number == self.pages:
|
||||
return self.hits
|
||||
return page_number * self.num_per_page
|
||||
|
||||
def _get_hits(self):
|
||||
if self._hits is None:
|
||||
self._hits = self.query_set.count()
|
||||
# Try .count() or fall back to len().
|
||||
try:
|
||||
self._hits = int(self.query_set.count())
|
||||
except (AttributeError, TypeError, ValueError):
|
||||
# AttributeError if query_set has no object count.
|
||||
# TypeError if query_set.count() required arguments.
|
||||
# ValueError if int() fails.
|
||||
self._hits = len(self.query_set)
|
||||
return self._hits
|
||||
|
||||
def _get_pages(self):
|
||||
if self._pages is None:
|
||||
self._pages = int(ceil(self.hits / float(self.num_per_page)))
|
||||
hits = (self.hits - 1 - self.orphans)
|
||||
if hits < 1:
|
||||
hits = 0
|
||||
self._pages = hits // self.num_per_page + 1
|
||||
return self._pages
|
||||
|
||||
hits = property(_get_hits)
|
||||
|
@ -29,7 +29,7 @@ _serializers = {}
|
||||
|
||||
def register_serializer(format, serializer_module):
|
||||
"""Register a new serializer by passing in a module name."""
|
||||
module = __import__(serializer_module, '', '', [''])
|
||||
module = __import__(serializer_module, {}, {}, [''])
|
||||
_serializers[format] = module
|
||||
|
||||
def unregister_serializer(format):
|
||||
|
@ -28,6 +28,7 @@ class Serializer(object):
|
||||
self.options = options
|
||||
|
||||
self.stream = options.get("stream", StringIO())
|
||||
self.selected_fields = options.get("fields")
|
||||
|
||||
self.start_serialization()
|
||||
for obj in queryset:
|
||||
@ -36,11 +37,14 @@ class Serializer(object):
|
||||
if field is obj._meta.pk:
|
||||
continue
|
||||
elif field.rel is None:
|
||||
self.handle_field(obj, field)
|
||||
if self.selected_fields is None or field.attname in self.selected_fields:
|
||||
self.handle_field(obj, field)
|
||||
else:
|
||||
self.handle_fk_field(obj, field)
|
||||
if self.selected_fields is None or field.attname[:-3] in self.selected_fields:
|
||||
self.handle_fk_field(obj, field)
|
||||
for field in obj._meta.many_to_many:
|
||||
self.handle_m2m_field(obj, field)
|
||||
if self.selected_fields is None or field.attname in self.selected_fields:
|
||||
self.handle_m2m_field(obj, field)
|
||||
self.end_object(obj)
|
||||
self.end_serialization()
|
||||
return self.getvalue()
|
||||
|
@ -76,7 +76,7 @@ def Deserializer(object_list, **options):
|
||||
m2m_data[field.name] = field.rel.to._default_manager.in_bulk(field_value).values()
|
||||
|
||||
# Handle FK fields
|
||||
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
||||
elif field.rel and isinstance(field.rel, models.ManyToOneRel) and field_value is not None:
|
||||
try:
|
||||
data[field.name] = field.rel.to._default_manager.get(pk=field_value)
|
||||
except field.rel.to.DoesNotExist:
|
||||
|
@ -166,7 +166,11 @@ class Deserializer(base.Deserializer):
|
||||
# If it doesn't exist, set the field to None (which might trigger
|
||||
# validation error, but that's expected).
|
||||
RelatedModel = self._get_model_from_node(node, "to")
|
||||
return RelatedModel.objects.get(pk=getInnerText(node).strip().encode(self.encoding))
|
||||
# Check if there is a child node named 'None', returning None if so.
|
||||
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
|
||||
return None
|
||||
else:
|
||||
return RelatedModel.objects.get(pk=getInnerText(node).strip().encode(self.encoding))
|
||||
|
||||
def _handle_m2m_field_node(self, node):
|
||||
"""
|
||||
|
@ -31,9 +31,11 @@ Optional Fcgi settings: (setting=value)
|
||||
port=PORTNUM port to listen on.
|
||||
socket=FILE UNIX socket to listen on.
|
||||
method=IMPL prefork or threaded (default prefork)
|
||||
maxspare=NUMBER max number of spare processes to keep running.
|
||||
minspare=NUMBER min number of spare processes to prefork.
|
||||
maxchildren=NUMBER hard limit number of processes in prefork mode.
|
||||
maxrequests=NUMBER number of requests a child handles before it is
|
||||
killed and a new child is forked (0 = no limit).
|
||||
maxspare=NUMBER max number of spare processes / threads
|
||||
minspare=NUMBER min number of spare processes / threads.
|
||||
maxchildren=NUMBER hard limit number of processes / threads
|
||||
daemonize=BOOL whether to detach from terminal.
|
||||
pidfile=FILE write the spawned process-id to this file.
|
||||
workdir=DIRECTORY change to this directory when daemonizing
|
||||
@ -66,6 +68,7 @@ FASTCGI_OPTIONS = {
|
||||
'maxspare': 5,
|
||||
'minspare': 2,
|
||||
'maxchildren': 50,
|
||||
'maxrequests': 0,
|
||||
}
|
||||
|
||||
def fastcgi_help(message=None):
|
||||
@ -103,10 +106,15 @@ def runfastcgi(argset=[], **kwargs):
|
||||
'maxSpare': int(options["maxspare"]),
|
||||
'minSpare': int(options["minspare"]),
|
||||
'maxChildren': int(options["maxchildren"]),
|
||||
'maxRequests': int(options["maxrequests"]),
|
||||
}
|
||||
elif options['method'] in ('thread', 'threaded'):
|
||||
from flup.server.fcgi import WSGIServer
|
||||
wsgi_opts = {}
|
||||
wsgi_opts = {
|
||||
'maxSpare': int(options["maxspare"]),
|
||||
'minSpare': int(options["minspare"]),
|
||||
'maxThreads': int(options["maxchildren"]),
|
||||
}
|
||||
else:
|
||||
return fastcgi_help("ERROR: Implementation must be one of prefork or thread.")
|
||||
|
||||
|
@ -21,7 +21,10 @@ class NoReverseMatch(Exception):
|
||||
def get_mod_func(callback):
|
||||
# Converts 'django.views.news.stories.story_detail' to
|
||||
# ['django.views.news.stories', 'story_detail']
|
||||
dot = callback.rindex('.')
|
||||
try:
|
||||
dot = callback.rindex('.')
|
||||
except ValueError:
|
||||
return callback, ''
|
||||
return callback[:dot], callback[dot+1:]
|
||||
|
||||
def reverse_helper(regex, *args, **kwargs):
|
||||
@ -119,7 +122,7 @@ class RegexURLPattern(object):
|
||||
return self._callback
|
||||
mod_name, func_name = get_mod_func(self._callback_str)
|
||||
try:
|
||||
self._callback = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||
self._callback = getattr(__import__(mod_name, {}, {}, ['']), func_name)
|
||||
except ImportError, e:
|
||||
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
|
||||
except AttributeError, e:
|
||||
@ -130,7 +133,7 @@ class RegexURLPattern(object):
|
||||
def reverse(self, viewname, *args, **kwargs):
|
||||
mod_name, func_name = get_mod_func(viewname)
|
||||
try:
|
||||
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
|
||||
except (ImportError, AttributeError):
|
||||
raise NoReverseMatch
|
||||
if lookup_view != self.callback:
|
||||
@ -171,7 +174,7 @@ class RegexURLResolver(object):
|
||||
return self._urlconf_module
|
||||
except AttributeError:
|
||||
try:
|
||||
self._urlconf_module = __import__(self.urlconf_name, '', '', [''])
|
||||
self._urlconf_module = __import__(self.urlconf_name, {}, {}, [''])
|
||||
except ValueError, e:
|
||||
# Invalid urlconf_name, such as "foo.bar." (note trailing period)
|
||||
raise ImproperlyConfigured, "Error while importing URLconf %r: %s" % (self.urlconf_name, e)
|
||||
@ -186,7 +189,7 @@ class RegexURLResolver(object):
|
||||
callback = getattr(self.urlconf_module, 'handler%s' % view_type)
|
||||
mod_name, func_name = get_mod_func(callback)
|
||||
try:
|
||||
return getattr(__import__(mod_name, '', '', ['']), func_name), {}
|
||||
return getattr(__import__(mod_name, {}, {}, ['']), func_name), {}
|
||||
except (ImportError, AttributeError), e:
|
||||
raise ViewDoesNotExist, "Tried %s. Error was: %s" % (callback, str(e))
|
||||
|
||||
@ -200,7 +203,7 @@ class RegexURLResolver(object):
|
||||
if not callable(lookup_view):
|
||||
mod_name, func_name = get_mod_func(lookup_view)
|
||||
try:
|
||||
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
|
||||
except (ImportError, AttributeError):
|
||||
raise NoReverseMatch
|
||||
for pattern in self.urlconf_module.urlpatterns:
|
||||
|
@ -8,6 +8,7 @@ validator will *always* be run, regardless of whether its associated
|
||||
form field is required.
|
||||
"""
|
||||
|
||||
import urllib2
|
||||
from django.conf import settings
|
||||
from django.utils.translation import gettext, gettext_lazy, ngettext
|
||||
from django.utils.functional import Promise, lazy
|
||||
@ -223,18 +224,26 @@ def isWellFormedXmlFragment(field_data, all_data):
|
||||
isWellFormedXml('<root>%s</root>' % field_data, all_data)
|
||||
|
||||
def isExistingURL(field_data, all_data):
|
||||
import urllib2
|
||||
try:
|
||||
u = urllib2.urlopen(field_data)
|
||||
headers = {
|
||||
"Accept" : "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
|
||||
"Accept-Language" : "en-us,en;q=0.5",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Connection" : "close",
|
||||
"User-Agent": settings.URL_VALIDATOR_USER_AGENT
|
||||
}
|
||||
req = urllib2.Request(field_data,None, headers)
|
||||
u = urllib2.urlopen(req)
|
||||
except ValueError:
|
||||
raise ValidationError, gettext("Invalid URL: %s") % field_data
|
||||
raise ValidationError, _("Invalid URL: %s") % field_data
|
||||
except urllib2.HTTPError, e:
|
||||
# 401s are valid; they just mean authorization is required.
|
||||
if e.code not in ('401',):
|
||||
raise ValidationError, gettext("The URL %s is a broken link.") % field_data
|
||||
# 301 and 302 are redirects; they just mean look somewhere else.
|
||||
if str(e.code) not in ('401','301','302'):
|
||||
raise ValidationError, _("The URL %s is a broken link.") % field_data
|
||||
except: # urllib2.URLError, httplib.InvalidURL, etc.
|
||||
raise ValidationError, gettext("The URL %s is a broken link.") % field_data
|
||||
|
||||
raise ValidationError, _("The URL %s is a broken link.") % field_data
|
||||
|
||||
def isValidUSState(field_data, all_data):
|
||||
"Checks that the given string is a valid two-letter U.S. state abbreviation"
|
||||
states = ['AA', 'AE', 'AK', 'AL', 'AP', 'AR', 'AS', 'AZ', 'CA', 'CO', 'CT', 'DC', 'DE', 'FL', 'FM', 'GA', 'GU', 'HI', 'IA', 'ID', 'IL', 'IN', 'KS', 'KY', 'LA', 'MA', 'MD', 'ME', 'MH', 'MI', 'MN', 'MO', 'MP', 'MS', 'MT', 'NC', 'ND', 'NE', 'NH', 'NJ', 'NM', 'NV', 'NY', 'OH', 'OK', 'OR', 'PA', 'PR', 'PW', 'RI', 'SC', 'SD', 'TN', 'TX', 'UT', 'VA', 'VI', 'VT', 'WA', 'WI', 'WV', 'WY']
|
||||
@ -344,6 +353,38 @@ class UniqueAmongstFieldsWithPrefix(object):
|
||||
if field_name != self.field_name and value == field_data:
|
||||
raise ValidationError, self.error_message
|
||||
|
||||
class NumberIsInRange(object):
|
||||
"""
|
||||
Validator that tests if a value is in a range (inclusive).
|
||||
"""
|
||||
def __init__(self, lower=None, upper=None, error_message=''):
|
||||
self.lower, self.upper = lower, upper
|
||||
if not error_message:
|
||||
if lower and upper:
|
||||
self.error_message = gettext("This value must be between %s and %s.") % (lower, upper)
|
||||
elif lower:
|
||||
self.error_message = gettext("This value must be at least %s.") % lower
|
||||
elif upper:
|
||||
self.error_message = gettext("This value must be no more than %s.") % upper
|
||||
else:
|
||||
self.error_message = error_message
|
||||
|
||||
def __call__(self, field_data, all_data):
|
||||
# Try to make the value numeric. If this fails, we assume another
|
||||
# validator will catch the problem.
|
||||
try:
|
||||
val = float(field_data)
|
||||
except ValueError:
|
||||
return
|
||||
|
||||
# Now validate
|
||||
if self.lower and self.upper and (val < self.lower or val > self.upper):
|
||||
raise ValidationError(self.error_message)
|
||||
elif self.lower and val < self.lower:
|
||||
raise ValidationError(self.error_message)
|
||||
elif self.upper and val > self.upper:
|
||||
raise ValidationError(self.error_message)
|
||||
|
||||
class IsAPowerOf(object):
|
||||
"""
|
||||
>>> v = IsAPowerOf(2)
|
||||
|
@ -8,7 +8,7 @@ if not settings.DATABASE_ENGINE:
|
||||
settings.DATABASE_ENGINE = 'dummy'
|
||||
|
||||
try:
|
||||
backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, '', '', [''])
|
||||
backend = __import__('django.db.backends.%s.base' % settings.DATABASE_ENGINE, {}, {}, [''])
|
||||
except ImportError, e:
|
||||
# The database backend wasn't found. Display a helpful error message
|
||||
# listing all possible database backends.
|
||||
@ -23,11 +23,11 @@ except ImportError, e:
|
||||
else:
|
||||
raise # If there's some other error, this must be an error in Django itself.
|
||||
|
||||
get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, '', '', [''])
|
||||
get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, '', '', [''])
|
||||
runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, '', '', ['']).runshell()
|
||||
get_introspection_module = lambda: __import__('django.db.backends.%s.introspection' % settings.DATABASE_ENGINE, {}, {}, [''])
|
||||
get_creation_module = lambda: __import__('django.db.backends.%s.creation' % settings.DATABASE_ENGINE, {}, {}, [''])
|
||||
runshell = lambda: __import__('django.db.backends.%s.client' % settings.DATABASE_ENGINE, {}, {}, ['']).runshell()
|
||||
|
||||
connection = backend.DatabaseWrapper()
|
||||
connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS)
|
||||
DatabaseError = backend.DatabaseError
|
||||
|
||||
# Register an event that closes the database connection
|
||||
|
@ -55,7 +55,7 @@ except ImportError:
|
||||
from django.utils._threading_local import local
|
||||
|
||||
class DatabaseWrapper(local):
|
||||
def __init__(self):
|
||||
def __init__(self, **kwargs):
|
||||
self.connection = None
|
||||
self.queries = []
|
||||
|
||||
|
@ -20,6 +20,9 @@ class DatabaseWrapper:
|
||||
_commit = complain
|
||||
_rollback = complain
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
pass # close()
|
||||
|
||||
|
@ -65,10 +65,11 @@ except ImportError:
|
||||
from django.utils._threading_local import local
|
||||
|
||||
class DatabaseWrapper(local):
|
||||
def __init__(self):
|
||||
def __init__(self, **kwargs):
|
||||
self.connection = None
|
||||
self.queries = []
|
||||
self.server_version = None
|
||||
self.options = kwargs
|
||||
|
||||
def _valid_connection(self):
|
||||
if self.connection is not None:
|
||||
@ -95,6 +96,7 @@ class DatabaseWrapper(local):
|
||||
kwargs['host'] = settings.DATABASE_HOST
|
||||
if settings.DATABASE_PORT:
|
||||
kwargs['port'] = int(settings.DATABASE_PORT)
|
||||
kwargs.update(self.options)
|
||||
self.connection = Database.connect(**kwargs)
|
||||
cursor = self.connection.cursor()
|
||||
if self.connection.get_server_info() >= '4.1':
|
||||
|
@ -21,9 +21,10 @@ except ImportError:
|
||||
from django.utils._threading_local import local
|
||||
|
||||
class DatabaseWrapper(local):
|
||||
def __init__(self):
|
||||
def __init__(self, **kwargs):
|
||||
self.connection = None
|
||||
self.queries = []
|
||||
self.options = kwargs
|
||||
|
||||
def _valid_connection(self):
|
||||
return self.connection is not None
|
||||
@ -35,10 +36,10 @@ class DatabaseWrapper(local):
|
||||
settings.DATABASE_HOST = 'localhost'
|
||||
if len(settings.DATABASE_PORT.strip()) != 0:
|
||||
dsn = Database.makedsn(settings.DATABASE_HOST, int(settings.DATABASE_PORT), settings.DATABASE_NAME)
|
||||
self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn)
|
||||
self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn, **self.options)
|
||||
else:
|
||||
conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)
|
||||
self.connection = Database.connect(conn_string)
|
||||
self.connection = Database.connect(conn_string, **self.options)
|
||||
return FormatStylePlaceholderCursor(self.connection)
|
||||
|
||||
def _commit(self):
|
||||
|
@ -21,9 +21,10 @@ except ImportError:
|
||||
from django.utils._threading_local import local
|
||||
|
||||
class DatabaseWrapper(local):
|
||||
def __init__(self):
|
||||
def __init__(self, **kwargs):
|
||||
self.connection = None
|
||||
self.queries = []
|
||||
self.options = kwargs
|
||||
|
||||
def cursor(self):
|
||||
from django.conf import settings
|
||||
@ -40,7 +41,7 @@ class DatabaseWrapper(local):
|
||||
conn_string += " host=%s" % settings.DATABASE_HOST
|
||||
if settings.DATABASE_PORT:
|
||||
conn_string += " port=%s" % settings.DATABASE_PORT
|
||||
self.connection = Database.connect(conn_string)
|
||||
self.connection = Database.connect(conn_string, **self.options)
|
||||
self.connection.set_isolation_level(1) # make transactions transparent to all cursors
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
|
||||
|
@ -21,9 +21,10 @@ except ImportError:
|
||||
from django.utils._threading_local import local
|
||||
|
||||
class DatabaseWrapper(local):
|
||||
def __init__(self):
|
||||
def __init__(self, **kwargs):
|
||||
self.connection = None
|
||||
self.queries = []
|
||||
self.options = kwargs
|
||||
|
||||
def cursor(self):
|
||||
from django.conf import settings
|
||||
@ -40,7 +41,7 @@ class DatabaseWrapper(local):
|
||||
conn_string += " host=%s" % settings.DATABASE_HOST
|
||||
if settings.DATABASE_PORT:
|
||||
conn_string += " port=%s" % settings.DATABASE_PORT
|
||||
self.connection = Database.connect(conn_string)
|
||||
self.connection = Database.connect(conn_string, **self.options)
|
||||
self.connection.set_isolation_level(1) # make transactions transparent to all cursors
|
||||
cursor = self.connection.cursor()
|
||||
cursor.tzinfo_factory = None
|
||||
|
@ -42,16 +42,20 @@ except ImportError:
|
||||
from django.utils._threading_local import local
|
||||
|
||||
class DatabaseWrapper(local):
|
||||
def __init__(self):
|
||||
def __init__(self, **kwargs):
|
||||
self.connection = None
|
||||
self.queries = []
|
||||
self.options = kwargs
|
||||
|
||||
def cursor(self):
|
||||
from django.conf import settings
|
||||
if self.connection is None:
|
||||
self.connection = Database.connect(settings.DATABASE_NAME,
|
||||
detect_types=Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES)
|
||||
|
||||
kwargs = {
|
||||
'database': settings.DATABASE_NAME,
|
||||
'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES,
|
||||
}
|
||||
kwargs.update(self.options)
|
||||
self.connection = Database.connect(**kwargs)
|
||||
# Register extract and date_trunc functions.
|
||||
self.connection.create_function("django_extract", 2, _sqlite_extract)
|
||||
self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc)
|
||||
|
@ -17,7 +17,7 @@ class CursorDebugWrapper(object):
|
||||
if not isinstance(params, (tuple, dict)):
|
||||
params = tuple(params)
|
||||
self.db.queries.append({
|
||||
'sql': sql % tuple(params),
|
||||
'sql': sql % params,
|
||||
'time': "%.3f" % (stop - start),
|
||||
})
|
||||
|
||||
|
@ -376,24 +376,6 @@ class Model(object):
|
||||
setattr(self, cachename, get_image_dimensions(filename))
|
||||
return getattr(self, cachename)
|
||||
|
||||
# Handles setting many-to-many related objects.
|
||||
# Example: Album.set_songs()
|
||||
def _set_related_many_to_many(self, rel_class, rel_field, id_list):
|
||||
id_list = map(int, id_list) # normalize to integers
|
||||
rel = rel_field.rel.to
|
||||
m2m_table = rel_field.m2m_db_table()
|
||||
this_id = self._get_pk_val()
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
|
||||
(backend.quote_name(m2m_table),
|
||||
backend.quote_name(rel_field.m2m_column_name())), [this_id])
|
||||
sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
|
||||
(backend.quote_name(m2m_table),
|
||||
backend.quote_name(rel_field.m2m_column_name()),
|
||||
backend.quote_name(rel_field.m2m_reverse_name()))
|
||||
cursor.executemany(sql, [(this_id, i) for i in id_list])
|
||||
transaction.commit_unless_managed()
|
||||
|
||||
############################################
|
||||
# HELPER FUNCTIONS (CURRIED MODEL METHODS) #
|
||||
############################################
|
||||
|
@ -457,7 +457,9 @@ class DateField(Field):
|
||||
|
||||
def get_db_prep_save(self, value):
|
||||
# Casts dates into string format for entry into database.
|
||||
if value is not None:
|
||||
if isinstance(value, datetime.datetime):
|
||||
value = value.date().strftime('%Y-%m-%d')
|
||||
elif isinstance(value, datetime.date):
|
||||
value = value.strftime('%Y-%m-%d')
|
||||
return Field.get_db_prep_save(self, value)
|
||||
|
||||
@ -487,12 +489,19 @@ class DateTimeField(DateField):
|
||||
|
||||
def get_db_prep_save(self, value):
|
||||
# Casts dates into string format for entry into database.
|
||||
if value is not None:
|
||||
if isinstance(value, datetime.datetime):
|
||||
# MySQL will throw a warning if microseconds are given, because it
|
||||
# doesn't support microseconds.
|
||||
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
|
||||
value = value.replace(microsecond=0)
|
||||
value = str(value)
|
||||
elif isinstance(value, datetime.date):
|
||||
# MySQL will throw a warning if microseconds are given, because it
|
||||
# doesn't support microseconds.
|
||||
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
|
||||
value = datetime.datetime(value.year, value.month, value.day, microsecond=0)
|
||||
value = str(value)
|
||||
|
||||
return Field.get_db_prep_save(self, value)
|
||||
|
||||
def get_db_prep_lookup(self, lookup_type, value):
|
||||
@ -576,7 +585,7 @@ class FileField(Field):
|
||||
# If the raw path is passed in, validate it's under the MEDIA_ROOT.
|
||||
def isWithinMediaRoot(field_data, all_data):
|
||||
f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data))
|
||||
if not f.startswith(os.path.normpath(settings.MEDIA_ROOT)):
|
||||
if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))):
|
||||
raise validators.ValidationError, _("Enter a valid filename.")
|
||||
field_list[1].validator_list.append(isWithinMediaRoot)
|
||||
return field_list
|
||||
|
@ -2,7 +2,7 @@ from django.db import backend, transaction
|
||||
from django.db.models import signals, get_model
|
||||
from django.db.models.fields import AutoField, Field, IntegerField, get_ul_class
|
||||
from django.db.models.related import RelatedObject
|
||||
from django.utils.translation import gettext_lazy, string_concat
|
||||
from django.utils.translation import gettext_lazy, string_concat, ngettext
|
||||
from django.utils.functional import curry
|
||||
from django.core import validators
|
||||
from django import forms
|
||||
|
@ -48,7 +48,7 @@ def get_app(app_label, emptyOK=False):
|
||||
def load_app(app_name):
|
||||
"Loads the app with the provided fully qualified name, and returns the model module."
|
||||
global _app_list
|
||||
mod = __import__(app_name, '', '', ['models'])
|
||||
mod = __import__(app_name, {}, {}, ['models'])
|
||||
if not hasattr(mod, 'models'):
|
||||
return None
|
||||
if mod.models not in _app_list:
|
||||
|
@ -286,7 +286,7 @@ def manipulator_validator_unique_together(field_name_list, opts, self, field_dat
|
||||
# This is really not going to work for fields that have different
|
||||
# form fields, e.g. DateTime.
|
||||
# This validation needs to occur after html2python to be effective.
|
||||
field_val = all_data.get(f.attname, None)
|
||||
field_val = all_data.get(f.name, None)
|
||||
if field_val is None:
|
||||
# This will be caught by another validator, assuming the field
|
||||
# doesn't have blank=True.
|
||||
@ -303,7 +303,7 @@ def manipulator_validator_unique_together(field_name_list, opts, self, field_dat
|
||||
pass
|
||||
else:
|
||||
raise validators.ValidationError, _("%(object)s with this %(type)s already exists for the given %(field)s.") % \
|
||||
{'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list([f.verbose_name for f in field_list[1:]], 'and')}
|
||||
{'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list([f.verbose_name for f in field_list[1:]], _('and'))}
|
||||
|
||||
def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_type, self, field_data, all_data):
|
||||
from django.db.models.fields.related import ManyToOneRel
|
||||
|
@ -108,8 +108,13 @@ class FormWrapper(object):
|
||||
This allows dictionary-style lookups of formfields. It also handles feeding
|
||||
prepopulated data and validation error messages to the formfield objects.
|
||||
"""
|
||||
def __init__(self, manipulator, data, error_dict, edit_inline=True):
|
||||
self.manipulator, self.data = manipulator, data
|
||||
def __init__(self, manipulator, data=None, error_dict=None, edit_inline=True):
|
||||
self.manipulator = manipulator
|
||||
if data is None:
|
||||
data = {}
|
||||
if error_dict is None:
|
||||
error_dict = {}
|
||||
self.data = data
|
||||
self.error_dict = error_dict
|
||||
self._inline_collections = None
|
||||
self.edit_inline = edit_inline
|
||||
|
28
django/newforms/__init__.py
Normal file
28
django/newforms/__init__.py
Normal file
@ -0,0 +1,28 @@
|
||||
"""
|
||||
Django validation and HTML form handling.
|
||||
|
||||
TODO:
|
||||
Default value for field
|
||||
Field labels
|
||||
Nestable Forms
|
||||
FatalValidationError -- short-circuits all other validators on a form
|
||||
ValidationWarning
|
||||
"This form field requires foo.js" and form.js_includes()
|
||||
"""
|
||||
|
||||
from util import ValidationError
|
||||
from widgets import *
|
||||
from fields import *
|
||||
from forms import Form
|
||||
|
||||
##########################
|
||||
# DATABASE API SHORTCUTS #
|
||||
##########################
|
||||
|
||||
def form_for_model(model):
|
||||
"Returns a Form instance for the given Django model class."
|
||||
raise NotImplementedError
|
||||
|
||||
def form_for_fields(field_list):
|
||||
"Returns a Form instance for the given list of Django database field instances."
|
||||
raise NotImplementedError
|
295
django/newforms/fields.py
Normal file
295
django/newforms/fields.py
Normal file
@ -0,0 +1,295 @@
|
||||
"""
|
||||
Field classes
|
||||
"""
|
||||
|
||||
from util import ValidationError, DEFAULT_ENCODING
|
||||
from widgets import TextInput, CheckboxInput, Select, SelectMultiple
|
||||
import datetime
|
||||
import re
|
||||
import time
|
||||
|
||||
__all__ = (
|
||||
'Field', 'CharField', 'IntegerField',
|
||||
'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
|
||||
'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
|
||||
'RegexField', 'EmailField', 'URLField', 'BooleanField',
|
||||
'ChoiceField', 'MultipleChoiceField',
|
||||
'ComboField',
|
||||
)
|
||||
|
||||
# These values, if given to to_python(), will trigger the self.required check.
|
||||
EMPTY_VALUES = (None, '')
|
||||
|
||||
try:
|
||||
set # Only available in Python 2.4+
|
||||
except NameError:
|
||||
from sets import Set as set # Python 2.3 fallback
|
||||
|
||||
class Field(object):
|
||||
widget = TextInput # Default widget to use when rendering this type of Field.
|
||||
|
||||
def __init__(self, required=True, widget=None):
|
||||
self.required = required
|
||||
widget = widget or self.widget
|
||||
if isinstance(widget, type):
|
||||
widget = widget()
|
||||
self.widget = widget
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates the given value and returns its "cleaned" value as an
|
||||
appropriate Python object.
|
||||
|
||||
Raises ValidationError for any errors.
|
||||
"""
|
||||
if self.required and value in EMPTY_VALUES:
|
||||
raise ValidationError(u'This field is required.')
|
||||
return value
|
||||
|
||||
class CharField(Field):
|
||||
def __init__(self, max_length=None, min_length=None, required=True, widget=None):
|
||||
Field.__init__(self, required, widget)
|
||||
self.max_length, self.min_length = max_length, min_length
|
||||
|
||||
def clean(self, value):
|
||||
"Validates max_length and min_length. Returns a Unicode object."
|
||||
Field.clean(self, value)
|
||||
if value in EMPTY_VALUES: value = u''
|
||||
if not isinstance(value, basestring):
|
||||
value = unicode(str(value), DEFAULT_ENCODING)
|
||||
elif not isinstance(value, unicode):
|
||||
value = unicode(value, DEFAULT_ENCODING)
|
||||
if self.max_length is not None and len(value) > self.max_length:
|
||||
raise ValidationError(u'Ensure this value has at most %d characters.' % self.max_length)
|
||||
if self.min_length is not None and len(value) < self.min_length:
|
||||
raise ValidationError(u'Ensure this value has at least %d characters.' % self.min_length)
|
||||
return value
|
||||
|
||||
class IntegerField(Field):
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates that int() can be called on the input. Returns the result
|
||||
of int().
|
||||
"""
|
||||
super(IntegerField, self).clean(value)
|
||||
try:
|
||||
return int(value)
|
||||
except (ValueError, TypeError):
|
||||
raise ValidationError(u'Enter a whole number.')
|
||||
|
||||
DEFAULT_DATE_INPUT_FORMATS = (
|
||||
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
|
||||
'%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
|
||||
'%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
|
||||
'%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
|
||||
'%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
|
||||
)
|
||||
|
||||
class DateField(Field):
|
||||
def __init__(self, input_formats=None, required=True, widget=None):
|
||||
Field.__init__(self, required, widget)
|
||||
self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates that the input can be converted to a date. Returns a Python
|
||||
datetime.date object.
|
||||
"""
|
||||
Field.clean(self, value)
|
||||
if value in EMPTY_VALUES:
|
||||
return None
|
||||
if isinstance(value, datetime.datetime):
|
||||
return value.date()
|
||||
if isinstance(value, datetime.date):
|
||||
return value
|
||||
for format in self.input_formats:
|
||||
try:
|
||||
return datetime.date(*time.strptime(value, format)[:3])
|
||||
except ValueError:
|
||||
continue
|
||||
raise ValidationError(u'Enter a valid date.')
|
||||
|
||||
DEFAULT_DATETIME_INPUT_FORMATS = (
|
||||
'%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
|
||||
'%Y-%m-%d %H:%M', # '2006-10-25 14:30'
|
||||
'%Y-%m-%d', # '2006-10-25'
|
||||
'%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59'
|
||||
'%m/%d/%Y %H:%M', # '10/25/2006 14:30'
|
||||
'%m/%d/%Y', # '10/25/2006'
|
||||
'%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59'
|
||||
'%m/%d/%y %H:%M', # '10/25/06 14:30'
|
||||
'%m/%d/%y', # '10/25/06'
|
||||
)
|
||||
|
||||
class DateTimeField(Field):
|
||||
def __init__(self, input_formats=None, required=True, widget=None):
|
||||
Field.__init__(self, required, widget)
|
||||
self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates that the input can be converted to a datetime. Returns a
|
||||
Python datetime.datetime object.
|
||||
"""
|
||||
Field.clean(self, value)
|
||||
if value in EMPTY_VALUES:
|
||||
return None
|
||||
if isinstance(value, datetime.datetime):
|
||||
return value
|
||||
if isinstance(value, datetime.date):
|
||||
return datetime.datetime(value.year, value.month, value.day)
|
||||
for format in self.input_formats:
|
||||
try:
|
||||
return datetime.datetime(*time.strptime(value, format)[:6])
|
||||
except ValueError:
|
||||
continue
|
||||
raise ValidationError(u'Enter a valid date/time.')
|
||||
|
||||
class RegexField(Field):
|
||||
def __init__(self, regex, error_message=None, required=True, widget=None):
|
||||
"""
|
||||
regex can be either a string or a compiled regular expression object.
|
||||
error_message is an optional error message to use, if
|
||||
'Enter a valid value' is too generic for you.
|
||||
"""
|
||||
Field.__init__(self, required, widget)
|
||||
if isinstance(regex, basestring):
|
||||
regex = re.compile(regex)
|
||||
self.regex = regex
|
||||
self.error_message = error_message or u'Enter a valid value.'
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates that the input matches the regular expression. Returns a
|
||||
Unicode object.
|
||||
"""
|
||||
Field.clean(self, value)
|
||||
if value in EMPTY_VALUES: value = u''
|
||||
if not isinstance(value, basestring):
|
||||
value = unicode(str(value), DEFAULT_ENCODING)
|
||||
elif not isinstance(value, unicode):
|
||||
value = unicode(value, DEFAULT_ENCODING)
|
||||
if not self.regex.search(value):
|
||||
raise ValidationError(self.error_message)
|
||||
return value
|
||||
|
||||
email_re = re.compile(
|
||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
|
||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
|
||||
r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain
|
||||
|
||||
class EmailField(RegexField):
|
||||
def __init__(self, required=True, widget=None):
|
||||
RegexField.__init__(self, email_re, u'Enter a valid e-mail address.', required, widget)
|
||||
|
||||
url_re = re.compile(
|
||||
r'^https?://' # http:// or https://
|
||||
r'(?:[A-Z0-9-]+\.)+[A-Z]{2,6}' # domain
|
||||
r'(?::\d+)?' # optional port
|
||||
r'(?:/?|/\S+)$', re.IGNORECASE)
|
||||
|
||||
try:
|
||||
from django.conf import settings
|
||||
URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT
|
||||
except ImportError:
|
||||
# It's OK if Django settings aren't configured.
|
||||
URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
|
||||
|
||||
class URLField(RegexField):
|
||||
def __init__(self, required=True, verify_exists=False, widget=None,
|
||||
validator_user_agent=URL_VALIDATOR_USER_AGENT):
|
||||
RegexField.__init__(self, url_re, u'Enter a valid URL.', required, widget)
|
||||
self.verify_exists = verify_exists
|
||||
self.user_agent = validator_user_agent
|
||||
|
||||
def clean(self, value):
|
||||
value = RegexField.clean(self, value)
|
||||
if self.verify_exists:
|
||||
import urllib2
|
||||
from django.conf import settings
|
||||
headers = {
|
||||
"Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
|
||||
"Accept-Language": "en-us,en;q=0.5",
|
||||
"Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
|
||||
"Connection": "close",
|
||||
"User-Agent": self.user_agent,
|
||||
}
|
||||
try:
|
||||
req = urllib2.Request(field_data, None, headers)
|
||||
u = urllib2.urlopen(req)
|
||||
except ValueError:
|
||||
raise ValidationError(u'Enter a valid URL.')
|
||||
except: # urllib2.URLError, httplib.InvalidURL, etc.
|
||||
raise ValidationError(u'This URL appears to be a broken link.')
|
||||
return value
|
||||
|
||||
class BooleanField(Field):
|
||||
widget = CheckboxInput
|
||||
|
||||
def clean(self, value):
|
||||
"Returns a Python boolean object."
|
||||
Field.clean(self, value)
|
||||
return bool(value)
|
||||
|
||||
class ChoiceField(Field):
|
||||
def __init__(self, choices=(), required=True, widget=Select):
|
||||
if isinstance(widget, type):
|
||||
widget = widget(choices=choices)
|
||||
Field.__init__(self, required, widget)
|
||||
self.choices = choices
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates that the input is in self.choices.
|
||||
"""
|
||||
value = Field.clean(self, value)
|
||||
if value in EMPTY_VALUES: value = u''
|
||||
if not isinstance(value, basestring):
|
||||
value = unicode(str(value), DEFAULT_ENCODING)
|
||||
elif not isinstance(value, unicode):
|
||||
value = unicode(value, DEFAULT_ENCODING)
|
||||
valid_values = set([str(k) for k, v in self.choices])
|
||||
if value not in valid_values:
|
||||
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % value)
|
||||
return value
|
||||
|
||||
class MultipleChoiceField(ChoiceField):
|
||||
def __init__(self, choices=(), required=True, widget=SelectMultiple):
|
||||
ChoiceField.__init__(self, choices, required, widget)
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates that the input is a list or tuple.
|
||||
"""
|
||||
if not isinstance(value, (list, tuple)):
|
||||
raise ValidationError(u'Enter a list of values.')
|
||||
if self.required and not value:
|
||||
raise ValidationError(u'This field is required.')
|
||||
new_value = []
|
||||
for val in value:
|
||||
if not isinstance(val, basestring):
|
||||
value = unicode(str(val), DEFAULT_ENCODING)
|
||||
elif not isinstance(val, unicode):
|
||||
value = unicode(val, DEFAULT_ENCODING)
|
||||
new_value.append(value)
|
||||
# Validate that each value in the value list is in self.choices.
|
||||
valid_values = set([k for k, v in self.choices])
|
||||
for val in new_value:
|
||||
if val not in valid_values:
|
||||
raise ValidationError(u'Select a valid choice. %s is not one of the available choices.' % val)
|
||||
return new_value
|
||||
|
||||
class ComboField(Field):
|
||||
def __init__(self, fields=(), required=True, widget=None):
|
||||
Field.__init__(self, required, widget)
|
||||
self.fields = fields
|
||||
|
||||
def clean(self, value):
|
||||
"""
|
||||
Validates the given value against all of self.fields, which is a
|
||||
list of Field instances.
|
||||
"""
|
||||
Field.clean(self, value)
|
||||
for field in self.fields:
|
||||
value = field.clean(value)
|
||||
return value
|
169
django/newforms/forms.py
Normal file
169
django/newforms/forms.py
Normal file
@ -0,0 +1,169 @@
|
||||
"""
|
||||
Form classes
|
||||
"""
|
||||
|
||||
from fields import Field
|
||||
from widgets import TextInput, Textarea
|
||||
from util import ErrorDict, ErrorList, ValidationError
|
||||
|
||||
NON_FIELD_ERRORS = '__all__'
|
||||
|
||||
def pretty_name(name):
|
||||
"Converts 'first_name' to 'First name'"
|
||||
name = name[0].upper() + name[1:]
|
||||
return name.replace('_', ' ')
|
||||
|
||||
class DeclarativeFieldsMetaclass(type):
|
||||
"Metaclass that converts Field attributes to a dictionary called 'fields'."
|
||||
def __new__(cls, name, bases, attrs):
|
||||
attrs['fields'] = dict([(name, attrs.pop(name)) for name, obj in attrs.items() if isinstance(obj, Field)])
|
||||
return type.__new__(cls, name, bases, attrs)
|
||||
|
||||
class Form(object):
|
||||
"A collection of Fields, plus their associated data."
|
||||
__metaclass__ = DeclarativeFieldsMetaclass
|
||||
|
||||
def __init__(self, data=None): # TODO: prefix stuff
|
||||
self.data = data or {}
|
||||
self.clean_data = None # Stores the data after clean() has been called.
|
||||
self.__errors = None # Stores the errors after clean() has been called.
|
||||
|
||||
def __str__(self):
|
||||
return self.as_table()
|
||||
|
||||
def __iter__(self):
|
||||
for name, field in self.fields.items():
|
||||
yield BoundField(self, field, name)
|
||||
|
||||
def __getitem__(self, name):
|
||||
"Returns a BoundField with the given name."
|
||||
try:
|
||||
field = self.fields[name]
|
||||
except KeyError:
|
||||
raise KeyError('Key %r not found in Form' % name)
|
||||
return BoundField(self, field, name)
|
||||
|
||||
def clean(self):
|
||||
if self.__errors is None:
|
||||
self.full_clean()
|
||||
return self.clean_data
|
||||
|
||||
def errors(self):
|
||||
"Returns an ErrorDict for self.data"
|
||||
if self.__errors is None:
|
||||
self.full_clean()
|
||||
return self.__errors
|
||||
|
||||
def is_valid(self):
|
||||
"""
|
||||
Returns True if the form has no errors. Otherwise, False. This exists
|
||||
solely for convenience, so client code can use positive logic rather
|
||||
than confusing negative logic ("if not form.errors()").
|
||||
"""
|
||||
return not bool(self.errors())
|
||||
|
||||
def as_table(self):
|
||||
"Returns this form rendered as an HTML <table>."
|
||||
output = u'\n'.join(['<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()])
|
||||
return '<table>\n%s\n</table>' % output
|
||||
|
||||
def as_ul(self):
|
||||
"Returns this form rendered as an HTML <ul>."
|
||||
output = u'\n'.join(['<li>%s: %s</li>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()])
|
||||
return '<ul>\n%s\n</ul>' % output
|
||||
|
||||
def as_table_with_errors(self):
|
||||
"Returns this form rendered as an HTML <table>, with errors."
|
||||
output = []
|
||||
if self.errors().get(NON_FIELD_ERRORS):
|
||||
# Errors not corresponding to a particular field are displayed at the top.
|
||||
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
|
||||
for name, field in self.fields.items():
|
||||
bf = BoundField(self, field, name)
|
||||
if bf.errors:
|
||||
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors]))
|
||||
output.append('<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), bf))
|
||||
return '<table>\n%s\n</table>' % '\n'.join(output)
|
||||
|
||||
def as_ul_with_errors(self):
|
||||
"Returns this form rendered as an HTML <ul>, with errors."
|
||||
output = []
|
||||
if self.errors().get(NON_FIELD_ERRORS):
|
||||
# Errors not corresponding to a particular field are displayed at the top.
|
||||
output.append('<li><ul>%s</ul></li>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
|
||||
for name, field in self.fields.items():
|
||||
bf = BoundField(self, field, name)
|
||||
line = '<li>'
|
||||
if bf.errors:
|
||||
line += '<ul>%s</ul>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors])
|
||||
line += '%s: %s</li>' % (pretty_name(name), bf)
|
||||
output.append(line)
|
||||
return '<ul>\n%s\n</ul>' % '\n'.join(output)
|
||||
|
||||
def full_clean(self):
|
||||
"""
|
||||
Cleans all of self.data and populates self.__errors and self.clean_data.
|
||||
"""
|
||||
self.clean_data = {}
|
||||
errors = ErrorDict()
|
||||
for name, field in self.fields.items():
|
||||
value = self.data.get(name, None)
|
||||
try:
|
||||
value = field.clean(value)
|
||||
self.clean_data[name] = value
|
||||
if hasattr(self, 'clean_%s' % name):
|
||||
value = getattr(self, 'clean_%s' % name)()
|
||||
self.clean_data[name] = value
|
||||
except ValidationError, e:
|
||||
errors[name] = e.messages
|
||||
try:
|
||||
self.clean_data = self.clean()
|
||||
except ValidationError, e:
|
||||
errors[NON_FIELD_ERRORS] = e.messages
|
||||
if errors:
|
||||
self.clean_data = None
|
||||
self.__errors = errors
|
||||
|
||||
def clean(self):
|
||||
"""
|
||||
Hook for doing any extra form-wide cleaning after Field.clean() been
|
||||
called on every field.
|
||||
"""
|
||||
return self.clean_data
|
||||
|
||||
class BoundField(object):
|
||||
"A Field plus data"
|
||||
def __init__(self, form, field, name):
|
||||
self._form = form
|
||||
self._field = field
|
||||
self._name = name
|
||||
|
||||
def __str__(self):
|
||||
"Renders this field as an HTML widget."
|
||||
# Use the 'widget' attribute on the field to determine which type
|
||||
# of HTML widget to use.
|
||||
return self.as_widget(self._field.widget)
|
||||
|
||||
def _errors(self):
|
||||
"""
|
||||
Returns an ErrorList for this field. Returns an empty ErrorList
|
||||
if there are none.
|
||||
"""
|
||||
try:
|
||||
return self._form.errors()[self._name]
|
||||
except KeyError:
|
||||
return ErrorList()
|
||||
errors = property(_errors)
|
||||
|
||||
def as_widget(self, widget, attrs=None):
|
||||
return widget.render(self._name, self._form.data.get(self._name, None), attrs=attrs)
|
||||
|
||||
def as_text(self, attrs=None):
|
||||
"""
|
||||
Returns a string of HTML for representing this as an <input type="text">.
|
||||
"""
|
||||
return self.as_widget(TextInput(), attrs)
|
||||
|
||||
def as_textarea(self, attrs=None):
|
||||
"Returns a string of HTML for representing this as a <textarea>."
|
||||
return self.as_widget(Textarea(), attrs)
|
55
django/newforms/util.py
Normal file
55
django/newforms/util.py
Normal file
@ -0,0 +1,55 @@
|
||||
# Default encoding for input byte strings.
|
||||
DEFAULT_ENCODING = 'utf-8' # TODO: First look at django.conf.settings, then fall back to this.
|
||||
|
||||
def smart_unicode(s):
|
||||
if not isinstance(s, unicode):
|
||||
s = unicode(s, DEFAULT_ENCODING)
|
||||
return s
|
||||
|
||||
class ErrorDict(dict):
|
||||
"""
|
||||
A collection of errors that knows how to display itself in various formats.
|
||||
|
||||
The dictionary keys are the field names, and the values are the errors.
|
||||
"""
|
||||
def __str__(self):
|
||||
return self.as_ul()
|
||||
|
||||
def as_ul(self):
|
||||
if not self: return u''
|
||||
return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s%s</li>' % (k, v) for k, v in self.items()])
|
||||
|
||||
def as_text(self):
|
||||
return u'\n'.join([u'* %s\n%s' % (k, u'\n'.join([u' * %s' % i for i in v])) for k, v in self.items()])
|
||||
|
||||
class ErrorList(list):
|
||||
"""
|
||||
A collection of errors that knows how to display itself in various formats.
|
||||
"""
|
||||
def __str__(self):
|
||||
return self.as_ul()
|
||||
|
||||
def as_ul(self):
|
||||
if not self: return u''
|
||||
return u'<ul class="errorlist">%s</ul>' % ''.join([u'<li>%s</li>' % e for e in self])
|
||||
|
||||
def as_text(self):
|
||||
if not self: return u''
|
||||
return u'\n'.join([u'* %s' % e for e in self])
|
||||
|
||||
class ValidationError(Exception):
|
||||
def __init__(self, message):
|
||||
"ValidationError can be passed a string or a list."
|
||||
if isinstance(message, list):
|
||||
self.messages = ErrorList([smart_unicode(msg) for msg in message])
|
||||
else:
|
||||
assert isinstance(message, basestring), ("%s should be a basestring" % repr(message))
|
||||
message = smart_unicode(message)
|
||||
self.messages = ErrorList([message])
|
||||
|
||||
def __str__(self):
|
||||
# This is needed because, without a __str__(), printing an exception
|
||||
# instance would result in this:
|
||||
# AttributeError: ValidationError instance has no attribute 'args'
|
||||
# See http://www.python.org/doc/current/tut/node10.html#handling
|
||||
return repr(self.messages)
|
113
django/newforms/widgets.py
Normal file
113
django/newforms/widgets.py
Normal file
@ -0,0 +1,113 @@
|
||||
"""
|
||||
HTML Widget classes
|
||||
"""
|
||||
|
||||
__all__ = (
|
||||
'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'FileInput',
|
||||
'Textarea', 'CheckboxInput',
|
||||
'Select', 'SelectMultiple',
|
||||
)
|
||||
|
||||
from django.utils.html import escape
|
||||
from itertools import chain
|
||||
|
||||
try:
|
||||
set # Only available in Python 2.4+
|
||||
except NameError:
|
||||
from sets import Set as set # Python 2.3 fallback
|
||||
|
||||
# Converts a dictionary to a single string with key="value", XML-style.
|
||||
# Assumes keys do not need to be XML-escaped.
|
||||
flatatt = lambda attrs: ' '.join(['%s="%s"' % (k, escape(v)) for k, v in attrs.items()])
|
||||
|
||||
class Widget(object):
|
||||
requires_data_list = False # Determines whether render()'s 'value' argument should be a list.
|
||||
def __init__(self, attrs=None):
|
||||
self.attrs = attrs or {}
|
||||
|
||||
def render(self, name, value):
|
||||
raise NotImplementedError
|
||||
|
||||
class Input(Widget):
|
||||
"Base class for all <input> widgets (except type='checkbox', which is special)"
|
||||
input_type = None # Subclasses must define this.
|
||||
def render(self, name, value, attrs=None):
|
||||
if value is None: value = ''
|
||||
final_attrs = dict(self.attrs, type=self.input_type, name=name)
|
||||
if attrs:
|
||||
final_attrs.update(attrs)
|
||||
if value != '': final_attrs['value'] = value # Only add the 'value' attribute if a value is non-empty.
|
||||
return u'<input %s />' % flatatt(final_attrs)
|
||||
|
||||
class TextInput(Input):
|
||||
input_type = 'text'
|
||||
|
||||
class PasswordInput(Input):
|
||||
input_type = 'password'
|
||||
|
||||
class HiddenInput(Input):
|
||||
input_type = 'hidden'
|
||||
|
||||
class FileInput(Input):
|
||||
input_type = 'file'
|
||||
|
||||
class Textarea(Widget):
|
||||
def render(self, name, value, attrs=None):
|
||||
if value is None: value = ''
|
||||
final_attrs = dict(self.attrs, name=name)
|
||||
if attrs:
|
||||
final_attrs.update(attrs)
|
||||
return u'<textarea %s>%s</textarea>' % (flatatt(final_attrs), escape(value))
|
||||
|
||||
class CheckboxInput(Widget):
|
||||
def render(self, name, value, attrs=None):
|
||||
final_attrs = dict(self.attrs, type='checkbox', name=name)
|
||||
if attrs:
|
||||
final_attrs.update(attrs)
|
||||
if value: final_attrs['checked'] = 'checked'
|
||||
return u'<input %s />' % flatatt(final_attrs)
|
||||
|
||||
class Select(Widget):
|
||||
def __init__(self, attrs=None, choices=()):
|
||||
# choices can be any iterable
|
||||
self.attrs = attrs or {}
|
||||
self.choices = choices
|
||||
|
||||
def render(self, name, value, attrs=None, choices=()):
|
||||
if value is None: value = ''
|
||||
final_attrs = dict(self.attrs, name=name)
|
||||
if attrs:
|
||||
final_attrs.update(attrs)
|
||||
output = [u'<select %s>' % flatatt(final_attrs)]
|
||||
str_value = str(value) # Normalize to string.
|
||||
for option_value, option_label in chain(self.choices, choices):
|
||||
selected_html = (str(option_value) == str_value) and ' selected="selected"' or ''
|
||||
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(option_label)))
|
||||
output.append(u'</select>')
|
||||
return u'\n'.join(output)
|
||||
|
||||
class SelectMultiple(Widget):
|
||||
requires_data_list = True
|
||||
def __init__(self, attrs=None, choices=()):
|
||||
# choices can be any iterable
|
||||
self.attrs = attrs or {}
|
||||
self.choices = choices
|
||||
|
||||
def render(self, name, value, attrs=None, choices=()):
|
||||
if value is None: value = []
|
||||
final_attrs = dict(self.attrs, name=name)
|
||||
if attrs:
|
||||
final_attrs.update(attrs)
|
||||
output = [u'<select multiple="multiple" %s>' % flatatt(final_attrs)]
|
||||
str_values = set([str(v) for v in value]) # Normalize to strings.
|
||||
for option_value, option_label in chain(self.choices, choices):
|
||||
selected_html = (str(option_value) in str_values) and ' selected="selected"' or ''
|
||||
output.append(u'<option value="%s"%s>%s</option>' % (escape(option_value), selected_html, escape(option_label)))
|
||||
output.append(u'</select>')
|
||||
return u'\n'.join(output)
|
||||
|
||||
class RadioSelect(Widget):
|
||||
pass
|
||||
|
||||
class CheckboxSelectMultiple(Widget):
|
||||
pass
|
@ -66,6 +66,7 @@ __all__ = ('Template', 'Context', 'RequestContext', 'compile_string')
|
||||
TOKEN_TEXT = 0
|
||||
TOKEN_VAR = 1
|
||||
TOKEN_BLOCK = 2
|
||||
TOKEN_COMMENT = 3
|
||||
|
||||
# template syntax constants
|
||||
FILTER_SEPARATOR = '|'
|
||||
@ -75,6 +76,8 @@ BLOCK_TAG_START = '{%'
|
||||
BLOCK_TAG_END = '%}'
|
||||
VARIABLE_TAG_START = '{{'
|
||||
VARIABLE_TAG_END = '}}'
|
||||
COMMENT_TAG_START = '{#'
|
||||
COMMENT_TAG_END = '#}'
|
||||
SINGLE_BRACE_START = '{'
|
||||
SINGLE_BRACE_END = '}'
|
||||
|
||||
@ -85,8 +88,9 @@ ALLOWED_VARIABLE_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01
|
||||
UNKNOWN_SOURCE="<unknown source>"
|
||||
|
||||
# match a variable or block tag and capture the entire tag, including start/end delimiters
|
||||
tag_re = re.compile('(%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
|
||||
re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END)))
|
||||
tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
|
||||
re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
|
||||
re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END)))
|
||||
|
||||
# global dictionary of libraries that have been loaded using get_library
|
||||
libraries = {}
|
||||
@ -163,12 +167,12 @@ def compile_string(template_string, origin):
|
||||
|
||||
class Token(object):
|
||||
def __init__(self, token_type, contents):
|
||||
"The token_type must be TOKEN_TEXT, TOKEN_VAR or TOKEN_BLOCK"
|
||||
"The token_type must be TOKEN_TEXT, TOKEN_VAR, TOKEN_BLOCK or TOKEN_COMMENT"
|
||||
self.token_type, self.contents = token_type, contents
|
||||
|
||||
def __str__(self):
|
||||
return '<%s token: "%s...">' % \
|
||||
({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block'}[self.token_type],
|
||||
({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block', TOKEN_COMMENT: 'Comment'}[self.token_type],
|
||||
self.contents[:20].replace('\n', ''))
|
||||
|
||||
def split_contents(self):
|
||||
@ -191,6 +195,8 @@ class Lexer(object):
|
||||
token = Token(TOKEN_VAR, token_string[len(VARIABLE_TAG_START):-len(VARIABLE_TAG_END)].strip())
|
||||
elif token_string.startswith(BLOCK_TAG_START):
|
||||
token = Token(TOKEN_BLOCK, token_string[len(BLOCK_TAG_START):-len(BLOCK_TAG_END)].strip())
|
||||
elif token_string.startswith(COMMENT_TAG_START):
|
||||
token = Token(TOKEN_COMMENT, '')
|
||||
else:
|
||||
token = Token(TOKEN_TEXT, token_string)
|
||||
return token
|
||||
@ -862,8 +868,11 @@ class Library(object):
|
||||
dict = func(*args)
|
||||
|
||||
if not getattr(self, 'nodelist', False):
|
||||
from django.template.loader import get_template
|
||||
t = get_template(file_name)
|
||||
from django.template.loader import get_template, select_template
|
||||
if hasattr(file_name, '__iter__'):
|
||||
t = select_template(file_name)
|
||||
else:
|
||||
t = get_template(file_name)
|
||||
self.nodelist = t.nodelist
|
||||
return self.nodelist.render(context_class(dict))
|
||||
|
||||
@ -877,7 +886,7 @@ def get_library(module_name):
|
||||
lib = libraries.get(module_name, None)
|
||||
if not lib:
|
||||
try:
|
||||
mod = __import__(module_name, '', '', [''])
|
||||
mod = __import__(module_name, {}, {}, [''])
|
||||
except ImportError, e:
|
||||
raise InvalidTemplateLibrary, "Could not load template library from %s, %s" % (module_name, e)
|
||||
try:
|
||||
|
@ -69,7 +69,7 @@ def get_standard_processors():
|
||||
i = path.rfind('.')
|
||||
module, attr = path[:i], path[i+1:]
|
||||
try:
|
||||
mod = __import__(module, '', '', [attr])
|
||||
mod = __import__(module, {}, {}, [attr])
|
||||
except ImportError, e:
|
||||
raise ImproperlyConfigured, 'Error importing request processor module %s: "%s"' % (module, e)
|
||||
try:
|
||||
|
@ -421,7 +421,11 @@ def filesizeformat(bytes):
|
||||
Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, 102
|
||||
bytes, etc).
|
||||
"""
|
||||
bytes = float(bytes)
|
||||
try:
|
||||
bytes = float(bytes)
|
||||
except TypeError:
|
||||
return "0 bytes"
|
||||
|
||||
if bytes < 1024:
|
||||
return "%d byte%s" % (bytes, bytes != 1 and 's' or '')
|
||||
if bytes < 1024 * 1024:
|
||||
|
@ -1,7 +1,7 @@
|
||||
"Default tags used by the template system, available to all templates."
|
||||
|
||||
from django.template import Node, NodeList, Template, Context, resolve_variable
|
||||
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END
|
||||
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END
|
||||
from django.template import get_library, Library, InvalidTemplateLibrary
|
||||
from django.conf import settings
|
||||
import sys
|
||||
@ -124,17 +124,27 @@ class ForNode(Node):
|
||||
return nodelist.render(context)
|
||||
|
||||
class IfChangedNode(Node):
|
||||
def __init__(self, nodelist):
|
||||
def __init__(self, nodelist, *varlist):
|
||||
self.nodelist = nodelist
|
||||
self._last_seen = None
|
||||
self._varlist = varlist
|
||||
|
||||
def render(self, context):
|
||||
if context.has_key('forloop') and context['forloop']['first']:
|
||||
self._last_seen = None
|
||||
content = self.nodelist.render(context)
|
||||
if content != self._last_seen:
|
||||
try:
|
||||
if self._varlist:
|
||||
# Consider multiple parameters.
|
||||
# This automatically behaves like a OR evaluation of the multiple variables.
|
||||
compare_to = [resolve_variable(var, context) for var in self._varlist]
|
||||
else:
|
||||
compare_to = self.nodelist.render(context)
|
||||
except VariableDoesNotExist:
|
||||
compare_to = None
|
||||
|
||||
if compare_to != self._last_seen:
|
||||
firstloop = (self._last_seen == None)
|
||||
self._last_seen = content
|
||||
self._last_seen = compare_to
|
||||
context.push()
|
||||
context['ifchanged'] = {'firstloop': firstloop}
|
||||
content = self.nodelist.render(context)
|
||||
@ -295,6 +305,8 @@ class TemplateTagNode(Node):
|
||||
'closevariable': VARIABLE_TAG_END,
|
||||
'openbrace': SINGLE_BRACE_START,
|
||||
'closebrace': SINGLE_BRACE_END,
|
||||
'opencomment': COMMENT_TAG_START,
|
||||
'closecomment': COMMENT_TAG_END,
|
||||
}
|
||||
|
||||
def __init__(self, tagtype):
|
||||
@ -632,23 +644,34 @@ def ifchanged(parser, token):
|
||||
"""
|
||||
Check if a value has changed from the last iteration of a loop.
|
||||
|
||||
The 'ifchanged' block tag is used within a loop. It checks its own rendered
|
||||
contents against its previous state and only displays its content if the
|
||||
value has changed::
|
||||
The 'ifchanged' block tag is used within a loop. It has two possible uses.
|
||||
|
||||
<h1>Archive for {{ year }}</h1>
|
||||
1. Checks its own rendered contents against its previous state and only
|
||||
displays the content if it has changed. For example, this displays a list of
|
||||
days, only displaying the month if it changes::
|
||||
|
||||
{% for date in days %}
|
||||
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
|
||||
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
|
||||
{% endfor %}
|
||||
<h1>Archive for {{ year }}</h1>
|
||||
|
||||
{% for date in days %}
|
||||
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
|
||||
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
|
||||
{% endfor %}
|
||||
|
||||
2. If given a variable, check whether that variable has changed. For example, the
|
||||
following shows the date every time it changes, but only shows the hour if both
|
||||
the hour and the date have changed::
|
||||
|
||||
{% for date in days %}
|
||||
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
|
||||
{% ifchanged date.hour date.date %}
|
||||
{{ date.hour }}
|
||||
{% endifchanged %}
|
||||
{% endfor %}
|
||||
"""
|
||||
bits = token.contents.split()
|
||||
if len(bits) != 1:
|
||||
raise TemplateSyntaxError, "'ifchanged' tag takes no arguments"
|
||||
nodelist = parser.parse(('endifchanged',))
|
||||
parser.delete_first_token()
|
||||
return IfChangedNode(nodelist)
|
||||
return IfChangedNode(nodelist, *bits[1:])
|
||||
ifchanged = register.tag(ifchanged)
|
||||
|
||||
#@register.tag
|
||||
@ -831,6 +854,8 @@ def templatetag(parser, token):
|
||||
``closevariable`` ``}}``
|
||||
``openbrace`` ``{``
|
||||
``closebrace`` ``}``
|
||||
``opencomment`` ``{#``
|
||||
``closecomment`` ``#}``
|
||||
================== =======
|
||||
"""
|
||||
bits = token.contents.split()
|
||||
|
@ -15,9 +15,9 @@ for app in settings.INSTALLED_APPS:
|
||||
m, a = app[:i], app[i+1:]
|
||||
try:
|
||||
if a is None:
|
||||
mod = __import__(m, '', '', [])
|
||||
mod = __import__(m, {}, {}, [])
|
||||
else:
|
||||
mod = getattr(__import__(m, '', '', [a]), a)
|
||||
mod = getattr(__import__(m, {}, {}, [a]), a)
|
||||
except ImportError, e:
|
||||
raise ImproperlyConfigured, 'ImportError %s: %s' % (app, e.args[0])
|
||||
template_dir = os.path.join(os.path.dirname(mod.__file__), 'templates')
|
||||
|
@ -2,6 +2,6 @@ from django.conf import settings
|
||||
|
||||
for a in settings.INSTALLED_APPS:
|
||||
try:
|
||||
__path__.extend(__import__(a + '.templatetags', '', '', ['']).__path__)
|
||||
__path__.extend(__import__(a + '.templatetags', {}, {}, ['']).__path__)
|
||||
except ImportError:
|
||||
pass
|
||||
|
@ -28,7 +28,7 @@ def build_suite(app_module):
|
||||
# models module
|
||||
try:
|
||||
app_path = app_module.__name__.split('.')[:-1]
|
||||
test_module = __import__('.'.join(app_path + [TEST_MODULE]), [], [], TEST_MODULE)
|
||||
test_module = __import__('.'.join(app_path + [TEST_MODULE]), {}, {}, TEST_MODULE)
|
||||
|
||||
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_module))
|
||||
try:
|
||||
|
@ -75,7 +75,7 @@ def technical_500_response(request, exc_type, exc_value, tb):
|
||||
loader_debug_info = []
|
||||
for loader in template_source_loaders:
|
||||
try:
|
||||
source_list_func = getattr(__import__(loader.__module__, '', '', ['get_template_sources']), 'get_template_sources')
|
||||
source_list_func = getattr(__import__(loader.__module__, {}, {}, ['get_template_sources']), 'get_template_sources')
|
||||
# NOTE: This assumes exc_value is the name of the template that
|
||||
# the loader attempted to load.
|
||||
template_list = [{'name': t, 'exists': os.path.exists(t)} \
|
||||
|
@ -2,12 +2,18 @@ from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.http import HttpResponse, HttpResponsePermanentRedirect, HttpResponseGone
|
||||
|
||||
def direct_to_template(request, template, **kwargs):
|
||||
def direct_to_template(request, template, extra_context={}, **kwargs):
|
||||
"""
|
||||
Render a given template with any extra URL parameters in the context as
|
||||
``{{ params }}``.
|
||||
"""
|
||||
return render_to_response(template, {'params' : kwargs}, context_instance=RequestContext(request))
|
||||
dictionary = {'params': kwargs}
|
||||
for key, value in extra_context.items():
|
||||
if callable(value):
|
||||
dictionary[key] = value()
|
||||
else:
|
||||
dictionary[key] = value
|
||||
return render_to_response(template, dictionary, context_instance=RequestContext(request))
|
||||
|
||||
def redirect_to(request, url, **kwargs):
|
||||
"""
|
||||
@ -18,7 +24,7 @@ def redirect_to(request, url, **kwargs):
|
||||
``/foo/<id>/`` to ``/bar/<id>/``, you could use the following URLconf::
|
||||
|
||||
urlpatterns = patterns('',
|
||||
('^foo/(?p<id>\d+)/$', 'django.views.generic.simple.redirect_to', {'url' : '/bar/%(id)s/'}),
|
||||
('^foo/(?P<id>\d+)/$', 'django.views.generic.simple.redirect_to', {'url' : '/bar/%(id)s/'}),
|
||||
)
|
||||
|
||||
If the given url is ``None``, a HttpResponseGone (410) will be issued.
|
||||
|
@ -745,7 +745,7 @@ messages are made available in the `template context`_ as the template variable
|
||||
{% if messages %}
|
||||
<ul>
|
||||
{% for message in messages %}
|
||||
<li>{{ message.message }}</li>
|
||||
<li>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
@ -610,6 +610,15 @@ fails. If no message is passed in, a default message is used.
|
||||
string "123" is less than the string "2", for example. If you don't want
|
||||
string comparison here, you will need to write your own validator.
|
||||
|
||||
``NumberIsInRange``
|
||||
Takes two boundary numbers, ``lower`` and ``upper``, and checks that the
|
||||
field is greater than ``lower`` (if given) and less than ``upper`` (if
|
||||
given).
|
||||
|
||||
Both checks are inclusive. That is, ``NumberIsInRange(10, 20)`` will allow
|
||||
values of both 10 and 20. This validator only checks numeric values
|
||||
(e.g., float and integer values).
|
||||
|
||||
``IsAPowerOf``
|
||||
Takes an integer argument and when called as a validator, checks that the
|
||||
field being validated is a power of the integer.
|
||||
|
@ -92,6 +92,14 @@ which is a dictionary of the parameters captured in the URL.
|
||||
|
||||
* ``template``: The full name of a template to use.
|
||||
|
||||
**Optional arguments:**
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template
|
||||
context. By default, this is an empty dictionary. If a value in the
|
||||
dictionary is callable, the generic view will call it
|
||||
just before rendering the template. (**This is new in the
|
||||
Django development version.**)
|
||||
|
||||
**Example:**
|
||||
|
||||
Given the following URL patterns::
|
||||
@ -171,7 +179,7 @@ a date in the *future* are not included unless you set ``allow_future`` to
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template
|
||||
context. By default, this is an empty dictionary.
|
||||
context. By default, this is an empty dictionary. If a value in the
|
||||
dictionary is callable, the generic view will call it
|
||||
just before rendering the template.
|
||||
|
||||
|
@ -43,6 +43,11 @@ This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
|
||||
Django mod_python handler." It passes the value of ``DJANGO_SETTINGS_MODULE``
|
||||
so mod_python knows which settings to use.
|
||||
|
||||
Note that we're using the ``<Location>`` directive, not the ``<Directory>``
|
||||
directive. The latter is used for pointing at places on your filesystem,
|
||||
whereas ``<Location>`` points at places in the URL structure of a Web site.
|
||||
``<Directory>`` would be meaningless here.
|
||||
|
||||
Also, if you've manually altered your ``PYTHONPATH`` to put your Django project
|
||||
on it, you'll need to tell mod_python::
|
||||
|
||||
|
@ -265,6 +265,14 @@ Default: ``''`` (Empty string)
|
||||
The name of the database to use. For SQLite, it's the full path to the database
|
||||
file.
|
||||
|
||||
DATABASE_OPTIONS
|
||||
----------------
|
||||
|
||||
Default: ``{}`` (Empty dictionary)
|
||||
|
||||
Extra parameters to use when connecting to the database. Consult backend
|
||||
module's document for available keywords.
|
||||
|
||||
DATABASE_PASSWORD
|
||||
-----------------
|
||||
|
||||
@ -528,7 +536,7 @@ any code that uses ``LANGUAGES`` at runtime.
|
||||
MANAGERS
|
||||
--------
|
||||
|
||||
Default: ``ADMINS`` (Whatever ``ADMINS`` is set to)
|
||||
Default: ``()`` (Empty tuple)
|
||||
|
||||
A tuple in the same format as ``ADMINS`` that specifies who should get
|
||||
broken-link notifications when ``SEND_BROKEN_LINK_EMAILS=True``.
|
||||
@ -814,6 +822,16 @@ manual configuration option (see below), Django will *not* touch the ``TZ``
|
||||
environment variable, and it'll be up to you to ensure your processes are
|
||||
running in the correct environment.
|
||||
|
||||
URL_VALIDATOR_USER_AGENT
|
||||
------------------------
|
||||
|
||||
Default: ``Django/<version> (http://www.djangoproject.com/)``
|
||||
|
||||
The string to use as the ``User-Agent`` header when checking to see if URLs
|
||||
exist (see the ``verify_exists`` option on URLField_).
|
||||
|
||||
.. URLField: ../model_api/#urlfield
|
||||
|
||||
USE_ETAGS
|
||||
---------
|
||||
|
||||
|
@ -31,7 +31,7 @@ How to do it
|
||||
|
||||
Just put this in your URLconf_::
|
||||
|
||||
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
|
||||
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media'}),
|
||||
|
||||
...where ``site_media`` is the URL where your media will be rooted, and
|
||||
``/path/to/media`` is the filesystem root for your media.
|
||||
@ -60,7 +60,7 @@ listings for directories.
|
||||
|
||||
Example::
|
||||
|
||||
(r'^site_media/(.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
|
||||
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': '/path/to/media', 'show_indexes': True}),
|
||||
|
||||
You can customize the index view by creating a template called
|
||||
``static/directory_index``. That template gets two objects in its context:
|
||||
|
@ -95,7 +95,7 @@ latest five news items::
|
||||
from django.contrib.syndication.feeds import Feed
|
||||
from chicagocrime.models import NewsItem
|
||||
|
||||
class SiteNewsFeed(Feed):
|
||||
class LatestEntries(Feed):
|
||||
title = "Chicagocrime.org site news"
|
||||
link = "/sitenews/"
|
||||
description = "Updates on changes and additions to chicagocrime.org."
|
||||
@ -120,14 +120,14 @@ One thing's left to do. In an RSS feed, each ``<item>`` has a ``<title>``,
|
||||
put into those elements.
|
||||
|
||||
* To specify the contents of ``<title>`` and ``<description>``, create
|
||||
`Django templates`_ called ``feeds/sitenews_title.html`` and
|
||||
``feeds/sitenews_description.html``, where ``sitenews`` is the ``slug``
|
||||
`Django templates`_ called ``feeds/latest_title.html`` and
|
||||
``feeds/latest_description.html``, where ``latest`` is the ``slug``
|
||||
specified in the URLconf for the given feed. Note the ``.html`` extension
|
||||
is required. The RSS system renders that template for each item, passing
|
||||
it two template context variables:
|
||||
|
||||
* ``{{ obj }}`` -- The current object (one of whichever objects you
|
||||
returned in ``items()``).
|
||||
returned in ``items()``).
|
||||
* ``{{ site }}`` -- A ``django.models.core.sites.Site`` object
|
||||
representing the current site. This is useful for
|
||||
``{{ site.domain }}`` or ``{{ site.name }}``.
|
||||
@ -145,6 +145,16 @@ put into those elements.
|
||||
Both ``get_absolute_url()`` and ``item_link()`` should return the item's
|
||||
URL as a normal Python string.
|
||||
|
||||
* For the LatestEntries example above, we could have very simple feed templates:
|
||||
|
||||
* latest_title.html::
|
||||
|
||||
{{ obj.title }}
|
||||
|
||||
* latest_description.html::
|
||||
|
||||
{{ obj.description }}
|
||||
|
||||
.. _chicagocrime.org: http://www.chicagocrime.org/
|
||||
.. _object-relational mapper: http://www.djangoproject.com/documentation/db_api/
|
||||
.. _Django templates: http://www.djangoproject.com/documentation/templates/
|
||||
|
@ -109,6 +109,21 @@ Some tags require beginning and ending tags (i.e.
|
||||
below describes all the built-in tags. You can create your own tags, if you
|
||||
know how to write Python code.
|
||||
|
||||
Comments
|
||||
========
|
||||
|
||||
**New in Django development version**
|
||||
|
||||
To comment-out part of a template, use the comment syntax: ``{# #}``.
|
||||
|
||||
For example, this template would render as ``'hello'``::
|
||||
|
||||
{# greeting #}hello
|
||||
|
||||
A comment can contain any template code, invalid or not. For example::
|
||||
|
||||
{# {% if foo %}bar{% else %} #}
|
||||
|
||||
Template inheritance
|
||||
====================
|
||||
|
||||
@ -458,7 +473,7 @@ block are output::
|
||||
In the above, if ``athlete_list`` is not empty, the number of athletes will be
|
||||
displayed by the ``{{ athlete_list|length }}`` variable.
|
||||
|
||||
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
|
||||
As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that
|
||||
will be displayed if the test fails.
|
||||
|
||||
``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or
|
||||
@ -510,16 +525,29 @@ ifchanged
|
||||
|
||||
Check if a value has changed from the last iteration of a loop.
|
||||
|
||||
The ``ifchanged`` block tag is used within a loop. It checks its own rendered
|
||||
contents against its previous state and only displays its content if the value
|
||||
has changed::
|
||||
The 'ifchanged' block tag is used within a loop. It has two possible uses.
|
||||
|
||||
<h1>Archive for {{ year }}</h1>
|
||||
1. Checks its own rendered contents against its previous state and only
|
||||
displays the content if it has changed. For example, this displays a list of
|
||||
days, only displaying the month if it changes::
|
||||
|
||||
{% for day in days %}
|
||||
{% ifchanged %}<h3>{{ day|date:"F" }}</h3>{% endifchanged %}
|
||||
<a href="{{ day|date:"M/d"|lower }}/">{{ day|date:"j" }}</a>
|
||||
{% endfor %}
|
||||
<h1>Archive for {{ year }}</h1>
|
||||
|
||||
{% for date in days %}
|
||||
{% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %}
|
||||
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
|
||||
{% endfor %}
|
||||
|
||||
2. **New in Django development version.** If given a variable, check whether that
|
||||
variable has changed. For example, the following shows the date every time it
|
||||
changes, but only shows the hour if both the hour and the date has changed::
|
||||
|
||||
{% for date in days %}
|
||||
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
|
||||
{% ifchanged date.hour date.date %}
|
||||
{{ date.hour }}
|
||||
{% endifchanged %}
|
||||
{% endfor %}
|
||||
|
||||
ifequal
|
||||
~~~~~~~
|
||||
@ -785,8 +813,12 @@ The argument tells which template bit to output:
|
||||
``closevariable`` ``}}``
|
||||
``openbrace`` ``{``
|
||||
``closebrace`` ``}``
|
||||
``opencomment`` ``{#``
|
||||
``closecomment`` ``#}``
|
||||
================== =======
|
||||
|
||||
Note: ``opencomment`` and ``closecomment`` are new in the Django development version.
|
||||
|
||||
widthratio
|
||||
~~~~~~~~~~
|
||||
|
||||
|
@ -312,18 +312,18 @@ optional, third positional argument, ``processors``. In this example, the
|
||||
}, [ip_address_processor])
|
||||
|
||||
Note::
|
||||
If you are using Django's ``render_to_response()`` shortcut to populate a
|
||||
If you're using Django's ``render_to_response()`` shortcut to populate a
|
||||
template with the contents of a dictionary, your template will be passed a
|
||||
``Context`` instance by default (not a ``RequestContext``). If you wish to
|
||||
use a ``RequestContext`` in your template rendering, you need to pass an
|
||||
optional third argument to ``render_to_response()``: a ``RequestContext``
|
||||
``Context`` instance by default (not a ``RequestContext``). To use a
|
||||
``RequestContext`` in your template rendering, pass an optional third
|
||||
argument to ``render_to_response()``: a ``RequestContext``
|
||||
instance. Your code might look like this::
|
||||
|
||||
def some_view(request):
|
||||
# ...
|
||||
return render_to_response('my_template'html',
|
||||
my_data_dictionary,
|
||||
context_instance = RequestContext(request))
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
Here's what each of the default processors does:
|
||||
|
||||
@ -1092,7 +1092,7 @@ Configuring the template system in standalone mode
|
||||
.. note::
|
||||
|
||||
This section is only of interest to people trying to use the template
|
||||
system as an output component in another application. If you are using the
|
||||
system as an output component in another application. If you're using the
|
||||
template system as part of a Django application, nothing here applies to
|
||||
you.
|
||||
|
||||
@ -1109,7 +1109,7 @@ described in the `settings file`_ documentation. Simply import the appropriate
|
||||
pieces of the templating system and then, *before* you call any of the
|
||||
templating functions, call ``django.conf.settings.configure()`` with any
|
||||
settings you wish to specify. You might want to consider setting at least
|
||||
``TEMPLATE_DIRS`` (if you are going to use template loaders),
|
||||
``TEMPLATE_DIRS`` (if you're going to use template loaders),
|
||||
``DEFAULT_CHARSET`` (although the default of ``utf-8`` is probably fine) and
|
||||
``TEMPLATE_DEBUG``. All available settings are described in the
|
||||
`settings documentation`_, and any setting starting with *TEMPLATE_*
|
||||
|
@ -383,10 +383,10 @@ Django where our templates live::
|
||||
Now copy the template ``admin/base_site.html`` from within the default Django
|
||||
admin template directory (``django/contrib/admin/templates``) into an ``admin``
|
||||
subdirectory of whichever directory you're using in ``TEMPLATE_DIRS``. For
|
||||
example, if your ``TEMPLATE_DIRS`` includes ``"/home/mytemplates"``, as above,
|
||||
then copy ``django/contrib/admin/templates/admin/base_site.html`` to
|
||||
``/home/mytemplates/admin/base_site.html``. Don't forget that ``admin``
|
||||
subdirectory.
|
||||
example, if your ``TEMPLATE_DIRS`` includes ``"/home/my_username/mytemplates"``,
|
||||
as above, then copy ``django/contrib/admin/templates/admin/base_site.html`` to
|
||||
``/home/my_username/mytemplates/admin/base_site.html``. Don't forget that
|
||||
``admin`` subdirectory.
|
||||
|
||||
Then, just edit the file and replace the generic Django text with your own
|
||||
site's name and URL as you see fit.
|
||||
|
@ -192,13 +192,13 @@ objects" and "display a detail page for a particular type of object."
|
||||
``object_id`` for the generic views.
|
||||
|
||||
By default, the ``object_detail`` generic view uses a template called
|
||||
``<app name>/<module name>_detail.html``. In our case, it'll use the template
|
||||
``<app name>/<model name>_detail.html``. In our case, it'll use the template
|
||||
``"polls/poll_detail.html"``. Thus, rename your ``polls/detail.html`` template to
|
||||
``polls/poll_detail.html``, and change the ``render_to_response()`` line in
|
||||
``vote()``.
|
||||
|
||||
Similarly, the ``object_list`` generic view uses a template called
|
||||
``<app name>/<module name>_list.html``. Thus, rename ``polls/index.html`` to
|
||||
``<app name>/<model name>_list.html``. Thus, rename ``polls/index.html`` to
|
||||
``polls/poll_list.html``.
|
||||
|
||||
Because we have more than one entry in the URLconf that uses ``object_detail``
|
||||
|
@ -64,4 +64,17 @@ True
|
||||
>>> paginator.last_on_page(1)
|
||||
9
|
||||
|
||||
# Add a few more records to test out the orphans feature.
|
||||
>>> for x in range(10, 13):
|
||||
... Article(headline="Article %s" % x, pub_date=datetime(2006, 10, 6)).save()
|
||||
|
||||
# With orphans set to 3 and 10 items per page, we should get all 12 items on a single page:
|
||||
>>> paginator = ObjectPaginator(Article.objects.all(), 10, orphans=3)
|
||||
>>> paginator.pages
|
||||
1
|
||||
|
||||
# With orphans only set to 1, we should get two pages:
|
||||
>>> paginator = ObjectPaginator(Article.objects.all(), 10, orphans=1)
|
||||
>>> paginator.pages
|
||||
2
|
||||
"""}
|
||||
|
0
tests/regressiontests/forms/__init__.py
Normal file
0
tests/regressiontests/forms/__init__.py
Normal file
0
tests/regressiontests/forms/models.py
Normal file
0
tests/regressiontests/forms/models.py
Normal file
1037
tests/regressiontests/forms/tests.py
Normal file
1037
tests/regressiontests/forms/tests.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -173,6 +173,22 @@ class Templates(unittest.TestCase):
|
||||
# Empty strings can be passed as arguments to filters
|
||||
'basic-syntax36': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'),
|
||||
|
||||
### COMMENT SYNTAX ########################################################
|
||||
'comment-syntax01': ("{# this is hidden #}hello", {}, "hello"),
|
||||
'comment-syntax02': ("{# this is hidden #}hello{# foo #}", {}, "hello"),
|
||||
|
||||
# Comments can contain invalid stuff.
|
||||
'comment-syntax03': ("foo{# {% if %} #}", {}, "foo"),
|
||||
'comment-syntax04': ("foo{# {% endblock %} #}", {}, "foo"),
|
||||
'comment-syntax05': ("foo{# {% somerandomtag %} #}", {}, "foo"),
|
||||
'comment-syntax06': ("foo{# {% #}", {}, "foo"),
|
||||
'comment-syntax07': ("foo{# %} #}", {}, "foo"),
|
||||
'comment-syntax08': ("foo{# %} #}bar", {}, "foobar"),
|
||||
'comment-syntax09': ("foo{# {{ #}", {}, "foo"),
|
||||
'comment-syntax10': ("foo{# }} #}", {}, "foo"),
|
||||
'comment-syntax11': ("foo{# { #}", {}, "foo"),
|
||||
'comment-syntax12': ("foo{# } #}", {}, "foo"),
|
||||
|
||||
### COMMENT TAG ###########################################################
|
||||
'comment-tag01': ("{% comment %}this is hidden{% endcomment %}hello", {}, "hello"),
|
||||
'comment-tag02': ("{% comment %}this is hidden{% endcomment %}hello{% comment %}foo{% endcomment %}", {}, "hello"),
|
||||
@ -312,6 +328,21 @@ class Templates(unittest.TestCase):
|
||||
'ifchanged05': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (1, 2, 3)}, '1123123123'),
|
||||
'ifchanged06': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2)}, '1222'),
|
||||
'ifchanged07': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% for x in numx %}{% ifchanged %}{{ x }}{% endifchanged %}{% for y in numy %}{% ifchanged %}{{ y }}{% endifchanged %}{% endfor %}{% endfor %}{% endfor %}', { 'num': (1, 1, 1), 'numx': (2, 2, 2), 'numy': (3, 3, 3)}, '1233323332333'),
|
||||
|
||||
# Test one parameter given to ifchanged.
|
||||
'ifchanged-param01': ('{% for n in num %}{% ifchanged n %}..{% endifchanged %}{{ n }}{% endfor %}', { 'num': (1,2,3) }, '..1..2..3'),
|
||||
'ifchanged-param02': ('{% for n in num %}{% for x in numx %}{% ifchanged n %}..{% endifchanged %}{{ x }}{% endfor %}{% endfor %}', { 'num': (1,2,3), 'numx': (5,6,7) }, '..567..567..567'),
|
||||
|
||||
# Test multiple parameters to ifchanged.
|
||||
'ifchanged-param03': ('{% for n in num %}{{ n }}{% for x in numx %}{% ifchanged x n %}{{ x }}{% endifchanged %}{% endfor %}{% endfor %}', { 'num': (1,1,2), 'numx': (5,6,6) }, '156156256'),
|
||||
|
||||
# Test a date+hour like construct, where the hour of the last day
|
||||
# is the same but the date had changed, so print the hour anyway.
|
||||
'ifchanged-param04': ('{% for d in days %}{% ifchanged %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),
|
||||
|
||||
# Logically the same as above, just written with explicit
|
||||
# ifchanged for the day.
|
||||
'ifchanged-param04': ('{% for d in days %}{% ifchanged d.day %}{{ d.day }}{% endifchanged %}{% for h in d.hours %}{% ifchanged d.day h %}{{ h }}{% endifchanged %}{% endfor %}{% endfor %}', {'days':[{'day':1, 'hours':[1,2,3]},{'day':2, 'hours':[3]},] }, '112323'),
|
||||
|
||||
### IFEQUAL TAG ###########################################################
|
||||
'ifequal01': ("{% ifequal a b %}yes{% endifequal %}", {"a": 1, "b": 2}, ""),
|
||||
@ -473,7 +504,7 @@ class Templates(unittest.TestCase):
|
||||
'i18n13': ('{{ _("Page not found") }}', {'LANGUAGE_CODE': 'de'}, 'Seite nicht gefunden'),
|
||||
|
||||
### HANDLING OF TEMPLATE_TAG_IF_INVALID ###################################
|
||||
|
||||
|
||||
'invalidstr01': ('{{ var|default:"Foo" }}', {}, ('Foo','INVALID')),
|
||||
'invalidstr02': ('{{ var|default_if_none:"Foo" }}', {}, ('','INVALID')),
|
||||
'invalidstr03': ('{% for v in var %}({{ v }}){% endfor %}', {}, ''),
|
||||
@ -536,6 +567,8 @@ class Templates(unittest.TestCase):
|
||||
'templatetag08': ('{% templatetag closebrace %}', {}, '}'),
|
||||
'templatetag09': ('{% templatetag openbrace %}{% templatetag openbrace %}', {}, '{{'),
|
||||
'templatetag10': ('{% templatetag closebrace %}{% templatetag closebrace %}', {}, '}}'),
|
||||
'templatetag11': ('{% templatetag opencomment %}', {}, '{#'),
|
||||
'templatetag12': ('{% templatetag closecomment %}', {}, '#}'),
|
||||
|
||||
### WIDTHRATIO TAG ########################################################
|
||||
'widthratio01': ('{% widthratio a b 0 %}', {'a':50,'b':100}, '0'),
|
||||
@ -606,20 +639,20 @@ class Templates(unittest.TestCase):
|
||||
|
||||
# Turn TEMPLATE_DEBUG off, because tests assume that.
|
||||
old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, False
|
||||
|
||||
# Set TEMPLATE_STRING_IF_INVALID to a known string
|
||||
|
||||
# Set TEMPLATE_STRING_IF_INVALID to a known string
|
||||
old_invalid = settings.TEMPLATE_STRING_IF_INVALID
|
||||
|
||||
|
||||
for name, vals in tests:
|
||||
install()
|
||||
|
||||
|
||||
if isinstance(vals[2], tuple):
|
||||
normal_string_result = vals[2][0]
|
||||
invalid_string_result = vals[2][1]
|
||||
else:
|
||||
normal_string_result = vals[2]
|
||||
invalid_string_result = vals[2]
|
||||
|
||||
|
||||
if 'LANGUAGE_CODE' in vals[1]:
|
||||
activate(vals[1]['LANGUAGE_CODE'])
|
||||
else:
|
||||
@ -636,10 +669,10 @@ class Templates(unittest.TestCase):
|
||||
continue
|
||||
if output != result:
|
||||
failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (invalid_str, name, result, output))
|
||||
|
||||
|
||||
if 'LANGUAGE_CODE' in vals[1]:
|
||||
deactivate()
|
||||
|
||||
|
||||
loader.template_source_loaders = old_template_loaders
|
||||
deactivate()
|
||||
settings.TEMPLATE_DEBUG = old_td
|
||||
|
Loading…
x
Reference in New Issue
Block a user