mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
multi-auth: Merged to [2964]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multi-auth@2965 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
d659956cf5
commit
681763a29c
@ -12,10 +12,63 @@ from django.conf import global_settings
|
||||
|
||||
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
||||
|
||||
class LazySettings:
|
||||
"""
|
||||
A lazy proxy for either global Django settings or a custom settings object.
|
||||
The user can manually configure settings prior to using them. Otherwise,
|
||||
Django uses the settings module pointed to by DJANGO_SETTINGS_MODULE.
|
||||
"""
|
||||
def __init__(self):
|
||||
# _target must be either None or something that supports attribute
|
||||
# access (getattr, hasattr, etc).
|
||||
self._target = None
|
||||
|
||||
def __getattr__(self, name):
|
||||
if self._target is None:
|
||||
self._import_settings()
|
||||
if name == '__members__':
|
||||
# Used to implement dir(obj), for example.
|
||||
return self._target.get_all_members()
|
||||
return getattr(self._target, name)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name == '_target':
|
||||
# Assign directly to self.__dict__, because otherwise we'd call
|
||||
# __setattr__(), which would be an infinite loop.
|
||||
self.__dict__['_target'] = value
|
||||
else:
|
||||
setattr(self._target, name, value)
|
||||
|
||||
def _import_settings(self):
|
||||
"""
|
||||
Load the settings module pointed to by the environment variable. This
|
||||
is used the first time we need any settings at all, if the user has not
|
||||
previously configured the settings manually.
|
||||
"""
|
||||
try:
|
||||
settings_module = os.environ[ENVIRONMENT_VARIABLE]
|
||||
if not settings_module: # If it's set but is an empty string.
|
||||
raise KeyError
|
||||
except KeyError:
|
||||
raise EnvironmentError, "Environment variable %s is undefined." % ENVIRONMENT_VARIABLE
|
||||
|
||||
self._target = Settings(settings_module)
|
||||
|
||||
def configure(self, default_settings=global_settings, **options):
|
||||
"""
|
||||
Called to manually configure the settings. The 'default_settings'
|
||||
parameter sets where to retrieve any unspecified values from (its
|
||||
argument must support attribute access (__getattr__)).
|
||||
"""
|
||||
if self._target != None:
|
||||
raise EnvironmentError, 'Settings already configured.'
|
||||
holder = UserSettingsHolder(default_settings)
|
||||
for name, value in options.items():
|
||||
setattr(holder, name, value)
|
||||
self._target = holder
|
||||
|
||||
class Settings:
|
||||
|
||||
def __init__(self, settings_module):
|
||||
|
||||
# update this dict from global settings (but only for ALL_CAPS settings)
|
||||
for setting in dir(global_settings):
|
||||
if setting == setting.upper():
|
||||
@ -27,7 +80,7 @@ class Settings:
|
||||
try:
|
||||
mod = __import__(self.SETTINGS_MODULE, '', '', [''])
|
||||
except ImportError, e:
|
||||
raise EnvironmentError, "Could not import settings '%s' (is it on sys.path?): %s" % (self.SETTINGS_MODULE, e)
|
||||
raise EnvironmentError, "Could not import settings '%s' (Is it on sys.path? Does it have syntax errors?): %s" % (self.SETTINGS_MODULE, e)
|
||||
|
||||
# Settings that should be converted into tuples if they're mistakenly entered
|
||||
# as strings.
|
||||
@ -56,18 +109,32 @@ class Settings:
|
||||
# move the time zone info into os.environ
|
||||
os.environ['TZ'] = self.TIME_ZONE
|
||||
|
||||
# try to load DJANGO_SETTINGS_MODULE
|
||||
try:
|
||||
settings_module = os.environ[ENVIRONMENT_VARIABLE]
|
||||
if not settings_module: # If it's set but is an empty string.
|
||||
raise KeyError
|
||||
except KeyError:
|
||||
raise EnvironmentError, "Environment variable %s is undefined." % ENVIRONMENT_VARIABLE
|
||||
def get_all_members(self):
|
||||
return dir(self)
|
||||
|
||||
# instantiate the configuration object
|
||||
settings = Settings(settings_module)
|
||||
class UserSettingsHolder:
|
||||
"""
|
||||
Holder for user configured settings.
|
||||
"""
|
||||
# SETTINGS_MODULE does not really make sense in the manually configured
|
||||
# (standalone) case.
|
||||
SETTINGS_MODULE = None
|
||||
|
||||
def __init__(self, default_settings):
|
||||
"""
|
||||
Requests for configuration variables not in this class are satisfied
|
||||
from the module specified in default_settings (if possible).
|
||||
"""
|
||||
self.default_settings = default_settings
|
||||
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.default_settings, name)
|
||||
|
||||
def get_all_members(self):
|
||||
return dir(self) + dir(self.default_settings)
|
||||
|
||||
settings = LazySettings()
|
||||
|
||||
# install the translation machinery so that it is available
|
||||
from django.utils import translation
|
||||
translation.install()
|
||||
|
||||
|
Binary file not shown.
@ -1,22 +1,19 @@
|
||||
# translation of Django.
|
||||
# Copyright (C) 2006 THE Django'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the Django package.
|
||||
# <>, 2006.
|
||||
# , fuzzy
|
||||
# <>, 2006.
|
||||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Django 1.0\n"
|
||||
"Project-Id-Version: Django 0.95\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-05-16 10:14+0200\n"
|
||||
"PO-Revision-Date: 2006-04-04 14:29+0300\n"
|
||||
"PO-Revision-Date: 2006-05-16 15:48+0300\n"
|
||||
"Last-Translator: Meir Kriheli <meir@mksoft.co.il>\n"
|
||||
"Language-Team: Hebrew\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Content-Transfer-Encoding: 8bit"
|
||||
|
||||
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
||||
msgid "object ID"
|
||||
@ -88,12 +85,11 @@ msgid ""
|
||||
"Check this box if the comment is inappropriate. A \"This comment has been "
|
||||
"removed\" message will be displayed instead."
|
||||
msgstr ""
|
||||
"יש לסמן תיבה זו עבור תגובה לא נאותה. הודעת \"תגובה זונמחקה\" תוצג במקום."
|
||||
"יש לסמן תיבה זו עבור תגובה לא נאותה. הודעת \"תגובה זו נמחקה\" תוצג במקום."
|
||||
|
||||
#: contrib/comments/models.py:91
|
||||
#, fuzzy
|
||||
msgid "comments"
|
||||
msgstr "תגובה"
|
||||
msgstr "תגובות"
|
||||
|
||||
#: contrib/comments/models.py:131 contrib/comments/models.py:207
|
||||
msgid "Content object"
|
||||
@ -127,12 +123,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 "הערות אנונימיות"
|
||||
|
||||
@ -145,14 +139,12 @@ msgid "score date"
|
||||
msgstr "תאריך ציון"
|
||||
|
||||
#: contrib/comments/models.py:237
|
||||
#, fuzzy
|
||||
msgid "karma score"
|
||||
msgstr "ציון קארמה"
|
||||
msgstr "ניקוד קארמה"
|
||||
|
||||
#: contrib/comments/models.py:238
|
||||
#, fuzzy
|
||||
msgid "karma scores"
|
||||
msgstr "ציוני קארמה"
|
||||
msgstr "ניקודי קארמה"
|
||||
|
||||
#: contrib/comments/models.py:242
|
||||
#, python-format
|
||||
@ -175,14 +167,12 @@ msgid "flag date"
|
||||
msgstr "תאריך סימון"
|
||||
|
||||
#: contrib/comments/models.py:268
|
||||
#, fuzzy
|
||||
msgid "user flag"
|
||||
msgstr "סימן משתמש"
|
||||
msgstr "סימון ע\"י משתמש"
|
||||
|
||||
#: contrib/comments/models.py:269
|
||||
#, fuzzy
|
||||
msgid "user flags"
|
||||
msgstr "סימני משתמש"
|
||||
msgstr "סימונים ע\"י משתמש"
|
||||
|
||||
#: contrib/comments/models.py:273
|
||||
#, python-format
|
||||
@ -194,14 +184,12 @@ msgid "deletion date"
|
||||
msgstr "תאריך מחיקה"
|
||||
|
||||
#: contrib/comments/models.py:280
|
||||
#, fuzzy
|
||||
msgid "moderator deletion"
|
||||
msgstr "מחיקת מודרציה"
|
||||
msgstr "מחיקת מודרטור"
|
||||
|
||||
#: contrib/comments/models.py:281
|
||||
#, fuzzy
|
||||
msgid "moderator deletions"
|
||||
msgstr "מחיקות מודרציה"
|
||||
msgstr "מחיקות מודרטור"
|
||||
|
||||
#: contrib/comments/models.py:285
|
||||
#, python-format
|
||||
@ -226,23 +214,23 @@ msgid ""
|
||||
msgstr "הדירוג נדרש מאחר והזנת לפחות דרוג אחד אחר."
|
||||
|
||||
#: contrib/comments/views/comments.py:112
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This comment was posted by a user who has posted fewer than %(count)s "
|
||||
"comment:\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
msgid_plural ""
|
||||
"This comment was posted by a user who has posted fewer than %(count)s "
|
||||
"comments:\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
msgstr[0] ""
|
||||
"ההודעה נשלחה ע\"י משתמש מפוקפק:\n"
|
||||
msgstr ""
|
||||
"תגובה זו נשלחה ע\"י משתמש אשר שלח פחות מ %(count)s "
|
||||
"תגובה:\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
msgstr[1] ""
|
||||
"ההודעה נשלחה ע\"י משתמש מפוקפק:\n"
|
||||
"תגובה זו נשלחה ע\"י משתמש אשר שלח פחות מ %(count)s "
|
||||
"תגובות:\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
|
||||
@ -296,9 +284,8 @@ msgid "Password:"
|
||||
msgstr "סיסמה:"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:6
|
||||
#, fuzzy
|
||||
msgid "Forgotten your password?"
|
||||
msgstr "שנה את סיסמתי"
|
||||
msgstr "שכחת את סיסמתך ?"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:8
|
||||
#: contrib/admin/templates/admin/object_history.html:3
|
||||
@ -322,40 +309,36 @@ msgid "Log out"
|
||||
msgstr "יציאה"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#, fuzzy
|
||||
msgid "Ratings"
|
||||
msgstr "דירוג #1"
|
||||
msgstr "דירוג"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Required"
|
||||
msgstr ""
|
||||
msgstr "נדרש"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Optional"
|
||||
msgstr ""
|
||||
msgstr "אופציונלי"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Post a photo"
|
||||
msgstr ""
|
||||
msgstr "שליחת תמונה"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:27
|
||||
#: contrib/comments/templates/comments/freeform.html:5
|
||||
#, fuzzy
|
||||
msgid "Comment:"
|
||||
msgstr "תגובה"
|
||||
msgstr "תגובה:"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:32
|
||||
#: contrib/comments/templates/comments/freeform.html:9
|
||||
#, fuzzy
|
||||
msgid "Preview comment"
|
||||
msgstr "הערה אנונימית"
|
||||
msgstr "תצוגה מקדימה של התגובה"
|
||||
|
||||
#: contrib/comments/templates/comments/freeform.html:4
|
||||
#, fuzzy
|
||||
msgid "Your name:"
|
||||
msgstr "שם משתמש"
|
||||
msgstr "שמך:"
|
||||
|
||||
#: contrib/admin/filterspecs.py:40
|
||||
#, python-format
|
||||
@ -752,7 +735,7 @@ msgstr "אנו מצטערים, לא ניתן למצוא את הדף המבוקש
|
||||
#: contrib/admin/templates/admin/index.html:17
|
||||
#, python-format
|
||||
msgid "Models available in the %(name)s application."
|
||||
msgstr ""
|
||||
msgstr "מודלים זמינים ביישום %(name)s."
|
||||
|
||||
#: contrib/admin/templates/admin/index.html:28
|
||||
#: contrib/admin/templates/admin/change_form.html:15
|
||||
@ -834,11 +817,8 @@ msgid "View on site"
|
||||
msgstr "צפיה באתר"
|
||||
|
||||
#: contrib/admin/templates/admin/change_form.html:30
|
||||
#, fuzzy
|
||||
msgid "Please correct the error below."
|
||||
msgid_plural "Please correct the errors below."
|
||||
msgstr[0] "נא לתקן את השגיאה הבאה:"
|
||||
msgstr[1] "נא לתקן את השגיאה הבאה:"
|
||||
msgstr "נא לתקן את השגיאה המופיעה מתחת."
|
||||
|
||||
#: contrib/admin/templates/admin/change_form.html:48
|
||||
msgid "Ordering"
|
||||
@ -1139,22 +1119,18 @@ msgid "codename"
|
||||
msgstr "שם קוד"
|
||||
|
||||
#: contrib/auth/models.py:17
|
||||
#, fuzzy
|
||||
msgid "permission"
|
||||
msgstr "הרשאה"
|
||||
|
||||
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
||||
#, fuzzy
|
||||
msgid "permissions"
|
||||
msgstr "הרשאות"
|
||||
|
||||
#: contrib/auth/models.py:29
|
||||
#, fuzzy
|
||||
msgid "group"
|
||||
msgstr "קבוצה"
|
||||
|
||||
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
||||
#, fuzzy
|
||||
msgid "groups"
|
||||
msgstr "קבוצות"
|
||||
|
||||
@ -1215,17 +1191,14 @@ msgstr ""
|
||||
"המשוייכת אליו/ה."
|
||||
|
||||
#: contrib/auth/models.py:67
|
||||
#, fuzzy
|
||||
msgid "user permissions"
|
||||
msgstr "הרשאות"
|
||||
msgstr "הרשאות משתמש"
|
||||
|
||||
#: contrib/auth/models.py:70
|
||||
#, fuzzy
|
||||
msgid "user"
|
||||
msgstr "משתמש"
|
||||
|
||||
#: contrib/auth/models.py:71
|
||||
#, fuzzy
|
||||
msgid "users"
|
||||
msgstr "משתמשים"
|
||||
|
||||
@ -1246,7 +1219,6 @@ msgid "Groups"
|
||||
msgstr "קבוצות"
|
||||
|
||||
#: contrib/auth/models.py:219
|
||||
#, fuzzy
|
||||
msgid "message"
|
||||
msgstr "הודעה"
|
||||
|
||||
@ -1257,9 +1229,8 @@ msgid ""
|
||||
msgstr "נראה שעוגיות לא מאופשרות בדפדפן שלך.הן נדרשות כדי להתחבר."
|
||||
|
||||
#: contrib/contenttypes/models.py:25
|
||||
#, fuzzy
|
||||
msgid "python model class name"
|
||||
msgstr "שם מודל פייתון"
|
||||
msgstr "שם ה-class של מודל פייתון"
|
||||
|
||||
#: contrib/contenttypes/models.py:28
|
||||
msgid "content type"
|
||||
@ -1394,54 +1365,52 @@ msgid "December"
|
||||
msgstr "תצבר"
|
||||
|
||||
#: utils/dates.py:19
|
||||
#, fuzzy
|
||||
msgid "jan"
|
||||
msgstr "ו"
|
||||
msgstr "יאנ"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "feb"
|
||||
msgstr ""
|
||||
msgstr "פבר"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "mar"
|
||||
msgstr ""
|
||||
msgstr "מרץ"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "apr"
|
||||
msgstr ""
|
||||
msgstr "אפר"
|
||||
|
||||
#: utils/dates.py:19
|
||||
#, fuzzy
|
||||
msgid "may"
|
||||
msgstr "יום"
|
||||
msgstr "מאי"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "jun"
|
||||
msgstr ""
|
||||
msgstr "יונ"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "jul"
|
||||
msgstr ""
|
||||
msgstr "יול"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "aug"
|
||||
msgstr ""
|
||||
msgstr "אוג"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "sep"
|
||||
msgstr ""
|
||||
msgstr "ספט"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "oct"
|
||||
msgstr ""
|
||||
msgstr "אוק"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "nov"
|
||||
msgstr ""
|
||||
msgstr "נוב"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "dec"
|
||||
msgstr ""
|
||||
msgstr "דצמ"
|
||||
|
||||
#: utils/dates.py:27
|
||||
msgid "Jan."
|
||||
@ -1472,46 +1441,28 @@ msgid "Dec."
|
||||
msgstr "דצמ'"
|
||||
|
||||
#: utils/timesince.py:12
|
||||
#, fuzzy
|
||||
msgid "year"
|
||||
msgid_plural "years"
|
||||
msgstr[0] "שנה"
|
||||
msgstr[1] "שנה"
|
||||
msgstr "שנה"
|
||||
|
||||
#: utils/timesince.py:13
|
||||
#, fuzzy
|
||||
msgid "month"
|
||||
msgid_plural "months"
|
||||
msgstr[0] "חודש"
|
||||
msgstr[1] "חודש"
|
||||
msgstr "חודש"
|
||||
|
||||
#: utils/timesince.py:14
|
||||
#, fuzzy
|
||||
msgid "week"
|
||||
msgid_plural "weeks"
|
||||
msgstr[0] "יוונית - Greek"
|
||||
msgstr[1] "יוונית - Greek"
|
||||
msgstr "שבוע"
|
||||
|
||||
#: utils/timesince.py:15
|
||||
#, fuzzy
|
||||
msgid "day"
|
||||
msgid_plural "days"
|
||||
msgstr[0] "יום"
|
||||
msgstr[1] "יום"
|
||||
msgstr "יום"
|
||||
|
||||
#: utils/timesince.py:16
|
||||
#, fuzzy
|
||||
msgid "hour"
|
||||
msgid_plural "hours"
|
||||
msgstr[0] "שעה"
|
||||
msgstr[1] "שעה"
|
||||
msgstr "שעה"
|
||||
|
||||
#: utils/timesince.py:17
|
||||
#, fuzzy
|
||||
msgid "minute"
|
||||
msgid_plural "minutes"
|
||||
msgstr[0] "דקה"
|
||||
msgstr[1] "דקה"
|
||||
msgstr "דקה"
|
||||
|
||||
#: conf/global_settings.py:37
|
||||
msgid "Bengali"
|
||||
@ -1555,7 +1506,7 @@ msgstr "גאליצית - Galician"
|
||||
|
||||
#: conf/global_settings.py:47
|
||||
msgid "Hungarian"
|
||||
msgstr ""
|
||||
msgstr "הונגרית (Hungarian)"
|
||||
|
||||
#: conf/global_settings.py:48
|
||||
msgid "Hebrew"
|
||||
@ -1610,9 +1561,8 @@ msgid "Swedish"
|
||||
msgstr "שוודית - Swedish"
|
||||
|
||||
#: conf/global_settings.py:61
|
||||
#, fuzzy
|
||||
msgid "Ukrainian"
|
||||
msgstr "ברזילאית - Brazilian"
|
||||
msgstr "אוקראינית - Ukrainian"
|
||||
|
||||
#: conf/global_settings.py:62
|
||||
msgid "Simplified Chinese"
|
||||
@ -1742,11 +1692,9 @@ msgid "Enter a valid U.S. state abbreviation."
|
||||
msgstr "יש להזין קיצור חוקי למדינה בארה\"ב."
|
||||
|
||||
#: core/validators.py:229
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "Watch your mouth! The word %s is not allowed here."
|
||||
msgid_plural "Watch your mouth! The words %s are not allowed here."
|
||||
msgstr[0] "שמור על לשונך! המילה %s אינה מותרת לשימוש כאן."
|
||||
msgstr[1] "שמור על לשונך! המילה %s אינה מותרת לשימוש כאן."
|
||||
msgstr "שמור על לשונך! המילה %s אינה מותרת לשימוש כאן."
|
||||
|
||||
#: core/validators.py:236
|
||||
#, python-format
|
||||
@ -1785,20 +1733,18 @@ msgid "Please enter a valid decimal number."
|
||||
msgstr "יש להזין מספר עשרוני חוקי."
|
||||
|
||||
#: core/validators.py:349
|
||||
#, fuzzy, python-format
|
||||
#, 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] "יש להזין מספר עשרוני חוקי."
|
||||
msgstr[1] "יש להזין מספר עשרוני חוקי."
|
||||
msgstr "נא להזין מספר שלם המכיל %s ספרה לכל היותר."
|
||||
"נא להזין מספר שלם המכיל %s ספרות לכל היותר."
|
||||
|
||||
#: core/validators.py:352
|
||||
#, fuzzy, python-format
|
||||
#, 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] "יש להזין מספר עשרוני חוקי."
|
||||
msgstr[1] "יש להזין מספר עשרוני חוקי."
|
||||
msgstr "נא·להזין·מספר·עשרוני·חוקי·המכיל·%s·ספרה·אחרי·הנקודה·לכל·היותר."
|
||||
"נא להזין מספר עשרוני חוקי המכיל %s ספרות אחרי הנקודה לכל היותר."
|
||||
|
||||
#: core/validators.py:362
|
||||
#, python-format
|
||||
@ -1895,19 +1841,16 @@ msgid "This field is required."
|
||||
msgstr "יש להזין תוכן בשדה זה."
|
||||
|
||||
#: db/models/fields/__init__.py:337
|
||||
#, fuzzy
|
||||
msgid "This value must be an integer."
|
||||
msgstr "ערך זה חייב להיות חזקה של %s."
|
||||
msgstr "ערך זה חייב להיות מספר שלם."
|
||||
|
||||
#: db/models/fields/__init__.py:369
|
||||
#, fuzzy
|
||||
msgid "This value must be either True or False."
|
||||
msgstr "ערך זה חייב להיות חזקה של %s."
|
||||
msgstr "ערך זה חייב להיות אמת או שקר."
|
||||
|
||||
#: db/models/fields/__init__.py:385
|
||||
#, fuzzy
|
||||
msgid "This field cannot be null."
|
||||
msgstr "שדה זה אינו חוקי."
|
||||
msgstr "שדה זה אינו יכול להכיל null."
|
||||
|
||||
#: db/models/fields/__init__.py:562
|
||||
msgid "Enter a valid filename."
|
||||
@ -1919,35 +1862,26 @@ msgid "Please enter a valid %s."
|
||||
msgstr "יש להזין %s חוקי."
|
||||
|
||||
#: db/models/fields/related.py:579
|
||||
#, fuzzy
|
||||
msgid "Separate multiple IDs with commas."
|
||||
msgstr "יש להפריד מזהים מרובים בפסיקים."
|
||||
|
||||
#: db/models/fields/related.py:581
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr ""
|
||||
" יש להחזיק לחוץ את \"Control\" או \"Command\" על מק, כדי לבחור יותר מאחד."
|
||||
"החזק את \"Control\", או \"Command\" על מק, לחוץ כדי לבחור יותר מאחד."
|
||||
|
||||
#: db/models/fields/related.py:625
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
||||
msgid_plural ""
|
||||
"Please enter valid %(self)s IDs. The values %(value)r are invalid."
|
||||
msgstr[0] ""
|
||||
"נא להזין זיהוי·%(self)s·חוקי.·הערך·%(value)r·אינו חוקי.נא להזין זיהויי·%"
|
||||
"(self)s·חוקיים.·הערכים·%(value)r·אינם חוקיים."
|
||||
msgstr[1] ""
|
||||
"נא להזין זיהוי·%(self)s·חוקי.·הערך·%(value)r·אינו חוקי.נא להזין זיהויי·%"
|
||||
"(self)s·חוקיים.·הערכים·%(value)r·אינם חוקיים."
|
||||
msgstr "נא להזין זיהוי %(self)s חוקי. הערך %(value)r אינו חוקי."
|
||||
"נא להזין זיהויי %(self)s חוקיים. הערכים %(value)r אינם חוקיים."
|
||||
|
||||
#: forms/__init__.py:380
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "Ensure your text is less than %s character."
|
||||
msgid_plural "Ensure your text is less than %s characters."
|
||||
msgstr[0] "יש לוודא שהטקסט שלך מכיל פחות מ %s תו."
|
||||
msgstr[1] "יש לוודא שהטקסט שלך מכיל פחות מ %s תו."
|
||||
msgstr "נא לוודא שהטקסט שלך מכיל פחות מ %s תו."
|
||||
|
||||
#: forms/__init__.py:385
|
||||
msgid "Line breaks are not allowed here."
|
||||
@ -1978,61 +1912,3 @@ msgstr "יש להזין מספר שלם בין 0 ל- 32,767."
|
||||
msgid "yes,no,maybe"
|
||||
msgstr "כן,לא,אולי"
|
||||
|
||||
#~ msgid "label"
|
||||
#~ msgstr "תווית"
|
||||
|
||||
#~ msgid "package"
|
||||
#~ msgstr "חבילה"
|
||||
|
||||
#~ msgid "packages"
|
||||
#~ msgstr "חבילות"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Please enter a valid decimal number with at most %s total digit.Please "
|
||||
#~ "enter a valid decimal number with at most %s total digits."
|
||||
#~ msgstr ""
|
||||
#~ "#-#-#-#-# django.po (Django 1.0) #-#-#-#-#\n"
|
||||
#~ "יש להזין מספר עשרוני חוקי עם %s ספרה לכל היותר.יש להזין מספר עשרוני חוקי "
|
||||
#~ "עם %s ספרות לכל היותר.\n"
|
||||
#~ "#-#-#-#-# django.po (Django 1.0) #-#-#-#-#\n"
|
||||
#~ "יש להזין מספר עשרוני הכולל %s ספרה לכל היותר.יש להזין מספר עשרוני הכולל %"
|
||||
#~ "s ספרות לכל היותר."
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "Please enter a valid decimal number with at most %s decimal place.Please "
|
||||
#~ "enter a valid decimal number with at most %s decimal places."
|
||||
#~ msgstr ""
|
||||
#~ "#-#-#-#-# django.po (Django 1.0) #-#-#-#-#\n"
|
||||
#~ "יש להזין מספר עשרוני חוקי עם %s ספרה אחרי הנקודה לכל היותר."
|
||||
#~ "יש·להזין·מספר·עשרוני·חוקי·עם·%s·ספרות·אחרי·הנקודה·לכל·היותר.\n"
|
||||
#~ "#-#-#-#-# django.po (Django 1.0) #-#-#-#-#\n"
|
||||
#~ "יש להזין מספר עשרוני עם %s ספרה אחרי הנקודה העשרונית לכל היותר.יש להזין "
|
||||
#~ "מספר עשרוני עם %s ספרות אחרי הנקודה העשרונית לכל היותר."
|
||||
|
||||
#~ msgid "Comments"
|
||||
#~ msgstr "תגובות"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid ""
|
||||
#~ "This comment was posted by a user who has posted fewer than %(count)s "
|
||||
#~ "comment:\n"
|
||||
#~ "\n"
|
||||
#~ "%(text)sThis comment was posted by a user who has posted fewer than %"
|
||||
#~ "(count)s comments:\n"
|
||||
#~ "\n"
|
||||
#~ "%(text)s"
|
||||
#~ msgstr ""
|
||||
#~ "#-#-#-#-# django.po (Django 1.0) #-#-#-#-#\n"
|
||||
#~ "התגובה נשלחה ע\"י משתמש בעל פחות מ %(count)s תגובה:\n"
|
||||
#~ "\n"
|
||||
#~ "%(text)sהתגובה·נשלחה·ע\"י·משתמש·בעל·פחות·מ·%(count)s·תגובות:\n"
|
||||
#~ "\n"
|
||||
#~ "%(text)s\n"
|
||||
#~ "#-#-#-#-# django.po (Django 1.0) #-#-#-#-#\n"
|
||||
#~ "התגובה נשלח ע\"י משתמש ששלח פחות מ %(count)s·תגובה:\n"
|
||||
#~ "\n"
|
||||
#~ "%(text)sהתגובה נשלח ע\"י משתמש ששלח פחות מ %(count)s·תגובות:\n"
|
||||
#~ "\n"
|
||||
#~ "%(text)s"
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: django v1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2006-05-16 10:10+0200\n"
|
||||
"PO-Revision-Date: 2006-01-05 13:46+0800\n"
|
||||
"PO-Revision-Date: 2006-05-17 13:47+0800\n"
|
||||
"Last-Translator: limodou <limodou@gmail.com>\n"
|
||||
"Language-Team: Simplified Chinese <limodou@gmail.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -19,7 +19,8 @@ msgstr ""
|
||||
"X-Poedit-SourceCharset: utf-8\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
||||
#: contrib/comments/models.py:67
|
||||
#: contrib/comments/models.py:166
|
||||
msgid "object ID"
|
||||
msgstr "对象ID"
|
||||
|
||||
@ -27,7 +28,8 @@ msgstr "对象ID"
|
||||
msgid "headline"
|
||||
msgstr "大字标题"
|
||||
|
||||
#: contrib/comments/models.py:69 contrib/comments/models.py:90
|
||||
#: contrib/comments/models.py:69
|
||||
#: contrib/comments/models.py:90
|
||||
#: contrib/comments/models.py:167
|
||||
msgid "comment"
|
||||
msgstr "评论"
|
||||
@ -68,15 +70,18 @@ msgstr "等级 #8"
|
||||
msgid "is valid rating"
|
||||
msgstr "是无效等级"
|
||||
|
||||
#: contrib/comments/models.py:83 contrib/comments/models.py:169
|
||||
#: contrib/comments/models.py:83
|
||||
#: contrib/comments/models.py:169
|
||||
msgid "date/time submitted"
|
||||
msgstr "日期/时间已提交"
|
||||
|
||||
#: contrib/comments/models.py:84 contrib/comments/models.py:170
|
||||
#: contrib/comments/models.py:84
|
||||
#: contrib/comments/models.py:170
|
||||
msgid "is public"
|
||||
msgstr "公开"
|
||||
|
||||
#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
|
||||
#: contrib/comments/models.py:85
|
||||
#: contrib/admin/views/doc.py:289
|
||||
msgid "IP address"
|
||||
msgstr "IP地址"
|
||||
|
||||
@ -85,18 +90,15 @@ msgid "is removed"
|
||||
msgstr "被删除"
|
||||
|
||||
#: contrib/comments/models.py:86
|
||||
msgid ""
|
||||
"Check this box if the comment is inappropriate. A \"This comment has been "
|
||||
"removed\" message will be displayed instead."
|
||||
msgstr ""
|
||||
"如果评论不适合选中这个检查框。评论将被一条\"此评论已经被删除\"的消息所替换。"
|
||||
msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead."
|
||||
msgstr "如果评论不适合选中这个检查框。评论将被一条\"此评论已经被删除\"的消息所替换。"
|
||||
|
||||
#: contrib/comments/models.py:91
|
||||
#, fuzzy
|
||||
msgid "comments"
|
||||
msgstr "评论"
|
||||
|
||||
#: contrib/comments/models.py:131 contrib/comments/models.py:207
|
||||
#: contrib/comments/models.py:131
|
||||
#: contrib/comments/models.py:207
|
||||
msgid "Content object"
|
||||
msgstr "内容对象"
|
||||
|
||||
@ -128,12 +130,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 "自由评论"
|
||||
|
||||
@ -146,12 +146,10 @@ msgid "score date"
|
||||
msgstr "得分日期"
|
||||
|
||||
#: contrib/comments/models.py:237
|
||||
#, fuzzy
|
||||
msgid "karma score"
|
||||
msgstr "Karma得分"
|
||||
|
||||
#: contrib/comments/models.py:238
|
||||
#, fuzzy
|
||||
msgid "karma scores"
|
||||
msgstr "Karma得分"
|
||||
|
||||
@ -176,12 +174,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 "用户标志"
|
||||
|
||||
@ -195,14 +191,12 @@ msgid "deletion date"
|
||||
msgstr "删除日期"
|
||||
|
||||
#: contrib/comments/models.py:280
|
||||
#, fuzzy
|
||||
msgid "moderator deletion"
|
||||
msgstr "仲裁删除"
|
||||
msgstr "删除仲裁"
|
||||
|
||||
#: contrib/comments/models.py:281
|
||||
#, fuzzy
|
||||
msgid "moderator deletions"
|
||||
msgstr "仲裁删除"
|
||||
msgstr "删除仲裁"
|
||||
|
||||
#: contrib/comments/models.py:285
|
||||
#, python-format
|
||||
@ -222,20 +216,17 @@ msgid "No voting for yourself"
|
||||
msgstr "不能给自已投票"
|
||||
|
||||
#: contrib/comments/views/comments.py:28
|
||||
msgid ""
|
||||
"This rating is required because you've entered at least one other rating."
|
||||
msgid "This rating is required because you've entered at least one other rating."
|
||||
msgstr "要求此等级,因为你已经输入了至少一个等级。"
|
||||
|
||||
#: contrib/comments/views/comments.py:112
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This comment was posted by a user who has posted fewer than %(count)s "
|
||||
"comment:\n"
|
||||
"This comment was posted by a user who has posted fewer than %(count)s comment:\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
msgid_plural ""
|
||||
"This comment was posted by a user who has posted fewer than %(count)s "
|
||||
"comments:\n"
|
||||
"This comment was posted by a user who has posted fewer than %(count)s comments:\n"
|
||||
"\n"
|
||||
"%(text)s"
|
||||
msgstr[0] ""
|
||||
@ -271,9 +262,7 @@ msgstr "有人篡改了评论表格(安全侵害)"
|
||||
|
||||
#: contrib/comments/views/comments.py:207
|
||||
#: contrib/comments/views/comments.py:292
|
||||
msgid ""
|
||||
"The comment form had an invalid 'target' parameter -- the object ID was "
|
||||
"invalid"
|
||||
msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid"
|
||||
msgstr "评论表格有一个无效的 'target' 参数 -- 对象 ID 无效"
|
||||
|
||||
#: contrib/comments/views/comments.py:257
|
||||
@ -293,9 +282,8 @@ msgid "Password:"
|
||||
msgstr "口令:"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:6
|
||||
#, fuzzy
|
||||
msgid "Forgotten your password?"
|
||||
msgstr "修改我的口令"
|
||||
msgstr "忘记你的口令?"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:8
|
||||
#: contrib/admin/templates/admin/object_history.html:3
|
||||
@ -319,40 +307,36 @@ msgid "Log out"
|
||||
msgstr "注销"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#, fuzzy
|
||||
msgid "Ratings"
|
||||
msgstr "等级 #1"
|
||||
msgstr "等级"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Required"
|
||||
msgstr ""
|
||||
msgstr "必须的"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:12
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Optional"
|
||||
msgstr ""
|
||||
msgstr "可选的"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:23
|
||||
msgid "Post a photo"
|
||||
msgstr ""
|
||||
msgstr "上传一张照片"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:27
|
||||
#: contrib/comments/templates/comments/freeform.html:5
|
||||
#, fuzzy
|
||||
msgid "Comment:"
|
||||
msgstr "评论"
|
||||
msgstr "评论:"
|
||||
|
||||
#: contrib/comments/templates/comments/form.html:32
|
||||
#: contrib/comments/templates/comments/freeform.html:9
|
||||
#, fuzzy
|
||||
msgid "Preview comment"
|
||||
msgstr "自由评论"
|
||||
msgstr "预览评论"
|
||||
|
||||
#: contrib/comments/templates/comments/freeform.html:4
|
||||
#, fuzzy
|
||||
msgid "Your name:"
|
||||
msgstr "用户名"
|
||||
msgstr "你的名字:"
|
||||
|
||||
#: contrib/admin/filterspecs.py:40
|
||||
#, python-format
|
||||
@ -363,7 +347,8 @@ msgstr ""
|
||||
"<h3>由 %s:</h3>\n"
|
||||
"<ul>\n"
|
||||
|
||||
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
|
||||
#: contrib/admin/filterspecs.py:70
|
||||
#: contrib/admin/filterspecs.py:88
|
||||
#: contrib/admin/filterspecs.py:143
|
||||
msgid "All"
|
||||
msgstr "全部"
|
||||
@ -432,11 +417,10 @@ msgstr "日志记录"
|
||||
msgid "All dates"
|
||||
msgstr "全有日期"
|
||||
|
||||
#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
|
||||
#: contrib/admin/views/decorators.py:9
|
||||
#: contrib/auth/forms.py:36
|
||||
#: contrib/auth/forms.py:41
|
||||
msgid ""
|
||||
"Please enter a correct username and password. Note that both fields are case-"
|
||||
"sensitive."
|
||||
msgid "Please enter a correct username and password. Note that both fields are case-sensitive."
|
||||
msgstr "请输入正确的用户名和口令。请注意两个域都是大小写敏感的。"
|
||||
|
||||
#: contrib/admin/views/decorators.py:23
|
||||
@ -445,18 +429,12 @@ msgid "Log in"
|
||||
msgstr "登录"
|
||||
|
||||
#: contrib/admin/views/decorators.py:61
|
||||
msgid ""
|
||||
"Please log in again, because your session has expired. Don't worry: Your "
|
||||
"submission has been saved."
|
||||
msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved."
|
||||
msgstr "请重新登录,因为你的会话已经过期。不用担心:你的提交已经被保存。"
|
||||
|
||||
#: contrib/admin/views/decorators.py:68
|
||||
msgid ""
|
||||
"Looks like your browser isn't configured to accept cookies. Please enable "
|
||||
"cookies, reload this page, and try again."
|
||||
msgstr ""
|
||||
"看上去你的浏览器没有配置成接受 cookie 。请允许 cookie,重新装入本页面,再试一"
|
||||
"次。"
|
||||
msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again."
|
||||
msgstr "看上去你的浏览器没有配置成接受 cookie 。请允许 cookie,重新装入本页面,再试一次。"
|
||||
|
||||
#: contrib/admin/views/decorators.py:82
|
||||
msgid "Usernames cannot contain the '@' character."
|
||||
@ -476,11 +454,13 @@ msgstr "站点管理员"
|
||||
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
||||
msgstr "%(name)s \"%(obj)s\" 添加成功。"
|
||||
|
||||
#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
|
||||
#: contrib/admin/views/main.py:264
|
||||
#: contrib/admin/views/main.py:348
|
||||
msgid "You may edit it again below."
|
||||
msgstr "你可以在下面再次编辑它。"
|
||||
|
||||
#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
|
||||
#: contrib/admin/views/main.py:272
|
||||
#: contrib/admin/views/main.py:357
|
||||
#, python-format
|
||||
msgid "You may add another %s below."
|
||||
msgstr "你可以在下面增加另一个 %s 。"
|
||||
@ -495,7 +475,8 @@ msgstr "增加 %s"
|
||||
msgid "Added %s."
|
||||
msgstr "%s 已增加。"
|
||||
|
||||
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
|
||||
#: contrib/admin/views/main.py:336
|
||||
#: contrib/admin/views/main.py:338
|
||||
#: contrib/admin/views/main.py:340
|
||||
msgid "and"
|
||||
msgstr "和"
|
||||
@ -521,8 +502,7 @@ msgstr "%(name)s \"%(obj)s\" 修改成功。"
|
||||
|
||||
#: contrib/admin/views/main.py:354
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
||||
msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
||||
msgstr "%(name)s \"%(obj)s\" 添加成功。你可以在下面再次编辑它。"
|
||||
|
||||
#: contrib/admin/views/main.py:392
|
||||
@ -564,9 +544,12 @@ msgstr "选择 %s"
|
||||
msgid "Select %s to change"
|
||||
msgstr "选择 %s 来修改"
|
||||
|
||||
#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
|
||||
#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
|
||||
#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
|
||||
#: contrib/admin/views/doc.py:277
|
||||
#: contrib/admin/views/doc.py:286
|
||||
#: contrib/admin/views/doc.py:288
|
||||
#: contrib/admin/views/doc.py:294
|
||||
#: contrib/admin/views/doc.py:295
|
||||
#: contrib/admin/views/doc.py:297
|
||||
msgid "Integer"
|
||||
msgstr "整数"
|
||||
|
||||
@ -574,7 +557,8 @@ msgstr "整数"
|
||||
msgid "Boolean (Either True or False)"
|
||||
msgstr "布尔(True或False)"
|
||||
|
||||
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
|
||||
#: contrib/admin/views/doc.py:279
|
||||
#: contrib/admin/views/doc.py:296
|
||||
#, python-format
|
||||
msgid "String (up to %(maxlength)s)"
|
||||
msgstr "字符串(最长 %(maxlength)s)"
|
||||
@ -595,7 +579,8 @@ msgstr "日期(带时间)"
|
||||
msgid "E-mail address"
|
||||
msgstr "邮箱地址"
|
||||
|
||||
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
|
||||
#: contrib/admin/views/doc.py:284
|
||||
#: contrib/admin/views/doc.py:287
|
||||
msgid "File path"
|
||||
msgstr "文件路径"
|
||||
|
||||
@ -623,7 +608,8 @@ msgstr "文本"
|
||||
msgid "Time"
|
||||
msgstr "时间"
|
||||
|
||||
#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
|
||||
#: contrib/admin/views/doc.py:300
|
||||
#: contrib/flatpages/models.py:7
|
||||
msgid "URL"
|
||||
msgstr "URL"
|
||||
|
||||
@ -703,9 +689,7 @@ msgid "DATE_WITH_TIME_FULL"
|
||||
msgstr "N j, Y, P"
|
||||
|
||||
#: contrib/admin/templates/admin/object_history.html:36
|
||||
msgid ""
|
||||
"This object doesn't have a change history. It probably wasn't added via this "
|
||||
"admin site."
|
||||
msgid "This object doesn't have a change history. It probably wasn't added via this admin site."
|
||||
msgstr "此对象没有修改历史。可能不能通过这个管理站点来增加。"
|
||||
|
||||
#: contrib/admin/templates/admin/base_site.html:4
|
||||
@ -729,12 +713,8 @@ msgid "Server Error <em>(500)</em>"
|
||||
msgstr "服务器错误 <em>(500)</em>"
|
||||
|
||||
#: contrib/admin/templates/admin/500.html:10
|
||||
msgid ""
|
||||
"There's been an error. It's been reported to the site administrators via e-"
|
||||
"mail and should be fixed shortly. Thanks for your patience."
|
||||
msgstr ""
|
||||
"存在一个错误。它已经通过电子邮件被报告给站点管理员了,并且应该很快被改正。谢"
|
||||
"谢你的关心。"
|
||||
msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience."
|
||||
msgstr "存在一个错误。它已经通过电子邮件被报告给站点管理员了,并且应该很快被改正。谢谢你的关心。"
|
||||
|
||||
#: contrib/admin/templates/admin/404.html:4
|
||||
#: contrib/admin/templates/admin/404.html:8
|
||||
@ -748,7 +728,7 @@ msgstr "很报歉,请求页面无法找到。"
|
||||
#: contrib/admin/templates/admin/index.html:17
|
||||
#, python-format
|
||||
msgid "Models available in the %(name)s application."
|
||||
msgstr ""
|
||||
msgstr "在 %(name)s 应用中模块有效。"
|
||||
|
||||
#: contrib/admin/templates/admin/index.html:28
|
||||
#: contrib/admin/templates/admin/change_form.html:15
|
||||
@ -795,21 +775,13 @@ msgstr "删除"
|
||||
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:14
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Deleting the %(object_name)s '%(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' 会导致删除相关的对象,但你的帐号无权删除下"
|
||||
"列类型的对象:"
|
||||
msgid "Deleting the %(object_name)s '%(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' 会导致删除相关的对象,但你的帐号无权删除下列类型的对象:"
|
||||
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:21
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
|
||||
"the following related items will be deleted:"
|
||||
msgstr ""
|
||||
"你确信相要删除 %(object_name)s \"%(object)s\"?所有相关的项目都将被删除:"
|
||||
msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:"
|
||||
msgstr "你确信相要删除 %(object_name)s \"%(object)s\"?所有相关的项目都将被删除:"
|
||||
|
||||
#: contrib/admin/templates/admin/delete_confirmation.html:26
|
||||
msgid "Yes, I'm sure"
|
||||
@ -881,12 +853,8 @@ msgid "Password reset"
|
||||
msgstr "口令重设"
|
||||
|
||||
#: contrib/admin/templates/registration/password_reset_form.html:12
|
||||
msgid ""
|
||||
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
||||
"your password and e-mail the new one to you."
|
||||
msgstr ""
|
||||
"忘记你的口令?在下面输入你的邮箱地址,我们将重设你的口令并且将新的口令通过邮"
|
||||
"件发送给你。"
|
||||
msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you."
|
||||
msgstr "忘记你的口令?在下面输入你的邮箱地址,我们将重设你的口令并且将新的口令通过邮件发送给你。"
|
||||
|
||||
#: contrib/admin/templates/registration/password_reset_form.html:16
|
||||
msgid "E-mail address:"
|
||||
@ -910,19 +878,12 @@ msgid "Password reset successful"
|
||||
msgstr "口令重设成功"
|
||||
|
||||
#: contrib/admin/templates/registration/password_reset_done.html:12
|
||||
msgid ""
|
||||
"We've e-mailed a new password to the e-mail address you submitted. You "
|
||||
"should be receiving it shortly."
|
||||
msgstr ""
|
||||
"我们已经按你所提交的邮箱地址发送了一个新的口令给你。你应该很会收到这封邮件。"
|
||||
msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly."
|
||||
msgstr "我们已经按你所提交的邮箱地址发送了一个新的口令给你。你应该很会收到这封邮件。"
|
||||
|
||||
#: contrib/admin/templates/registration/password_change_form.html:12
|
||||
msgid ""
|
||||
"Please enter your old password, for security's sake, and then enter your new "
|
||||
"password twice so we can verify you typed it in correctly."
|
||||
msgstr ""
|
||||
"请输入你的旧口令,为了安全起见,接着要输入你的新口令两遍,这样我们可以校验你"
|
||||
"输入的是否正确。"
|
||||
msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly."
|
||||
msgstr "请输入你的旧口令,为了安全起见,接着要输入你的新口令两遍,这样我们可以校验你输入的是否正确。"
|
||||
|
||||
#: contrib/admin/templates/registration/password_change_form.html:17
|
||||
msgid "Old password:"
|
||||
@ -1002,9 +963,7 @@ msgid "Documentation for this page"
|
||||
msgstr "本页面的文档"
|
||||
|
||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:20
|
||||
msgid ""
|
||||
"Jumps you from any page to the documentation for the view that generates "
|
||||
"that page."
|
||||
msgid "Jumps you from any page to the documentation for the view that generates that page."
|
||||
msgstr "对于任何页面跳转到生成这个页面的view所在的文件。"
|
||||
|
||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
|
||||
@ -1012,9 +971,7 @@ msgid "Show object ID"
|
||||
msgstr "显示对象ID"
|
||||
|
||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:23
|
||||
msgid ""
|
||||
"Shows the content-type and unique ID for pages that represent a single "
|
||||
"object."
|
||||
msgid "Shows the content-type and unique ID for pages that represent a single object."
|
||||
msgstr "用于那些表现单个对象的页面显示 content-type 和唯一ID。"
|
||||
|
||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
|
||||
@ -1054,9 +1011,7 @@ msgid "redirect from"
|
||||
msgstr "重定向自"
|
||||
|
||||
#: contrib/redirects/models.py:8
|
||||
msgid ""
|
||||
"This should be an absolute path, excluding the domain name. Example: '/"
|
||||
"events/search/'."
|
||||
msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'."
|
||||
msgstr "应该是一个绝对路径,不包括域名。例如:'/events/search/'。"
|
||||
|
||||
#: contrib/redirects/models.py:9
|
||||
@ -1064,9 +1019,7 @@ msgid "redirect to"
|
||||
msgstr "重定向到"
|
||||
|
||||
#: contrib/redirects/models.py:10
|
||||
msgid ""
|
||||
"This can be either an absolute path (as above) or a full URL starting with "
|
||||
"'http://'."
|
||||
msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'."
|
||||
msgstr "可以是绝对路径(同上)或以'http://'开始的全URL。"
|
||||
|
||||
#: contrib/redirects/models.py:12
|
||||
@ -1078,8 +1031,7 @@ msgid "redirects"
|
||||
msgstr "重定向"
|
||||
|
||||
#: contrib/flatpages/models.py:8
|
||||
msgid ""
|
||||
"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
|
||||
msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
|
||||
msgstr "例如:'/about/contact/'。请确保前导和结尾的除号。"
|
||||
|
||||
#: contrib/flatpages/models.py:9
|
||||
@ -1099,11 +1051,8 @@ msgid "template name"
|
||||
msgstr "模板名称"
|
||||
|
||||
#: contrib/flatpages/models.py:13
|
||||
msgid ""
|
||||
"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
|
||||
"use 'flatpages/default'."
|
||||
msgstr ""
|
||||
"例如:'flatfiles/contact_page'。如果未提供,系统将使用'flatfiles/default'。"
|
||||
msgid "Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'."
|
||||
msgstr "例如:'flatfiles/contact_page'。如果未提供,系统将使用'flatfiles/default'。"
|
||||
|
||||
#: contrib/flatpages/models.py:14
|
||||
msgid "registration required"
|
||||
@ -1121,7 +1070,8 @@ msgstr "简单页面"
|
||||
msgid "flat pages"
|
||||
msgstr "简单页面"
|
||||
|
||||
#: contrib/auth/models.py:13 contrib/auth/models.py:26
|
||||
#: contrib/auth/models.py:13
|
||||
#: contrib/auth/models.py:26
|
||||
msgid "name"
|
||||
msgstr "名称"
|
||||
|
||||
@ -1130,22 +1080,20 @@ msgid "codename"
|
||||
msgstr "代码名称"
|
||||
|
||||
#: contrib/auth/models.py:17
|
||||
#, fuzzy
|
||||
msgid "permission"
|
||||
msgstr "许可"
|
||||
msgstr "权限"
|
||||
|
||||
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
||||
#, fuzzy
|
||||
#: contrib/auth/models.py:18
|
||||
#: contrib/auth/models.py:27
|
||||
msgid "permissions"
|
||||
msgstr "许可"
|
||||
msgstr "权限"
|
||||
|
||||
#: contrib/auth/models.py:29
|
||||
#, fuzzy
|
||||
msgid "group"
|
||||
msgstr "组"
|
||||
|
||||
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
||||
#, fuzzy
|
||||
#: contrib/auth/models.py:30
|
||||
#: contrib/auth/models.py:65
|
||||
msgid "groups"
|
||||
msgstr "组"
|
||||
|
||||
@ -1198,24 +1146,18 @@ msgid "date joined"
|
||||
msgstr "加入日期"
|
||||
|
||||
#: contrib/auth/models.py:66
|
||||
msgid ""
|
||||
"In addition to the permissions manually assigned, this user will also get "
|
||||
"all permissions granted to each group he/she is in."
|
||||
msgstr ""
|
||||
"除了手动设置权限以外,用户也会从他(她)所在的小组获得所赋组小组的所有权限。"
|
||||
msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."
|
||||
msgstr "除了手动设置权限以外,用户也会从他(她)所在的小组获得所赋组小组的所有权限。"
|
||||
|
||||
#: contrib/auth/models.py:67
|
||||
#, fuzzy
|
||||
msgid "user permissions"
|
||||
msgstr "许可"
|
||||
msgstr "用户权限"
|
||||
|
||||
#: contrib/auth/models.py:70
|
||||
#, fuzzy
|
||||
msgid "user"
|
||||
msgstr "用户"
|
||||
|
||||
#: contrib/auth/models.py:71
|
||||
#, fuzzy
|
||||
msgid "users"
|
||||
msgstr "用户"
|
||||
|
||||
@ -1236,20 +1178,16 @@ msgid "Groups"
|
||||
msgstr "组"
|
||||
|
||||
#: contrib/auth/models.py:219
|
||||
#, fuzzy
|
||||
msgid "message"
|
||||
msgstr "消息"
|
||||
|
||||
#: contrib/auth/forms.py:30
|
||||
msgid ""
|
||||
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
|
||||
"required for logging in."
|
||||
msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."
|
||||
msgstr "你的Web浏览器好象不允许使用cookie。登录需要使用cookie。"
|
||||
|
||||
#: contrib/contenttypes/models.py:25
|
||||
#, fuzzy
|
||||
msgid "python model class name"
|
||||
msgstr "python模块名"
|
||||
msgstr "python模块类名"
|
||||
|
||||
#: contrib/contenttypes/models.py:28
|
||||
msgid "content type"
|
||||
@ -1343,23 +1281,28 @@ msgstr "一月"
|
||||
msgid "February"
|
||||
msgstr "二月"
|
||||
|
||||
#: utils/dates.py:14 utils/dates.py:27
|
||||
#: utils/dates.py:14
|
||||
#: utils/dates.py:27
|
||||
msgid "March"
|
||||
msgstr "三月"
|
||||
|
||||
#: utils/dates.py:14 utils/dates.py:27
|
||||
#: utils/dates.py:14
|
||||
#: utils/dates.py:27
|
||||
msgid "April"
|
||||
msgstr "四月"
|
||||
|
||||
#: utils/dates.py:14 utils/dates.py:27
|
||||
#: utils/dates.py:14
|
||||
#: utils/dates.py:27
|
||||
msgid "May"
|
||||
msgstr "五月"
|
||||
|
||||
#: utils/dates.py:14 utils/dates.py:27
|
||||
#: utils/dates.py:14
|
||||
#: utils/dates.py:27
|
||||
msgid "June"
|
||||
msgstr "六月"
|
||||
|
||||
#: utils/dates.py:15 utils/dates.py:27
|
||||
#: utils/dates.py:15
|
||||
#: utils/dates.py:27
|
||||
msgid "July"
|
||||
msgstr "七月"
|
||||
|
||||
@ -1384,54 +1327,52 @@ msgid "December"
|
||||
msgstr "十二月"
|
||||
|
||||
#: utils/dates.py:19
|
||||
#, fuzzy
|
||||
msgid "jan"
|
||||
msgstr "和"
|
||||
msgstr "一月"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "feb"
|
||||
msgstr ""
|
||||
msgstr "二月"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "mar"
|
||||
msgstr ""
|
||||
msgstr "三月"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "apr"
|
||||
msgstr ""
|
||||
msgstr "四月"
|
||||
|
||||
#: utils/dates.py:19
|
||||
#, fuzzy
|
||||
msgid "may"
|
||||
msgstr "天"
|
||||
msgstr "三月"
|
||||
|
||||
#: utils/dates.py:19
|
||||
msgid "jun"
|
||||
msgstr ""
|
||||
msgstr "六月"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "jul"
|
||||
msgstr ""
|
||||
msgstr "七月"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "aug"
|
||||
msgstr ""
|
||||
msgstr "八月"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "sep"
|
||||
msgstr ""
|
||||
msgstr "九月"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "oct"
|
||||
msgstr ""
|
||||
msgstr "十月"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "nov"
|
||||
msgstr ""
|
||||
msgstr "十一月"
|
||||
|
||||
#: utils/dates.py:20
|
||||
msgid "dec"
|
||||
msgstr ""
|
||||
msgstr "十二月"
|
||||
|
||||
#: utils/dates.py:27
|
||||
msgid "Jan."
|
||||
@ -1474,7 +1415,7 @@ msgstr[0] "月"
|
||||
#: utils/timesince.py:14
|
||||
msgid "week"
|
||||
msgid_plural "weeks"
|
||||
msgstr[0] ""
|
||||
msgstr[0] "周"
|
||||
|
||||
#: utils/timesince.py:15
|
||||
msgid "day"
|
||||
@ -1513,7 +1454,7 @@ msgstr "德语"
|
||||
|
||||
#: conf/global_settings.py:42
|
||||
msgid "Greek"
|
||||
msgstr ""
|
||||
msgstr "希腊语"
|
||||
|
||||
#: conf/global_settings.py:43
|
||||
msgid "English"
|
||||
@ -1533,11 +1474,11 @@ msgstr "加利西亚语"
|
||||
|
||||
#: conf/global_settings.py:47
|
||||
msgid "Hungarian"
|
||||
msgstr ""
|
||||
msgstr "匈牙利语"
|
||||
|
||||
#: conf/global_settings.py:48
|
||||
msgid "Hebrew"
|
||||
msgstr ""
|
||||
msgstr "希伯来语"
|
||||
|
||||
#: conf/global_settings.py:49
|
||||
msgid "Icelandic"
|
||||
@ -1553,7 +1494,7 @@ msgstr "日语"
|
||||
|
||||
#: conf/global_settings.py:52
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
msgstr "荷兰语"
|
||||
|
||||
#: conf/global_settings.py:53
|
||||
msgid "Norwegian"
|
||||
@ -1576,9 +1517,8 @@ msgid "Slovak"
|
||||
msgstr "斯洛伐克语"
|
||||
|
||||
#: conf/global_settings.py:58
|
||||
#, fuzzy
|
||||
msgid "Slovenian"
|
||||
msgstr "斯洛伐克语"
|
||||
msgstr "斯洛文尼亚语"
|
||||
|
||||
#: conf/global_settings.py:59
|
||||
msgid "Serbian"
|
||||
@ -1589,9 +1529,8 @@ msgid "Swedish"
|
||||
msgstr "瑞典语"
|
||||
|
||||
#: conf/global_settings.py:61
|
||||
#, fuzzy
|
||||
msgid "Ukrainian"
|
||||
msgstr "巴西语"
|
||||
msgstr "乌克兰语"
|
||||
|
||||
#: conf/global_settings.py:62
|
||||
msgid "Simplified Chinese"
|
||||
@ -1606,11 +1545,8 @@ msgid "This value must contain only letters, numbers and underscores."
|
||||
msgstr "此值只能包含字母、数字和下划线。"
|
||||
|
||||
#: core/validators.py:64
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"This value must contain only letters, numbers, underscores, dashes or "
|
||||
"slashes."
|
||||
msgstr "此值只能包含字母、数字、下划线和斜线。"
|
||||
msgid "This value must contain only letters, numbers, underscores, dashes or slashes."
|
||||
msgstr "此值只能包含字母、数字、下划线、反斜线和斜线。"
|
||||
|
||||
#: core/validators.py:72
|
||||
msgid "Uppercase letters are not allowed here."
|
||||
@ -1660,7 +1596,8 @@ msgstr "输入一个 YYYY-MM-DD 格式的有效日期。"
|
||||
msgid "Enter a valid time in HH:MM format."
|
||||
msgstr "输入一个 HH:MM 格式的有效时间。"
|
||||
|
||||
#: core/validators.py:132 db/models/fields/__init__.py:468
|
||||
#: core/validators.py:132
|
||||
#: db/models/fields/__init__.py:468
|
||||
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
||||
msgstr "输入一个 YYYY-MM-DD HH:MM 格式的有效日期/时间。"
|
||||
|
||||
@ -1669,9 +1606,7 @@ msgid "Enter a valid e-mail address."
|
||||
msgstr "输入一个有效的邮件地址。"
|
||||
|
||||
#: core/validators.py:148
|
||||
msgid ""
|
||||
"Upload a valid image. The file you uploaded was either not an image or a "
|
||||
"corrupted image."
|
||||
msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image."
|
||||
msgstr "上传一个有效的图片。您所上传的文件或者不是图片或是一个破坏的图片。"
|
||||
|
||||
#: core/validators.py:155
|
||||
@ -1712,7 +1647,8 @@ msgstr "格式错误的 XML: %s"
|
||||
msgid "Invalid URL: %s"
|
||||
msgstr "无效 URL: %s"
|
||||
|
||||
#: core/validators.py:206 core/validators.py:208
|
||||
#: core/validators.py:206
|
||||
#: core/validators.py:208
|
||||
#, python-format
|
||||
msgid "The URL %s is a broken link."
|
||||
msgstr "URL %s 是一个断开的链接。"
|
||||
@ -1736,7 +1672,8 @@ msgstr "这个字段必须与 '%s' 字段相匹配。"
|
||||
msgid "Please enter something for at least one field."
|
||||
msgstr "请至少在一个字段上输入些什么。"
|
||||
|
||||
#: core/validators.py:264 core/validators.py:275
|
||||
#: core/validators.py:264
|
||||
#: core/validators.py:275
|
||||
msgid "Please enter both fields or leave them both empty."
|
||||
msgstr "请要么两个字段都输入或者两个字段都空着。"
|
||||
|
||||
@ -1766,15 +1703,13 @@ msgstr "请输入一个有效的小数。"
|
||||
#: core/validators.py:349
|
||||
#, 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."
|
||||
msgid_plural "Please enter a valid decimal number with at most %s total digits."
|
||||
msgstr[0] "请输入一个有效的小数,最多 %s 个数字。 "
|
||||
|
||||
#: core/validators.py:352
|
||||
#, 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."
|
||||
msgid_plural "Please enter a valid decimal number with at most %s decimal places."
|
||||
msgstr[0] "请输入一个有效的小数,最多 %s 个小数位。 "
|
||||
|
||||
#: core/validators.py:362
|
||||
@ -1802,57 +1737,38 @@ msgstr "不能从 %s 得到任何东西。"
|
||||
|
||||
#: core/validators.py:429
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
||||
msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
||||
msgstr "URL %(url)s 返回了无效的 Content-Type 头 '%(contenttype)s'。"
|
||||
|
||||
#: core/validators.py:462
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
|
||||
"\"%(start)s\".)"
|
||||
msgstr ""
|
||||
"请关闭未关闭的 %(tag)s 标签从第 %(line)s 行。(行开始于 \"%(start)s\"。)"
|
||||
msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)"
|
||||
msgstr "请关闭未关闭的 %(tag)s 标签从第 %(line)s 行。(行开始于 \"%(start)s\"。)"
|
||||
|
||||
#: core/validators.py:466
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Some text starting on line %(line)s is not allowed in that context. (Line "
|
||||
"starts with \"%(start)s\".)"
|
||||
msgstr ""
|
||||
"在 %(line)s 行开始的一些文本不允许在那个上下文中。(行开始于 \"%(start)s\"。)"
|
||||
msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)"
|
||||
msgstr "在 %(line)s 行开始的一些文本不允许在那个上下文中。(行开始于 \"%(start)s\"。)"
|
||||
|
||||
#: core/validators.py:471
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
|
||||
"(start)s\".)"
|
||||
msgstr ""
|
||||
"在 %(line)s 行的\"%(attr)s\"不是一个有效的属性。(行开始于 \"%(start)s\"。)"
|
||||
msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)"
|
||||
msgstr "在 %(line)s 行的\"%(attr)s\"不是一个有效的属性。(行开始于 \"%(start)s\"。)"
|
||||
|
||||
#: core/validators.py:476
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
|
||||
"(start)s\".)"
|
||||
msgstr ""
|
||||
"在 %(line)s 行的\"<%(tag)s>\"不是一个有效的标签。(行开始于 \"%(start)s\"。)"
|
||||
msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)"
|
||||
msgstr "在 %(line)s 行的\"<%(tag)s>\"不是一个有效的标签。(行开始于 \"%(start)s\"。)"
|
||||
|
||||
#: core/validators.py:480
|
||||
#, python-format
|
||||
msgid ""
|
||||
"A tag on line %(line)s is missing one or more required attributes. (Line "
|
||||
"starts with \"%(start)s\".)"
|
||||
msgstr ""
|
||||
"在行 %(line)s 的标签少了一个或多个必须的属性。(行开始于 \"%(start)s\"。)"
|
||||
msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)"
|
||||
msgstr "在行 %(line)s 的标签少了一个或多个必须的属性。(行开始于 \"%(start)s\"。)"
|
||||
|
||||
#: core/validators.py:485
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
|
||||
"starts with \"%(start)s\".)"
|
||||
msgstr ""
|
||||
"在行 %(line)s 的\"%(attr)s\"属性有一个无效的值。(行开始于 \"%(start)s\"。)"
|
||||
msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)"
|
||||
msgstr "在行 %(line)s 的\"%(attr)s\"属性有一个无效的值。(行开始于 \"%(start)s\"。)"
|
||||
|
||||
#: db/models/manipulators.py:302
|
||||
#, python-format
|
||||
@ -1864,26 +1780,25 @@ msgstr "带有这个 %(type)s 的 %(object)s 对于给定的 %(field)s 已经存
|
||||
msgid "%(optname)s with this %(fieldname)s already exists."
|
||||
msgstr "%(optname)s 带有 %(fieldname)s 已经存在。"
|
||||
|
||||
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
|
||||
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
|
||||
#: db/models/fields/__init__.py:114
|
||||
#: db/models/fields/__init__.py:265
|
||||
#: db/models/fields/__init__.py:542
|
||||
#: db/models/fields/__init__.py:553
|
||||
#: forms/__init__.py:346
|
||||
msgid "This field is required."
|
||||
msgstr "这个字段是必输项。"
|
||||
|
||||
#: db/models/fields/__init__.py:337
|
||||
#, fuzzy
|
||||
msgid "This value must be an integer."
|
||||
msgstr "这个值必须是 %s 的乘方。"
|
||||
msgstr "这个值必须是一个整数。"
|
||||
|
||||
#: db/models/fields/__init__.py:369
|
||||
#, fuzzy
|
||||
msgid "This value must be either True or False."
|
||||
msgstr "这个值必须是 %s 的乘方。"
|
||||
msgstr "这个值必须是 True 或 False。"
|
||||
|
||||
#: db/models/fields/__init__.py:385
|
||||
#, fuzzy
|
||||
msgid "This field cannot be null."
|
||||
msgstr "这个字段无效。"
|
||||
msgstr "这个值不能为 null。"
|
||||
|
||||
#: db/models/fields/__init__.py:562
|
||||
msgid "Enter a valid filename."
|
||||
@ -1895,21 +1810,17 @@ msgid "Please enter a valid %s."
|
||||
msgstr "请输入一个有效的 %s 。"
|
||||
|
||||
#: db/models/fields/related.py:579
|
||||
#, fuzzy
|
||||
msgid "Separate multiple IDs with commas."
|
||||
msgstr " 用逗号分隔多个ID。"
|
||||
msgstr "用逗号分隔多个ID。"
|
||||
|
||||
#: db/models/fields/related.py:581
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr " 按下 \"Control\",或者在Mac上按 \"Command\" 来选择一个或多个值。"
|
||||
msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||
msgstr "按下 \"Control\",或者在Mac上按 \"Command\" 来选择多个值。"
|
||||
|
||||
#: db/models/fields/related.py:625
|
||||
#, python-format
|
||||
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
||||
msgid_plural ""
|
||||
"Please enter valid %(self)s IDs. The values %(value)r are invalid."
|
||||
msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid."
|
||||
msgstr[0] "请输入有效的 %(self)s ID。值 %(value)r 无效。"
|
||||
|
||||
#: forms/__init__.py:380
|
||||
@ -1922,7 +1833,9 @@ msgstr[0] "确定你输入的文本少于 %s 个字符。"
|
||||
msgid "Line breaks are not allowed here."
|
||||
msgstr "这里不允许换行符。"
|
||||
|
||||
#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589
|
||||
#: forms/__init__.py:480
|
||||
#: forms/__init__.py:551
|
||||
#: forms/__init__.py:589
|
||||
#, python-format
|
||||
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
|
||||
msgstr "选择一个有效的选项: '%(data)s' 不在 %(choices)s 中。"
|
||||
@ -1949,22 +1862,18 @@ msgstr "是、否、也许"
|
||||
|
||||
#~ msgid "Comment"
|
||||
#~ msgstr "评论"
|
||||
|
||||
#~ msgid "Comments"
|
||||
#~ msgstr "评论"
|
||||
|
||||
#~ msgid "String (up to 50)"
|
||||
#~ msgstr "整数(最长50)"
|
||||
|
||||
#~ msgid "label"
|
||||
#~ msgstr "标签"
|
||||
|
||||
#~ msgid "package"
|
||||
#~ msgstr "包"
|
||||
|
||||
#~ msgid "packages"
|
||||
#~ msgstr "包"
|
||||
|
||||
#, fuzzy
|
||||
#~ msgid "count"
|
||||
#~ msgstr "内容"
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
{{ block.super }}
|
||||
<style type="text/css">
|
||||
.module table { width:100%; }
|
||||
.module table p { padding: 0; margin: 0; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -206,12 +206,14 @@ def model_detail(request, app_label, model_name):
|
||||
verbose = "related `%s.%s` objects" % (rel.opts.app_label, rel.opts.object_name)
|
||||
accessor = rel.get_accessor_name()
|
||||
fields.append({
|
||||
'name' : "%s.all" % accessor,
|
||||
'verbose' : utils.parse_rst("all " + verbose , 'model', 'model:' + opts.module_name),
|
||||
'name' : "%s.all" % accessor,
|
||||
'data_type' : 'List',
|
||||
'verbose' : utils.parse_rst("all " + verbose , 'model', 'model:' + opts.module_name),
|
||||
})
|
||||
fields.append({
|
||||
'name' : "%s.count" % accessor,
|
||||
'verbose' : utils.parse_rst("number of " + verbose , 'model', 'model:' + opts.module_name),
|
||||
'name' : "%s.count" % accessor,
|
||||
'data_type' : 'Integer',
|
||||
'verbose' : utils.parse_rst("number of " + verbose , 'model', 'model:' + opts.module_name),
|
||||
})
|
||||
|
||||
return render_to_response('admin_doc/model_detail.html', {
|
||||
@ -282,6 +284,7 @@ DATA_TYPE_MAPPING = {
|
||||
'DateTimeField' : _('Date (with time)'),
|
||||
'EmailField' : _('E-mail address'),
|
||||
'FileField' : _('File path'),
|
||||
'FilePathField' : _('File path'),
|
||||
'FloatField' : _('Decimal number'),
|
||||
'ForeignKey' : _('Integer'),
|
||||
'ImageField' : _('File path'),
|
||||
|
@ -1,5 +1,6 @@
|
||||
from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
|
||||
from django.http import HttpResponseRedirect
|
||||
from urllib import quote
|
||||
|
||||
def user_passes_test(test_func, login_url=LOGIN_URL):
|
||||
"""
|
||||
@ -11,7 +12,7 @@ def user_passes_test(test_func, login_url=LOGIN_URL):
|
||||
def _checklogin(request, *args, **kwargs):
|
||||
if test_func(request.user):
|
||||
return view_func(request, *args, **kwargs)
|
||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, request.path))
|
||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
|
||||
|
||||
return _checklogin
|
||||
return _dec
|
||||
|
26
django/contrib/sites/managers.py
Normal file
26
django/contrib/sites/managers.py
Normal file
@ -0,0 +1,26 @@
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.db.models.fields import FieldDoesNotExist
|
||||
|
||||
class CurrentSiteManager(models.Manager):
|
||||
"Use this to limit objects to those associated with the current site."
|
||||
def __init__(self, field_name='site'):
|
||||
super(CurrentSiteManager, self).__init__()
|
||||
self.__field_name = field_name
|
||||
|
||||
def contribute_to_class(self, *args, **kwargs):
|
||||
# This method is overridden purely to check for errors in
|
||||
# self.field_name. We can't do this in __init__() because of
|
||||
# how Managers are implemented -- self.model isn't available
|
||||
# until after contribute_to_class() is called.
|
||||
super(CurrentSiteManager, self).contribute_to_class(*args, **kwargs)
|
||||
try:
|
||||
self.model._meta.get_field(self.__field_name)
|
||||
except FieldDoesNotExist:
|
||||
raise ValueError, "%s couldn't find a field named %s in %s." % \
|
||||
(self.__class__.__name__, self.__field_name, self.model._meta.object_name)
|
||||
self.__lookup = self.__field_name + '__id__exact'
|
||||
del self.__field_name
|
||||
|
||||
def get_query_set(self):
|
||||
return super(SiteLimitManager, self).get_query_set().filter(**{self.__lookup: settings.SITE_ID})
|
@ -665,6 +665,9 @@ def startapp(app_name, directory):
|
||||
# the parent directory.
|
||||
project_dir = os.path.normpath(os.path.join(directory, '..'))
|
||||
project_name = os.path.basename(project_dir)
|
||||
if app_name == os.path.basename(directory):
|
||||
sys.stderr.write(style.ERROR("Error: You cannot create an app with the same name (%r) as your project.\n" % app_name))
|
||||
sys.exit(1)
|
||||
_start_helper('app', app_name, directory, project_name)
|
||||
startapp.help_doc = "Creates a Django app directory structure for the given app name in the current directory."
|
||||
startapp.args = "[appname]"
|
||||
|
0
django/db/backends/postgresql_psycopg2/__init__.py
Normal file
0
django/db/backends/postgresql_psycopg2/__init__.py
Normal file
123
django/db/backends/postgresql_psycopg2/base.py
Normal file
123
django/db/backends/postgresql_psycopg2/base.py
Normal file
@ -0,0 +1,123 @@
|
||||
"""
|
||||
PostgreSQL database backend for Django.
|
||||
|
||||
Requires psycopg 2: http://initd.org/projects/psycopg2
|
||||
"""
|
||||
|
||||
from django.db.backends import util
|
||||
import psycopg2 as Database
|
||||
|
||||
DatabaseError = Database.DatabaseError
|
||||
|
||||
try:
|
||||
# Only exists in Python 2.4+
|
||||
from threading import local
|
||||
except ImportError:
|
||||
# Import copy of _thread_local.py from Python 2.4
|
||||
from django.utils._threading_local import local
|
||||
|
||||
class DatabaseWrapper(local):
|
||||
def __init__(self):
|
||||
self.connection = None
|
||||
self.queries = []
|
||||
|
||||
def cursor(self):
|
||||
from django.conf import settings
|
||||
if self.connection is None:
|
||||
if settings.DATABASE_NAME == '':
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
raise ImproperlyConfigured, "You need to specify DATABASE_NAME in your Django settings file."
|
||||
conn_string = "dbname=%s" % settings.DATABASE_NAME
|
||||
if settings.DATABASE_USER:
|
||||
conn_string = "user=%s %s" % (settings.DATABASE_USER, conn_string)
|
||||
if settings.DATABASE_PASSWORD:
|
||||
conn_string += " password='%s'" % settings.DATABASE_PASSWORD
|
||||
if settings.DATABASE_HOST:
|
||||
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.set_isolation_level(1) # make transactions transparent to all cursors
|
||||
cursor = self.connection.cursor()
|
||||
cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE])
|
||||
if settings.DEBUG:
|
||||
return util.CursorDebugWrapper(cursor, self)
|
||||
return cursor
|
||||
|
||||
def _commit(self):
|
||||
return self.connection.commit()
|
||||
|
||||
def _rollback(self):
|
||||
if self.connection:
|
||||
return self.connection.rollback()
|
||||
|
||||
def close(self):
|
||||
if self.connection is not None:
|
||||
self.connection.close()
|
||||
self.connection = None
|
||||
|
||||
supports_constraints = True
|
||||
|
||||
def quote_name(name):
|
||||
if name.startswith('"') and name.endswith('"'):
|
||||
return name # Quoting once is enough.
|
||||
return '"%s"' % name
|
||||
|
||||
def dictfetchone(cursor):
|
||||
"Returns a row from the cursor as a dict"
|
||||
# TODO: cursor.dictfetchone() doesn't exist in psycopg2,
|
||||
# but no Django code uses this. Safe to remove?
|
||||
return cursor.dictfetchone()
|
||||
|
||||
def dictfetchmany(cursor, number):
|
||||
"Returns a certain number of rows from a cursor as a dict"
|
||||
# TODO: cursor.dictfetchmany() doesn't exist in psycopg2,
|
||||
# but no Django code uses this. Safe to remove?
|
||||
return cursor.dictfetchmany(number)
|
||||
|
||||
def dictfetchall(cursor):
|
||||
"Returns all rows from a cursor as a dict"
|
||||
# TODO: cursor.dictfetchall() doesn't exist in psycopg2,
|
||||
# but no Django code uses this. Safe to remove?
|
||||
return cursor.dictfetchall()
|
||||
|
||||
def get_last_insert_id(cursor, table_name, pk_name):
|
||||
cursor.execute("SELECT CURRVAL('\"%s_%s_seq\"')" % (table_name, pk_name))
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
def get_date_extract_sql(lookup_type, table_name):
|
||||
# lookup_type is 'year', 'month', 'day'
|
||||
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-EXTRACT
|
||||
return "EXTRACT('%s' FROM %s)" % (lookup_type, table_name)
|
||||
|
||||
def get_date_trunc_sql(lookup_type, field_name):
|
||||
# lookup_type is 'year', 'month', 'day'
|
||||
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
|
||||
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
|
||||
|
||||
def get_limit_offset_sql(limit, offset=None):
|
||||
sql = "LIMIT %s" % limit
|
||||
if offset and offset != 0:
|
||||
sql += " OFFSET %s" % offset
|
||||
return sql
|
||||
|
||||
def get_random_function_sql():
|
||||
return "RANDOM()"
|
||||
|
||||
def get_drop_foreignkey_sql():
|
||||
return "DROP CONSTRAINT"
|
||||
|
||||
OPERATOR_MAPPING = {
|
||||
'exact': '= %s',
|
||||
'iexact': 'ILIKE %s',
|
||||
'contains': 'LIKE %s',
|
||||
'icontains': 'ILIKE %s',
|
||||
'gt': '> %s',
|
||||
'gte': '>= %s',
|
||||
'lt': '< %s',
|
||||
'lte': '<= %s',
|
||||
'startswith': 'LIKE %s',
|
||||
'endswith': 'LIKE %s',
|
||||
'istartswith': 'ILIKE %s',
|
||||
'iendswith': 'ILIKE %s',
|
||||
}
|
1
django/db/backends/postgresql_psycopg2/client.py
Normal file
1
django/db/backends/postgresql_psycopg2/client.py
Normal file
@ -0,0 +1 @@
|
||||
from django.db.backends.postgresql.client import *
|
1
django/db/backends/postgresql_psycopg2/creation.py
Normal file
1
django/db/backends/postgresql_psycopg2/creation.py
Normal file
@ -0,0 +1 @@
|
||||
from django.db.backends.postgresql.creation import *
|
85
django/db/backends/postgresql_psycopg2/introspection.py
Normal file
85
django/db/backends/postgresql_psycopg2/introspection.py
Normal file
@ -0,0 +1,85 @@
|
||||
from django.db import transaction
|
||||
from django.db.backends.postgresql_psycopg2.base import quote_name
|
||||
|
||||
def get_table_list(cursor):
|
||||
"Returns a list of table names in the current database."
|
||||
cursor.execute("""
|
||||
SELECT c.relname
|
||||
FROM pg_catalog.pg_class c
|
||||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
||||
WHERE c.relkind IN ('r', 'v', '')
|
||||
AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
|
||||
AND pg_catalog.pg_table_is_visible(c.oid)""")
|
||||
return [row[0] for row in cursor.fetchall()]
|
||||
|
||||
def get_table_description(cursor, table_name):
|
||||
"Returns a description of the table, with the DB-API cursor.description interface."
|
||||
cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name))
|
||||
return cursor.description
|
||||
|
||||
def get_relations(cursor, table_name):
|
||||
"""
|
||||
Returns a dictionary of {field_index: (field_index_other_table, other_table)}
|
||||
representing all relationships to the given table. Indexes are 0-based.
|
||||
"""
|
||||
cursor.execute("""
|
||||
SELECT con.conkey, con.confkey, c2.relname
|
||||
FROM pg_constraint con, pg_class c1, pg_class c2
|
||||
WHERE c1.oid = con.conrelid
|
||||
AND c2.oid = con.confrelid
|
||||
AND c1.relname = %s
|
||||
AND con.contype = 'f'""", [table_name])
|
||||
relations = {}
|
||||
for row in cursor.fetchall():
|
||||
try:
|
||||
# row[0] and row[1] are like "{2}", so strip the curly braces.
|
||||
relations[int(row[0][1:-1]) - 1] = (int(row[1][1:-1]) - 1, row[2])
|
||||
except ValueError:
|
||||
continue
|
||||
return relations
|
||||
|
||||
def get_indexes(cursor, table_name):
|
||||
"""
|
||||
Returns a dictionary of fieldname -> infodict for the given table,
|
||||
where each infodict is in the format:
|
||||
{'primary_key': boolean representing whether it's the primary key,
|
||||
'unique': boolean representing whether it's a unique index}
|
||||
"""
|
||||
# Get the table description because we only have the column indexes, and we
|
||||
# need the column names.
|
||||
desc = get_table_description(cursor, table_name)
|
||||
# This query retrieves each index on the given table.
|
||||
cursor.execute("""
|
||||
SELECT idx.indkey, idx.indisunique, idx.indisprimary
|
||||
FROM pg_catalog.pg_class c, pg_catalog.pg_class c2,
|
||||
pg_catalog.pg_index idx
|
||||
WHERE c.oid = idx.indrelid
|
||||
AND idx.indexrelid = c2.oid
|
||||
AND c.relname = %s""", [table_name])
|
||||
indexes = {}
|
||||
for row in cursor.fetchall():
|
||||
# row[0] (idx.indkey) is stored in the DB as an array. It comes out as
|
||||
# a string of space-separated integers. This designates the field
|
||||
# indexes (1-based) of the fields that have indexes on the table.
|
||||
# Here, we skip any indexes across multiple fields.
|
||||
if ' ' in row[0]:
|
||||
continue
|
||||
col_name = desc[int(row[0])-1][0]
|
||||
indexes[col_name] = {'primary_key': row[2], 'unique': row[1]}
|
||||
return indexes
|
||||
|
||||
# Maps type codes to Django Field types.
|
||||
DATA_TYPES_REVERSE = {
|
||||
16: 'BooleanField',
|
||||
21: 'SmallIntegerField',
|
||||
23: 'IntegerField',
|
||||
25: 'TextField',
|
||||
869: 'IPAddressField',
|
||||
1043: 'CharField',
|
||||
1082: 'DateField',
|
||||
1083: 'TimeField',
|
||||
1114: 'DateTimeField',
|
||||
1184: 'DateTimeField',
|
||||
1266: 'TimeField',
|
||||
1700: 'FloatField',
|
||||
}
|
@ -341,16 +341,16 @@ class Model(object):
|
||||
_save_FIELD_file.alters_data = True
|
||||
|
||||
def _get_FIELD_width(self, field):
|
||||
return self.__get_image_dimensions(field)[0]
|
||||
return self._get_image_dimensions(field)[0]
|
||||
|
||||
def _get_FIELD_height(self, field):
|
||||
return self.__get_image_dimensions(field)[1]
|
||||
return self._get_image_dimensions(field)[1]
|
||||
|
||||
def _get_image_dimensions(self, field):
|
||||
cachename = "__%s_dimensions_cache" % field.name
|
||||
if not hasattr(self, cachename):
|
||||
from django.utils.images import get_image_dimensions
|
||||
filename = self.__get_FIELD_filename(field)()
|
||||
filename = self._get_FIELD_filename(field)()
|
||||
setattr(self, cachename, get_image_dimensions(filename))
|
||||
return getattr(self, cachename)
|
||||
|
||||
|
@ -327,14 +327,18 @@ def get_digit(value, arg):
|
||||
# DATES #
|
||||
###################
|
||||
|
||||
def date(value, arg=settings.DATE_FORMAT):
|
||||
def date(value, arg=None):
|
||||
"Formats a date according to the given format"
|
||||
from django.utils.dateformat import format
|
||||
if arg is None:
|
||||
arg = settings.DATE_FORMAT
|
||||
return format(value, arg)
|
||||
|
||||
def time(value, arg=settings.TIME_FORMAT):
|
||||
def time(value, arg=None):
|
||||
"Formats a time according to the given format"
|
||||
from django.utils.dateformat import time_format
|
||||
if arg is None:
|
||||
arg = settings.TIME_FORMAT
|
||||
return time_format(value, arg)
|
||||
|
||||
def timesince(value):
|
||||
|
@ -117,9 +117,12 @@ def translation(language):
|
||||
|
||||
globalpath = os.path.join(os.path.dirname(sys.modules[settings.__module__].__file__), 'locale')
|
||||
|
||||
parts = settings.SETTINGS_MODULE.split('.')
|
||||
project = __import__(parts[0], {}, {}, [])
|
||||
projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
|
||||
if settings.SETTINGS_MODULE is not None:
|
||||
parts = settings.SETTINGS_MODULE.split('.')
|
||||
project = __import__(parts[0], {}, {}, [])
|
||||
projectpath = os.path.join(os.path.dirname(project.__file__), 'locale')
|
||||
else:
|
||||
projectpath = None
|
||||
|
||||
def _fetch(lang, fallback=None):
|
||||
|
||||
@ -155,7 +158,7 @@ def translation(language):
|
||||
if os.path.isdir(localepath):
|
||||
res = _merge(localepath)
|
||||
|
||||
if os.path.isdir(projectpath):
|
||||
if projectpath and os.path.isdir(projectpath):
|
||||
res = _merge(projectpath)
|
||||
|
||||
for appname in settings.INSTALLED_APPS:
|
||||
|
@ -107,7 +107,7 @@ def update_object(request, model, object_id=None, slug=None,
|
||||
errors = manipulator.get_validation_errors(new_data)
|
||||
manipulator.do_html2python(new_data)
|
||||
if not errors:
|
||||
manipulator.save(new_data)
|
||||
object = manipulator.save(new_data)
|
||||
|
||||
if not request.user.is_anonymous():
|
||||
request.user.message_set.create(message="The %s was updated successfully." % model._meta.verbose_name)
|
||||
|
@ -16,11 +16,35 @@ The automatic Django administrative interface. For more information, see
|
||||
|
||||
.. _Tutorial 2: http://www.djangoproject.com/documentation/tutorial2/
|
||||
|
||||
auth
|
||||
====
|
||||
|
||||
Django's authentication framework.
|
||||
|
||||
See the `authentication documentation`_.
|
||||
|
||||
.. _authentication documentation: http://www.djangoproject.com/documentation/authentication/
|
||||
|
||||
comments
|
||||
========
|
||||
|
||||
A simple yet flexible comments system. This is not yet documented.
|
||||
|
||||
contenttypes
|
||||
============
|
||||
|
||||
A light framework for hooking into "types" of content, where each installed
|
||||
Django model is a separate content type. This is not yet documented.
|
||||
|
||||
csrf
|
||||
====
|
||||
|
||||
A middleware for preventing Cross Site Request Forgeries
|
||||
|
||||
See the `csrf documentation`_.
|
||||
|
||||
.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/
|
||||
|
||||
flatpages
|
||||
=========
|
||||
|
||||
@ -48,6 +72,17 @@ See the `redirects documentation`_.
|
||||
|
||||
.. _redirects documentation: http://www.djangoproject.com/documentation/redirects/
|
||||
|
||||
sites
|
||||
=====
|
||||
|
||||
A light framework that lets you operate multiple Web sites off of the same
|
||||
database and Django installation. It gives you hooks for associating objects to
|
||||
one or more sites.
|
||||
|
||||
See the `sites documentation`_.
|
||||
|
||||
.. _sites documentation: http://www.djangoproject.com/documentation/sites/
|
||||
|
||||
syndication
|
||||
===========
|
||||
|
||||
@ -57,16 +92,6 @@ See the `syndication documentation`_.
|
||||
|
||||
.. _syndication documentation: http://www.djangoproject.com/documentation/syndication/
|
||||
|
||||
csrf
|
||||
====
|
||||
|
||||
A middleware for preventing Cross Site Request Forgeries
|
||||
|
||||
See the `csrf documentation`_.
|
||||
|
||||
.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/
|
||||
|
||||
|
||||
Other add-ons
|
||||
=============
|
||||
|
||||
|
@ -338,6 +338,60 @@ introduced in Python 2.4::
|
||||
* If the user is logged in, execute the view normally. The view code is
|
||||
free to assume the user is logged in.
|
||||
|
||||
Note that you'll need to map the appropriate Django view to ``/accounts/login/``.
|
||||
To do this, add the following line to your URLconf::
|
||||
|
||||
(r'^accounts/login/$', 'django.contrib.auth.views.login'),
|
||||
|
||||
Here's what ``django.contrib.auth.views.login`` does::
|
||||
|
||||
* If called via ``GET``, it displays a login form that POSTs to the same
|
||||
URL. More on this in a bit.
|
||||
|
||||
* If called via ``POST``, it tries to log the user in. If login is
|
||||
successful, the view redirects to the URL specified in ``next``. If
|
||||
``next`` isn't provided, it redirects to ``/accounts/profile/`` (which is
|
||||
currently hard-coded). If login isn't successful, it redisplays the login
|
||||
form.
|
||||
|
||||
It's your responsibility to provide the login form in a template called
|
||||
``registration/login.html``. This template gets passed three template context
|
||||
variables:
|
||||
|
||||
* ``form``: A ``FormWrapper`` object representing the login form. See the
|
||||
`forms documentation`_ for more on ``FormWrapper`` objects.
|
||||
* ``next``: The URL to redirect to after successful login. This may contain
|
||||
a query string, too.
|
||||
* ``site_name``: The name of the current ``Site``, according to the
|
||||
``SITE_ID`` setting. See the `site framework docs`_.
|
||||
|
||||
Here's a sample ``registration/login.html`` template you can use as a starting
|
||||
point. It assumes you have a ``base.html`` template that defines a ``content``
|
||||
block::
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% if form.has_errors %}
|
||||
<p>Your username and password didn't match. Please try again.</p>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action=".">
|
||||
<table>
|
||||
<tr><td><label for="id_username">Username:</label></td><td>{{ form.username }}</td></tr>
|
||||
<tr><td><label for="id_password">Password:</label></td><td>{{ form.password }}</td></tr>
|
||||
</table>
|
||||
|
||||
<input type="submit" value="login" />
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
.. _forms documentation: http://www.djangoproject.com/documentation/forms/
|
||||
.. _site framework docs: http://www.djangoproject.com/documentation/sites/
|
||||
|
||||
Limiting access to logged-in users that pass a test
|
||||
---------------------------------------------------
|
||||
|
||||
|
@ -177,6 +177,16 @@ Port 7000 on IP address 1.2.3.4::
|
||||
|
||||
django-admin.py runserver 1.2.3.4:7000
|
||||
|
||||
Serving static files with the development server
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
By default, the development server doesn't serve any static files for your site
|
||||
(such as CSS files, images, things under ``MEDIA_ROOT_URL`` and so forth). If
|
||||
you want to configure Django to serve static media, read the `serving static files`_
|
||||
documentation.
|
||||
|
||||
.. _serving static files: http://www.djangoproject.com/documentation/static_files/
|
||||
|
||||
shell
|
||||
-----
|
||||
|
||||
@ -200,6 +210,9 @@ sqlall [appname appname ...]
|
||||
|
||||
Prints the CREATE TABLE and initial-data SQL statements for the given appnames.
|
||||
|
||||
Refer to the description of ``sqlinitialdata`` for an explanation of how to
|
||||
specify initial data.
|
||||
|
||||
sqlclear [appname appname ...]
|
||||
--------------------------------------
|
||||
|
||||
@ -215,6 +228,18 @@ sqlinitialdata [appname appname ...]
|
||||
|
||||
Prints the initial INSERT SQL statements for the given appnames.
|
||||
|
||||
For each model in each specified app, this command looks for the file
|
||||
``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given appname and
|
||||
``<modelname>`` is the model's name in lowercase. For example, if you have an
|
||||
app ``news`` that includes a ``Story`` model, ``sqlinitialdata`` will attempt
|
||||
to read a file ``news/sql/story.sql`` and append it to the output of this
|
||||
command.
|
||||
|
||||
Each of the SQL files, if given, is expected to contain valid SQL. The SQL
|
||||
files are piped directly into the database after all of the models'
|
||||
table-creation statements have been executed. Use this SQL hook to populate
|
||||
tables with any necessary initial records, SQL functions or test data.
|
||||
|
||||
sqlreset [appname appname ...]
|
||||
--------------------------------------
|
||||
|
||||
@ -240,6 +265,20 @@ startproject [projectname]
|
||||
Creates a Django project directory structure for the given project name in the
|
||||
current directory.
|
||||
|
||||
syncdb
|
||||
------
|
||||
|
||||
Creates the database tables for all apps in ``INSTALLED_APPS`` whose tables
|
||||
have not already been created.
|
||||
|
||||
Use this command when you've added new applications to your project and want to
|
||||
install them in the database. This includes any apps shipped with Django that
|
||||
might be in ``INSTALLED_APPS`` by default. When you start a new project, run
|
||||
this command to install the default apps.
|
||||
|
||||
If you're installing the ``django.contrib.auth`` application, ``syncdb`` will
|
||||
give you the option of creating a superuser immediately.
|
||||
|
||||
validate
|
||||
--------
|
||||
|
||||
@ -286,6 +325,16 @@ setting the Python path for you.
|
||||
Displays a help message that includes a terse list of all available actions and
|
||||
options.
|
||||
|
||||
--version
|
||||
---------
|
||||
|
||||
Displays the current Django version.
|
||||
|
||||
Example output::
|
||||
|
||||
0.9.1
|
||||
0.9.1 (SVN)
|
||||
|
||||
Extra niceties
|
||||
==============
|
||||
|
||||
|
@ -62,6 +62,15 @@ Most generic views require the ``queryset`` key, which is a ``QuerySet``
|
||||
instance; see the `database API docs`_ for more information about ``Queryset``
|
||||
objects.
|
||||
|
||||
Most views also take an optional ``extra_context`` dictionary that you can use
|
||||
to pass any auxiliary information you wish to the view. The values in the
|
||||
``extra_context`` dictionary can be either functions (or other callables) or
|
||||
other objects. Functions are evaluated just before they are passed to the
|
||||
template. However, note that QuerySets retrieve and cache their data when they
|
||||
are first evaluated, so if you want to pass in a QuerySet via
|
||||
``extra_context`` that is always fresh you need to wrap it in a function or
|
||||
lambda that returns the QuerySet.
|
||||
|
||||
.. _database API docs: http://www.djangoproject.com/documentation/db_api/
|
||||
|
||||
"Simple" generic views
|
||||
@ -160,10 +169,10 @@ a date in the *future* are not included.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``extra_context``: A dictionary of values to add to the template
|
||||
context. By default, this is an empty dictionary.
|
||||
dictionary is callable, the generic view will call it
|
||||
just before rendering the template.
|
||||
|
||||
* ``allow_empty``: A boolean specifying whether to display the page if no
|
||||
objects are available. If this is ``False`` and no objects are available,
|
||||
@ -225,10 +234,10 @@ with a date in the *future* are not displayed.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``allow_empty``: A boolean specifying whether to display the page if no
|
||||
objects are available. If this is ``False`` and no objects are available,
|
||||
@ -287,10 +296,10 @@ date in the *future* are not displayed.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``allow_empty``: A boolean specifying whether to display the page if no
|
||||
objects are available. If this is ``False`` and no objects are available,
|
||||
@ -360,10 +369,10 @@ in the *future* are not displayed.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``allow_empty``: A boolean specifying whether to display the page if no
|
||||
objects are available. If this is ``False`` and no objects are available,
|
||||
@ -436,10 +445,10 @@ a 404 error, regardless of whether any objects exist for future days.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``allow_empty``: A boolean specifying whether to display the page if no
|
||||
objects are available. If this is ``False`` and no objects are available,
|
||||
@ -543,10 +552,10 @@ A page representing an individual object.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``context_processors``: A list of template-context processors to apply to
|
||||
the view's template. See the `RequestContext docs`_.
|
||||
@ -600,10 +609,10 @@ A page representing a list of objects.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``allow_empty``: A boolean specifying whether to display the page if no
|
||||
objects are available. If this is ``False`` and no objects are available,
|
||||
@ -697,10 +706,10 @@ A page representing an individual object.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``context_processors``: A list of template-context processors to apply to
|
||||
the view's template. See the `RequestContext docs`_.
|
||||
@ -764,10 +773,10 @@ automatic manipulators that come with Django models.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``context_processors``: A list of template-context processors to apply to
|
||||
the view's template. See the `RequestContext docs`_.
|
||||
@ -843,10 +852,10 @@ object. This uses the automatic manipulators that come with Django models.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``context_processors``: A list of template-context processors to apply to
|
||||
the view's template. See the `RequestContext docs`_.
|
||||
@ -924,10 +933,10 @@ contain a form that POSTs to the same URL.
|
||||
* ``template_loader``: The template loader to use when loading the
|
||||
template. By default, it's ``django.template.loader``.
|
||||
|
||||
* ``extra_context``: A dictionary of values to add to the template context.
|
||||
If a value in the dictionary is callable, the generic view will call it
|
||||
just before rendering the template. By default, this is an empty
|
||||
dictionary.
|
||||
* ``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.
|
||||
|
||||
* ``context_processors``: A list of template-context processors to apply to
|
||||
the view's template. See the `RequestContext docs`_.
|
||||
|
@ -540,6 +540,17 @@ you can override base translations in your project path. Or, you can just build
|
||||
a big project out of several apps and put all translations into one big project
|
||||
message file. The choice is yours.
|
||||
|
||||
.. note::
|
||||
|
||||
If you're using manually configured settings, as described in the
|
||||
`settings documentation`_, the ``locale`` directory in the project
|
||||
directory will not be examined, since Django loses the ability to work out
|
||||
the location of the project directory. (Django normally uses the location
|
||||
of the settings file to determine this, and a settings file doesn't exist
|
||||
if you're manually configuring your settings.)
|
||||
|
||||
.. _settings documentation: http://www.djangoproject.com/documentation/settings/#using-settings-without-the-django-settings-module-environment-variable
|
||||
|
||||
All message file repositories are structured the same way. They are:
|
||||
|
||||
* ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
|
||||
|
@ -77,9 +77,9 @@ It's easy either way.
|
||||
Installing the official version
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1. Download Django-0.92.tar.gz from our `download page`_.
|
||||
2. ``tar xzvf Django-0.92.tar.gz``
|
||||
3. ``cd Django-0.92``
|
||||
1. Download Django-0.91.tar.gz from our `download page`_.
|
||||
2. ``tar xzvf Django-0.91.tar.gz``
|
||||
3. ``cd Django-0.91``
|
||||
4. ``sudo python setup.py install``
|
||||
|
||||
Note that the last command will automatically download and install setuptools_
|
||||
@ -89,6 +89,14 @@ connection.
|
||||
This will install Django in your Python installation's ``site-packages``
|
||||
directory.
|
||||
|
||||
.. note::
|
||||
|
||||
Due to recent backwards-incompatible changes, it is strongly recommended
|
||||
that you use the development version (below) for any new applications or
|
||||
if you are just starting to work with Django. The 0.91 release is a
|
||||
dead-end branch that is primarily of use for supporting legacy Django
|
||||
applications.
|
||||
|
||||
.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
|
||||
|
||||
Installing the development version
|
||||
|
@ -59,8 +59,12 @@ Adds a few conveniences for perfectionists:
|
||||
|
||||
* Performs URL rewriting based on the ``APPEND_SLASH`` and ``PREPEND_WWW``
|
||||
settings. If ``APPEND_SLASH`` is ``True``, URLs that lack a trailing
|
||||
slash will be redirected to the same URL with a trailing slash. If
|
||||
``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be
|
||||
slash will be redirected to the same URL with a trailing slash, unless the
|
||||
last component in the path contains a period. So ``foo.com/bar`` is
|
||||
redirected to ``foo.com/bar/``, but ``foo.com/bar/file.txt`` is passed
|
||||
through unchanged.
|
||||
|
||||
If ``PREPEND_WWW`` is ``True``, URLs that lack a leading "www." will be
|
||||
redirected to the same URL with a leading "www."
|
||||
|
||||
Both of these options are meant to normalize URLs. The philosophy is that
|
||||
|
@ -202,22 +202,22 @@ Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few
|
||||
steps:
|
||||
|
||||
1. In your settings file, you'll need to define ``MEDIA_ROOT`` as the
|
||||
full path to a directory where you'd like Django to store uploaded
|
||||
files. (For performance, these files are not stored in the database.)
|
||||
Define ``MEDIA_URL`` as the base public URL of that directory. Make
|
||||
sure that this directory is writable by the Web server's user
|
||||
account.
|
||||
full path to a directory where you'd like Django to store uploaded
|
||||
files. (For performance, these files are not stored in the database.)
|
||||
Define ``MEDIA_URL`` as the base public URL of that directory. Make
|
||||
sure that this directory is writable by the Web server's user
|
||||
account.
|
||||
|
||||
2. Add the ``FileField`` or ``ImageField`` to your model, making sure
|
||||
to define the ``upload_to`` option to tell Django to which
|
||||
subdirectory of ``MEDIA_ROOT`` it should upload files.
|
||||
to define the ``upload_to`` option to tell Django to which
|
||||
subdirectory of ``MEDIA_ROOT`` it should upload files.
|
||||
|
||||
3. All that will be stored in your database is a path to the file
|
||||
(relative to ``MEDIA_ROOT``). You'll must likely want to use the
|
||||
convenience ``get_<fieldname>_url`` function provided by Django. For
|
||||
example, if your ``ImageField`` is called ``mug_shot``, you can get
|
||||
the absolute URL to your image in a template with ``{{
|
||||
object.get_mug_shot_url }}``.
|
||||
(relative to ``MEDIA_ROOT``). You'll must likely want to use the
|
||||
convenience ``get_<fieldname>_url`` function provided by Django. For
|
||||
example, if your ``ImageField`` is called ``mug_shot``, you can get
|
||||
the absolute URL to your image in a template with ``{{
|
||||
object.get_mug_shot_url }}``.
|
||||
|
||||
.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
|
||||
|
||||
@ -1599,6 +1599,39 @@ API. See `Other lookup options`_.
|
||||
.. _Python DB-API: http://www.python.org/peps/pep-0249.html
|
||||
.. _Other lookup options: http://www.djangoproject.com/documentation/db_api/#extra-params-select-where-tables
|
||||
|
||||
Overriding default model methods
|
||||
--------------------------------
|
||||
|
||||
As explained in the `database API docs`_, each model gets a few methods
|
||||
automatically -- most notably, ``save()`` and ``delete()``. You can override
|
||||
these methods to alter behavior.
|
||||
|
||||
A classic use-case for overriding the built-in methods is if you want something
|
||||
to happen whenever you save an object. For example::
|
||||
|
||||
class Blog(models.Model):
|
||||
name = models.CharField(maxlength=100)
|
||||
tagline = models.TextField()
|
||||
|
||||
def save(self):
|
||||
do_something()
|
||||
super(Blog, self).save() # Call the "real" save() method.
|
||||
do_something_else()
|
||||
|
||||
You can also prevent saving::
|
||||
|
||||
class Blog(models.Model):
|
||||
name = models.CharField(maxlength=100)
|
||||
tagline = models.TextField()
|
||||
|
||||
def save(self):
|
||||
if self.name == "Yoko Ono's blog":
|
||||
return # Yoko shall never have her own blog!
|
||||
else:
|
||||
super(Blog, self).save() # Call the "real" save() method.
|
||||
|
||||
.. _database API docs: http://www.djangoproject.com/documentation/db_api/
|
||||
|
||||
Models across files
|
||||
===================
|
||||
|
||||
@ -1631,3 +1664,52 @@ read, in part::
|
||||
'mysite.myapp',
|
||||
#...
|
||||
)
|
||||
|
||||
Providing initial SQL data
|
||||
==========================
|
||||
|
||||
Django provides a hook for passing the database arbitrary SQL that's executed
|
||||
just after the CREATE TABLE statements. Use this hook, for example, if you want
|
||||
to populate default records, or create SQL functions, automatically.
|
||||
|
||||
The hook is simple: Django just looks for a file called
|
||||
``<appname>/sql/<modelname>.sql``, where ``<appname>`` is your app directory and
|
||||
``<modelname>`` is the model's name in lowercase.
|
||||
|
||||
In the ``Person`` example model at the top of this document, assuming it lives
|
||||
in an app called ``myapp``, you could add arbitrary SQL to the file
|
||||
``myapp/sql/person.sql``. Here's an example of what the file might contain::
|
||||
|
||||
INSERT INTO myapp_person (first_name, last_name) VALUES ('John', 'Lennon');
|
||||
INSERT INTO myapp_person (first_name, last_name) VALUES ('Paul', 'McCartney');
|
||||
|
||||
Each SQL file, if given, is expected to contain valid SQL. The SQL files are
|
||||
piped directly into the database after all of the models' table-creation
|
||||
statements have been executed.
|
||||
|
||||
The SQL files are read by the ``sqlinitialdata``, ``sqlreset``, ``sqlall`` and
|
||||
``reset`` commands in ``manage.py``. Refer to the `manage.py documentation`_
|
||||
for more information.
|
||||
|
||||
Note that if you have multiple SQL data files, there's no guarantee of the
|
||||
order in which they're executed. The only thing you can assume is that, by the
|
||||
time your custom data files are executed, all the database tables already will
|
||||
have been created.
|
||||
|
||||
.. _`manage.py documentation`: http://www.djangoproject.com/documentation/django_admin/#sqlinitialdata-appname-appname
|
||||
|
||||
Database-backend-specific SQL data
|
||||
----------------------------------
|
||||
|
||||
There's also a hook for backend-specific SQL data. For example, you can have
|
||||
separate initial-data files for PostgreSQL and MySQL. For each app, Django
|
||||
looks for a file called ``<appname>/sql/<modelname>.<backend>.sql``, where
|
||||
``<appname>`` is your app directory, ``<modelname>`` is the model's name in
|
||||
lowercase and ``<backend>`` is the value of ``DATABASE_ENGINE`` in your
|
||||
settings file (e.g., ``postgresql``, ``mysql``).
|
||||
|
||||
Backend-specific SQL data is executed before non-backend-specific SQL data. For
|
||||
example, if your app contains the files ``sql/person.sql`` and
|
||||
``sql/person.postgresql.sql`` and you're installing the app on PostgreSQL,
|
||||
Django will execute the contents of ``sql/person.postgresql.sql`` first, then
|
||||
``sql/person.sql``.
|
||||
|
@ -619,6 +619,10 @@ The ID, as an integer, of the current site in the ``django_site`` database
|
||||
table. This is used so that application data can hook into specific site(s)
|
||||
and a single database can manage content for multiple sites.
|
||||
|
||||
See the `site framework docs`_.
|
||||
|
||||
.. _site framework docs: http://www.djangoproject.com/documentation/sites/
|
||||
|
||||
TEMPLATE_CONTEXT_PROCESSORS
|
||||
---------------------------
|
||||
|
||||
@ -724,3 +728,77 @@ Django apps. Just follow these conventions:
|
||||
* For settings that are sequences, use tuples instead of lists. This is
|
||||
purely for performance.
|
||||
* Don't reinvent an already-existing setting.
|
||||
|
||||
Using settings without setting DJANGO_SETTINGS_MODULE
|
||||
=====================================================
|
||||
|
||||
In some cases, you might want to bypass the ``DJANGO_SETTINGS_MODULE``
|
||||
environment variable. For example, if you're using the template system by
|
||||
itself, you likely don't want to have to set up an environment variable
|
||||
pointing to a settings module.
|
||||
|
||||
In these cases, you can configure Django's settings manually. Do this by
|
||||
calling ``django.conf.settings.configure()``.
|
||||
|
||||
Example::
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
settings.configure(DEBUG=True, TEMPLATE_DEBUG=True,
|
||||
TEMPLATE_DIRS=('/home/web-apps/myapp', '/home/web-apps/base'))
|
||||
|
||||
Pass ``configure()`` as many keyword arguments as you'd like, with each keyword
|
||||
argument representing a setting and its value. Each argument name should be all
|
||||
uppercase, with the same name as the settings described above. If a particular
|
||||
setting is not passed to ``configure()`` and is needed at some later point,
|
||||
Django will use the default setting value.
|
||||
|
||||
Custom default settings
|
||||
-----------------------
|
||||
|
||||
If you'd like default values to come from somewhere other than
|
||||
``django.conf.global_settings``, you can pass in a module or class that
|
||||
provides the default settings as the ``default_settings`` argument (or as the
|
||||
first positional argument) in the call to ``configure()``.
|
||||
|
||||
In this example, default settings are taken from ``myapp_defaults``, and the
|
||||
``DEBUG`` setting is set to ``True``, regardless of its value in
|
||||
``myapp_defaults``::
|
||||
|
||||
from django.conf import settings
|
||||
from myapp import myapp_defaults
|
||||
|
||||
settings.configure(default_settings=myapp_defaults, DEBUG=True)
|
||||
|
||||
The following example, which uses ``myapp_defaults`` as a positional argument,
|
||||
is equivalent::
|
||||
|
||||
settings.configure(myapp_defaults, DEBUG = True)
|
||||
|
||||
Normally, you will not need to override the defaults in this fashion. The
|
||||
Django defaults are sufficiently tame that you can safely use them. Be aware
|
||||
that if you do pass in a new default module, it entirely *replaces* the Django
|
||||
defaults, so you must specify a value for every possible setting that might be
|
||||
used in that code you are importing. Check in
|
||||
``django.conf.settings.global_settings`` for the full list.
|
||||
|
||||
Either configure() or DJANGO_SETTINGS_MODULE is required
|
||||
--------------------------------------------------------
|
||||
|
||||
If you're not setting the ``DJANGO_SETTINGS_MODULE`` environment variable, you
|
||||
*must* call ``configure()`` at some point before using any code that reads
|
||||
settings.
|
||||
|
||||
If you don't set ``DJANGO_SETTINGS_MODULE`` and don't call ``configure()``,
|
||||
Django will raise an ``EnvironmentError`` exception the first time a setting
|
||||
is accessed.
|
||||
|
||||
If you set ``DJANGO_SETTINGS_MODULE``, access settings values somehow, *then*
|
||||
call ``configure()``, Django will raise an ``EnvironmentError`` saying settings
|
||||
have already been configured.
|
||||
|
||||
Also, it's an error to call ``configure()`` more than once, or to call
|
||||
``configure()`` after any setting has been accessed.
|
||||
|
||||
It boils down to this: Use exactly one of either ``configure()`` or
|
||||
``DJANGO_SETTINGS_MODULE``. Not both, and not neither.
|
||||
|
311
docs/sites.txt
Normal file
311
docs/sites.txt
Normal file
@ -0,0 +1,311 @@
|
||||
=====================
|
||||
The "sites" framework
|
||||
=====================
|
||||
|
||||
Django comes with an optional "sites" framework. It's a hook for associating
|
||||
objects and functionality to particular Web sites, and it's a holding place for
|
||||
the domain names and "verbose" names of your Django-powered sites.
|
||||
|
||||
Use it if your single Django installation powers more than one site and you
|
||||
need to differentiate between those sites in some way.
|
||||
|
||||
The whole sites framework is based on two simple concepts:
|
||||
|
||||
* The ``Site`` model, found in ``django.contrib.sites``, has ``domain`` and
|
||||
``name`` fields.
|
||||
* The ``SITE_ID`` setting specifies the database ID of the ``Site`` object
|
||||
associated with that particular settings file.
|
||||
|
||||
How you use this is up to you, but Django uses it in a couple of ways
|
||||
automatically via simple conventions.
|
||||
|
||||
Example usage
|
||||
=============
|
||||
|
||||
Why would you use sites? It's best explained through examples.
|
||||
|
||||
Associating content with multiple sites
|
||||
---------------------------------------
|
||||
|
||||
The Django-powered sites LJWorld.com_ and Lawrence.com_ are operated by the
|
||||
same news organization -- the Lawrence Journal-World newspaper in Lawrence,
|
||||
Kansas. LJWorld.com focuses on news, while Lawrence.com focuses on local
|
||||
entertainment. But sometimes editors want to publish an article on *both*
|
||||
sites.
|
||||
|
||||
The brain-dead way of solving the problem would be to require site producers to
|
||||
publish the same story twice: once for LJWorld.com and again for Lawrence.com.
|
||||
But that's inefficient for site producers, and it's redundant to store
|
||||
multiple copies of the same story in the database.
|
||||
|
||||
The better solution is simple: Both sites use the same article database, and an
|
||||
article is associated with one or more sites. In Django model terminology,
|
||||
that's represented by a ``ManyToManyField`` in the ``Article`` model::
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
class Article(models.Model):
|
||||
headline = models.CharField(maxlength=200)
|
||||
# ...
|
||||
sites = models.ManyToManyField(Site)
|
||||
|
||||
This accomplishes several things quite nicely:
|
||||
|
||||
* It lets the site producers edit all content -- on both sites -- in a
|
||||
single interface (the Django admin).
|
||||
|
||||
* It means the same story doesn't have to be published twice in the
|
||||
database; it only has a single record in the database.
|
||||
|
||||
* It lets the site developers use the same Django view code for both sites.
|
||||
The view code that displays a given story just checks to make sure the
|
||||
requested story is on the current site. It looks something like this::
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
def article_detail(request, article_id):
|
||||
try:
|
||||
a = Article.objects.get(id=article_id, sites__id__exact=settings.SITE_ID)
|
||||
except Article.DoesNotExist:
|
||||
raise Http404
|
||||
# ...
|
||||
|
||||
.. _ljworld.com: http://www.ljworld.com/
|
||||
.. _lawrence.com: http://www.lawrence.com/
|
||||
|
||||
Associating content with a single site
|
||||
--------------------------------------
|
||||
|
||||
Similarly, you can associate a model to the ``Site`` model in a many-to-one
|
||||
relationship, using ``ForeignKey``.
|
||||
|
||||
For example, if an article is only allowed on a single site, you'd use a model
|
||||
like this::
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
class Article(models.Model):
|
||||
headline = models.CharField(maxlength=200)
|
||||
# ...
|
||||
site = models.ForeignKey(Site)
|
||||
|
||||
This has the same benefits as described in the last section.
|
||||
|
||||
Hooking into the current site from views
|
||||
----------------------------------------
|
||||
|
||||
On a lower level, you can use the sites framework in your Django views to do
|
||||
particular things based on what site in which the view is being called.
|
||||
For example::
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
def my_view(request):
|
||||
if settings.SITE_ID == 3:
|
||||
# Do something.
|
||||
else:
|
||||
# Do something else.
|
||||
|
||||
Of course, it's ugly to hard-code the site IDs like that. This sort of
|
||||
hard-coding is best for hackish fixes that you need done quickly. A slightly
|
||||
cleaner way of accomplishing the same thing is to check the current site's
|
||||
domain::
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
def my_view(request):
|
||||
current_site = Site.objects.get(id=settings.SITE_ID)
|
||||
if current_site.domain == 'foo.com':
|
||||
# Do something
|
||||
else:
|
||||
# Do something else.
|
||||
|
||||
The idiom of retrieving the ``Site`` object for the value of
|
||||
``settings.SITE_ID`` is quite common, so the ``Site`` model's manager has a
|
||||
``get_current()`` method. This example is equivalent to the previous one::
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
def my_view(request):
|
||||
current_site = Site.objects.get_current()
|
||||
if current_site.domain == 'foo.com':
|
||||
# Do something
|
||||
else:
|
||||
# Do something else.
|
||||
|
||||
Getting the current domain for display
|
||||
--------------------------------------
|
||||
|
||||
LJWorld.com and Lawrence.com both have e-mail alert functionality, which lets
|
||||
readers sign up to get notifications when news happens. It's pretty basic: A
|
||||
reader signs up on a Web form, and he immediately gets an e-mail saying,
|
||||
"Thanks for your subscription."
|
||||
|
||||
It'd be inefficient and redundant to implement this signup-processing code
|
||||
twice, so the sites use the same code behind the scenes. But the "thank you for
|
||||
signing up" notice needs to be different for each site. By using ``Site``
|
||||
objects, we can abstract the "thank you" notice to use the values of the
|
||||
current site's ``name`` and ``domain``.
|
||||
|
||||
Here's an example of what the form-handling view looks like::
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.mail import send_mail
|
||||
|
||||
def register_for_newsletter(request):
|
||||
# Check form values, etc., and subscribe the user.
|
||||
# ...
|
||||
|
||||
current_site = Site.objects.get_current()
|
||||
send_mail('Thanks for subscribing to %s alerts' % current_site.name,
|
||||
'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name,
|
||||
'editor@%s' % current_site.domain,
|
||||
[user.email])
|
||||
|
||||
# ...
|
||||
|
||||
On Lawrence.com, this e-mail has the subject line "Thanks for subscribing to
|
||||
lawrence.com alerts." On LJWorld.com, the e-mail has the subject "Thanks for
|
||||
subscribing to LJWorld.com alerts." Same goes for the e-mail's message body.
|
||||
|
||||
Note that an even more flexible (but more heavyweight) way of doing this would
|
||||
be to use Django's template system. Assuming Lawrence.com and LJWorld.com have
|
||||
different template directories (``TEMPLATE_DIRS``), you could simply farm out
|
||||
to the template system like so::
|
||||
|
||||
from django.core.mail import send_mail
|
||||
from django.template import loader, Context
|
||||
|
||||
def register_for_newsletter(request):
|
||||
# Check form values, etc., and subscribe the user.
|
||||
# ...
|
||||
|
||||
subject = loader.get_template('alerts/subject.txt').render(Context({}))
|
||||
message = loader.get_template('alerts/message.txt').render(Context({}))
|
||||
send_mail(subject, message, 'editor@ljworld.com', [user.email])
|
||||
|
||||
# ...
|
||||
|
||||
In this case, you'd have to create ``subject.txt`` and ``message.txt`` template
|
||||
files for both the LJWorld.com and Lawrence.com template directories. That
|
||||
gives you more flexibility, but it's also more complex.
|
||||
|
||||
It's a good idea to exploit the ``Site`` objects as much as possible, to remove
|
||||
unneeded complexity and redundancy.
|
||||
|
||||
Getting the current domain for full URLs
|
||||
----------------------------------------
|
||||
|
||||
Django's ``get_absolute_url()`` convention is nice for getting your objects'
|
||||
URL without the domain name, but in some cases you might want to display the
|
||||
full URL -- with ``http://`` and the domain and everything -- for an object.
|
||||
To do this, you can use the sites framework. A simple example::
|
||||
|
||||
>>> from django.contrib.sites.models import Site
|
||||
>>> obj = MyModel.objects.get(id=3)
|
||||
>>> obj.get_absolute_url()
|
||||
'/mymodel/objects/3/'
|
||||
>>> Site.objects.get_current().domain
|
||||
'example.com'
|
||||
>>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())
|
||||
'http://example.com/mymodel/objects/3/'
|
||||
|
||||
The ``CurrentSiteManager``
|
||||
==========================
|
||||
|
||||
If ``Site``\s play a key role in your application, consider using the helpful
|
||||
``CurrentSiteManager`` in your model(s). It's a model manager_ that
|
||||
automatically filters its queries to include only objects associated with the
|
||||
current ``Site``.
|
||||
|
||||
Use ``CurrentSiteManager`` by adding it to your model explicitly. For example::
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.sites.models import Site
|
||||
from django.contrib.sites.managers import CurrentSiteManager
|
||||
|
||||
class Photo(models.Model):
|
||||
photo = models.FileField(upload_to='/home/photos')
|
||||
photographer_name = models.CharField(maxlength=100)
|
||||
pub_date = models.DateField()
|
||||
site = models.ForeignKey(Site)
|
||||
objects = models.Manager()
|
||||
on_site = CurrentSiteManager()
|
||||
|
||||
With this model, ``Photo.objects.all()`` will return all ``Photo`` objects in
|
||||
the database, but ``Photo.on_site.all()`` will return only the ``Photo``
|
||||
objects associated with the current site, according to the ``SITE_ID`` setting.
|
||||
|
||||
Put another way, these two statements are equivalent::
|
||||
|
||||
Photo.objects.filter(site=settings.SITE_ID)
|
||||
Photo.on_site.all()
|
||||
|
||||
How did ``CurrentSiteManager`` know which field of ``Photo`` was the ``Site``?
|
||||
It defaults to looking for a field called ``site``. If your model has a
|
||||
``ForeignKey`` or ``ManyToManyField`` called something *other* than ``site``,
|
||||
you need to explicitly pass that as the parameter to ``CurrentSiteManager``.
|
||||
The following model, which has a field called ``publish_on``, demonstrates
|
||||
this::
|
||||
|
||||
from django.db import models
|
||||
from django.contrib.sites.models import Site
|
||||
from django.contrib.sites.managers import CurrentSiteManager
|
||||
|
||||
class Photo(models.Model):
|
||||
photo = models.FileField(upload_to='/home/photos')
|
||||
photographer_name = models.CharField(maxlength=100)
|
||||
pub_date = models.DateField()
|
||||
publish_on = models.ForeignKey(Site)
|
||||
objects = models.Manager()
|
||||
on_site = CurrentSiteManager('publish_on')
|
||||
|
||||
If you attempt to use ``CurrentSiteManager`` and pass a field name that doesn't
|
||||
exist, Django will raise a ``ValueError``.
|
||||
|
||||
.. _manager: http://www.djangoproject.com/documentation/model_api/#managers
|
||||
|
||||
How Django uses the sites framework
|
||||
===================================
|
||||
|
||||
Although it's not required that you use the sites framework, it's strongly
|
||||
encouraged, because Django takes advantage of it in a few places. Even if your
|
||||
Django installation is powering only a single site, you should take the two
|
||||
seconds to create the site object with your ``domain`` and ``name``, and point
|
||||
to its ID in your ``SITE_ID`` setting.
|
||||
|
||||
Here's how Django uses the sites framework:
|
||||
|
||||
* In the `redirects framework`_, each redirect object is associated with a
|
||||
particular site. When Django searches for a redirect, it takes into
|
||||
account the current ``SITE_ID``.
|
||||
|
||||
* In the comments framework, each comment is associated with a particular
|
||||
site. When a comment is posted, its ``site`` is set to the current
|
||||
``SITE_ID``, and when comments are listed via the appropriate template
|
||||
tag, only the comments for the current site are displayed.
|
||||
|
||||
* In the `flatpages framework`_, each flatpage is associated with a
|
||||
particular site. When a flatpage is created, you specify its ``site``,
|
||||
and the ``FlatpageFallbackMiddleware`` checks the current ``SITE_ID`` in
|
||||
retrieving flatpages to display.
|
||||
|
||||
* In the `syndication framework`_, the templates for ``title`` and
|
||||
``description`` automatically have access to a variable ``{{{ site }}}``,
|
||||
which is the ``Site`` object representing the current site. Also, the
|
||||
hook for providing item URLs will use the ``domain`` from the current
|
||||
``Site`` object if you don't specify a fully-qualified domain.
|
||||
|
||||
* In the `authentication framework`_, the ``django.contrib.auth.views.login``
|
||||
view passes the current ``Site`` name to the template as ``{{{ site_name }}}``.
|
||||
|
||||
* The shortcut view (``django.views.defaults.shortcut``) uses the domain of
|
||||
the current ``Site`` object when calculating an object's URL.
|
||||
|
||||
.. _redirects framework: http://www.djangoproject.com/documentation/redirects/
|
||||
.. _flatpages framework: http://www.djangoproject.com/documentation/flatpages/
|
||||
.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
|
||||
.. _authentication framework: http://www.djangoproject.com/documentation/syndication/
|
@ -7,6 +7,10 @@ perspective -- how it works and how to extend it. If you're just looking for
|
||||
reference on the language syntax, see
|
||||
`The Django template language: For template authors`_.
|
||||
|
||||
If you're looking to use the Django template system as part of another
|
||||
application -- i.e., without the rest of the framework -- make sure to read
|
||||
the `configuration`_ section later in this document.
|
||||
|
||||
.. _`The Django template language: For template authors`: http://www.djangoproject.com/documentation/templates/
|
||||
|
||||
Basics
|
||||
@ -739,6 +743,164 @@ Python 2.4 and above::
|
||||
If you leave off the ``name`` argument, as in the second example above, Django
|
||||
will use the function's name as the tag name.
|
||||
|
||||
Shortcut for simple tags
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Many template tags take a single argument -- a string or a template variable
|
||||
reference -- and return a string after doing some processing based solely on
|
||||
the input argument and some external information. For example, the
|
||||
``current_time`` tag we wrote above is of this variety: we give it a format
|
||||
string, it returns the time as a string.
|
||||
|
||||
To ease the creation of the types of tags, Django provides a helper function,
|
||||
``simple_tag``. This function, which is a method of
|
||||
``django.template.Library``, takes a function that accepts one argument, wraps
|
||||
it in a ``render`` function and the other necessary bits mentioned above and
|
||||
registers it with the template system.
|
||||
|
||||
Our earlier ``current_time`` function could thus be written like this::
|
||||
|
||||
# This version of do_current_time takes only a single argument and returns
|
||||
# a string.
|
||||
|
||||
def do_current_time(token):
|
||||
try:
|
||||
# Splitting by None == splitting by spaces.
|
||||
tag_name, format_string = token.contents.split(None, 1)
|
||||
except ValueError:
|
||||
raise template.TemplateSyntaxError, "%r tag requires an argument" % token.contents[0]
|
||||
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
|
||||
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
|
||||
return datetime.datetime.now().strftime(self.format_string[1:-1])
|
||||
|
||||
register.simple_tag(do_current_time)
|
||||
|
||||
In Python 2.4, the decorator syntax also works::
|
||||
|
||||
@simple_tag
|
||||
def do_current_time(token):
|
||||
...
|
||||
|
||||
Inclusion tags
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Another type of template tag that is sometimes useful is when you want to
|
||||
display some data that is computed at render time in a template fragment. For
|
||||
example, in Django's admin interface, there is a line of buttons along the
|
||||
bottom of the `create/edit record` screen. These buttons always look the same,
|
||||
but the link targets change depending upon the object being edited. So they
|
||||
are a perfect example for using a small template that is filled in with
|
||||
details from the current object. To save typing, it would also be nice if we
|
||||
could wrap this whole display up in a single tag (in the admin templates this
|
||||
is the ``submit_row`` tag).
|
||||
|
||||
We call these sorts of tags `inclusion tags`. In your template, you pass in
|
||||
any appropriate arguments and the tag uses those arguments, together with the
|
||||
current context to render a template and include the result in the output.
|
||||
|
||||
Writing inclusion tags is probably best demonstrated by example. We will write
|
||||
a tag that outputs a list of choices for a Poll object, such as was created in
|
||||
the tutorials_. We will use this tag like this::
|
||||
|
||||
{{ show_results poll }}
|
||||
|
||||
and the output will be something like this::
|
||||
|
||||
<ul>
|
||||
<li>First choice</li>
|
||||
<li>Second choice</li>
|
||||
<li>Third choice</li>
|
||||
</ul>
|
||||
|
||||
First, we define the function which takes the argument and produces a
|
||||
dictionary of data for the result. The important point here is we only need to
|
||||
return a dictionary, not anything more complex. This will be used to substitue
|
||||
for values in the template fragment, just as when templates are used
|
||||
elsewhere.
|
||||
|
||||
::
|
||||
|
||||
def show_results(poll):
|
||||
choices = poll.choice_set.all()
|
||||
return {'choices': choices}
|
||||
|
||||
We also need to create the template that is used to render the output. This
|
||||
template is a fixed feature of the tag: the tag writer specifies it, not the
|
||||
template designer. In our case, the template is very simple::
|
||||
|
||||
<ul>
|
||||
{% for choice in choices %}
|
||||
<li> {{ choice }} </li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
Now we can create the inclusion tag. Suppose the above template is in a file
|
||||
called ``results.html`` in a directory that is searched by the template
|
||||
loader. We register our new tag similarly to a normal tag.
|
||||
|
||||
::
|
||||
|
||||
# Here, register is a django.template.Library instance, as before
|
||||
register.inclusion_tag('results.html')(show_results)
|
||||
|
||||
As always, Python 2.4 decorator syntax works as well, so we could have
|
||||
written
|
||||
|
||||
::
|
||||
|
||||
@inclusion_tag('results.html')
|
||||
def show_results(poll):
|
||||
...
|
||||
|
||||
when first creating the function.
|
||||
|
||||
In some cases, an inclusion tag might require a large number of arguments to
|
||||
display itself properly. In essence, it would depend largely on the current
|
||||
context it was being rendered with. We can make these sorts of tags easier to
|
||||
write by telling the ``inclusion_tag`` function that the whole context
|
||||
should be passed in as an argument to the function. This will be done
|
||||
invisibly as far as the template tag user is concerned: they will not need to
|
||||
do anything to pass in the context.
|
||||
|
||||
For example, suppose we are writing an inclusion tag that will always be used
|
||||
in a context that contains ``home_link`` and ``home_title`` variables that
|
||||
point back to the main page. We can write a tag that is used like this::
|
||||
|
||||
{{ jump_link }}
|
||||
|
||||
and renders this::
|
||||
|
||||
Jump directly to <a href="http://example.com/home">Home</a>
|
||||
|
||||
The tag function is almost as simple as before. This time it takes no
|
||||
arguments except the ``context`` (and the parameter `must` be called
|
||||
``context`` in this case; the special parameter named is used internally by
|
||||
Django to fill in the values correctly).
|
||||
|
||||
::
|
||||
|
||||
# The first argument *must* be called "context" here.
|
||||
def jump_link(context):
|
||||
return {
|
||||
'link': context['home_link'],
|
||||
'title': context['home_title'],
|
||||
}
|
||||
|
||||
Our template is very simple again::
|
||||
|
||||
Jump directly to <a href="{{ link }}">{{ title }}</a>.
|
||||
|
||||
Assuming the template is in a file called ``link.html``, we register this new
|
||||
tag as follows::
|
||||
|
||||
register.inclusion_tag('link.html', takes_context = True)(jump_link)
|
||||
|
||||
The ``takes_context`` parameter here defaults to *False*. When it is set to
|
||||
*True*, our tag is passed the implicit context as in this example. That is the
|
||||
only difference between this case and our previous use of ``inclusion_tag``.
|
||||
|
||||
.. _tutorials: http://www.djangoproject.com/documentation/tutorial1/#creating-models
|
||||
|
||||
Setting a variable in the context
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@ -876,3 +1038,37 @@ The only new concept here is the ``self.nodelist.render(context)`` in
|
||||
For more examples of complex rendering, see the source code for ``{% if %}``,
|
||||
``{% for %}``, ``{% ifequal %}`` and ``{% ifchanged %}``. They live in
|
||||
``django/template/defaulttags.py``.
|
||||
|
||||
.. _configuration:
|
||||
|
||||
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
|
||||
template system as part of a Django application, nothing here applies to
|
||||
you.
|
||||
|
||||
Normally, Django will load all the configuration information it needs from its
|
||||
own default configuration file, combined with the settings in the module given
|
||||
in the ``DJANGO_SETTINGS_MODULE`` environment variable. But if you're using the
|
||||
template system independently of the rest of Django, the environment variable
|
||||
approach isn't very convenient, because you probably want to configure the
|
||||
template system in line with the rest of your application rather than dealing
|
||||
with settings files and pointing to them via environment variables.
|
||||
|
||||
To solve this problem, you need to use the manual configuration option
|
||||
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),
|
||||
``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_*
|
||||
is of obvious interest.
|
||||
|
||||
.. _settings file: http://www.djangoproject.com/documentation/settings/#using-settings-without-the-django-settings-module-environment-variable
|
||||
.. _settings documentation: http://www.djangoproject.com/documentation/settings/
|
||||
|
@ -445,13 +445,13 @@ Once you're in the shell, explore the database API::
|
||||
|
||||
# objects.all() displays all the polls in the database.
|
||||
>>> Poll.objects.all()
|
||||
[<Poll object>]
|
||||
[<Poll: Poll object>]
|
||||
|
||||
|
||||
Wait a minute. ``<Poll object>`` is, utterly, an unhelpful representation of
|
||||
this object. Let's fix that by editing the polls model
|
||||
(in the ``polls/models.py`` file) and adding a ``__str__()`` method to
|
||||
both ``Poll`` and ``Choice``::
|
||||
Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful
|
||||
representation of this object. Let's fix that by editing the polls model (in
|
||||
the ``polls/models.py`` file) and adding a ``__str__()`` method to both
|
||||
``Poll`` and ``Choice``::
|
||||
|
||||
class Poll(models.Model):
|
||||
# ...
|
||||
@ -487,30 +487,30 @@ Let's jump back into the Python interactive shell by running
|
||||
|
||||
# Make sure our __str__() addition worked.
|
||||
>>> Poll.objects.all()
|
||||
[What's up?]
|
||||
[<Poll: What's up?>]
|
||||
|
||||
# Django provides a rich database lookup API that's entirely driven by
|
||||
# keyword arguments.
|
||||
>>> Poll.objects.filter(id=1)
|
||||
[What's up?]
|
||||
[<Poll: What's up?>]
|
||||
>>> Poll.objects.filter(question__startswith='What')
|
||||
[What's up?]
|
||||
[<Poll: What's up?>]
|
||||
|
||||
# Get the poll whose year is 2005. Of course, if you're going through this
|
||||
# tutorial in another year, change as appropriate.
|
||||
>>> Poll.objects.get(pub_date__year=2005)
|
||||
What's up?
|
||||
<Poll: What's up?>
|
||||
|
||||
>>> Poll.objects.get(id=2)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
DoesNotExist: Poll does not exist for {'id': 2}
|
||||
DoesNotExist: Poll matching query does not exist.
|
||||
|
||||
# Lookup by a primary key is the most common case, so Django provides a
|
||||
# shortcut for primary-key exact lookups.
|
||||
# The following is identical to Poll.objects.get(id=1).
|
||||
>>> Poll.objects.get(pk=1)
|
||||
What's up?
|
||||
<Poll: What's up?>
|
||||
|
||||
# Make sure our custom method worked.
|
||||
>>> p = Poll.objects.get(pk=1)
|
||||
@ -522,18 +522,18 @@ Let's jump back into the Python interactive shell by running
|
||||
# of available choices and returns the new Choice object.
|
||||
>>> p = Poll.objects.get(pk=1)
|
||||
>>> p.choice_set.create(choice='Not much', votes=0)
|
||||
Not much
|
||||
<Choice: Not much>
|
||||
>>> p.choice_set.create(choice='The sky', votes=0)
|
||||
The sky
|
||||
<Choice: The sky>
|
||||
>>> c = p.choice_set.create(choice='Just hacking again', votes=0)
|
||||
|
||||
# Choice objects have API access to their related Poll objects.
|
||||
>>> c.poll
|
||||
What's up?
|
||||
<Poll: What's up?>
|
||||
|
||||
# And vice versa: Poll objects get access to Choice objects.
|
||||
>>> p.choice_set.all()
|
||||
[Not much, The sky, Just hacking again]
|
||||
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
|
||||
>>> p.choice_set.count()
|
||||
3
|
||||
|
||||
@ -542,7 +542,7 @@ Let's jump back into the Python interactive shell by running
|
||||
# This works as many levels deep as you want. There's no limit.
|
||||
# Find all Choices for any poll whose pub_date is in 2005.
|
||||
>>> Choice.objects.filter(poll__pub_date__year=2005)
|
||||
[Not much, The sky, Just hacking again]
|
||||
[<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]
|
||||
|
||||
# Let's delete one of the choices. Use delete() for that.
|
||||
>>> c = p.choice_set.filter(choice__startswith='Just hacking')
|
||||
|
@ -507,4 +507,5 @@ def run_tests(verbosity=0, standalone=False):
|
||||
raise Exception, msg
|
||||
|
||||
if __name__ == "__main__":
|
||||
settings.configure()
|
||||
run_tests(1, True)
|
||||
|
@ -73,6 +73,10 @@ class TestRunner:
|
||||
def run_tests(self):
|
||||
from django.conf import settings
|
||||
|
||||
# An empty access of the settings to force the default options to be
|
||||
# installed prior to assigning to them.
|
||||
settings.INSTALLED_APPS
|
||||
|
||||
# Manually set INSTALLED_APPS to point to the test models.
|
||||
settings.INSTALLED_APPS = [MODEL_TESTS_DIR_NAME + '.' + a for a in get_test_models()]
|
||||
|
||||
@ -110,14 +114,11 @@ class TestRunner:
|
||||
global TEST_DATABASE_NAME
|
||||
TEST_DATABASE_NAME = ":memory:"
|
||||
else:
|
||||
# Create the test database and connect to it. We need autocommit()
|
||||
# because PostgreSQL doesn't allow CREATE DATABASE statements
|
||||
# within transactions.
|
||||
# Create the test database and connect to it. We need to autocommit
|
||||
# if the database supports it because PostgreSQL doesn't allow
|
||||
# CREATE/DROP DATABASE statements within transactions.
|
||||
cursor = connection.cursor()
|
||||
try:
|
||||
connection.connection.autocommit(1)
|
||||
except AttributeError:
|
||||
pass
|
||||
self._set_autocommit(connection)
|
||||
self.output(1, "Creating test database")
|
||||
try:
|
||||
cursor.execute("CREATE DATABASE %s" % TEST_DATABASE_NAME)
|
||||
@ -220,12 +221,8 @@ class TestRunner:
|
||||
settings.DATABASE_NAME = old_database_name
|
||||
cursor = connection.cursor()
|
||||
self.output(1, "Deleting test database")
|
||||
try:
|
||||
connection.connection.autocommit(1)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
time.sleep(1) # To avoid "database is being accessed by other users" errors.
|
||||
self._set_autocommit(connection)
|
||||
time.sleep(1) # To avoid "database is being accessed by other users" errors.
|
||||
cursor.execute("DROP DATABASE %s" % TEST_DATABASE_NAME)
|
||||
|
||||
# Display output.
|
||||
@ -239,6 +236,15 @@ class TestRunner:
|
||||
else:
|
||||
print "All tests passed."
|
||||
|
||||
def _set_autocommit(self, connection):
|
||||
"""
|
||||
Make sure a connection is in autocommit mode.
|
||||
"""
|
||||
if hasattr(connection.connection, "autocommit"):
|
||||
connection.connection.autocommit(True)
|
||||
elif hasattr(connection.connection, "set_isolation_level"):
|
||||
connection.connection.set_isolation_level(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
from optparse import OptionParser
|
||||
usage = "%prog [options] [model model model ...]"
|
||||
|
Loading…
x
Reference in New Issue
Block a user