mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
[per-object-permissions] Merged to revision 3582
git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@3583 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
4f0118995c
commit
4cfd3203a6
21
AUTHORS
21
AUTHORS
@ -16,12 +16,23 @@ before Simon departed and currently oversees things with Adrian.
|
|||||||
|
|
||||||
Wilson Miner <http://www.wilsonminer.com/>, who designed Django's admin
|
Wilson Miner <http://www.wilsonminer.com/>, who designed Django's admin
|
||||||
interface, pretty error pages, official Web site (djangoproject.com) and has
|
interface, pretty error pages, official Web site (djangoproject.com) and has
|
||||||
made many other contributions.
|
made many other contributions. He makes us look good.
|
||||||
|
|
||||||
|
Malcolm Tredinnick <http://www.pointy-stick.com/blog/>, who has made
|
||||||
|
significant contributions to all levels of the framework, from its database
|
||||||
|
layer to template system and documentation.
|
||||||
|
|
||||||
Georg "Hugo" Bauer <http://hugo.muensterland.org/>, who added
|
Georg "Hugo" Bauer <http://hugo.muensterland.org/>, who added
|
||||||
internationalization support, manages i18n contributions and has made a ton
|
internationalization support, manages i18n contributions and has made a ton
|
||||||
of excellent tweaks, feature additions and bug fixes.
|
of excellent tweaks, feature additions and bug fixes.
|
||||||
|
|
||||||
|
Luke Plant <http://lukeplant.me.uk/>, who has contributed many excellent
|
||||||
|
improvements, including database-level improvements, the CSRF middleware and
|
||||||
|
unit tests.
|
||||||
|
|
||||||
|
Russell Keith-Magee <freakboy@iinet.net.au>, who has contributed many excellent
|
||||||
|
improvements, including refactoring of the Django ORM code and unit tests.
|
||||||
|
|
||||||
Robert Wittams <http://robert.wittams.com/>, who majorly refactored the Django
|
Robert Wittams <http://robert.wittams.com/>, who majorly refactored the Django
|
||||||
admin application to allow for easier reuse and has made a ton of excellent
|
admin application to allow for easier reuse and has made a ton of excellent
|
||||||
tweaks, feature additions and bug fixes.
|
tweaks, feature additions and bug fixes.
|
||||||
@ -49,6 +60,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Amit Chakradeo <http://amit.chakradeo.net/>
|
Amit Chakradeo <http://amit.chakradeo.net/>
|
||||||
ChaosKCW
|
ChaosKCW
|
||||||
Ian Clelland <clelland@gmail.com>
|
Ian Clelland <clelland@gmail.com>
|
||||||
|
crankycoder@gmail.com
|
||||||
Matt Croydon <http://www.postneo.com/>
|
Matt Croydon <http://www.postneo.com/>
|
||||||
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
|
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
|
||||||
Jason Davies (Esaj) <http://www.jasondavies.com/>
|
Jason Davies (Esaj) <http://www.jasondavies.com/>
|
||||||
@ -59,6 +71,8 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Clint Ecker
|
Clint Ecker
|
||||||
gandalf@owca.info
|
gandalf@owca.info
|
||||||
Baishampayan Ghose
|
Baishampayan Ghose
|
||||||
|
martin.glueck@gmail.com
|
||||||
|
Simon Greenhill <dev@simon.net.nz>
|
||||||
Espen Grindhaug <http://grindhaug.org/>
|
Espen Grindhaug <http://grindhaug.org/>
|
||||||
Brant Harris
|
Brant Harris
|
||||||
hipertracker@gmail.com
|
hipertracker@gmail.com
|
||||||
@ -70,7 +84,6 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Michael Josephson <http://www.sdjournal.com/>
|
Michael Josephson <http://www.sdjournal.com/>
|
||||||
jpellerin@gmail.com
|
jpellerin@gmail.com
|
||||||
junzhang.jn@gmail.com
|
junzhang.jn@gmail.com
|
||||||
Russell Keith-Magee <freakboy@iinet.net.au>
|
|
||||||
Garth Kidd <http://www.deadlybloodyserious.com/>
|
Garth Kidd <http://www.deadlybloodyserious.com/>
|
||||||
kilian <kilian.cavalotti@lip6.fr>
|
kilian <kilian.cavalotti@lip6.fr>
|
||||||
Sune Kirkeby <http://ibofobi.dk/>
|
Sune Kirkeby <http://ibofobi.dk/>
|
||||||
@ -98,6 +111,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Sam Newman <http://www.magpiebrain.com/>
|
Sam Newman <http://www.magpiebrain.com/>
|
||||||
Neal Norwitz <nnorwitz@google.com>
|
Neal Norwitz <nnorwitz@google.com>
|
||||||
oggie rob <oz.robharvey@gmail.com>
|
oggie rob <oz.robharvey@gmail.com>
|
||||||
|
Jay Parlar <parlar@gmail.com>
|
||||||
pgross@thoughtworks.com
|
pgross@thoughtworks.com
|
||||||
phaedo <http://phaedo.cx/>
|
phaedo <http://phaedo.cx/>
|
||||||
phil@produxion.net
|
phil@produxion.net
|
||||||
@ -112,13 +126,14 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
|
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
|
||||||
David Schein
|
David Schein
|
||||||
sopel
|
sopel
|
||||||
|
Thomas Steinacher <tom@eggdrop.ch>
|
||||||
Radek Švarz <http://www.svarz.cz/translate/>
|
Radek Švarz <http://www.svarz.cz/translate/>
|
||||||
Swaroop C H <http://www.swaroopch.info>
|
Swaroop C H <http://www.swaroopch.info>
|
||||||
Aaron Swartz <http://www.aaronsw.com/>
|
Aaron Swartz <http://www.aaronsw.com/>
|
||||||
Tom Tobin
|
Tom Tobin
|
||||||
Tom Insam
|
Tom Insam
|
||||||
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
||||||
Malcolm Tredinnick
|
Karen Tracey <graybark@bellsouth.net>
|
||||||
Amit Upadhyay
|
Amit Upadhyay
|
||||||
Geert Vanderkelen
|
Geert Vanderkelen
|
||||||
Milton Waddams
|
Milton Waddams
|
||||||
|
17
INSTALL
17
INSTALL
@ -1,7 +1,22 @@
|
|||||||
Thanks for downloading Django.
|
Thanks for downloading Django.
|
||||||
|
|
||||||
To install it, make sure you have Python 2.3 or greater installed. Then run this command:
|
To install it, make sure you have Python 2.3 or greater installed. Then run
|
||||||
|
this command from the command prompt:
|
||||||
|
|
||||||
python setup.py install
|
python setup.py install
|
||||||
|
|
||||||
|
Note this requires a working Internet connection if you don't already have the
|
||||||
|
Python utility "setuptools" installed.
|
||||||
|
|
||||||
|
AS AN ALTERNATIVE, you can just copy the entire "django" directory to Python's
|
||||||
|
site-packages directory, which is located wherever your Python installation
|
||||||
|
lives. Some places you might check are:
|
||||||
|
|
||||||
|
/usr/lib/python2.4/site-packages (Unix, Python 2.4)
|
||||||
|
/usr/lib/python2.3/site-packages (Unix, Python 2.3)
|
||||||
|
C:\\PYTHON\site-packages (Windows)
|
||||||
|
|
||||||
|
This second solution does not require a working Internet connection; it
|
||||||
|
bypasses "setuptools" entirely.
|
||||||
|
|
||||||
For more detailed instructions, see docs/install.txt.
|
For more detailed instructions, see docs/install.txt.
|
||||||
|
@ -1 +1 @@
|
|||||||
VERSION = (0, 95, 'post-magic-removal')
|
VERSION = (0, 96, 'pre')
|
||||||
|
@ -14,7 +14,7 @@ def compile_messages():
|
|||||||
print "this script should be run from the django svn tree or your project or app tree"
|
print "this script should be run from the django svn tree or your project or app tree"
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
for (dirpath, dirnames, filenames) in os.walk(basedir):
|
for dirpath, dirnames, filenames in os.walk(basedir):
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
if f.endswith('.po'):
|
if f.endswith('.po'):
|
||||||
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
|
sys.stderr.write('processing file %s in %s\n' % (f, dirpath))
|
||||||
|
@ -252,6 +252,7 @@ MIDDLEWARE_CLASSES = (
|
|||||||
SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want.
|
SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want.
|
||||||
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
|
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
|
||||||
SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
|
SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
|
||||||
|
SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only).
|
||||||
SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request.
|
SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request.
|
||||||
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser.
|
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser.
|
||||||
|
|
||||||
|
Binary file not shown.
@ -5,17 +5,21 @@
|
|||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: django\n"
|
"Project-Id-Version: django 0.95\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2006-05-16 10:11+0200\n"
|
"POT-Creation-Date: 2006-05-16 10:11+0200\n"
|
||||||
"PO-Revision-Date: 2005-11-26 00:00\n"
|
"PO-Revision-Date: 2006-08-14 18:08+0300\n"
|
||||||
"Last-Translator: Dmitry Sorokin <ds@dial.com.ru>\n"
|
"Last-Translator: Grigory Fateyev <greg@dial.com.ru>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: Dialcom Services <greg@dial.com.ru>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Poedit-Language: Russian\n"
|
||||||
|
"X-Poedit-Country: RUSSIAN FEDERATION\n"
|
||||||
|
"X-Poedit-SourceCharset: utf-8\n"
|
||||||
|
|
||||||
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
#: contrib/comments/models.py:67
|
||||||
|
#: contrib/comments/models.py:166
|
||||||
msgid "object ID"
|
msgid "object ID"
|
||||||
msgstr "ID объекта"
|
msgstr "ID объекта"
|
||||||
|
|
||||||
@ -23,7 +27,8 @@ msgstr "ID объекта"
|
|||||||
msgid "headline"
|
msgid "headline"
|
||||||
msgstr "заголовок"
|
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
|
#: contrib/comments/models.py:167
|
||||||
msgid "comment"
|
msgid "comment"
|
||||||
msgstr "комментарий"
|
msgstr "комментарий"
|
||||||
@ -64,15 +69,18 @@ msgstr "рейтинг #8"
|
|||||||
msgid "is valid rating"
|
msgid "is valid rating"
|
||||||
msgstr "доступный рейтинг"
|
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"
|
msgid "date/time submitted"
|
||||||
msgstr "дата/время добавления"
|
msgstr "дата/время добавления"
|
||||||
|
|
||||||
#: contrib/comments/models.py:84 contrib/comments/models.py:170
|
#: contrib/comments/models.py:84
|
||||||
|
#: contrib/comments/models.py:170
|
||||||
msgid "is public"
|
msgid "is public"
|
||||||
msgstr "публичный"
|
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"
|
msgid "IP address"
|
||||||
msgstr "IP адрес"
|
msgstr "IP адрес"
|
||||||
|
|
||||||
@ -81,19 +89,15 @@ msgid "is removed"
|
|||||||
msgstr "удален"
|
msgstr "удален"
|
||||||
|
|
||||||
#: contrib/comments/models.py:86
|
#: contrib/comments/models.py:86
|
||||||
msgid ""
|
msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead."
|
||||||
"Check this box if the comment is inappropriate. A \"This comment has been "
|
msgstr "Отметте, если комментарий нежелателен. Сообщение \"Этот комментарий был удалён\" будет показано взамен."
|
||||||
"removed\" message will be displayed instead."
|
|
||||||
msgstr ""
|
|
||||||
"Отметте, если комментарий нежелателен. Сообщение \"Этот комментарий был "
|
|
||||||
"удалён\" будет показано взамен."
|
|
||||||
|
|
||||||
#: contrib/comments/models.py:91
|
#: contrib/comments/models.py:91
|
||||||
#, fuzzy
|
|
||||||
msgid "comments"
|
msgid "comments"
|
||||||
msgstr "комментарий"
|
msgstr "комментарии"
|
||||||
|
|
||||||
#: contrib/comments/models.py:131 contrib/comments/models.py:207
|
#: contrib/comments/models.py:131
|
||||||
|
#: contrib/comments/models.py:207
|
||||||
msgid "Content object"
|
msgid "Content object"
|
||||||
msgstr "Объект наполнения"
|
msgstr "Объект наполнения"
|
||||||
|
|
||||||
@ -151,7 +155,7 @@ msgstr "Карма счета"
|
|||||||
#: contrib/comments/models.py:242
|
#: contrib/comments/models.py:242
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(score)d rating by %(user)s"
|
msgid "%(score)d rating by %(user)s"
|
||||||
msgstr ""
|
msgstr "%(score)d рейтинг %(user)s"
|
||||||
|
|
||||||
#: contrib/comments/models.py:258
|
#: contrib/comments/models.py:258
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -196,7 +200,7 @@ msgstr "Удаления модератором"
|
|||||||
#: contrib/comments/models.py:285
|
#: contrib/comments/models.py:285
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Moderator deletion by %r"
|
msgid "Moderator deletion by %r"
|
||||||
msgstr ""
|
msgstr "Удаления модератора %r"
|
||||||
|
|
||||||
#: contrib/comments/views/karma.py:19
|
#: contrib/comments/views/karma.py:19
|
||||||
msgid "Anonymous users cannot vote"
|
msgid "Anonymous users cannot vote"
|
||||||
@ -211,20 +215,17 @@ msgid "No voting for yourself"
|
|||||||
msgstr "Нельзя голосовать за себя"
|
msgstr "Нельзя голосовать за себя"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:28
|
#: contrib/comments/views/comments.py:28
|
||||||
msgid ""
|
msgid "This rating is required because you've entered at least one other rating."
|
||||||
"This rating is required because you've entered at least one other rating."
|
msgstr "Этот рейтинг необходим, так как вы входили хоть однажды в другие рейтинги."
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:112
|
#: contrib/comments/views/comments.py:112
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"This comment was posted by a user who has posted fewer than %(count)s "
|
"This comment was posted by a user who has posted fewer than %(count)s comment:\n"
|
||||||
"comment:\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
"This comment was posted by a user who has posted fewer than %(count)s "
|
"This comment was posted by a user who has posted fewer than %(count)s comments:\n"
|
||||||
"comments:\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
@ -258,11 +259,8 @@ msgstr "Кто-то вмешивается в форму комментария
|
|||||||
|
|
||||||
#: contrib/comments/views/comments.py:207
|
#: contrib/comments/views/comments.py:207
|
||||||
#: contrib/comments/views/comments.py:292
|
#: contrib/comments/views/comments.py:292
|
||||||
msgid ""
|
msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid"
|
||||||
"The comment form had an invalid 'target' parameter -- the object ID was "
|
msgstr "Форма комментария имеет неверный 'target' параметр -- ID объекта неверно"
|
||||||
"invalid"
|
|
||||||
msgstr ""
|
|
||||||
"Форма комментария имеет неверный 'target' параметр -- ID объекта неверно"
|
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:257
|
#: contrib/comments/views/comments.py:257
|
||||||
#: contrib/comments/views/comments.py:321
|
#: contrib/comments/views/comments.py:321
|
||||||
@ -343,8 +341,11 @@ msgid ""
|
|||||||
"<h3>By %s:</h3>\n"
|
"<h3>By %s:</h3>\n"
|
||||||
"<ul>\n"
|
"<ul>\n"
|
||||||
msgstr ""
|
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
|
#: contrib/admin/filterspecs.py:143
|
||||||
msgid "All"
|
msgid "All"
|
||||||
msgstr "Все"
|
msgstr "Все"
|
||||||
@ -413,14 +414,11 @@ msgstr "журнальные записи"
|
|||||||
msgid "All dates"
|
msgid "All dates"
|
||||||
msgstr "Все даты"
|
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
|
#: contrib/auth/forms.py:41
|
||||||
msgid ""
|
msgid "Please enter a correct username and password. Note that both fields are case-sensitive."
|
||||||
"Please enter a correct username and password. Note that both fields are case-"
|
msgstr "Пожалуйста, вводите верные данные именя пользователя и пароль. Помните, оба поля чувствительны к регистру."
|
||||||
"sensitive."
|
|
||||||
msgstr ""
|
|
||||||
"Пожалуйста, вводите верные данные именя пользователя и пароль. Помните, оба "
|
|
||||||
"поля чувствительны к регистру."
|
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:23
|
#: contrib/admin/views/decorators.py:23
|
||||||
#: contrib/admin/templates/admin/login.html:25
|
#: contrib/admin/templates/admin/login.html:25
|
||||||
@ -428,20 +426,12 @@ msgid "Log in"
|
|||||||
msgstr "Вход"
|
msgstr "Вход"
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:61
|
#: contrib/admin/views/decorators.py:61
|
||||||
msgid ""
|
msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved."
|
||||||
"Please log in again, because your session has expired. Don't worry: Your "
|
msgstr "Пожалуйста войдите снова, посколькук ваша сессия устарела. Не беспокойтесь:введенные вами данные сохранены."
|
||||||
"submission has been saved."
|
|
||||||
msgstr ""
|
|
||||||
"Пожалуйста войдите снова, посколькук ваша сессия устарела. Не беспокойтесь:"
|
|
||||||
"введенные вами данные сохранены."
|
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:68
|
#: contrib/admin/views/decorators.py:68
|
||||||
msgid ""
|
msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again."
|
||||||
"Looks like your browser isn't configured to accept cookies. Please enable "
|
msgstr "Похоже, что ваш броузер не настроен на прием cookies. Пожалуйства включите cookie, перезагрузите страницу и попытайтесь снова. "
|
||||||
"cookies, reload this page, and try again."
|
|
||||||
msgstr ""
|
|
||||||
"Похоже, что ваш броузер не настроен на прием cookies. Пожалуйства включите "
|
|
||||||
"cookie, перезагрузите страницу и попытайтесь снова. "
|
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:82
|
#: contrib/admin/views/decorators.py:82
|
||||||
msgid "Usernames cannot contain the '@' character."
|
msgid "Usernames cannot contain the '@' character."
|
||||||
@ -450,7 +440,7 @@ msgstr "Имя пользователя не может включать сим
|
|||||||
#: contrib/admin/views/decorators.py:84
|
#: contrib/admin/views/decorators.py:84
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your e-mail address is not your username. Try '%s' instead."
|
msgid "Your e-mail address is not your username. Try '%s' instead."
|
||||||
msgstr ""
|
msgstr "Ваш e-mail адрес не ваше имя. Попробуйте '%s' в замен."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:226
|
#: contrib/admin/views/main.py:226
|
||||||
msgid "Site administration"
|
msgid "Site administration"
|
||||||
@ -461,11 +451,13 @@ msgstr "Администрирование сайта"
|
|||||||
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
||||||
msgstr "%(name)s \"%(obj)s\" были успешно добавлены."
|
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."
|
msgid "You may edit it again below."
|
||||||
msgstr "Вы снова можете редактировать их внизу"
|
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
|
#, python-format
|
||||||
msgid "You may add another %s below."
|
msgid "You may add another %s below."
|
||||||
msgstr "Вы можете добавить %s внизу."
|
msgstr "Вы можете добавить %s внизу."
|
||||||
@ -480,7 +472,8 @@ msgstr "Добавить %s"
|
|||||||
msgid "Added %s."
|
msgid "Added %s."
|
||||||
msgstr "Добавлено %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
|
#: contrib/admin/views/main.py:340
|
||||||
msgid "and"
|
msgid "and"
|
||||||
msgstr "и"
|
msgstr "и"
|
||||||
@ -497,18 +490,17 @@ msgstr "Удалено %s."
|
|||||||
|
|
||||||
#: contrib/admin/views/main.py:343
|
#: contrib/admin/views/main.py:343
|
||||||
msgid "No fields changed."
|
msgid "No fields changed."
|
||||||
msgstr ""
|
msgstr "Ни одно поле не изменено."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:346
|
#: contrib/admin/views/main.py:346
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
||||||
msgstr ""
|
msgstr "%(name)s \"%(obj)s\" было успешно изменено"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:354
|
#: contrib/admin/views/main.py:354
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
||||||
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
msgstr "%(name)s \"%(obj)s\" было успешно изменено. Вы можете редактировать его снова."
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:392
|
#: contrib/admin/views/main.py:392
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -549,9 +541,12 @@ msgstr "Выберите %s"
|
|||||||
msgid "Select %s to change"
|
msgid "Select %s to change"
|
||||||
msgstr "Выберите %s для изменения"
|
msgstr "Выберите %s для изменения"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
|
#: contrib/admin/views/doc.py:277
|
||||||
#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
|
#: contrib/admin/views/doc.py:286
|
||||||
#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
|
#: 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"
|
msgid "Integer"
|
||||||
msgstr "Целое"
|
msgstr "Целое"
|
||||||
|
|
||||||
@ -559,7 +554,8 @@ msgstr "Целое"
|
|||||||
msgid "Boolean (Either True or False)"
|
msgid "Boolean (Either True or False)"
|
||||||
msgstr "Логическое (True или 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
|
#, python-format
|
||||||
msgid "String (up to %(maxlength)s)"
|
msgid "String (up to %(maxlength)s)"
|
||||||
msgstr "Строка (до %(maxlength)s символов)"
|
msgstr "Строка (до %(maxlength)s символов)"
|
||||||
@ -580,7 +576,8 @@ msgstr "Дата (с указанием времени)"
|
|||||||
msgid "E-mail address"
|
msgid "E-mail address"
|
||||||
msgstr "E-mail адрес"
|
msgstr "E-mail адрес"
|
||||||
|
|
||||||
#: 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"
|
msgid "File path"
|
||||||
msgstr "Путь к файлу"
|
msgstr "Путь к файлу"
|
||||||
|
|
||||||
@ -594,7 +591,7 @@ msgstr "Логическое (True, False или None)"
|
|||||||
|
|
||||||
#: contrib/admin/views/doc.py:292
|
#: contrib/admin/views/doc.py:292
|
||||||
msgid "Relation to parent model"
|
msgid "Relation to parent model"
|
||||||
msgstr ""
|
msgstr "Зависимость на родительскую модель."
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:293
|
#: contrib/admin/views/doc.py:293
|
||||||
msgid "Phone number"
|
msgid "Phone number"
|
||||||
@ -608,7 +605,8 @@ msgstr "Текст"
|
|||||||
msgid "Time"
|
msgid "Time"
|
||||||
msgstr "Время"
|
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"
|
msgid "URL"
|
||||||
msgstr "URL"
|
msgstr "URL"
|
||||||
|
|
||||||
@ -688,12 +686,8 @@ msgid "DATE_WITH_TIME_FULL"
|
|||||||
msgstr "j. N Y, H:i"
|
msgstr "j. N Y, H:i"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/object_history.html:36
|
#: contrib/admin/templates/admin/object_history.html:36
|
||||||
msgid ""
|
msgid "This object doesn't have a change history. It probably wasn't added via this admin site."
|
||||||
"This object doesn't have a change history. It probably wasn't added via this "
|
msgstr "Данный обьект не имеет истории изменения. Возможно он не был добавлен через данный административный сайт."
|
||||||
"admin site."
|
|
||||||
msgstr ""
|
|
||||||
"Данный обьект не имеет истории изменения. Возможно он не был добавлен через "
|
|
||||||
"данный административный сайт."
|
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/base_site.html:4
|
#: contrib/admin/templates/admin/base_site.html:4
|
||||||
msgid "Django site admin"
|
msgid "Django site admin"
|
||||||
@ -716,12 +710,8 @@ msgid "Server Error <em>(500)</em>"
|
|||||||
msgstr "Ошибка сервера <em>(500)</em>"
|
msgstr "Ошибка сервера <em>(500)</em>"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/500.html:10
|
#: contrib/admin/templates/admin/500.html:10
|
||||||
msgid ""
|
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."
|
||||||
"There's been an error. It's been reported to the site administrators via e-"
|
msgstr "Произошла ошибка. Отчет об ошибке отправлен администраторам сайта по e-mailи она должна быть вскоре исправлена. Благодарим вас на терпение и помощь."
|
||||||
"mail and should be fixed shortly. Thanks for your patience."
|
|
||||||
msgstr ""
|
|
||||||
"Произошла ошибка. Отчет об ошибке отправлен администраторам сайта по e-mailи "
|
|
||||||
"она должна быть вскоре исправлена. Благодарим вас на терпение и помощь."
|
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/404.html:4
|
#: contrib/admin/templates/admin/404.html:4
|
||||||
#: contrib/admin/templates/admin/404.html:8
|
#: contrib/admin/templates/admin/404.html:8
|
||||||
@ -782,23 +772,13 @@ msgstr "Удалить"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/delete_confirmation.html:14
|
#: contrib/admin/templates/admin/delete_confirmation.html:14
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
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:"
|
||||||
"Deleting the %(object_name)s '%(object)s' would result in deleting related "
|
msgstr "Удаление объекта %(object_name)s '%(object)s' приведет к удалению зависимых элементов, но предоставленных вам прав недостаточно для удаления следующих типов объектов:"
|
||||||
"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
|
#: contrib/admin/templates/admin/delete_confirmation.html:21
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:"
|
||||||
"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of "
|
msgstr "Вы уверены, что хотите удалить %(object_name)s \"%(object)s\"? Все следующие объекты также будут удалены:"
|
||||||
"the following related items will be deleted:"
|
|
||||||
msgstr ""
|
|
||||||
"Вы уверены, что хотите удалить %(object_name)s \"%(object)s\"? Все "
|
|
||||||
"следующие объекты также будут удалены:"
|
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/delete_confirmation.html:26
|
#: contrib/admin/templates/admin/delete_confirmation.html:26
|
||||||
msgid "Yes, I'm sure"
|
msgid "Yes, I'm sure"
|
||||||
@ -807,7 +787,7 @@ msgstr "Да, я уверен"
|
|||||||
#: contrib/admin/templates/admin/filter.html:2
|
#: contrib/admin/templates/admin/filter.html:2
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid " By %(title)s "
|
msgid " By %(title)s "
|
||||||
msgstr ""
|
msgstr "К%(title)s "
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/search_form.html:8
|
#: contrib/admin/templates/admin/search_form.html:8
|
||||||
msgid "Go"
|
msgid "Go"
|
||||||
@ -871,12 +851,8 @@ msgid "Password reset"
|
|||||||
msgstr "Сброс пароля"
|
msgstr "Сброс пароля"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_form.html:12
|
#: contrib/admin/templates/registration/password_reset_form.html:12
|
||||||
msgid ""
|
msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you."
|
||||||
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
msgstr "Забыли пароль? Введите ваш e-mail адрес ниже и мы очистим ваш старый пароль, и вышлем вам по e-mail новый."
|
||||||
"your password and e-mail the new one to you."
|
|
||||||
msgstr ""
|
|
||||||
"Забыли пароль? Введите ваш e-mail адрес ниже и мы очистим ваш старый пароль, "
|
|
||||||
"и вышлем вам по e-mail новый."
|
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_form.html:16
|
#: contrib/admin/templates/registration/password_reset_form.html:16
|
||||||
msgid "E-mail address:"
|
msgid "E-mail address:"
|
||||||
@ -900,20 +876,12 @@ msgid "Password reset successful"
|
|||||||
msgstr "Успешная очистка пароля"
|
msgstr "Успешная очистка пароля"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_done.html:12
|
#: contrib/admin/templates/registration/password_reset_done.html:12
|
||||||
msgid ""
|
msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly."
|
||||||
"We've e-mailed a new password to the e-mail address you submitted. You "
|
msgstr "Мы отправили новый пароль по указанному вами адресу электронной почты. Вы должны его вскоре получить."
|
||||||
"should be receiving it shortly."
|
|
||||||
msgstr ""
|
|
||||||
"Мы отправили новый пароль по указанному вами адресу электронной почты. Вы "
|
|
||||||
"должны его вскоре получить."
|
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:12
|
#: contrib/admin/templates/registration/password_change_form.html:12
|
||||||
msgid ""
|
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."
|
||||||
"Please enter your old password, for security's sake, and then enter your new "
|
msgstr "В целях безопасности, пожалуйста, введите ваш старый пароль, затем - новый пароль дважды, с тем, чтобы мы могли убедиться в правильности написания."
|
||||||
"password twice so we can verify you typed it in correctly."
|
|
||||||
msgstr ""
|
|
||||||
"В целях безопасности, пожалуйста, введите ваш старый пароль, затем - новый "
|
|
||||||
"пароль дважды, с тем, чтобы мы могли убедиться в правильности написания."
|
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:17
|
#: contrib/admin/templates/registration/password_change_form.html:17
|
||||||
msgid "Old password:"
|
msgid "Old password:"
|
||||||
@ -986,24 +954,16 @@ msgid "Documentation for this page"
|
|||||||
msgstr "Документация по данной странице"
|
msgstr "Документация по данной странице"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:20
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:20
|
||||||
msgid ""
|
msgid "Jumps you from any page to the documentation for the view that generates that page."
|
||||||
"Jumps you from any page to the documentation for the view that generates "
|
msgstr "Перенаправит вас с любой страницы к просмотру документа, который генерирует эту страницу."
|
||||||
"that page."
|
|
||||||
msgstr ""
|
|
||||||
"Перенаправит вас с любой страницы к просмотру документа, который генерирует "
|
|
||||||
"эту страницу."
|
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
|
||||||
msgid "Show object ID"
|
msgid "Show object ID"
|
||||||
msgstr "Показать ID обьекта"
|
msgstr "Показать ID обьекта"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:23
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:23
|
||||||
msgid ""
|
msgid "Shows the content-type and unique ID for pages that represent a single object."
|
||||||
"Shows the content-type and unique ID for pages that represent a single "
|
msgstr "Показывает тип наполнения и уникальный ID для страниц, которые означают одинокий объект."
|
||||||
"object."
|
|
||||||
msgstr ""
|
|
||||||
"Показывает тип наполнения и уникальный ID для страниц, которые означают "
|
|
||||||
"одинокий объект."
|
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
|
||||||
msgid "Edit this object (current window)"
|
msgid "Edit this object (current window)"
|
||||||
@ -1042,24 +1002,16 @@ msgid "redirect from"
|
|||||||
msgstr "перенаправить из"
|
msgstr "перенаправить из"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:8
|
#: contrib/redirects/models.py:8
|
||||||
msgid ""
|
msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'."
|
||||||
"This should be an absolute path, excluding the domain name. Example: '/"
|
msgstr "Это должен быть абсолютный путь, исключая доменное имя. Пример: '/events/search/'."
|
||||||
"events/search/'."
|
|
||||||
msgstr ""
|
|
||||||
"Это должен быть абсолютный путь, исключая доменное имя. Пример: '/events/"
|
|
||||||
"search/'."
|
|
||||||
|
|
||||||
#: contrib/redirects/models.py:9
|
#: contrib/redirects/models.py:9
|
||||||
msgid "redirect to"
|
msgid "redirect to"
|
||||||
msgstr "перенаправить на"
|
msgstr "перенаправить на"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:10
|
#: contrib/redirects/models.py:10
|
||||||
msgid ""
|
msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'."
|
||||||
"This can be either an absolute path (as above) or a full URL starting with "
|
msgstr "Это должен быть, либо абсолютный путь (как выше) или полный URL начинающийся с 'http://'."
|
||||||
"'http://'."
|
|
||||||
msgstr ""
|
|
||||||
"Это должен быть, либо абсолютный путь (как выше) или полный URL начинающийся "
|
|
||||||
"с 'http://'."
|
|
||||||
|
|
||||||
#: contrib/redirects/models.py:12
|
#: contrib/redirects/models.py:12
|
||||||
msgid "redirect"
|
msgid "redirect"
|
||||||
@ -1070,10 +1022,8 @@ msgid "redirects"
|
|||||||
msgstr "перенаправления"
|
msgstr "перенаправления"
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:8
|
#: contrib/flatpages/models.py:8
|
||||||
msgid ""
|
msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
|
||||||
"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
|
msgstr "Пример: '/about/contact/'. Будьте уверенны, что вставили завепршающий слэш."
|
||||||
msgstr ""
|
|
||||||
"Пример: '/about/contact/'. Будьте уверенны, что вставили завепршающий слэш."
|
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:9
|
#: contrib/flatpages/models.py:9
|
||||||
msgid "title"
|
msgid "title"
|
||||||
@ -1092,10 +1042,8 @@ msgid "template name"
|
|||||||
msgstr "имя шаблона"
|
msgstr "имя шаблона"
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:13
|
#: contrib/flatpages/models.py:13
|
||||||
msgid ""
|
msgid "Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'."
|
||||||
"Example: 'flatpages/contact_page'. If this isn't provided, the system will "
|
msgstr "Пример: 'flatpages/contact_page'. Если этот файл не присутствует, система будет использовать 'flatpages/default'."
|
||||||
"use 'flatpages/default'."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:14
|
#: contrib/flatpages/models.py:14
|
||||||
msgid "registration required"
|
msgid "registration required"
|
||||||
@ -1113,7 +1061,8 @@ msgstr "простая страница"
|
|||||||
msgid "flat pages"
|
msgid "flat pages"
|
||||||
msgstr "простые страницы"
|
msgstr "простые страницы"
|
||||||
|
|
||||||
#: contrib/auth/models.py:13 contrib/auth/models.py:26
|
#: contrib/auth/models.py:13
|
||||||
|
#: contrib/auth/models.py:26
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr "имя"
|
msgstr "имя"
|
||||||
|
|
||||||
@ -1125,7 +1074,8 @@ msgstr "код"
|
|||||||
msgid "permission"
|
msgid "permission"
|
||||||
msgstr "Права"
|
msgstr "Права"
|
||||||
|
|
||||||
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
#: contrib/auth/models.py:18
|
||||||
|
#: contrib/auth/models.py:27
|
||||||
msgid "permissions"
|
msgid "permissions"
|
||||||
msgstr "Права"
|
msgstr "Права"
|
||||||
|
|
||||||
@ -1133,7 +1083,8 @@ msgstr "Права"
|
|||||||
msgid "group"
|
msgid "group"
|
||||||
msgstr "Группа"
|
msgstr "Группа"
|
||||||
|
|
||||||
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
#: contrib/auth/models.py:30
|
||||||
|
#: contrib/auth/models.py:65
|
||||||
msgid "groups"
|
msgid "groups"
|
||||||
msgstr "Группы"
|
msgstr "Группы"
|
||||||
|
|
||||||
@ -1159,7 +1110,7 @@ msgstr "пароль"
|
|||||||
|
|
||||||
#: contrib/auth/models.py:59
|
#: contrib/auth/models.py:59
|
||||||
msgid "Use '[algo]$[salt]$[hexdigest]'"
|
msgid "Use '[algo]$[salt]$[hexdigest]'"
|
||||||
msgstr ""
|
msgstr "Используйте '[algo]$[salt]$[hexdigest]'"
|
||||||
|
|
||||||
#: contrib/auth/models.py:60
|
#: contrib/auth/models.py:60
|
||||||
msgid "staff status"
|
msgid "staff status"
|
||||||
@ -1186,12 +1137,8 @@ msgid "date joined"
|
|||||||
msgstr "дата регистрации"
|
msgstr "дата регистрации"
|
||||||
|
|
||||||
#: contrib/auth/models.py:66
|
#: contrib/auth/models.py:66
|
||||||
msgid ""
|
msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."
|
||||||
"In addition to the permissions manually assigned, this user will also get "
|
msgstr "К добавлению к перавам выбрнанным вуручную, этот пользователь может получить все права группы, к которой он принадлежит."
|
||||||
"all permissions granted to each group he/she is in."
|
|
||||||
msgstr ""
|
|
||||||
"К добавлению к перавам выбрнанным вуручную, этот пользователь может получить "
|
|
||||||
"все права группы, к которой он принадлежит."
|
|
||||||
|
|
||||||
#: contrib/auth/models.py:67
|
#: contrib/auth/models.py:67
|
||||||
msgid "user permissions"
|
msgid "user permissions"
|
||||||
@ -1226,10 +1173,8 @@ msgid "message"
|
|||||||
msgstr "Сообщение"
|
msgstr "Сообщение"
|
||||||
|
|
||||||
#: contrib/auth/forms.py:30
|
#: contrib/auth/forms.py:30
|
||||||
msgid ""
|
msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in."
|
||||||
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
|
msgstr "У вашего браузера не включены cookies. Cookies необходимы для входа."
|
||||||
"required for logging in."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:25
|
#: contrib/contenttypes/models.py:25
|
||||||
msgid "python model class name"
|
msgid "python model class name"
|
||||||
@ -1327,23 +1272,28 @@ msgstr "Январь"
|
|||||||
msgid "February"
|
msgid "February"
|
||||||
msgstr "Февраль"
|
msgstr "Февраль"
|
||||||
|
|
||||||
#: utils/dates.py:14 utils/dates.py:27
|
#: utils/dates.py:14
|
||||||
|
#: utils/dates.py:27
|
||||||
msgid "March"
|
msgid "March"
|
||||||
msgstr "Март"
|
msgstr "Март"
|
||||||
|
|
||||||
#: utils/dates.py:14 utils/dates.py:27
|
#: utils/dates.py:14
|
||||||
|
#: utils/dates.py:27
|
||||||
msgid "April"
|
msgid "April"
|
||||||
msgstr "Апрель"
|
msgstr "Апрель"
|
||||||
|
|
||||||
#: utils/dates.py:14 utils/dates.py:27
|
#: utils/dates.py:14
|
||||||
|
#: utils/dates.py:27
|
||||||
msgid "May"
|
msgid "May"
|
||||||
msgstr "Май"
|
msgstr "Май"
|
||||||
|
|
||||||
#: utils/dates.py:14 utils/dates.py:27
|
#: utils/dates.py:14
|
||||||
|
#: utils/dates.py:27
|
||||||
msgid "June"
|
msgid "June"
|
||||||
msgstr "Июнь"
|
msgstr "Июнь"
|
||||||
|
|
||||||
#: utils/dates.py:15 utils/dates.py:27
|
#: utils/dates.py:15
|
||||||
|
#: utils/dates.py:27
|
||||||
msgid "July"
|
msgid "July"
|
||||||
msgstr "Июль"
|
msgstr "Июль"
|
||||||
|
|
||||||
@ -1592,11 +1542,8 @@ msgid "This value must contain only letters, numbers and underscores."
|
|||||||
msgstr "Значение может содержать только буквы, цифры и подчеркивания."
|
msgstr "Значение может содержать только буквы, цифры и подчеркивания."
|
||||||
|
|
||||||
#: core/validators.py:64
|
#: core/validators.py:64
|
||||||
msgid ""
|
msgid "This value must contain only letters, numbers, underscores, dashes or slashes."
|
||||||
"This value must contain only letters, numbers, underscores, dashes or "
|
msgstr "Значение может содержать только буквы, цифры, подчеркивания, дифисы или тере."
|
||||||
"slashes."
|
|
||||||
msgstr "Значение может содержать только буквы, цифры, подчеркивания, дифисы или "
|
|
||||||
"тере."
|
|
||||||
|
|
||||||
#: core/validators.py:72
|
#: core/validators.py:72
|
||||||
msgid "Uppercase letters are not allowed here."
|
msgid "Uppercase letters are not allowed here."
|
||||||
@ -1646,7 +1593,8 @@ msgstr "Вводите реальную дату в формате YYYY-MM-DD."
|
|||||||
msgid "Enter a valid time in HH:MM format."
|
msgid "Enter a valid time in HH:MM format."
|
||||||
msgstr "Вводите реальное время в формате HH:MM."
|
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."
|
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
||||||
msgstr "Вводите реальные дата/время в формате YYYY-MM-DD HH:MM."
|
msgstr "Вводите реальные дата/время в формате YYYY-MM-DD HH:MM."
|
||||||
|
|
||||||
@ -1655,12 +1603,8 @@ msgid "Enter a valid e-mail address."
|
|||||||
msgstr "Укажите реальный e-mail адрес."
|
msgstr "Укажите реальный e-mail адрес."
|
||||||
|
|
||||||
#: core/validators.py:148
|
#: core/validators.py:148
|
||||||
msgid ""
|
msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image."
|
||||||
"Upload a valid image. The file you uploaded was either not an image or a "
|
msgstr "Загрузите реальное изображение. Файл, который вы загружали, не был изображением или был поврежден."
|
||||||
"corrupted image."
|
|
||||||
msgstr ""
|
|
||||||
"Загрузите реальное изображение. Файл, который вы загружали, не был "
|
|
||||||
"изображением или был поврежден."
|
|
||||||
|
|
||||||
#: core/validators.py:155
|
#: core/validators.py:155
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1700,7 +1644,8 @@ msgstr "Неверный формат XML: %s"
|
|||||||
msgid "Invalid URL: %s"
|
msgid "Invalid URL: %s"
|
||||||
msgstr "Неверный URL: %s"
|
msgstr "Неверный URL: %s"
|
||||||
|
|
||||||
#: core/validators.py:206 core/validators.py:208
|
#: core/validators.py:206
|
||||||
|
#: core/validators.py:208
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The URL %s is a broken link."
|
msgid "The URL %s is a broken link."
|
||||||
msgstr "URL %s сломанная ссылка."
|
msgstr "URL %s сломанная ссылка."
|
||||||
@ -1725,7 +1670,8 @@ msgstr "Это поле должно совпадать с полем '%s'."
|
|||||||
msgid "Please enter something for at least one field."
|
msgid "Please enter something for at least one field."
|
||||||
msgstr "Пожалуйста, заполните хотя бы одно поле."
|
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."
|
msgid "Please enter both fields or leave them both empty."
|
||||||
msgstr "Пожалуйста, заполните оба поля либо оставьте их пустыми."
|
msgstr "Пожалуйста, заполните оба поля либо оставьте их пустыми."
|
||||||
|
|
||||||
@ -1755,26 +1701,16 @@ msgstr "Пожалуйста, вводите корректное десятич
|
|||||||
#: core/validators.py:349
|
#: core/validators.py:349
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid decimal number with at most %s total digit."
|
msgid "Please enter a valid decimal number with at most %s total digit."
|
||||||
msgid_plural ""
|
msgid_plural "Please enter a valid decimal number with at most %s total digits."
|
||||||
"Please enter a valid decimal number with at most %s total digits."
|
msgstr[0] "Пожалуйста, вводите корректное десятичное число с максимальным количеством знаков %s."
|
||||||
msgstr[0] ""
|
msgstr[1] "Пожалуйста, вводите корректное десятичное число с максимальным количеством знаков %s."
|
||||||
"Пожалуйста, вводите корректное десятичное число с максимальным количеством "
|
|
||||||
"знаков %s."
|
|
||||||
msgstr[1] ""
|
|
||||||
"Пожалуйста, вводите корректное десятичное число с максимальным количеством "
|
|
||||||
"знаков %s."
|
|
||||||
|
|
||||||
#: core/validators.py:352
|
#: core/validators.py:352
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid decimal number with at most %s decimal place."
|
msgid "Please enter a valid decimal number with at most %s decimal place."
|
||||||
msgid_plural ""
|
msgid_plural "Please enter a valid decimal number with at most %s decimal places."
|
||||||
"Please enter a valid decimal number with at most %s decimal places."
|
msgstr[0] "Пожалуйста, вводите корректное десятичное число с максимальным количеством знаков после запятой %s."
|
||||||
msgstr[0] ""
|
msgstr[1] "Пожалуйста, вводите корректное десятичное число с максимальным количеством знаков после запятой %s."
|
||||||
"Пожалуйста, вводите корректное десятичное число с максимальным количеством "
|
|
||||||
"знаков после запятой %s."
|
|
||||||
msgstr[1] ""
|
|
||||||
"Пожалуйста, вводите корректное десятичное число с максимальным количеством "
|
|
||||||
"знаков после запятой %s."
|
|
||||||
|
|
||||||
#: core/validators.py:362
|
#: core/validators.py:362
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1801,50 +1737,37 @@ msgstr "Невозможно получить что-либо с %s."
|
|||||||
|
|
||||||
#: core/validators.py:429
|
#: core/validators.py:429
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
||||||
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
msgstr "URL %(url)s вернул неверный заголовок Content-Type '%(contenttype)s'."
|
||||||
msgstr "URL %(url) вернул неверный заголовок Content-Type '%(contenttype)'."
|
|
||||||
|
|
||||||
#: core/validators.py:462
|
#: core/validators.py:462
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)"
|
||||||
"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with "
|
|
||||||
"\"%(start)s\".)"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: core/validators.py:466
|
#: core/validators.py:466
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)"
|
||||||
"Some text starting on line %(line)s is not allowed in that context. (Line "
|
|
||||||
"starts with \"%(start)s\".)"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: core/validators.py:471
|
#: core/validators.py:471
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)"
|
||||||
"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%"
|
|
||||||
"(start)s\".)"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: core/validators.py:476
|
#: core/validators.py:476
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)"
|
||||||
"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%"
|
|
||||||
"(start)s\".)"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: core/validators.py:480
|
#: core/validators.py:480
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)"
|
||||||
"A tag on line %(line)s is missing one or more required attributes. (Line "
|
|
||||||
"starts with \"%(start)s\".)"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: core/validators.py:485
|
#: core/validators.py:485
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)"
|
||||||
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
|
|
||||||
"starts with \"%(start)s\".)"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: db/models/manipulators.py:302
|
#: db/models/manipulators.py:302
|
||||||
@ -1857,8 +1780,10 @@ msgstr ""
|
|||||||
msgid "%(optname)s with this %(fieldname)s already exists."
|
msgid "%(optname)s with this %(fieldname)s already exists."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
|
#: db/models/fields/__init__.py:114
|
||||||
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
|
#: db/models/fields/__init__.py:265
|
||||||
|
#: db/models/fields/__init__.py:542
|
||||||
|
#: db/models/fields/__init__.py:553
|
||||||
#: forms/__init__.py:346
|
#: forms/__init__.py:346
|
||||||
msgid "This field is required."
|
msgid "This field is required."
|
||||||
msgstr "Обязательное поле."
|
msgstr "Обязательное поле."
|
||||||
@ -1868,14 +1793,12 @@ msgid "This value must be an integer."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:369
|
#: db/models/fields/__init__.py:369
|
||||||
#, fuzzy
|
|
||||||
msgid "This value must be either True or False."
|
msgid "This value must be either True or False."
|
||||||
msgstr "Логическое (True или False)"
|
msgstr "Значение должно либо True либо False."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:385
|
#: db/models/fields/__init__.py:385
|
||||||
#, fuzzy
|
|
||||||
msgid "This field cannot be null."
|
msgid "This field cannot be null."
|
||||||
msgstr "Это поле неверно."
|
msgstr "Это поле не может быть нулевым."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:562
|
#: db/models/fields/__init__.py:562
|
||||||
msgid "Enter a valid filename."
|
msgid "Enter a valid filename."
|
||||||
@ -1887,23 +1810,17 @@ msgid "Please enter a valid %s."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: db/models/fields/related.py:579
|
#: db/models/fields/related.py:579
|
||||||
#, fuzzy
|
|
||||||
msgid "Separate multiple IDs with commas."
|
msgid "Separate multiple IDs with commas."
|
||||||
msgstr "Несколько значений ID разделяйте запятыми."
|
msgstr "Несколько значений ID разделяйте запятыми."
|
||||||
|
|
||||||
#: db/models/fields/related.py:581
|
#: db/models/fields/related.py:581
|
||||||
#, fuzzy
|
msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||||
msgid ""
|
msgstr " Удерживайте \"Control\", или \"Command\" на Макинтош, для выбора больше чем одного."
|
||||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
|
||||||
msgstr ""
|
|
||||||
" Удерживайте \"Control\", или \"Command\" на Макинтош, для выбора больше чем "
|
|
||||||
"одного."
|
|
||||||
|
|
||||||
#: db/models/fields/related.py:625
|
#: db/models/fields/related.py:625
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
||||||
msgid_plural ""
|
msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid."
|
||||||
"Please enter valid %(self)s IDs. The values %(value)r are invalid."
|
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
@ -1918,7 +1835,9 @@ msgstr[1] ""
|
|||||||
msgid "Line breaks are not allowed here."
|
msgid "Line breaks are not allowed here."
|
||||||
msgstr "Переносы строк не допускаются здесь."
|
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
|
#, python-format
|
||||||
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
|
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1943,30 +1862,3 @@ msgstr "Введите целое число в диапазоне от 0 до 3
|
|||||||
msgid "yes,no,maybe"
|
msgid "yes,no,maybe"
|
||||||
msgstr "да,нет,может быть"
|
msgstr "да,нет,может быть"
|
||||||
|
|
||||||
#~ msgid "Comment"
|
|
||||||
#~ msgstr "Комментарий"
|
|
||||||
|
|
||||||
#~ msgid "Comments"
|
|
||||||
#~ msgstr "Комментарии"
|
|
||||||
|
|
||||||
#~ msgid "label"
|
|
||||||
#~ msgstr "метка"
|
|
||||||
|
|
||||||
#~ msgid "package"
|
|
||||||
#~ msgstr "пакет"
|
|
||||||
|
|
||||||
#~ msgid "packages"
|
|
||||||
#~ msgstr "пакеты"
|
|
||||||
|
|
||||||
#~ msgid "String (up to 50)"
|
|
||||||
#~ msgstr "Строка (до 50 символов)"
|
|
||||||
|
|
||||||
#~ msgid ""
|
|
||||||
#~ "Example: 'flatfiles/contact_page'. If this isn't provided, the system "
|
|
||||||
#~ "will use 'flatfiles/default'."
|
|
||||||
#~ msgstr ""
|
|
||||||
#~ "Пример: 'flatfiles/contact_page'. Если не предусмотрена, система будет "
|
|
||||||
#~ "использовать 'flatfiles/default'."
|
|
||||||
|
|
||||||
#~ msgid "Server error <em>(500)</em>"
|
|
||||||
#~ msgstr "Ошибка сервера <em>(500)</em>"
|
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -60,8 +60,9 @@ MIDDLEWARE_CLASSES = (
|
|||||||
ROOT_URLCONF = '{{ project_name }}.urls'
|
ROOT_URLCONF = '{{ project_name }}.urls'
|
||||||
|
|
||||||
TEMPLATE_DIRS = (
|
TEMPLATE_DIRS = (
|
||||||
# Put strings here, like "/home/html/django_templates".
|
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
|
||||||
# Always use forward slashes, even on Windows.
|
# Always use forward slashes, even on Windows.
|
||||||
|
# Don't forget to use absolute paths, not relative paths.
|
||||||
)
|
)
|
||||||
|
|
||||||
INSTALLED_APPS = (
|
INSTALLED_APPS = (
|
||||||
|
@ -10,8 +10,10 @@ include = lambda urlconf_module: [urlconf_module]
|
|||||||
def patterns(prefix, *tuples):
|
def patterns(prefix, *tuples):
|
||||||
pattern_list = []
|
pattern_list = []
|
||||||
for t in tuples:
|
for t in tuples:
|
||||||
if type(t[1]) == list:
|
regex, view_or_include = t[:2]
|
||||||
pattern_list.append(RegexURLResolver(t[0], t[1][0]))
|
default_kwargs = t[2:]
|
||||||
|
if type(view_or_include) == list:
|
||||||
|
pattern_list.append(RegexURLResolver(regex, view_or_include[0], *default_kwargs))
|
||||||
else:
|
else:
|
||||||
pattern_list.append(RegexURLPattern(t[0], prefix and (prefix + '.' + t[1]) or t[1], *t[2:]))
|
pattern_list.append(RegexURLPattern(regex, prefix and (prefix + '.' + view_or_include) or view_or_include, *default_kwargs))
|
||||||
return pattern_list
|
return pattern_list
|
||||||
|
@ -8,7 +8,9 @@ var DateTimeShortcuts = {
|
|||||||
clockInputs: [],
|
clockInputs: [],
|
||||||
calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
|
calendarDivName1: 'calendarbox', // name of calendar <div> that gets toggled
|
||||||
calendarDivName2: 'calendarin', // name of <div> that contains calendar
|
calendarDivName2: 'calendarin', // name of <div> that contains calendar
|
||||||
|
calendarLinkName: 'calendarlink',// name of the link that is used to toggle
|
||||||
clockDivName: 'clockbox', // name of clock <div> that gets toggled
|
clockDivName: 'clockbox', // name of clock <div> that gets toggled
|
||||||
|
clockLinkName: 'clocklink', // name of the link that is used to toggle
|
||||||
admin_media_prefix: '',
|
admin_media_prefix: '',
|
||||||
init: function() {
|
init: function() {
|
||||||
// Deduce admin_media_prefix by looking at the <script>s in the
|
// Deduce admin_media_prefix by looking at the <script>s in the
|
||||||
@ -46,6 +48,7 @@ var DateTimeShortcuts = {
|
|||||||
now_link.appendChild(document.createTextNode(gettext('Now')));
|
now_link.appendChild(document.createTextNode(gettext('Now')));
|
||||||
var clock_link = document.createElement('a');
|
var clock_link = document.createElement('a');
|
||||||
clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
|
clock_link.setAttribute('href', 'javascript:DateTimeShortcuts.openClock(' + num + ');');
|
||||||
|
clock_link.id = DateTimeShortcuts.clockLinkName + num;
|
||||||
quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock'));
|
quickElement('img', clock_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_clock.gif', 'alt', gettext('Clock'));
|
||||||
shortcuts_span.appendChild(document.createTextNode('\240'));
|
shortcuts_span.appendChild(document.createTextNode('\240'));
|
||||||
shortcuts_span.appendChild(now_link);
|
shortcuts_span.appendChild(now_link);
|
||||||
@ -69,17 +72,6 @@ var DateTimeShortcuts = {
|
|||||||
var clock_box = document.createElement('div');
|
var clock_box = document.createElement('div');
|
||||||
clock_box.style.display = 'none';
|
clock_box.style.display = 'none';
|
||||||
clock_box.style.position = 'absolute';
|
clock_box.style.position = 'absolute';
|
||||||
if (getStyle(document.body,'direction')!='rtl') {
|
|
||||||
clock_box.style.left = findPosX(clock_link) + 17 + 'px';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// since style's width is in em, it'd be tough to calculate
|
|
||||||
// px value of it. let's use an estimated px for now
|
|
||||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
|
||||||
// (it returns as it was left aligned), needs to be fixed.
|
|
||||||
clock_box.style.left = findPosX(clock_link) - 110 + 'px';
|
|
||||||
}
|
|
||||||
clock_box.style.top = findPosY(clock_link) - 30 + 'px';
|
|
||||||
clock_box.className = 'clockbox module';
|
clock_box.className = 'clockbox module';
|
||||||
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
|
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
|
||||||
document.body.appendChild(clock_box);
|
document.body.appendChild(clock_box);
|
||||||
@ -98,7 +90,25 @@ var DateTimeShortcuts = {
|
|||||||
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
|
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissClock(' + num + ');');
|
||||||
},
|
},
|
||||||
openClock: function(num) {
|
openClock: function(num) {
|
||||||
document.getElementById(DateTimeShortcuts.clockDivName + num).style.display = 'block';
|
var clock_box = document.getElementById(DateTimeShortcuts.clockDivName+num)
|
||||||
|
var clock_link = document.getElementById(DateTimeShortcuts.clockLinkName+num)
|
||||||
|
|
||||||
|
// Recalculate the clockbox position
|
||||||
|
// is it left-to-right or right-to-left layout ?
|
||||||
|
if (getStyle(document.body,'direction')!='rtl') {
|
||||||
|
clock_box.style.left = findPosX(clock_link) + 17 + 'px';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// since style's width is in em, it'd be tough to calculate
|
||||||
|
// px value of it. let's use an estimated px for now
|
||||||
|
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||||
|
// (it returns as it was left aligned), needs to be fixed.
|
||||||
|
clock_box.style.left = findPosX(clock_link) - 110 + 'px';
|
||||||
|
}
|
||||||
|
clock_box.style.top = findPosY(clock_link) - 30 + 'px';
|
||||||
|
|
||||||
|
// Show the clock box
|
||||||
|
clock_box.style.display = 'block';
|
||||||
addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
|
addEvent(window, 'click', function() { DateTimeShortcuts.dismissClock(num); return true; });
|
||||||
},
|
},
|
||||||
dismissClock: function(num) {
|
dismissClock: function(num) {
|
||||||
@ -123,6 +133,7 @@ var DateTimeShortcuts = {
|
|||||||
today_link.appendChild(document.createTextNode(gettext('Today')));
|
today_link.appendChild(document.createTextNode(gettext('Today')));
|
||||||
var cal_link = document.createElement('a');
|
var cal_link = document.createElement('a');
|
||||||
cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
|
cal_link.setAttribute('href', 'javascript:DateTimeShortcuts.openCalendar(' + num + ');');
|
||||||
|
cal_link.id = DateTimeShortcuts.calendarLinkName + num;
|
||||||
quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar'));
|
quickElement('img', cal_link, '', 'src', DateTimeShortcuts.admin_media_prefix + 'img/admin/icon_calendar.gif', 'alt', gettext('Calendar'));
|
||||||
shortcuts_span.appendChild(document.createTextNode('\240'));
|
shortcuts_span.appendChild(document.createTextNode('\240'));
|
||||||
shortcuts_span.appendChild(today_link);
|
shortcuts_span.appendChild(today_link);
|
||||||
@ -149,18 +160,6 @@ var DateTimeShortcuts = {
|
|||||||
var cal_box = document.createElement('div');
|
var cal_box = document.createElement('div');
|
||||||
cal_box.style.display = 'none';
|
cal_box.style.display = 'none';
|
||||||
cal_box.style.position = 'absolute';
|
cal_box.style.position = 'absolute';
|
||||||
// is it left-to-right or right-to-left layout ?
|
|
||||||
if (getStyle(document.body,'direction')!='rtl') {
|
|
||||||
cal_box.style.left = findPosX(cal_link) + 17 + 'px';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// since style's width is in em, it'd be tough to calculate
|
|
||||||
// px value of it. let's use an estimated px for now
|
|
||||||
// TODO: IE returns wrong value for findPosX when in rtl mode
|
|
||||||
// (it returns as it was left aligned), needs to be fixed.
|
|
||||||
cal_box.style.left = findPosX(cal_link) - 180 + 'px';
|
|
||||||
}
|
|
||||||
cal_box.style.top = findPosY(cal_link) - 75 + 'px';
|
|
||||||
cal_box.className = 'calendarbox module';
|
cal_box.className = 'calendarbox module';
|
||||||
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
|
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
|
||||||
document.body.appendChild(cal_box);
|
document.body.appendChild(cal_box);
|
||||||
@ -195,7 +194,24 @@ var DateTimeShortcuts = {
|
|||||||
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
|
quickElement('a', cancel_p, gettext('Cancel'), 'href', 'javascript:DateTimeShortcuts.dismissCalendar(' + num + ');');
|
||||||
},
|
},
|
||||||
openCalendar: function(num) {
|
openCalendar: function(num) {
|
||||||
document.getElementById(DateTimeShortcuts.calendarDivName1+num).style.display = 'block';
|
var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num)
|
||||||
|
var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num)
|
||||||
|
|
||||||
|
// Recalculate the clockbox position
|
||||||
|
// is it left-to-right or right-to-left layout ?
|
||||||
|
if (getStyle(document.body,'direction')!='rtl') {
|
||||||
|
cal_box.style.left = findPosX(cal_link) + 17 + 'px';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// since style's width is in em, it'd be tough to calculate
|
||||||
|
// px value of it. let's use an estimated px for now
|
||||||
|
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||||
|
// (it returns as it was left aligned), needs to be fixed.
|
||||||
|
cal_box.style.left = findPosX(cal_link) - 180 + 'px';
|
||||||
|
}
|
||||||
|
cal_box.style.top = findPosY(cal_link) - 75 + 'px';
|
||||||
|
|
||||||
|
cal_box.style.display = 'block';
|
||||||
addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
|
addEvent(window, 'click', function() { DateTimeShortcuts.dismissCalendar(num); return true; });
|
||||||
},
|
},
|
||||||
dismissCalendar: function(num) {
|
dismissCalendar: function(num) {
|
||||||
|
@ -11,7 +11,7 @@ function showRelatedObjectLookupPopup(triggeringLink) {
|
|||||||
} else {
|
} else {
|
||||||
href = triggeringLink.href + '?pop=1';
|
href = triggeringLink.href + '?pop=1';
|
||||||
}
|
}
|
||||||
var win = window.open(href, name, 'height=500,width=740,resizable=yes,scrollbars=yes');
|
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||||
win.focus();
|
win.focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
28
django/contrib/admin/templates/admin/auth/user/add_form.html
Normal file
28
django/contrib/admin/templates/admin/auth/user/add_form.html
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{% extends "admin/change_form.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block after_field_sets %}
|
||||||
|
|
||||||
|
<p>{% trans "First, enter a username and password. Then, you'll be able to edit more user options." %}</p>
|
||||||
|
|
||||||
|
<fieldset class="module aligned">
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
{{ form.username.html_error_list }}
|
||||||
|
<label for="id_username" class="required">{% trans 'Username' %}:</label> {{ form.username }}
|
||||||
|
<p class="help">{{ username_help_text }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
{{ form.password1.html_error_list }}
|
||||||
|
<label for="id_password1" class="required">{% trans 'Password' %}:</label> {{ form.password1 }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
{{ form.password2.html_error_list }}
|
||||||
|
<label for="id_password2" class="required">{% trans 'Password (again)' %}:</label> {{ form.password2 }}
|
||||||
|
<p class="help">{% trans 'Enter the same password as above, for verification.' %}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</fieldset>
|
||||||
|
{% endblock %}
|
@ -21,7 +21,7 @@
|
|||||||
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
|
{% if has_absolute_url %}<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">{% trans "View on site" %}</a></li>{% endif%}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}{% endif %}
|
{% endif %}{% endif %}
|
||||||
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post">{% block form_top %}{% endblock %}
|
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="{{ form_url }}" method="post" id="{{ opts.module_name }}_form">{% block form_top %}{% endblock %}
|
||||||
<div>
|
<div>
|
||||||
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
|
{% if is_popup %}<input type="hidden" name="_popup" value="1" />{% endif %}
|
||||||
{% if opts.admin.save_on_top %}{% submit_row %}{% endif %}
|
{% if opts.admin.save_on_top %}{% submit_row %}{% endif %}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th>
|
<th{{ fw.header_class_attribute }}>{{ fw.field.verbose_name|capfirst|escape }}</th>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tr></thead>
|
||||||
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
{% for fcw in bound_related_object.form_field_collection_wrappers %}
|
||||||
{% if change %}{% if original_row_needed %}
|
{% if change %}{% if original_row_needed %}
|
||||||
{% if fcw.obj.original %}
|
{% if fcw.obj.original %}
|
||||||
|
39
django/contrib/admin/views/auth.py
Normal file
39
django/contrib/admin/views/auth.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
from django.contrib.auth.forms import UserCreationForm
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django import forms, template
|
||||||
|
from django.shortcuts import render_to_response
|
||||||
|
from django.http import HttpResponseRedirect
|
||||||
|
|
||||||
|
def user_add_stage(request):
|
||||||
|
manipulator = UserCreationForm()
|
||||||
|
if request.method == 'POST':
|
||||||
|
new_data = request.POST.copy()
|
||||||
|
errors = manipulator.get_validation_errors(new_data)
|
||||||
|
if not errors:
|
||||||
|
new_user = manipulator.save(new_data)
|
||||||
|
msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': 'user', 'obj': new_user}
|
||||||
|
if request.POST.has_key("_addanother"):
|
||||||
|
request.user.message_set.create(message=msg)
|
||||||
|
return HttpResponseRedirect(request.path)
|
||||||
|
else:
|
||||||
|
request.user.message_set.create(message=msg + ' ' + _("You may edit it again below."))
|
||||||
|
return HttpResponseRedirect('../%s/' % new_user.id)
|
||||||
|
else:
|
||||||
|
errors = new_data = {}
|
||||||
|
form = forms.FormWrapper(manipulator, new_data, errors)
|
||||||
|
return render_to_response('admin/auth/user/add_form.html', {
|
||||||
|
'title': _('Add user'),
|
||||||
|
'form': form,
|
||||||
|
'is_popup': request.REQUEST.has_key('_popup'),
|
||||||
|
'add': True,
|
||||||
|
'change': False,
|
||||||
|
'has_delete_permission': False,
|
||||||
|
'has_change_permission': True,
|
||||||
|
'has_file_field': False,
|
||||||
|
'has_absolute_url': False,
|
||||||
|
'auto_populated_fields': (),
|
||||||
|
'bound_field_sets': (),
|
||||||
|
'first_form_field_id': 'id_username',
|
||||||
|
'opts': User._meta,
|
||||||
|
'username_help_text': User._meta.get_field('username').help_text,
|
||||||
|
}, context_instance=template.RequestContext(request))
|
@ -43,11 +43,11 @@ def template_tag_index(request):
|
|||||||
for tag_name, tag_func in library.tags.items():
|
for tag_name, tag_func in library.tags.items():
|
||||||
title, body, metadata = utils.parse_docstring(tag_func.__doc__)
|
title, body, metadata = utils.parse_docstring(tag_func.__doc__)
|
||||||
if title:
|
if title:
|
||||||
title = utils.parse_rst(title, 'tag', 'tag:' + tag_name)
|
title = utils.parse_rst(title, 'tag', _('tag:') + tag_name)
|
||||||
if body:
|
if body:
|
||||||
body = utils.parse_rst(body, 'tag', 'tag:' + tag_name)
|
body = utils.parse_rst(body, 'tag', _('tag:') + tag_name)
|
||||||
for key in metadata:
|
for key in metadata:
|
||||||
metadata[key] = utils.parse_rst(metadata[key], 'tag', 'tag:' + tag_name)
|
metadata[key] = utils.parse_rst(metadata[key], 'tag', _('tag:') + tag_name)
|
||||||
if library in template.builtins:
|
if library in template.builtins:
|
||||||
tag_library = None
|
tag_library = None
|
||||||
else:
|
else:
|
||||||
@ -74,11 +74,11 @@ def template_filter_index(request):
|
|||||||
for filter_name, filter_func in library.filters.items():
|
for filter_name, filter_func in library.filters.items():
|
||||||
title, body, metadata = utils.parse_docstring(filter_func.__doc__)
|
title, body, metadata = utils.parse_docstring(filter_func.__doc__)
|
||||||
if title:
|
if title:
|
||||||
title = utils.parse_rst(title, 'filter', 'filter:' + filter_name)
|
title = utils.parse_rst(title, 'filter', _('filter:') + filter_name)
|
||||||
if body:
|
if body:
|
||||||
body = utils.parse_rst(body, 'filter', 'filter:' + filter_name)
|
body = utils.parse_rst(body, 'filter', _('filter:') + filter_name)
|
||||||
for key in metadata:
|
for key in metadata:
|
||||||
metadata[key] = utils.parse_rst(metadata[key], 'filter', 'filter:' + filter_name)
|
metadata[key] = utils.parse_rst(metadata[key], 'filter', _('filter:') + filter_name)
|
||||||
if library in template.builtins:
|
if library in template.builtins:
|
||||||
tag_library = None
|
tag_library = None
|
||||||
else:
|
else:
|
||||||
@ -132,11 +132,11 @@ def view_detail(request, view):
|
|||||||
raise Http404
|
raise Http404
|
||||||
title, body, metadata = utils.parse_docstring(view_func.__doc__)
|
title, body, metadata = utils.parse_docstring(view_func.__doc__)
|
||||||
if title:
|
if title:
|
||||||
title = utils.parse_rst(title, 'view', 'view:' + view)
|
title = utils.parse_rst(title, 'view', _('view:') + view)
|
||||||
if body:
|
if body:
|
||||||
body = utils.parse_rst(body, 'view', 'view:' + view)
|
body = utils.parse_rst(body, 'view', _('view:') + view)
|
||||||
for key in metadata:
|
for key in metadata:
|
||||||
metadata[key] = utils.parse_rst(metadata[key], 'model', 'view:' + view)
|
metadata[key] = utils.parse_rst(metadata[key], 'model', _('view:') + view)
|
||||||
return render_to_response('admin_doc/view_detail.html', {
|
return render_to_response('admin_doc/view_detail.html', {
|
||||||
'name': view,
|
'name': view,
|
||||||
'summary': title,
|
'summary': title,
|
||||||
@ -161,14 +161,14 @@ def model_detail(request, app_label, model_name):
|
|||||||
try:
|
try:
|
||||||
app_mod = models.get_app(app_label)
|
app_mod = models.get_app(app_label)
|
||||||
except ImproperlyConfigured:
|
except ImproperlyConfigured:
|
||||||
raise Http404, "App %r not found" % app_label
|
raise Http404, _("App %r not found") % app_label
|
||||||
model = None
|
model = None
|
||||||
for m in models.get_models(app_mod):
|
for m in models.get_models(app_mod):
|
||||||
if m._meta.object_name.lower() == model_name:
|
if m._meta.object_name.lower() == model_name:
|
||||||
model = m
|
model = m
|
||||||
break
|
break
|
||||||
if model is None:
|
if model is None:
|
||||||
raise Http404, "Model %r not found in app %r" % (model_name, app_label)
|
raise Http404, _("Model %r not found in app %r") % (model_name, app_label)
|
||||||
|
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ def model_detail(request, app_label, model_name):
|
|||||||
if isinstance(field, models.ForeignKey):
|
if isinstance(field, models.ForeignKey):
|
||||||
data_type = related_object_name = field.rel.to.__name__
|
data_type = related_object_name = field.rel.to.__name__
|
||||||
app_label = field.rel.to._meta.app_label
|
app_label = field.rel.to._meta.app_label
|
||||||
verbose = utils.parse_rst(("the related `%s.%s` object" % (app_label, data_type)), 'model', 'model:' + data_type)
|
verbose = utils.parse_rst((_("the related `%s.%s` object") % (app_label, data_type)), 'model', _('model:') + data_type)
|
||||||
else:
|
else:
|
||||||
data_type = get_readable_field_data_type(field)
|
data_type = get_readable_field_data_type(field)
|
||||||
verbose = field.verbose_name
|
verbose = field.verbose_name
|
||||||
@ -202,7 +202,7 @@ def model_detail(request, app_label, model_name):
|
|||||||
continue
|
continue
|
||||||
verbose = func.__doc__
|
verbose = func.__doc__
|
||||||
if verbose:
|
if verbose:
|
||||||
verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', 'model:' + opts.module_name)
|
verbose = utils.parse_rst(utils.trim_docstring(verbose), 'model', _('model:') + opts.module_name)
|
||||||
fields.append({
|
fields.append({
|
||||||
'name': func_name,
|
'name': func_name,
|
||||||
'data_type': get_return_data_type(func_name),
|
'data_type': get_return_data_type(func_name),
|
||||||
@ -211,17 +211,17 @@ def model_detail(request, app_label, model_name):
|
|||||||
|
|
||||||
# Gather related objects
|
# Gather related objects
|
||||||
for rel in opts.get_all_related_objects():
|
for rel in opts.get_all_related_objects():
|
||||||
verbose = "related `%s.%s` objects" % (rel.opts.app_label, rel.opts.object_name)
|
verbose = _("related `%s.%s` objects") % (rel.opts.app_label, rel.opts.object_name)
|
||||||
accessor = rel.get_accessor_name()
|
accessor = rel.get_accessor_name()
|
||||||
fields.append({
|
fields.append({
|
||||||
'name' : "%s.all" % accessor,
|
'name' : "%s.all" % accessor,
|
||||||
'data_type' : 'List',
|
'data_type' : 'List',
|
||||||
'verbose' : utils.parse_rst("all " + verbose , 'model', 'model:' + opts.module_name),
|
'verbose' : utils.parse_rst(_("all %s") % verbose , 'model', _('model:') + opts.module_name),
|
||||||
})
|
})
|
||||||
fields.append({
|
fields.append({
|
||||||
'name' : "%s.count" % accessor,
|
'name' : "%s.count" % accessor,
|
||||||
'data_type' : 'Integer',
|
'data_type' : 'Integer',
|
||||||
'verbose' : utils.parse_rst("number of " + verbose , 'model', 'model:' + opts.module_name),
|
'verbose' : utils.parse_rst(_("number of %s") % verbose , 'model', _('model:') + opts.module_name),
|
||||||
})
|
})
|
||||||
|
|
||||||
return render_to_response('admin_doc/model_detail.html', {
|
return render_to_response('admin_doc/model_detail.html', {
|
||||||
@ -336,7 +336,7 @@ def extract_views_from_urlpatterns(urlpatterns, base=''):
|
|||||||
elif hasattr(p, '_get_url_patterns'):
|
elif hasattr(p, '_get_url_patterns'):
|
||||||
views.extend(extract_views_from_urlpatterns(p.url_patterns, base + p.regex.pattern))
|
views.extend(extract_views_from_urlpatterns(p.url_patterns, base + p.regex.pattern))
|
||||||
else:
|
else:
|
||||||
raise TypeError, "%s does not appear to be a urlpattern object" % p
|
raise TypeError, _("%s does not appear to be a urlpattern object") % p
|
||||||
return views
|
return views
|
||||||
|
|
||||||
named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)')
|
named_group_matcher = re.compile(r'\(\?P(<\w+>).+?\)')
|
||||||
|
@ -263,7 +263,7 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
|
|||||||
post_url_continue += "?_popup=1"
|
post_url_continue += "?_popup=1"
|
||||||
return HttpResponseRedirect(post_url_continue % pk_value)
|
return HttpResponseRedirect(post_url_continue % pk_value)
|
||||||
if request.POST.has_key("_popup"):
|
if request.POST.has_key("_popup"):
|
||||||
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %s, "%s");</script>' % \
|
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, %r, "%s");</script>' % \
|
||||||
(pk_value, str(new_object).replace('"', '\\"')))
|
(pk_value, str(new_object).replace('"', '\\"')))
|
||||||
elif request.POST.has_key("_addanother"):
|
elif request.POST.has_key("_addanother"):
|
||||||
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
|
request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name))
|
||||||
|
@ -15,7 +15,6 @@ def user_passes_test(test_func, login_url=LOGIN_URL):
|
|||||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
|
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
|
||||||
_checklogin.__doc__ = view_func.__doc__
|
_checklogin.__doc__ = view_func.__doc__
|
||||||
_checklogin.__dict__ = view_func.__dict__
|
_checklogin.__dict__ = view_func.__dict__
|
||||||
_checklogin.__name__ = view_func.__name__
|
|
||||||
|
|
||||||
return _checklogin
|
return _checklogin
|
||||||
return _dec
|
return _dec
|
||||||
|
@ -5,6 +5,28 @@ from django.template import Context, loader
|
|||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django import forms
|
from django import forms
|
||||||
|
|
||||||
|
class UserCreationForm(forms.Manipulator):
|
||||||
|
"A form that creates a user, with no privileges, from the given username and password."
|
||||||
|
def __init__(self):
|
||||||
|
self.fields = (
|
||||||
|
forms.TextField(field_name='username', length=30, maxlength=30, is_required=True,
|
||||||
|
validator_list=[validators.isAlphaNumeric, self.isValidUsername]),
|
||||||
|
forms.PasswordField(field_name='password1', length=30, maxlength=60, is_required=True),
|
||||||
|
forms.PasswordField(field_name='password2', length=30, maxlength=60, is_required=True,
|
||||||
|
validator_list=[validators.AlwaysMatchesOtherField('password1', "The two password fields didn't match.")]),
|
||||||
|
)
|
||||||
|
|
||||||
|
def isValidUsername(self, field_data, all_data):
|
||||||
|
try:
|
||||||
|
User.objects.get(username=field_data)
|
||||||
|
except User.DoesNotExist:
|
||||||
|
return
|
||||||
|
raise validators.ValidationError, 'A user with that username already exists.'
|
||||||
|
|
||||||
|
def save(self, new_data):
|
||||||
|
"Creates the user."
|
||||||
|
return User.objects.create_user(new_data['username'], '', new_data['password1'])
|
||||||
|
|
||||||
class AuthenticationForm(forms.Manipulator):
|
class AuthenticationForm(forms.Manipulator):
|
||||||
"""
|
"""
|
||||||
Base class for authenticating users. Extend this to get a form that accepts
|
Base class for authenticating users. Extend this to get a form that accepts
|
||||||
|
@ -2,7 +2,7 @@ This is an optional add-on app, flatpages.
|
|||||||
|
|
||||||
For full documentation, see either of these:
|
For full documentation, see either of these:
|
||||||
|
|
||||||
* The file django/docs/flatpages.txt in the Django distribution
|
* The file docs/flatpages.txt in the Django distribution
|
||||||
* http://www.djangoproject.com/documentation/flatpages/ on the Web
|
* http://www.djangoproject.com/documentation/flatpages/ on the Web
|
||||||
|
|
||||||
Both have identical content.
|
Both have identical content.
|
@ -88,5 +88,6 @@ class SessionMiddleware(object):
|
|||||||
new_session = Session.objects.save(session_key, request.session._session,
|
new_session = Session.objects.save(session_key, request.session._session,
|
||||||
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
|
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
|
||||||
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
|
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key,
|
||||||
max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN)
|
max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
|
||||||
|
secure=settings.SESSION_COOKIE_SECURE or None)
|
||||||
return response
|
return response
|
||||||
|
@ -94,12 +94,15 @@ def get_sql_create(app):
|
|||||||
"Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n"))
|
"Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n"))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Get installed models, so we generate REFERENCES right
|
# Get installed models, so we generate REFERENCES right.
|
||||||
|
# We trim models from the current app so that the sqlreset command does not
|
||||||
|
# generate invalid SQL (leaving models out of known_models is harmless, so
|
||||||
|
# we can be conservative).
|
||||||
|
app_models = models.get_models(app)
|
||||||
final_output = []
|
final_output = []
|
||||||
known_models = set(_get_installed_models(_get_table_list()))
|
known_models = set([model for model in _get_installed_models(_get_table_list()) if model not in app_models])
|
||||||
pending_references = {}
|
pending_references = {}
|
||||||
|
|
||||||
app_models = models.get_models(app)
|
|
||||||
|
|
||||||
for model in app_models:
|
for model in app_models:
|
||||||
output, references = _get_sql_model_create(model, known_models)
|
output, references = _get_sql_model_create(model, known_models)
|
||||||
@ -118,10 +121,13 @@ def get_sql_create(app):
|
|||||||
# but don't exist physically
|
# but don't exist physically
|
||||||
not_installed_models = set(pending_references.keys())
|
not_installed_models = set(pending_references.keys())
|
||||||
if not_installed_models:
|
if not_installed_models:
|
||||||
final_output.append('-- The following references should be added but depend on non-existant tables:')
|
alter_sql = []
|
||||||
for model in not_installed_models:
|
for model in not_installed_models:
|
||||||
final_output.extend(['-- ' + sql for sql in
|
alter_sql.extend(['-- ' + sql for sql in
|
||||||
_get_sql_for_pending_references(model, pending_references)])
|
_get_sql_for_pending_references(model, pending_references)])
|
||||||
|
if alter_sql:
|
||||||
|
final_output.append('-- The following references should be added but depend on non-existent tables:')
|
||||||
|
final_output.extend(alter_sql)
|
||||||
|
|
||||||
return final_output
|
return final_output
|
||||||
get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app name(s)."
|
get_sql_create.help_doc = "Prints the CREATE TABLE SQL statements for the given app name(s)."
|
||||||
@ -192,7 +198,6 @@ def _get_sql_for_pending_references(model, pending_references):
|
|||||||
data_types = get_creation_module().DATA_TYPES
|
data_types = get_creation_module().DATA_TYPES
|
||||||
|
|
||||||
final_output = []
|
final_output = []
|
||||||
reference_names = {}
|
|
||||||
if backend.supports_constraints:
|
if backend.supports_constraints:
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
if model in pending_references:
|
if model in pending_references:
|
||||||
@ -202,12 +207,9 @@ def _get_sql_for_pending_references(model, pending_references):
|
|||||||
r_col = f.column
|
r_col = f.column
|
||||||
table = opts.db_table
|
table = opts.db_table
|
||||||
col = opts.get_field(f.rel.field_name).column
|
col = opts.get_field(f.rel.field_name).column
|
||||||
r_name = '%s_referencing_%s_%s' % (r_col, table, col)
|
# For MySQL, r_name must be unique in the first 64 characters.
|
||||||
if r_name in reference_names:
|
# So we are careful with character usage here.
|
||||||
reference_names[r_name] += 1
|
r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
|
||||||
r_name += '_%s' % reference_names[r_name]
|
|
||||||
else:
|
|
||||||
reference_names[r_name] = 0
|
|
||||||
final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
|
final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s);' % \
|
||||||
(backend.quote_name(r_table), r_name,
|
(backend.quote_name(r_table), r_name,
|
||||||
backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col)))
|
backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col)))
|
||||||
@ -299,7 +301,7 @@ def get_sql_delete(app):
|
|||||||
(style.SQL_KEYWORD('ALTER TABLE'),
|
(style.SQL_KEYWORD('ALTER TABLE'),
|
||||||
style.SQL_TABLE(backend.quote_name(table)),
|
style.SQL_TABLE(backend.quote_name(table)),
|
||||||
style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
|
style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
|
||||||
style.SQL_FIELD(backend.quote_name("%s_referencing_%s_%s" % (col, r_table, r_col)))))
|
style.SQL_FIELD(backend.quote_name('%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table))))))))
|
||||||
del references_to_delete[model]
|
del references_to_delete[model]
|
||||||
|
|
||||||
# Output DROP TABLE statements for many-to-many tables.
|
# Output DROP TABLE statements for many-to-many tables.
|
||||||
@ -696,9 +698,7 @@ def inspectdb():
|
|||||||
|
|
||||||
introspection_module = get_introspection_module()
|
introspection_module = get_introspection_module()
|
||||||
|
|
||||||
def table2model(table_name):
|
table2model = lambda table_name: table_name.title().replace('_', '')
|
||||||
object_name = table_name.title().replace('_', '')
|
|
||||||
return object_name.endswith('s') and object_name[:-1] or object_name
|
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
yield "# This is an auto-generated Django model module."
|
yield "# This is an auto-generated Django model module."
|
||||||
@ -727,6 +727,10 @@ def inspectdb():
|
|||||||
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
|
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
|
||||||
extra_params = {} # Holds Field parameters such as 'db_column'.
|
extra_params = {} # Holds Field parameters such as 'db_column'.
|
||||||
|
|
||||||
|
if ' ' in att_name:
|
||||||
|
extra_params['db_column'] = att_name
|
||||||
|
att_name = att_name.replace(' ', '')
|
||||||
|
comment_notes.append('Field renamed to remove spaces.')
|
||||||
if keyword.iskeyword(att_name):
|
if keyword.iskeyword(att_name):
|
||||||
extra_params['db_column'] = att_name
|
extra_params['db_column'] = att_name
|
||||||
att_name += '_field'
|
att_name += '_field'
|
||||||
@ -957,6 +961,12 @@ def get_validation_errors(outfile, app=None):
|
|||||||
f = opts.get_field(fn)
|
f = opts.get_field(fn)
|
||||||
except models.FieldDoesNotExist:
|
except models.FieldDoesNotExist:
|
||||||
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
|
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
|
||||||
|
# date_hierarchy
|
||||||
|
if opts.admin.date_hierarchy:
|
||||||
|
try:
|
||||||
|
f = opts.get_field(opts.admin.date_hierarchy)
|
||||||
|
except models.FieldDoesNotExist:
|
||||||
|
e.add(opts, '"admin.date_hierarchy" refers to %r, which isn\'t a field.' % opts.admin.date_hierarchy)
|
||||||
|
|
||||||
# Check ordering attribute.
|
# Check ordering attribute.
|
||||||
if opts.ordering:
|
if opts.ordering:
|
||||||
@ -1132,7 +1142,14 @@ def dbshell():
|
|||||||
dbshell.args = ""
|
dbshell.args = ""
|
||||||
|
|
||||||
def runfcgi(args):
|
def runfcgi(args):
|
||||||
"""Run this project as a FastCGI application. requires flup."""
|
"Runs this project as a FastCGI application. Requires flup."
|
||||||
|
from django.conf import settings
|
||||||
|
from django.utils import translation
|
||||||
|
# Activate the current language, because it won't get activated later.
|
||||||
|
try:
|
||||||
|
translation.activate(settings.LANGUAGE_CODE)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
from django.core.servers.fastcgi import runfastcgi
|
from django.core.servers.fastcgi import runfastcgi
|
||||||
runfastcgi(args)
|
runfastcgi(args)
|
||||||
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
|
runfcgi.args = '[various KEY=val options, use `runfcgi help` for help]'
|
||||||
@ -1289,7 +1306,11 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
|||||||
if action not in NO_SQL_TRANSACTION:
|
if action not in NO_SQL_TRANSACTION:
|
||||||
print style.SQL_KEYWORD("COMMIT;")
|
print style.SQL_KEYWORD("COMMIT;")
|
||||||
|
|
||||||
def execute_manager(settings_mod, argv=None):
|
def setup_environ(settings_mod):
|
||||||
|
"""
|
||||||
|
Configure the runtime environment. This can also be used by external
|
||||||
|
scripts wanting to set up a similar environment to manage.py.
|
||||||
|
"""
|
||||||
# Add this project to sys.path so that it's importable in the conventional
|
# Add this project to sys.path so that it's importable in the conventional
|
||||||
# way. For example, if this file (manage.py) lives in a directory
|
# way. For example, if this file (manage.py) lives in a directory
|
||||||
# "myproject", this code would add "/path/to/myproject" to sys.path.
|
# "myproject", this code would add "/path/to/myproject" to sys.path.
|
||||||
@ -1301,7 +1322,10 @@ def execute_manager(settings_mod, argv=None):
|
|||||||
|
|
||||||
# Set DJANGO_SETTINGS_MODULE appropriately.
|
# Set DJANGO_SETTINGS_MODULE appropriately.
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
|
os.environ['DJANGO_SETTINGS_MODULE'] = '%s.settings' % project_name
|
||||||
|
return project_directory
|
||||||
|
|
||||||
|
def execute_manager(settings_mod, argv=None):
|
||||||
|
project_directory = setup_environ(settings_mod)
|
||||||
action_mapping = DEFAULT_ACTION_MAPPING.copy()
|
action_mapping = DEFAULT_ACTION_MAPPING.copy()
|
||||||
|
|
||||||
# Remove the "startproject" command from the action_mapping, because that's
|
# Remove the "startproject" command from the action_mapping, because that's
|
||||||
|
@ -41,11 +41,11 @@ class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
|
|||||||
TIME_FORMAT = "%H:%M:%S"
|
TIME_FORMAT = "%H:%M:%S"
|
||||||
|
|
||||||
def default(self, o):
|
def default(self, o):
|
||||||
if isinstance(o, datetime.date):
|
if isinstance(o, datetime.datetime):
|
||||||
|
return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
|
||||||
|
elif isinstance(o, datetime.date):
|
||||||
return o.strftime(self.DATE_FORMAT)
|
return o.strftime(self.DATE_FORMAT)
|
||||||
elif isinstance(o, datetime.time):
|
elif isinstance(o, datetime.time):
|
||||||
return o.strftime(self.TIME_FORMAT)
|
return o.strftime(self.TIME_FORMAT)
|
||||||
elif isinstance(o, datetime.datetime):
|
|
||||||
return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT))
|
|
||||||
else:
|
else:
|
||||||
return super(self, DateTimeAwareJSONEncoder).default(o)
|
return super(self, DateTimeAwareJSONEncoder).default(o)
|
@ -547,10 +547,6 @@ class WSGIRequestHandler(BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
env['PATH_INFO'] = urllib.unquote(path)
|
env['PATH_INFO'] = urllib.unquote(path)
|
||||||
env['QUERY_STRING'] = query
|
env['QUERY_STRING'] = query
|
||||||
|
|
||||||
host = self.address_string()
|
|
||||||
if host != self.client_address[0]:
|
|
||||||
env['REMOTE_HOST'] = host
|
|
||||||
env['REMOTE_ADDR'] = self.client_address[0]
|
env['REMOTE_ADDR'] = self.client_address[0]
|
||||||
|
|
||||||
if self.headers.typeheader is None:
|
if self.headers.typeheader is None:
|
||||||
|
@ -86,10 +86,15 @@ class MatchChecker(object):
|
|||||||
class RegexURLPattern(object):
|
class RegexURLPattern(object):
|
||||||
def __init__(self, regex, callback, default_args=None):
|
def __init__(self, regex, callback, default_args=None):
|
||||||
# regex is a string representing a regular expression.
|
# regex is a string representing a regular expression.
|
||||||
# callback is something like 'foo.views.news.stories.story_detail',
|
# callback is either a string like 'foo.views.news.stories.story_detail'
|
||||||
# which represents the path to a module and a view function name.
|
# which represents the path to a module and a view function name, or a
|
||||||
|
# callable object (view).
|
||||||
self.regex = re.compile(regex)
|
self.regex = re.compile(regex)
|
||||||
self.callback = callback
|
if callable(callback):
|
||||||
|
self._callback = callback
|
||||||
|
else:
|
||||||
|
self._callback = None
|
||||||
|
self._callback_str = callback
|
||||||
self.default_args = default_args or {}
|
self.default_args = default_args or {}
|
||||||
|
|
||||||
def resolve(self, path):
|
def resolve(self, path):
|
||||||
@ -106,23 +111,28 @@ class RegexURLPattern(object):
|
|||||||
# In both cases, pass any extra_kwargs as **kwargs.
|
# In both cases, pass any extra_kwargs as **kwargs.
|
||||||
kwargs.update(self.default_args)
|
kwargs.update(self.default_args)
|
||||||
|
|
||||||
try: # Lazily load self.func.
|
return self.callback, args, kwargs
|
||||||
return self.func, args, kwargs
|
|
||||||
except AttributeError:
|
|
||||||
self.func = self.get_callback()
|
|
||||||
return self.func, args, kwargs
|
|
||||||
|
|
||||||
def get_callback(self):
|
def _get_callback(self):
|
||||||
mod_name, func_name = get_mod_func(self.callback)
|
if self._callback is not None:
|
||||||
|
return self._callback
|
||||||
|
mod_name, func_name = get_mod_func(self._callback_str)
|
||||||
try:
|
try:
|
||||||
return getattr(__import__(mod_name, '', '', ['']), func_name)
|
self._callback = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||||
except ImportError, e:
|
except ImportError, e:
|
||||||
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
|
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
|
||||||
except AttributeError, e:
|
except AttributeError, e:
|
||||||
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
|
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
|
||||||
|
return self._callback
|
||||||
|
callback = property(_get_callback)
|
||||||
|
|
||||||
def reverse(self, viewname, *args, **kwargs):
|
def reverse(self, viewname, *args, **kwargs):
|
||||||
if viewname != self.callback:
|
mod_name, func_name = get_mod_func(viewname)
|
||||||
|
try:
|
||||||
|
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
raise NoReverseMatch
|
||||||
|
if lookup_view != self.callback:
|
||||||
raise NoReverseMatch
|
raise NoReverseMatch
|
||||||
return self.reverse_helper(*args, **kwargs)
|
return self.reverse_helper(*args, **kwargs)
|
||||||
|
|
||||||
@ -130,12 +140,13 @@ class RegexURLPattern(object):
|
|||||||
return reverse_helper(self.regex, *args, **kwargs)
|
return reverse_helper(self.regex, *args, **kwargs)
|
||||||
|
|
||||||
class RegexURLResolver(object):
|
class RegexURLResolver(object):
|
||||||
def __init__(self, regex, urlconf_name):
|
def __init__(self, regex, urlconf_name, default_kwargs=None):
|
||||||
# regex is a string representing a regular expression.
|
# regex is a string representing a regular expression.
|
||||||
# urlconf_name is a string representing the module containing urlconfs.
|
# urlconf_name is a string representing the module containing urlconfs.
|
||||||
self.regex = re.compile(regex)
|
self.regex = re.compile(regex)
|
||||||
self.urlconf_name = urlconf_name
|
self.urlconf_name = urlconf_name
|
||||||
self.callback = None
|
self.callback = None
|
||||||
|
self.default_kwargs = default_kwargs or {}
|
||||||
|
|
||||||
def resolve(self, path):
|
def resolve(self, path):
|
||||||
tried = []
|
tried = []
|
||||||
@ -149,7 +160,8 @@ class RegexURLResolver(object):
|
|||||||
tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
|
tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']])
|
||||||
else:
|
else:
|
||||||
if sub_match:
|
if sub_match:
|
||||||
return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match[2])
|
sub_match_dict = dict(self.default_kwargs, **sub_match[2])
|
||||||
|
return sub_match[0], sub_match[1], dict(match.groupdict(), **sub_match_dict)
|
||||||
tried.append(pattern.regex.pattern)
|
tried.append(pattern.regex.pattern)
|
||||||
raise Resolver404, {'tried': tried, 'path': new_path}
|
raise Resolver404, {'tried': tried, 'path': new_path}
|
||||||
|
|
||||||
@ -183,22 +195,28 @@ class RegexURLResolver(object):
|
|||||||
def resolve500(self):
|
def resolve500(self):
|
||||||
return self._resolve_special('500')
|
return self._resolve_special('500')
|
||||||
|
|
||||||
def reverse(self, viewname, *args, **kwargs):
|
def reverse(self, lookup_view, *args, **kwargs):
|
||||||
|
if not callable(lookup_view):
|
||||||
|
mod_name, func_name = get_mod_func(lookup_view)
|
||||||
|
try:
|
||||||
|
lookup_view = getattr(__import__(mod_name, '', '', ['']), func_name)
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
raise NoReverseMatch
|
||||||
for pattern in self.urlconf_module.urlpatterns:
|
for pattern in self.urlconf_module.urlpatterns:
|
||||||
if isinstance(pattern, RegexURLResolver):
|
if isinstance(pattern, RegexURLResolver):
|
||||||
try:
|
try:
|
||||||
return pattern.reverse_helper(viewname, *args, **kwargs)
|
return pattern.reverse_helper(lookup_view, *args, **kwargs)
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
continue
|
continue
|
||||||
elif pattern.callback == viewname:
|
elif pattern.callback == lookup_view:
|
||||||
try:
|
try:
|
||||||
return pattern.reverse_helper(*args, **kwargs)
|
return pattern.reverse_helper(*args, **kwargs)
|
||||||
except NoReverseMatch:
|
except NoReverseMatch:
|
||||||
continue
|
continue
|
||||||
raise NoReverseMatch
|
raise NoReverseMatch
|
||||||
|
|
||||||
def reverse_helper(self, viewname, *args, **kwargs):
|
def reverse_helper(self, lookup_view, *args, **kwargs):
|
||||||
sub_match = self.reverse(viewname, *args, **kwargs)
|
sub_match = self.reverse(lookup_view, *args, **kwargs)
|
||||||
result = reverse_helper(self.regex, *args, **kwargs)
|
result = reverse_helper(self.regex, *args, **kwargs)
|
||||||
return result + sub_match
|
return result + sub_match
|
||||||
|
|
||||||
@ -209,11 +227,11 @@ def resolve(path, urlconf=None):
|
|||||||
resolver = RegexURLResolver(r'^/', urlconf)
|
resolver = RegexURLResolver(r'^/', urlconf)
|
||||||
return resolver.resolve(path)
|
return resolver.resolve(path)
|
||||||
|
|
||||||
def reverse(viewname, urlconf, args=None, kwargs=None):
|
def reverse(viewname, urlconf=None, args=None, kwargs=None):
|
||||||
args = args or []
|
args = args or []
|
||||||
kwargs = kwargs or {}
|
kwargs = kwargs or {}
|
||||||
if urlconf is None:
|
if urlconf is None:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
urlconf = settings.ROOT_URLCONF
|
urlconf = settings.ROOT_URLCONF
|
||||||
resolver = RegexURLResolver(r'^/', urlconf)
|
resolver = RegexURLResolver(r'^/', urlconf)
|
||||||
return resolver.reverse(viewname, *args, **kwargs)
|
return '/' + resolver.reverse(viewname, *args, **kwargs)
|
||||||
|
@ -11,6 +11,10 @@ except ImportError, e:
|
|||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
raise ImproperlyConfigured, "Error loading psycopg2 module: %s" % e
|
raise ImproperlyConfigured, "Error loading psycopg2 module: %s" % e
|
||||||
|
|
||||||
|
# Register Unicode conversions
|
||||||
|
import psycopg2.extensions
|
||||||
|
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
|
||||||
|
|
||||||
DatabaseError = Database.DatabaseError
|
DatabaseError = Database.DatabaseError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -16,6 +16,18 @@ from django.utils.text import capfirst
|
|||||||
# Admin stages.
|
# Admin stages.
|
||||||
ADD, CHANGE, BOTH = 1, 2, 3
|
ADD, CHANGE, BOTH = 1, 2, 3
|
||||||
|
|
||||||
|
# Decorator. Takes a function that returns a tuple in this format:
|
||||||
|
# (viewname, viewargs, viewkwargs)
|
||||||
|
# Returns a function that calls urlresolvers.reverse() on that data, to return
|
||||||
|
# the URL for those parameters.
|
||||||
|
def permalink(func):
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
def inner(*args, **kwargs):
|
||||||
|
bits = func(*args, **kwargs)
|
||||||
|
viewname = bits[0]
|
||||||
|
return reverse(bits[0], None, *bits[1:3])
|
||||||
|
return inner
|
||||||
|
|
||||||
class LazyDate(object):
|
class LazyDate(object):
|
||||||
"""
|
"""
|
||||||
Use in limit_choices_to to compare the field to dates calculated at run time
|
Use in limit_choices_to to compare the field to dates calculated at run time
|
||||||
@ -35,7 +47,7 @@ class LazyDate(object):
|
|||||||
return "<LazyDate: %s>" % self.delta
|
return "<LazyDate: %s>" % self.delta
|
||||||
|
|
||||||
def __get_value__(self):
|
def __get_value__(self):
|
||||||
return datetime.datetime.now() + self.delta
|
return (datetime.datetime.now() + self.delta).date()
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
def __getattr__(self, attr):
|
||||||
return getattr(self.__get_value__(), attr)
|
return getattr(self.__get_value__(), attr)
|
||||||
|
@ -44,7 +44,7 @@ class ModelBase(type):
|
|||||||
new_class._meta.app_label = model_module.__name__.split('.')[-2]
|
new_class._meta.app_label = model_module.__name__.split('.')[-2]
|
||||||
|
|
||||||
# Bail out early if we have already created this class.
|
# Bail out early if we have already created this class.
|
||||||
m = get_model(new_class._meta.app_label, name)
|
m = get_model(new_class._meta.app_label, name, False)
|
||||||
if m is not None:
|
if m is not None:
|
||||||
return m
|
return m
|
||||||
|
|
||||||
@ -73,7 +73,7 @@ class ModelBase(type):
|
|||||||
# the first class for this model to register with the framework. There
|
# the first class for this model to register with the framework. There
|
||||||
# should only be one class for each model, so we must always return the
|
# should only be one class for each model, so we must always return the
|
||||||
# registered version.
|
# registered version.
|
||||||
return get_model(new_class._meta.app_label, name)
|
return get_model(new_class._meta.app_label, name, False)
|
||||||
|
|
||||||
class Model(object):
|
class Model(object):
|
||||||
__metaclass__ = ModelBase
|
__metaclass__ = ModelBase
|
||||||
@ -181,6 +181,7 @@ class Model(object):
|
|||||||
# If it does already exist, do an UPDATE.
|
# If it does already exist, do an UPDATE.
|
||||||
if cursor.fetchone():
|
if cursor.fetchone():
|
||||||
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
|
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
|
||||||
|
if db_values:
|
||||||
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
||||||
(backend.quote_name(self._meta.db_table),
|
(backend.quote_name(self._meta.db_table),
|
||||||
','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
|
','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
|
||||||
|
@ -20,7 +20,7 @@ BLANK_CHOICE_DASH = [("", "---------")]
|
|||||||
BLANK_CHOICE_NONE = [("", "None")]
|
BLANK_CHOICE_NONE = [("", "None")]
|
||||||
|
|
||||||
# prepares a value for use in a LIKE query
|
# prepares a value for use in a LIKE query
|
||||||
prep_for_like_query = lambda x: str(x).replace("%", "\%").replace("_", "\_")
|
prep_for_like_query = lambda x: str(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
|
||||||
|
|
||||||
# returns the <ul> class for a given radio_admin value
|
# returns the <ul> class for a given radio_admin value
|
||||||
get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '')
|
get_ul_class = lambda x: 'radiolist%s' % ((x == HORIZONTAL) and ' inline' or '')
|
||||||
@ -247,9 +247,9 @@ class Field(object):
|
|||||||
params['is_required'] = not self.blank and not self.primary_key and not rel
|
params['is_required'] = not self.blank and not self.primary_key and not rel
|
||||||
|
|
||||||
# BooleanFields (CheckboxFields) are a special case. They don't take
|
# BooleanFields (CheckboxFields) are a special case. They don't take
|
||||||
# is_required or validator_list.
|
# is_required.
|
||||||
if isinstance(self, BooleanField):
|
if isinstance(self, BooleanField):
|
||||||
del params['validator_list'], params['is_required']
|
del params['is_required']
|
||||||
|
|
||||||
# If this field is in a related context, check whether any other fields
|
# If this field is in a related context, check whether any other fields
|
||||||
# in the related object have core=True. If so, add a validator --
|
# in the related object have core=True. If so, add a validator --
|
||||||
@ -289,8 +289,11 @@ class Field(object):
|
|||||||
if self.choices:
|
if self.choices:
|
||||||
return first_choice + list(self.choices)
|
return first_choice + list(self.choices)
|
||||||
rel_model = self.rel.to
|
rel_model = self.rel.to
|
||||||
return first_choice + [(x._get_pk_val(), str(x))
|
if hasattr(self.rel, 'get_related_field'):
|
||||||
for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
|
lst = [(getattr(x, self.rel.get_related_field().attname), str(x)) for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
|
||||||
|
else:
|
||||||
|
lst = [(x._get_pk_val(), str(x)) for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
|
||||||
|
return first_choice + lst
|
||||||
|
|
||||||
def get_choices_default(self):
|
def get_choices_default(self):
|
||||||
if self.radio_admin:
|
if self.radio_admin:
|
||||||
|
@ -25,7 +25,7 @@ def add_lookup(rel_cls, field):
|
|||||||
key = (module, name)
|
key = (module, name)
|
||||||
# Has the model already been loaded?
|
# Has the model already been loaded?
|
||||||
# If so, resolve the string reference right away
|
# If so, resolve the string reference right away
|
||||||
model = get_model(rel_cls._meta.app_label,field.rel.to)
|
model = get_model(rel_cls._meta.app_label, field.rel.to, False)
|
||||||
if model:
|
if model:
|
||||||
field.rel.to = model
|
field.rel.to = model
|
||||||
field.do_related_class(model, rel_cls)
|
field.do_related_class(model, rel_cls)
|
||||||
|
@ -75,11 +75,15 @@ def get_models(app_mod=None):
|
|||||||
model_list.extend(get_models(app_mod))
|
model_list.extend(get_models(app_mod))
|
||||||
return model_list
|
return model_list
|
||||||
|
|
||||||
def get_model(app_label, model_name):
|
def get_model(app_label, model_name, seed_cache=True):
|
||||||
"""
|
"""
|
||||||
Returns the model matching the given app_label and case-insensitive model_name.
|
Returns the model matching the given app_label and case-insensitive
|
||||||
|
model_name.
|
||||||
|
|
||||||
Returns None if no model is found.
|
Returns None if no model is found.
|
||||||
"""
|
"""
|
||||||
|
if seed_cache:
|
||||||
|
get_apps()
|
||||||
try:
|
try:
|
||||||
model_dict = _app_models[app_label]
|
model_dict = _app_models[app_label]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -138,7 +138,7 @@ class AutomaticManipulator(forms.Manipulator):
|
|||||||
child_follow = self.follow.get(related.name, None)
|
child_follow = self.follow.get(related.name, None)
|
||||||
|
|
||||||
if child_follow:
|
if child_follow:
|
||||||
obj_list = expanded_data[related.var_name].items()
|
obj_list = expanded_data.get(related.var_name, {}).items()
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -434,10 +434,12 @@ class HiddenField(FormField):
|
|||||||
(self.get_id(), self.field_name, escape(data))
|
(self.get_id(), self.field_name, escape(data))
|
||||||
|
|
||||||
class CheckboxField(FormField):
|
class CheckboxField(FormField):
|
||||||
def __init__(self, field_name, checked_by_default=False):
|
def __init__(self, field_name, checked_by_default=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
self.field_name = field_name
|
self.field_name = field_name
|
||||||
self.checked_by_default = checked_by_default
|
self.checked_by_default = checked_by_default
|
||||||
self.is_required, self.validator_list = False, [] # because the validator looks for these
|
self.is_required = False # because the validator looks for these
|
||||||
|
self.validator_list = validator_list[:]
|
||||||
|
|
||||||
def render(self, data):
|
def render(self, data):
|
||||||
checked_html = ''
|
checked_html = ''
|
||||||
|
@ -203,11 +203,14 @@ class HttpResponse(object):
|
|||||||
if val is not None:
|
if val is not None:
|
||||||
self.cookies[key][var.replace('_', '-')] = val
|
self.cookies[key][var.replace('_', '-')] = val
|
||||||
|
|
||||||
def delete_cookie(self, key):
|
def delete_cookie(self, key, path='/', domain=None):
|
||||||
try:
|
self.cookies[key] = ''
|
||||||
self.cookies[key]['max_age'] = 0
|
if path is not None:
|
||||||
except KeyError:
|
self.cookies[key]['path'] = path
|
||||||
pass
|
if domain is not None:
|
||||||
|
self.cookies[key]['domain'] = path
|
||||||
|
self.cookies[key]['expires'] = 0
|
||||||
|
self.cookies[key]['max-age'] = 0
|
||||||
|
|
||||||
def _get_content(self):
|
def _get_content(self):
|
||||||
content = ''.join(self._iterator)
|
content = ''.join(self._iterator)
|
||||||
|
@ -12,7 +12,11 @@ class GZipMiddleware(object):
|
|||||||
"""
|
"""
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
patch_vary_headers(response, ('Accept-Encoding',))
|
patch_vary_headers(response, ('Accept-Encoding',))
|
||||||
if response.has_header('Content-Encoding'):
|
|
||||||
|
# Avoid gzipping if we've already got a content-encoding or if the
|
||||||
|
# content-type is Javascript (silly IE...)
|
||||||
|
is_js = "javascript" in response.headers.get('Content-Type', '').lower()
|
||||||
|
if response.has_header('Content-Encoding') or is_js:
|
||||||
return response
|
return response
|
||||||
|
|
||||||
ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
|
ae = request.META.get('HTTP_ACCEPT_ENCODING', '')
|
||||||
|
@ -339,7 +339,7 @@ def date(value, arg=None):
|
|||||||
def time(value, arg=None):
|
def time(value, arg=None):
|
||||||
"Formats a time according to the given format"
|
"Formats a time according to the given format"
|
||||||
from django.utils.dateformat import time_format
|
from django.utils.dateformat import time_format
|
||||||
if not value:
|
if value in (None, ''):
|
||||||
return ''
|
return ''
|
||||||
if arg is None:
|
if arg is None:
|
||||||
arg = settings.TIME_FORMAT
|
arg = settings.TIME_FORMAT
|
||||||
|
@ -50,6 +50,8 @@ class ExtendsNode(Node):
|
|||||||
if self.parent_name_expr:
|
if self.parent_name_expr:
|
||||||
error_msg += " Got this from the %r variable." % self.parent_name_expr #TODO nice repr.
|
error_msg += " Got this from the %r variable." % self.parent_name_expr #TODO nice repr.
|
||||||
raise TemplateSyntaxError, error_msg
|
raise TemplateSyntaxError, error_msg
|
||||||
|
if hasattr(parent, 'render'):
|
||||||
|
return parent
|
||||||
try:
|
try:
|
||||||
source, origin = find_template_source(parent, self.template_dirs)
|
source, origin = find_template_source(parent, self.template_dirs)
|
||||||
except TemplateDoesNotExist:
|
except TemplateDoesNotExist:
|
||||||
@ -137,8 +139,9 @@ def do_extends(parser, token):
|
|||||||
|
|
||||||
This tag may be used in two ways: ``{% extends "base" %}`` (with quotes)
|
This tag may be used in two ways: ``{% extends "base" %}`` (with quotes)
|
||||||
uses the literal value "base" as the name of the parent template to extend,
|
uses the literal value "base" as the name of the parent template to extend,
|
||||||
or ``{% extends variable %}`` uses the value of ``variable`` as the name
|
or ``{% extends variable %}`` uses the value of ``variable`` as either the
|
||||||
of the parent template to extend.
|
name of the parent template to extend (if it evaluates to a string,) or as
|
||||||
|
the parent tempate itelf (if it evaluates to a Template object).
|
||||||
"""
|
"""
|
||||||
bits = token.contents.split()
|
bits = token.contents.split()
|
||||||
if len(bits) != 2:
|
if len(bits) != 2:
|
||||||
|
@ -17,7 +17,7 @@ def load_template_source(template_name, template_dirs=None):
|
|||||||
return (open(filepath).read(), filepath)
|
return (open(filepath).read(), filepath)
|
||||||
except IOError:
|
except IOError:
|
||||||
tried.append(filepath)
|
tried.append(filepath)
|
||||||
if template_dirs:
|
if tried:
|
||||||
error_msg = "Tried %s" % tried
|
error_msg = "Tried %s" % tried
|
||||||
else:
|
else:
|
||||||
error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
|
error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory."
|
||||||
|
@ -35,6 +35,14 @@ try:
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
import dummy_thread as thread
|
import dummy_thread as thread
|
||||||
|
|
||||||
|
# This import does nothing, but it's necessary to avoid some race conditions
|
||||||
|
# in the threading module. See http://code.djangoproject.com/ticket/2330 .
|
||||||
|
try:
|
||||||
|
import threading
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
RUN_RELOADER = True
|
RUN_RELOADER = True
|
||||||
|
|
||||||
def reloader_thread():
|
def reloader_thread():
|
||||||
|
@ -6,6 +6,7 @@ from django.contrib.auth.views import redirect_to_login
|
|||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
from django.http import Http404, HttpResponse, HttpResponseRedirect
|
||||||
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
|
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
|
||||||
|
from django.utils.translation import gettext
|
||||||
|
|
||||||
def create_object(request, model, template_name=None,
|
def create_object(request, model, template_name=None,
|
||||||
template_loader=loader, extra_context=None, post_save_redirect=None,
|
template_loader=loader, extra_context=None, post_save_redirect=None,
|
||||||
@ -39,7 +40,7 @@ def create_object(request, model, template_name=None,
|
|||||||
new_object = manipulator.save(new_data)
|
new_object = manipulator.save(new_data)
|
||||||
|
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
request.user.message_set.create(message="The %s was created successfully." % model._meta.verbose_name)
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was created successfully.") % {"verbose_name": model._meta.verbose_name})
|
||||||
|
|
||||||
# Redirect to the new object: first by trying post_save_redirect,
|
# Redirect to the new object: first by trying post_save_redirect,
|
||||||
# then by obj.get_absolute_url; fail if neither works.
|
# then by obj.get_absolute_url; fail if neither works.
|
||||||
@ -113,7 +114,7 @@ def update_object(request, model, object_id=None, slug=None,
|
|||||||
object = manipulator.save(new_data)
|
object = manipulator.save(new_data)
|
||||||
|
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
request.user.message_set.create(message="The %s was updated successfully." % model._meta.verbose_name)
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was updated successfully.") % {"verbose_name": model._meta.verbose_name})
|
||||||
|
|
||||||
# Do a post-after-redirect so that reload works, etc.
|
# Do a post-after-redirect so that reload works, etc.
|
||||||
if post_save_redirect:
|
if post_save_redirect:
|
||||||
@ -180,7 +181,7 @@ def delete_object(request, model, post_delete_redirect,
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
object.delete()
|
object.delete()
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
request.user.message_set.create(message="The %s was deleted." % model._meta.verbose_name)
|
request.user.message_set.create(message=gettext("The %(verbose_name)s was deleted.") % {"verbose_name": model._meta.verbose_name})
|
||||||
return HttpResponseRedirect(post_delete_redirect)
|
return HttpResponseRedirect(post_delete_redirect)
|
||||||
else:
|
else:
|
||||||
if not template_name:
|
if not template_name:
|
||||||
|
@ -2,12 +2,15 @@
|
|||||||
The "contrib" add-ons
|
The "contrib" add-ons
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
Django aims to follow Python's "batteries included" philosophy. It ships with a
|
Django aims to follow Python's `"batteries included" philosophy`_. It ships
|
||||||
variety of extra, optional tools that solve common Web-development problems.
|
with a variety of extra, optional tools that solve common Web-development
|
||||||
|
problems.
|
||||||
|
|
||||||
This code lives in ``django/contrib`` in the Django distribution. Here's a
|
This code lives in ``django/contrib`` in the Django distribution. Here's a
|
||||||
rundown of the packages in ``contrib``:
|
rundown of the packages in ``contrib``:
|
||||||
|
|
||||||
|
.. _"batteries included" philosophy: http://docs.python.org/tut/node12.html#batteries-included
|
||||||
|
|
||||||
admin
|
admin
|
||||||
=====
|
=====
|
||||||
|
|
||||||
|
@ -6,6 +6,9 @@ Although Django has not reached a 1.0 release, the bulk of Django's public APIs
|
|||||||
stable as of the 0.95 release. This document explains which APIs will and will not
|
stable as of the 0.95 release. This document explains which APIs will and will not
|
||||||
change before the 1.0 release.
|
change before the 1.0 release.
|
||||||
|
|
||||||
|
What "stable" means
|
||||||
|
===================
|
||||||
|
|
||||||
In this context, stable means:
|
In this context, stable means:
|
||||||
|
|
||||||
- All the public APIs -- everything documented in the linked documents, and
|
- All the public APIs -- everything documented in the linked documents, and
|
||||||
@ -24,6 +27,9 @@ In this context, stable means:
|
|||||||
- We'll only break backwards compatibility of these APIs if a bug or
|
- We'll only break backwards compatibility of these APIs if a bug or
|
||||||
security hole makes it completely unavoidable.
|
security hole makes it completely unavoidable.
|
||||||
|
|
||||||
|
Stable APIs
|
||||||
|
===========
|
||||||
|
|
||||||
These APIs are stable:
|
These APIs are stable:
|
||||||
|
|
||||||
- `Caching`_.
|
- `Caching`_.
|
||||||
|
@ -578,6 +578,9 @@ related ``Person`` *and* the related ``City``::
|
|||||||
p = b.author # Hits the database.
|
p = b.author # Hits the database.
|
||||||
c = p.hometown # Hits the database.
|
c = p.hometown # Hits the database.
|
||||||
|
|
||||||
|
Note that ``select_related()`` does not follow foreign keys that have
|
||||||
|
``null=True``.
|
||||||
|
|
||||||
``extra(select=None, where=None, params=None, tables=None)``
|
``extra(select=None, where=None, params=None, tables=None)``
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -1468,11 +1471,12 @@ the ``ForeignKey`` ``Manager`` has these additional methods:
|
|||||||
b.entry_set.remove(e) # Disassociates Entry e from Blog b.
|
b.entry_set.remove(e) # Disassociates Entry e from Blog b.
|
||||||
|
|
||||||
In order to prevent database inconsistency, this method only exists on
|
In order to prevent database inconsistency, this method only exists on
|
||||||
``ForeignKey``s where ``null=True``. If the related field can't be set to
|
``ForeignKey`` objects where ``null=True``. If the related field can't be
|
||||||
``None`` (``NULL``), then an object can't be removed from a relation
|
set to ``None`` (``NULL``), then an object can't be removed from a
|
||||||
without being added to another. In the above example, removing ``e`` from
|
relation without being added to another. In the above example, removing
|
||||||
``b.entry_set()`` is equivalent to doing ``e.blog = None``, and because
|
``e`` from ``b.entry_set()`` is equivalent to doing ``e.blog = None``,
|
||||||
the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this is invalid.
|
and because the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this
|
||||||
|
is invalid.
|
||||||
|
|
||||||
* ``clear()``: Removes all objects from the related object set.
|
* ``clear()``: Removes all objects from the related object set.
|
||||||
|
|
||||||
|
148
docs/documentation.txt
Normal file
148
docs/documentation.txt
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
====================================
|
||||||
|
How to read the Django documentation
|
||||||
|
====================================
|
||||||
|
|
||||||
|
We've put a lot of effort into making Django's documentation useful, easy to
|
||||||
|
read and as complete as possible. Here are a few tips on how to make the best
|
||||||
|
of it, along with some style guidelines.
|
||||||
|
|
||||||
|
(Yes, this is documentation about documentation. Rest assured we have no plans
|
||||||
|
to write a document about how to read the document about documentation.)
|
||||||
|
|
||||||
|
How documentation is updated
|
||||||
|
============================
|
||||||
|
|
||||||
|
Just as the Django code base is developed and improved on a daily basis, our
|
||||||
|
documentation is consistently improving. We improve documentation for several
|
||||||
|
reasons:
|
||||||
|
|
||||||
|
* To make content fixes, such as grammar/typo corrections.
|
||||||
|
* To add information and/or examples to existing sections that need to be
|
||||||
|
expanded.
|
||||||
|
* To document Django features that aren't yet documented. (The list of
|
||||||
|
such features is shrinking but exists nonetheless.)
|
||||||
|
* To add documentation for new features as new features get added, or as
|
||||||
|
Django APIs or behaviors change.
|
||||||
|
|
||||||
|
Django's documentation is kept in the same source control system as its code.
|
||||||
|
It lives in the `django/trunk/docs`_ directory of our Subversion repository.
|
||||||
|
Each document is a separate text file that covers a narrowly focused topic,
|
||||||
|
such as the "generic views" framework or how to construct a database model.
|
||||||
|
|
||||||
|
.. _django/trunk/docs: http://code.djangoproject.com/browser/django/trunk/docs
|
||||||
|
|
||||||
|
Where to get it
|
||||||
|
===============
|
||||||
|
|
||||||
|
You can read Django documentation in several ways. They are, in order of
|
||||||
|
preference:
|
||||||
|
|
||||||
|
On the Web
|
||||||
|
----------
|
||||||
|
|
||||||
|
The most recent version of the Django documentation lives at
|
||||||
|
http://www.djangoproject.com/documentation/ . These HTML pages are generated
|
||||||
|
automatically from the text files in source control every 15 minutes. That
|
||||||
|
means they reflect the "latest and greatest" in Django -- they include the very
|
||||||
|
latest corrections and additions, and they discuss the latest Django features,
|
||||||
|
which may only be available to users of the Django development version. (See
|
||||||
|
"Differences between versions" below.)
|
||||||
|
|
||||||
|
A key advantage of the Web-based documentation is the comment section at the
|
||||||
|
bottom of each document. This is an area for anybody to submit changes,
|
||||||
|
corrections and suggestions about the given document. The Django developers
|
||||||
|
frequently monitor the comments there and use them to improve the documentation
|
||||||
|
for everybody.
|
||||||
|
|
||||||
|
We encourage you to help improve the docs: it's easy! Note, however, that
|
||||||
|
comments should explicitly relate to the documentation, rather than asking
|
||||||
|
broad tech-support questions. If you need help with your particular Django
|
||||||
|
setup, try the `django-users mailing list`_ instead of posting a comment to the
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
.. _django-users mailing list: http://groups.google.com/group/django-users
|
||||||
|
|
||||||
|
In plain text
|
||||||
|
-------------
|
||||||
|
|
||||||
|
For offline reading, or just for convenience, you can read the Django
|
||||||
|
documentation in plain text.
|
||||||
|
|
||||||
|
If you're using an official release of Django, note that the zipped package
|
||||||
|
(tarball) of the code includes a ``docs/`` directory, which contains all the
|
||||||
|
documentation for that release.
|
||||||
|
|
||||||
|
If you're using the development version of Django (aka the Subversion "trunk"),
|
||||||
|
note that the ``docs/`` directory contains all of the documentation. You can
|
||||||
|
``svn update`` it, just as you ``svn update`` the Python code, in order to get
|
||||||
|
the latest changes.
|
||||||
|
|
||||||
|
You can check out the latest Django documentation from Subversion using this
|
||||||
|
shell command::
|
||||||
|
|
||||||
|
svn co http://code.djangoproject.com/svn/django/trunk/docs/ django_docs
|
||||||
|
|
||||||
|
One low-tech way of taking advantage of the text documentation is by using the
|
||||||
|
Unix ``grep`` utility to search for a phrase in all of the documentation. For
|
||||||
|
example, this will show you each mention of the phrase "edit_inline" in any
|
||||||
|
Django document::
|
||||||
|
|
||||||
|
grep edit_inline /path/to/django/docs/*.txt
|
||||||
|
|
||||||
|
Formatting
|
||||||
|
~~~~~~~~~~
|
||||||
|
|
||||||
|
The text documentation is written in ReST (ReStructured Text) format. That
|
||||||
|
means it's easy to read but is also formatted in a way that makes it easy to
|
||||||
|
convert into other formats, such as HTML. If you're interested, the script that
|
||||||
|
converts the ReST text docs into djangoproject.com's HTML lives at
|
||||||
|
`djangoproject.com/django_website/apps/docs/parts/build_documentation.py`_ in
|
||||||
|
the Django Subversion repository.
|
||||||
|
|
||||||
|
.. _djangoproject.com/django_website/apps/docs/parts/build_documentation.py: http://code.djangoproject.com/browser/djangoproject.com/django_website/apps/docs/parts/build_documentation.py
|
||||||
|
|
||||||
|
Differences between versions
|
||||||
|
============================
|
||||||
|
|
||||||
|
As previously mentioned, the text documentation in our Subversion repository
|
||||||
|
contains the "latest and greatest" changes and additions. These changes often
|
||||||
|
include documentation of new features added in the Django development version
|
||||||
|
-- the Subversion ("trunk") version of Django. For that reason, it's worth
|
||||||
|
pointing out our policy on keeping straight the documentation for various
|
||||||
|
versions of the framework.
|
||||||
|
|
||||||
|
We follow this policy:
|
||||||
|
|
||||||
|
* The primary documentation on djangoproject.com is an HTML version of the
|
||||||
|
latest docs in Subversion. These docs always correspond to the latest
|
||||||
|
official Django release, plus whatever features we've added/changed in
|
||||||
|
the framework *since* the latest release.
|
||||||
|
|
||||||
|
* As we add features to Django's development version, we try to update the
|
||||||
|
documentation in the same Subversion commit transaction.
|
||||||
|
|
||||||
|
* To distinguish feature changes/additions in the docs, we use the phrase
|
||||||
|
**New in Django development version**. In practice, this means that the
|
||||||
|
current documentation on djangoproject.com can be used by users of either
|
||||||
|
the latest release *or* the development version.
|
||||||
|
|
||||||
|
* Documentation for a particular Django release is frozen once the version
|
||||||
|
has been released officially. It remains a snapshot of the docs as of the
|
||||||
|
moment of the release. We will make exceptions to this rule in
|
||||||
|
the case of retroactive security updates or other such retroactive
|
||||||
|
changes. Once documentation is frozen, we add a note to the top of each
|
||||||
|
frozen document that says "These docs are frozen for Django version XXX"
|
||||||
|
and links to the current version of that document.
|
||||||
|
|
||||||
|
* Once a document is frozen for a Django release, we remove comments from
|
||||||
|
that page, in favor of having comments on the latest version of that
|
||||||
|
document. This is for the sake of maintainability and usability, so that
|
||||||
|
users have one, and only one, place to leave comments on a particular
|
||||||
|
document. We realize that some people may be stuck on a previous version
|
||||||
|
of Django, but we believe the usability problems with multiple versions
|
||||||
|
of a document the outweigh the benefits.
|
||||||
|
|
||||||
|
* The `main documentation Web page`_ includes links to documentation for
|
||||||
|
all previous versions.
|
||||||
|
|
||||||
|
.. _main documentation Web page: http://www.djangoproject.com/documentation/
|
19
docs/faq.txt
19
docs/faq.txt
@ -251,6 +251,16 @@ information than the docs that come with the latest Django release.
|
|||||||
|
|
||||||
.. _stored in revision control: http://code.djangoproject.com/browser/django/trunk/docs
|
.. _stored in revision control: http://code.djangoproject.com/browser/django/trunk/docs
|
||||||
|
|
||||||
|
Where can I find Django developers for hire?
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
Consult our `developers for hire page`_ for a list of Django developers who
|
||||||
|
would be happy to help you.
|
||||||
|
|
||||||
|
You might also be interested in posting a job to http://www.gypsyjobs.com/ .
|
||||||
|
|
||||||
|
.. _developers for hire page: http://code.djangoproject.com/wiki/DevelopersForHire
|
||||||
|
|
||||||
Installation questions
|
Installation questions
|
||||||
======================
|
======================
|
||||||
|
|
||||||
@ -610,13 +620,10 @@ like to make should be possible by editing the stylesheet. We've got a
|
|||||||
How do I create users without having to edit password hashes?
|
How do I create users without having to edit password hashes?
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
|
|
||||||
We don't recommend you create users via the admin interface, because at the
|
If you'd like to use the admin site to create users, upgrade to the Django
|
||||||
moment it requires you to edit password hashes manually. (Passwords are hashed
|
development version, where this problem was fixed on Aug. 4, 2006.
|
||||||
using one-way hash algorithms for security; there's currently no Web interface
|
|
||||||
for changing passwords by entering the actual password rather than the hash.)
|
|
||||||
|
|
||||||
To create a user, you'll have to use the Python API. See `creating users`_ for
|
You can also use the Python API. See `creating users`_ for full info.
|
||||||
full info.
|
|
||||||
|
|
||||||
.. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users
|
.. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users
|
||||||
|
|
||||||
|
@ -405,6 +405,43 @@ Here's a simple function that might drive the above form::
|
|||||||
form = forms.FormWrapper(manipulator, new_data, errors)
|
form = forms.FormWrapper(manipulator, new_data, errors)
|
||||||
return render_to_response('contact_form.html', {'form': form})
|
return render_to_response('contact_form.html', {'form': form})
|
||||||
|
|
||||||
|
``FileField`` and ``ImageField`` special cases
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
Dealing with ``FileField`` and ``ImageField`` objects is a little more
|
||||||
|
complicated.
|
||||||
|
|
||||||
|
First, you'll need to make sure that your ``<form>`` element correctly defines
|
||||||
|
the ``enctype`` as ``"multipart/form-data"``, in order to upload files::
|
||||||
|
|
||||||
|
<form enctype="multipart/form-data" method="post" action="/foo/">
|
||||||
|
|
||||||
|
Next, you'll need to treat the field in the template slightly differently. A
|
||||||
|
``FileField`` or ``ImageField`` is represented by *two* HTML form elements.
|
||||||
|
|
||||||
|
For example, given this field in a model::
|
||||||
|
|
||||||
|
photo = model.ImageField('/path/to/upload/location')
|
||||||
|
|
||||||
|
You'd need to display two formfields in the template::
|
||||||
|
|
||||||
|
<p><label for="id_photo">Photo:</label> {{ form.photo }}{{ form.photo_file }}</p>
|
||||||
|
|
||||||
|
The first bit (``{{ form.photo }}``) displays the currently-selected file,
|
||||||
|
while the second (``{{ form.photo_file }}``) actually contains the file upload
|
||||||
|
form field. Thus, at the validation layer you need to check the ``photo_file``
|
||||||
|
key.
|
||||||
|
|
||||||
|
Finally, in your view, make sure to access ``request.FILES``, rather than
|
||||||
|
``request.POST``, for the uploaded files. This is necessary because
|
||||||
|
``request.POST`` does not contain file-upload data.
|
||||||
|
|
||||||
|
For example, following the ``new_data`` convention, you might do something like
|
||||||
|
this::
|
||||||
|
|
||||||
|
new_data = request.POST.copy()
|
||||||
|
new_data.update(request.FILES)
|
||||||
|
|
||||||
Validators
|
Validators
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410).
|
|||||||
This example redirects from ``/foo/<id>/`` to ``/bar/<id>/``::
|
This example redirects from ``/foo/<id>/`` to ``/bar/<id>/``::
|
||||||
|
|
||||||
urlpatterns = patterns('django.views.generic.simple',
|
urlpatterns = patterns('django.views.generic.simple',
|
||||||
('^foo/(?p<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
|
('^foo/(?P<id>\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}),
|
||||||
)
|
)
|
||||||
|
|
||||||
This example returns a 410 HTTP error for requests to ``/bar/``::
|
This example returns a 410 HTTP error for requests to ``/bar/``::
|
||||||
|
@ -77,9 +77,9 @@ It's easy either way.
|
|||||||
Installing the official version
|
Installing the official version
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
1. Download Django-0.91.tar.gz from our `download page`_.
|
1. Download Django-0.95.tar.gz from our `download page`_.
|
||||||
2. ``tar xzvf Django-0.91.tar.gz``
|
2. ``tar xzvf Django-0.95.tar.gz``
|
||||||
3. ``cd Django-0.91``
|
3. ``cd Django-0.95``
|
||||||
4. ``sudo python setup.py install``
|
4. ``sudo python setup.py install``
|
||||||
|
|
||||||
Note that the last command will automatically download and install setuptools_
|
Note that the last command will automatically download and install setuptools_
|
||||||
@ -89,14 +89,6 @@ connection.
|
|||||||
This will install Django in your Python installation's ``site-packages``
|
This will install Django in your Python installation's ``site-packages``
|
||||||
directory.
|
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
|
.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
|
||||||
|
|
||||||
Installing the development version
|
Installing the development version
|
||||||
|
@ -223,6 +223,13 @@ steps:
|
|||||||
the absolute URL to your image in a template with ``{{
|
the absolute URL to your image in a template with ``{{
|
||||||
object.get_mug_shot_url }}``.
|
object.get_mug_shot_url }}``.
|
||||||
|
|
||||||
|
For example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and
|
||||||
|
``upload_to`` is set to ``'photos/%Y/%m/%d'``. The ``'%Y/%m/%d'`` part of
|
||||||
|
``upload_to`` is strftime formatting; ``'%Y'`` is the four-digit year,
|
||||||
|
``'%m'`` is the two-digit month and ``'%d'`` is the two-digit day. If you
|
||||||
|
upload a file on Jan. 15, 2007, it will be saved in the directory
|
||||||
|
``/home/media/photos/2007/01/15``.
|
||||||
|
|
||||||
.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
|
.. _`strftime formatting`: http://docs.python.org/lib/module-time.html#l2h-1941
|
||||||
|
|
||||||
``FilePathField``
|
``FilePathField``
|
||||||
|
126
docs/release_notes_0.95.txt
Normal file
126
docs/release_notes_0.95.txt
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
=================================
|
||||||
|
Django version 0.95 release notes
|
||||||
|
=================================
|
||||||
|
|
||||||
|
|
||||||
|
Welcome to the Django 0.95 release.
|
||||||
|
|
||||||
|
This represents a significant advance in Django development since the 0.91
|
||||||
|
release in January 2006. The details of every change in this release would be
|
||||||
|
too extensive to list in full, but a summary is presented below.
|
||||||
|
|
||||||
|
Suitability and API stability
|
||||||
|
=============================
|
||||||
|
|
||||||
|
This release is intended to provide a stable reference point for developers
|
||||||
|
wanting to work on production-level applications that use Django.
|
||||||
|
|
||||||
|
However, it's not the 1.0 release, and we'll be introducing further changes
|
||||||
|
before 1.0. For a clear look at which areas of the framework will change (and
|
||||||
|
which ones will *not* change) before 1.0, see the api-stability.txt file, which
|
||||||
|
lives in the docs/ directory of the distribution.
|
||||||
|
|
||||||
|
You may have a need to use some of the features that are marked as
|
||||||
|
"subject to API change" in that document, but that's OK with us as long as it's
|
||||||
|
OK with you, and as long as you understand APIs may change in the future.
|
||||||
|
|
||||||
|
Fortunately, most of Django's core APIs won't be changing before version 1.0.
|
||||||
|
There likely won't be as big of a change between 0.95 and 1.0 versions as there
|
||||||
|
was between 0.91 and 0.95.
|
||||||
|
|
||||||
|
Changes and new features
|
||||||
|
========================
|
||||||
|
|
||||||
|
The major changes in this release (for developers currently using the 0.91
|
||||||
|
release) are a result of merging the 'magic-removal' branch of development.
|
||||||
|
This branch removed a number of constraints in the way Django code had to be
|
||||||
|
written that were a consequence of decisions made in the early days of Django,
|
||||||
|
prior to its open-source release. It's now possible to write more natural,
|
||||||
|
Pythonic code that works as expected, and there's less "black magic" happening
|
||||||
|
behind the scenes.
|
||||||
|
|
||||||
|
Aside from that, another main theme of this release is a dramatic increase in
|
||||||
|
usability. We've made countless improvements in error messages, documentation,
|
||||||
|
etc., to improve developers' quality of life.
|
||||||
|
|
||||||
|
The new features and changes introduced in 0.95 include:
|
||||||
|
|
||||||
|
* Django now uses a more consistent and natural filtering interface for
|
||||||
|
retrieving objects from the database.
|
||||||
|
|
||||||
|
* User-defined models, functions and constants now appear in the module
|
||||||
|
namespace they were defined in. (Previously everything was magically
|
||||||
|
transferred to the django.models.* namespace.)
|
||||||
|
|
||||||
|
* Some optional applications, such as the FlatPage, Sites and Redirects
|
||||||
|
apps, have been decoupled and moved into django.contrib. If you don't
|
||||||
|
want to use these applications, you no longer have to install their
|
||||||
|
database tables.
|
||||||
|
|
||||||
|
* Django now has support for managing database transactions.
|
||||||
|
|
||||||
|
* We've added the ability to write custom authentication and authorization
|
||||||
|
backends for authenticating users against alternate systems, such as
|
||||||
|
LDAP.
|
||||||
|
|
||||||
|
* We've made it easier to add custom table-level functions to models,
|
||||||
|
through a new "Manager" API.
|
||||||
|
|
||||||
|
* It's now possible to use Django without a database. This simply means
|
||||||
|
that the framework no longer requires you to have a working database set
|
||||||
|
up just to serve dynamic pages. In other words, you can just use
|
||||||
|
URLconfs/views on their own. Previously, the framework required that a
|
||||||
|
database be configured, regardless of whether you actually used it.
|
||||||
|
|
||||||
|
* It's now more explicit and natural to override save() and delete()
|
||||||
|
methods on models, rather than needing to hook into the pre_save() and
|
||||||
|
post_save() method hooks.
|
||||||
|
|
||||||
|
* Individual pieces of the framework now can be configured without
|
||||||
|
requiring the setting of an environment variable. This permits use of,
|
||||||
|
for example, the Django templating system inside other applications.
|
||||||
|
|
||||||
|
* More and more parts of the framework have been internationalized, as
|
||||||
|
we've expanded internationalization (i18n) support. The Django
|
||||||
|
codebase, including code and templates, has now been translated, at least
|
||||||
|
in part, into 31 languages. From Arabic to Chinese to Hungarian to Welsh,
|
||||||
|
it is now possible to use Django's admin site in your native language.
|
||||||
|
|
||||||
|
The number of changes required to port from 0.91-compatible code to the 0.95
|
||||||
|
code base are significant in some cases. However, they are, for the most part,
|
||||||
|
reasonably routine and only need to be done once. A list of the necessary
|
||||||
|
changes is described in the `Removing The Magic`_ wiki page. There is also an
|
||||||
|
easy checklist_ for reference when undertaking the porting operation.
|
||||||
|
|
||||||
|
.. _Removing The Magic: http://code.djangoproject.com/wiki/RemovingTheMagic
|
||||||
|
.. _checklist: http://code.djangoproject.com/wiki/MagicRemovalCheatSheet1
|
||||||
|
|
||||||
|
Problem reports and getting help
|
||||||
|
================================
|
||||||
|
|
||||||
|
Need help resolving a problem with Django? The documentation in the
|
||||||
|
distribution is also available online_ at the `Django website`_. The FAQ_
|
||||||
|
document is especially recommended, as it contains a number of issues that
|
||||||
|
come up time and again.
|
||||||
|
|
||||||
|
For more personalized help, the `django-users`_ mailing list is a very active
|
||||||
|
list, with more than 2,000 subscribers who can help you solve any sort of
|
||||||
|
Django problem. We recommend you search the archives first, though, because
|
||||||
|
many common questions appear with some regularity, and any particular problem
|
||||||
|
may already have been answered.
|
||||||
|
|
||||||
|
Finally, for those who prefer the more immediate feedback offered by IRC,
|
||||||
|
there's a #django channel or irc.freenode.net that is regularly populated by
|
||||||
|
Django users and developers from around the world. Friendly people are usually
|
||||||
|
available at any hour of the day -- to help, or just to chat.
|
||||||
|
|
||||||
|
.. _online: http://www.djangoproject.com/documentation/
|
||||||
|
.. _Django website: http://www.djangoproject.com/
|
||||||
|
.. _FAQ: http://www.djangoproject.com/documentation/faq/
|
||||||
|
.. _django-users: http://groups.google.com/group/django-users
|
||||||
|
|
||||||
|
Thanks for using Django!
|
||||||
|
|
||||||
|
The Django Team
|
||||||
|
July 2006
|
||||||
|
|
@ -380,10 +380,14 @@ Methods
|
|||||||
|
|
||||||
.. _`cookie Morsel`: http://www.python.org/doc/current/lib/morsel-objects.html
|
.. _`cookie Morsel`: http://www.python.org/doc/current/lib/morsel-objects.html
|
||||||
|
|
||||||
``delete_cookie(key)``
|
``delete_cookie(key, path='/', domain=None)``
|
||||||
Deletes the cookie with the given key. Fails silently if the key doesn't
|
Deletes the cookie with the given key. Fails silently if the key doesn't
|
||||||
exist.
|
exist.
|
||||||
|
|
||||||
|
The ``path`` and ``domain`` arguments are new in the Django development version.
|
||||||
|
Due to the way cookies work, ``path`` and ``domain`` should be the same
|
||||||
|
values you used in ``set_cookie()`` -- otherwise the cookie may not be deleted.
|
||||||
|
|
||||||
``content``
|
``content``
|
||||||
Returns the content as a Python string, encoding it from a Unicode object
|
Returns the content as a Python string, encoding it from a Unicode object
|
||||||
if necessary. Note this is a property, not a method, so use ``r.content``
|
if necessary. Note this is a property, not a method, so use ``r.content``
|
||||||
|
@ -245,6 +245,17 @@ Default: ``'sessionid'``
|
|||||||
|
|
||||||
The name of the cookie to use for sessions. This can be whatever you want.
|
The name of the cookie to use for sessions. This can be whatever you want.
|
||||||
|
|
||||||
|
SESSION_COOKIE_SECURE
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Whether to use a secure cookie for the session cookie. If this is set to
|
||||||
|
``True``, the cookie will be marked as "secure," which means browsers may
|
||||||
|
ensure that the cookie is only sent under an HTTPS connection.
|
||||||
|
|
||||||
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
@ -647,6 +647,18 @@ Default: ``'sessionid'``
|
|||||||
The name of the cookie to use for sessions. This can be whatever you want.
|
The name of the cookie to use for sessions. This can be whatever you want.
|
||||||
See the `session docs`_.
|
See the `session docs`_.
|
||||||
|
|
||||||
|
SESSION_COOKIE_SECURE
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
Default: ``False``
|
||||||
|
|
||||||
|
Whether to use a secure cookie for the session cookie. If this is set to
|
||||||
|
``True``, the cookie will be marked as "secure," which means browsers may
|
||||||
|
ensure that the cookie is only sent under an HTTPS connection.
|
||||||
|
See the `session docs`_.
|
||||||
|
|
||||||
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
SESSION_EXPIRE_AT_BROWSER_CLOSE
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
|
@ -363,10 +363,15 @@ extends
|
|||||||
|
|
||||||
Signal that this template extends a parent template.
|
Signal that this template extends a parent template.
|
||||||
|
|
||||||
This tag may be used in two ways: ``{% extends "base.html" %}`` (with quotes)
|
This tag can be used in two ways:
|
||||||
uses the literal value "base.html" as the name of the parent template to
|
|
||||||
extend, or ``{% extends variable %}`` uses the value of ``variable`` as the
|
* ``{% extends "base.html" %}`` (with quotes) uses the literal value
|
||||||
name of the parent template to extend.
|
``"base.html"`` as the name of the parent template to extend.
|
||||||
|
|
||||||
|
* ``{% extends variable %}`` uses the value of ``variable``. If the variable
|
||||||
|
evaluates to a string, Django will use that string as the name of the
|
||||||
|
parent template. If the variable evaluates to a ``Template`` object,
|
||||||
|
Django will use that object as the parent template.
|
||||||
|
|
||||||
See `Template inheritance`_ for more information.
|
See `Template inheritance`_ for more information.
|
||||||
|
|
||||||
@ -493,6 +498,11 @@ If you need to combine ``and`` and ``or`` to do advanced logic, just use nested
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
Multiple uses of the same logical operator are fine, as long as you use the
|
||||||
|
same operator. For example, this is valid::
|
||||||
|
|
||||||
|
{% if athlete_list or coach_list or parent_list or teacher_list %}
|
||||||
|
|
||||||
ifchanged
|
ifchanged
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
|
@ -198,21 +198,6 @@ some things to keep in mind:
|
|||||||
How invalid variables are handled
|
How invalid variables are handled
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
In Django 0.91, if a variable doesn't exist, the template system fails
|
|
||||||
silently. The variable is replaced with an empty string::
|
|
||||||
|
|
||||||
>>> t = Template("My name is {{ my_name }}.")
|
|
||||||
>>> c = Context({"foo": "bar"})
|
|
||||||
>>> t.render(c)
|
|
||||||
"My name is ."
|
|
||||||
|
|
||||||
This applies to any level of lookup::
|
|
||||||
|
|
||||||
>>> t = Template("My name is {{ person.fname }} {{ person.lname }}.")
|
|
||||||
>>> c = Context({"person": {"fname": "Stan"}})
|
|
||||||
>>> t.render(c)
|
|
||||||
"My name is Stan ."
|
|
||||||
|
|
||||||
If a variable doesn't exist, the template system inserts the value of the
|
If a variable doesn't exist, the template system inserts the value of the
|
||||||
``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` (the empty
|
``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` (the empty
|
||||||
string) by default.
|
string) by default.
|
||||||
|
@ -81,7 +81,7 @@ the following output on the command line::
|
|||||||
Validating models...
|
Validating models...
|
||||||
0 errors found.
|
0 errors found.
|
||||||
|
|
||||||
Django version 0.95 (post-magic-removal), using settings 'mysite.settings'
|
Django version 0.95, using settings 'mysite.settings'
|
||||||
Development server is running at http://127.0.0.1:8000/
|
Development server is running at http://127.0.0.1:8000/
|
||||||
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
|
Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows).
|
||||||
|
|
||||||
|
@ -263,12 +263,12 @@ Here's the example URLconf from the `Django overview`_::
|
|||||||
from django.conf.urls.defaults import *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
(r'^articles/(\d{4})/$', 'myproject.news.views.year_archive'),
|
(r'^articles/(\d{4})/$', 'mysite.news.views.year_archive'),
|
||||||
(r'^articles/(\d{4})/(\d{2})/$', 'myproject.news.views.month_archive'),
|
(r'^articles/(\d{4})/(\d{2})/$', 'mysite.news.views.month_archive'),
|
||||||
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'myproject.news.views.article_detail'),
|
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.news.views.article_detail'),
|
||||||
)
|
)
|
||||||
|
|
||||||
In this example, each view has a common prefix -- ``'myproject.news.views'``.
|
In this example, each view has a common prefix -- ``'mysite.news.views'``.
|
||||||
Instead of typing that out for each entry in ``urlpatterns``, you can use the
|
Instead of typing that out for each entry in ``urlpatterns``, you can use the
|
||||||
first argument to the ``patterns()`` function to specify a prefix to apply to
|
first argument to the ``patterns()`` function to specify a prefix to apply to
|
||||||
each view function.
|
each view function.
|
||||||
@ -277,7 +277,7 @@ With this in mind, the above example can be written more concisely as::
|
|||||||
|
|
||||||
from django.conf.urls.defaults import *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
urlpatterns = patterns('myproject.news.views',
|
urlpatterns = patterns('mysite.news.views',
|
||||||
(r'^articles/(\d{4})/$', 'year_archive'),
|
(r'^articles/(\d{4})/$', 'year_archive'),
|
||||||
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
|
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
|
||||||
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
|
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
|
||||||
@ -389,3 +389,90 @@ to pass metadata and options to views.
|
|||||||
|
|
||||||
.. _generic views: http://www.djangoproject.com/documentation/generic_views/
|
.. _generic views: http://www.djangoproject.com/documentation/generic_views/
|
||||||
.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
|
.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
|
||||||
|
|
||||||
|
Passing extra options to ``include()``
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
**New in the Django development version.**
|
||||||
|
|
||||||
|
Similarly, you can pass extra options to ``include()``. When you pass extra
|
||||||
|
options to ``include()``, *each* line in the included URLconf will be passed
|
||||||
|
the extra options.
|
||||||
|
|
||||||
|
For example, these two URLconf sets are functionally identical:
|
||||||
|
|
||||||
|
Set one::
|
||||||
|
|
||||||
|
# main.py
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^blog/', include('inner'), {'blogid': 3}),
|
||||||
|
)
|
||||||
|
|
||||||
|
# inner.py
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^archive/$', 'mysite.views.archive'),
|
||||||
|
(r'^about/$', 'mysite.views.about'),
|
||||||
|
)
|
||||||
|
|
||||||
|
Set two::
|
||||||
|
|
||||||
|
# main.py
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^blog/', include('inner')),
|
||||||
|
)
|
||||||
|
|
||||||
|
# inner.py
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
|
||||||
|
(r'^about/$', 'mysite.views.about', {'blogid': 3}),
|
||||||
|
)
|
||||||
|
|
||||||
|
Note that extra options will *always* be passed to *every* line in the included
|
||||||
|
URLconf, regardless of whether the line's view actually accepts those options
|
||||||
|
as valid. For this reason, this technique is only useful if you're certain that
|
||||||
|
every view in the the included URLconf accepts the extra options you're passing.
|
||||||
|
|
||||||
|
Passing callable objects instead of strings
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
**New in the Django development version.**
|
||||||
|
|
||||||
|
Some developers find it more natural to pass the actual Python function object
|
||||||
|
rather than a string containing the path to its module. This alternative is
|
||||||
|
supported -- you can pass any callable object as the view.
|
||||||
|
|
||||||
|
For example, given this URLconf in "string" notation::
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^archive/$', 'mysite.views.archive'),
|
||||||
|
(r'^about/$', 'mysite.views.about'),
|
||||||
|
(r'^contact/$', 'mysite.views.contact'),
|
||||||
|
)
|
||||||
|
|
||||||
|
You can accomplish the same thing by passing objects rather than strings. Just
|
||||||
|
be sure to import the objects::
|
||||||
|
|
||||||
|
from mysite.views import archive, about, contact
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^archive/$', archive),
|
||||||
|
(r'^about/$', about),
|
||||||
|
(r'^contact/$', contact),
|
||||||
|
)
|
||||||
|
|
||||||
|
The following example is functionally identical. It's just a bit more compact
|
||||||
|
because it imports the module that contains the views, rather than importing
|
||||||
|
each view individually::
|
||||||
|
|
||||||
|
from mysite import views
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
(r'^archive/$', views.archive),
|
||||||
|
(r'^about/$', views.about),
|
||||||
|
(r'^contact/$', views.contact),
|
||||||
|
)
|
||||||
|
|
||||||
|
The style you use is up to you.
|
||||||
|
|
||||||
|
Note that if you use this technique -- passing objects rather than strings --
|
||||||
|
the view prefix (as explained in "The view prefix" above) will have no effect.
|
||||||
|
33
setup.py
33
setup.py
@ -14,38 +14,9 @@ setup(
|
|||||||
packages = find_packages(exclude=['examples', 'examples.*']),
|
packages = find_packages(exclude=['examples', 'examples.*']),
|
||||||
package_data = {
|
package_data = {
|
||||||
'': ['*.TXT'],
|
'': ['*.TXT'],
|
||||||
'django.conf': ['locale/ar/LC_MESSAGES/*',
|
'django.conf': ['locale/*/LC_MESSAGES/*'],
|
||||||
'locale/bn/LC_MESSAGES/*',
|
|
||||||
'locale/cs/LC_MESSAGES/*',
|
|
||||||
'locale/cy/LC_MESSAGES/*',
|
|
||||||
'locale/da/LC_MESSAGES/*',
|
|
||||||
'locale/de/LC_MESSAGES/*',
|
|
||||||
'locale/el/LC_MESSAGES/*',
|
|
||||||
'locale/en/LC_MESSAGES/*',
|
|
||||||
'locale/es/LC_MESSAGES/*',
|
|
||||||
'locale/es_AR/LC_MESSAGES/*',
|
|
||||||
'locale/fr/LC_MESSAGES/*',
|
|
||||||
'locale/gl/LC_MESSAGES/*',
|
|
||||||
'locale/hu/LC_MESSAGES/*',
|
|
||||||
'locale/he/LC_MESSAGES/*',
|
|
||||||
'locale/is/LC_MESSAGES/*',
|
|
||||||
'locale/it/LC_MESSAGES/*',
|
|
||||||
'locale/ja/LC_MESSAGES/*',
|
|
||||||
'locale/nl/LC_MESSAGES/*',
|
|
||||||
'locale/no/LC_MESSAGES/*',
|
|
||||||
'locale/pl/LC_MESSAGES/*',
|
|
||||||
'locale/pt_BR/LC_MESSAGES/*',
|
|
||||||
'locale/ro/LC_MESSAGES/*',
|
|
||||||
'locale/ru/LC_MESSAGES/*',
|
|
||||||
'locale/sk/LC_MESSAGES/*',
|
|
||||||
'locale/sl/LC_MESSAGES/*',
|
|
||||||
'locale/sr/LC_MESSAGES/*',
|
|
||||||
'locale/sv/LC_MESSAGES/*',
|
|
||||||
'locale/ta/LC_MESSAGES/*',
|
|
||||||
'locale/uk/LC_MESSAGES/*',
|
|
||||||
'locale/zh_CN/LC_MESSAGES/*',
|
|
||||||
'locale/zh_TW/LC_MESSAGES/*'],
|
|
||||||
'django.contrib.admin': ['templates/admin/*.html',
|
'django.contrib.admin': ['templates/admin/*.html',
|
||||||
|
'templates/admin/auth/user/*.html',
|
||||||
'templates/admin_doc/*.html',
|
'templates/admin_doc/*.html',
|
||||||
'templates/registration/*.html',
|
'templates/registration/*.html',
|
||||||
'templates/widget/*.html',
|
'templates/widget/*.html',
|
||||||
|
@ -20,5 +20,7 @@ API_TESTS = """
|
|||||||
2
|
2
|
||||||
>>> m.id is not None
|
>>> m.id is not None
|
||||||
True
|
True
|
||||||
|
>>> existing = Empty(m.id)
|
||||||
|
>>> existing.save()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -15,7 +15,7 @@ class Article(models.Model):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.headline
|
return self.headline
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = r"""
|
||||||
# Create a couple of Articles.
|
# Create a couple of Articles.
|
||||||
>>> from datetime import datetime
|
>>> from datetime import datetime
|
||||||
>>> a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26))
|
>>> a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26))
|
||||||
@ -161,13 +161,14 @@ DoesNotExist: Article matching query does not exist.
|
|||||||
<Article: Article 1>
|
<Article: Article 1>
|
||||||
|
|
||||||
# Underscores and percent signs have special meaning in the underlying
|
# Underscores and percent signs have special meaning in the underlying
|
||||||
# database library, but Django handles the quoting of them automatically.
|
# SQL code, but Django handles the quoting of them automatically.
|
||||||
>>> a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
|
>>> a8 = Article(headline='Article_ with underscore', pub_date=datetime(2005, 11, 20))
|
||||||
>>> a8.save()
|
>>> a8.save()
|
||||||
>>> Article.objects.filter(headline__startswith='Article')
|
>>> Article.objects.filter(headline__startswith='Article')
|
||||||
[<Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
[<Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||||
>>> Article.objects.filter(headline__startswith='Article_')
|
>>> Article.objects.filter(headline__startswith='Article_')
|
||||||
[<Article: Article_ with underscore>]
|
[<Article: Article_ with underscore>]
|
||||||
|
|
||||||
>>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
|
>>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21))
|
||||||
>>> a9.save()
|
>>> a9.save()
|
||||||
>>> Article.objects.filter(headline__startswith='Article')
|
>>> Article.objects.filter(headline__startswith='Article')
|
||||||
@ -182,4 +183,12 @@ DoesNotExist: Article matching query does not exist.
|
|||||||
[<Article: Article% with percent sign>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
[<Article: Article% with percent sign>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 7>, <Article: Article 1>]
|
||||||
>>> Article.objects.exclude(headline="Article 7")
|
>>> Article.objects.exclude(headline="Article 7")
|
||||||
[<Article: Article% with percent sign>, <Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 1>]
|
[<Article: Article% with percent sign>, <Article: Article_ with underscore>, <Article: Article 5>, <Article: Article 6>, <Article: Article 4>, <Article: Article 2>, <Article: Article 3>, <Article: Article 1>]
|
||||||
|
|
||||||
|
# Backslashes also have special meaning in the underlying SQL code, but Django
|
||||||
|
# automatically quotes them appropriately.
|
||||||
|
>>> a10 = Article(headline='Article with \\ backslash', pub_date=datetime(2005, 11, 22))
|
||||||
|
>>> a10.save()
|
||||||
|
>>> Article.objects.filter(headline__contains='\\')
|
||||||
|
[<Article: Article with \ backslash>]
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -231,6 +231,9 @@ False
|
|||||||
>>> time(datetime.time(13), "h")
|
>>> time(datetime.time(13), "h")
|
||||||
'01'
|
'01'
|
||||||
|
|
||||||
|
>>> time(datetime.time(0), "h")
|
||||||
|
'12'
|
||||||
|
|
||||||
# real testing is done in timesince.py, where we can provide our own 'now'
|
# real testing is done in timesince.py, where we can provide our own 'now'
|
||||||
>>> timesince(datetime.datetime.now() - datetime.timedelta(1))
|
>>> timesince(datetime.datetime.now() - datetime.timedelta(1))
|
||||||
'1 day'
|
'1 day'
|
||||||
|
@ -410,6 +410,12 @@ TEMPLATE_TESTS = {
|
|||||||
# Three-level inheritance with {{ block.super }} from parent and grandparent
|
# Three-level inheritance with {{ block.super }} from parent and grandparent
|
||||||
'inheritance23': ("{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}", {}, '1_ab3_'),
|
'inheritance23': ("{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}", {}, '1_ab3_'),
|
||||||
|
|
||||||
|
# Inheritance from local context without use of template loader
|
||||||
|
'inheritance24': ("{% extends context_template %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")}, '1234'),
|
||||||
|
|
||||||
|
# Inheritance from local context with variable parent template
|
||||||
|
'inheritance25': ("{% extends context_template.1 %}{% block first %}2{% endblock %}{% block second %}4{% endblock %}", {'context_template': [template.Template("Wrong"), template.Template("1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}")]}, '1234'),
|
||||||
|
|
||||||
### I18N ##################################################################
|
### I18N ##################################################################
|
||||||
|
|
||||||
# {% spaceless %} tag
|
# {% spaceless %} tag
|
||||||
|
47
tests/othertests/urlpatterns_reverse.py
Normal file
47
tests/othertests/urlpatterns_reverse.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
"Unit tests for reverse URL lookup"
|
||||||
|
|
||||||
|
from django.core.urlresolvers import reverse_helper, NoReverseMatch
|
||||||
|
import re
|
||||||
|
|
||||||
|
test_data = (
|
||||||
|
('^places/(\d+)/$', 'places/3/', [3], {}),
|
||||||
|
('^places/(\d+)/$', 'places/3/', ['3'], {}),
|
||||||
|
('^places/(\d+)/$', NoReverseMatch, ['a'], {}),
|
||||||
|
('^places/(\d+)/$', NoReverseMatch, [], {}),
|
||||||
|
('^places/(?P<id>\d+)/$', 'places/3/', [], {'id': 3}),
|
||||||
|
('^people/(?P<name>\w+)/$', 'people/adrian/', ['adrian'], {}),
|
||||||
|
('^people/(?P<name>\w+)/$', 'people/adrian/', [], {'name': 'adrian'}),
|
||||||
|
('^people/(?P<name>\w+)/$', NoReverseMatch, ['name with spaces'], {}),
|
||||||
|
('^people/(?P<name>\w+)/$', NoReverseMatch, [], {'name': 'name with spaces'}),
|
||||||
|
('^people/(?P<name>\w+)/$', NoReverseMatch, [], {}),
|
||||||
|
('^hardcoded/$', 'hardcoded/', [], {}),
|
||||||
|
('^hardcoded/$', 'hardcoded/', ['any arg'], {}),
|
||||||
|
('^hardcoded/$', 'hardcoded/', [], {'kwarg': 'foo'}),
|
||||||
|
('^people/(?P<state>\w\w)/(?P<name>\w+)/$', 'people/il/adrian/', [], {'state': 'il', 'name': 'adrian'}),
|
||||||
|
('^people/(?P<state>\w\w)/(?P<name>\d)/$', NoReverseMatch, [], {'state': 'il', 'name': 'adrian'}),
|
||||||
|
('^people/(?P<state>\w\w)/(?P<name>\w+)/$', NoReverseMatch, [], {'state': 'il'}),
|
||||||
|
('^people/(?P<state>\w\w)/(?P<name>\w+)/$', NoReverseMatch, [], {'name': 'adrian'}),
|
||||||
|
('^people/(?P<state>\w\w)/(\w+)/$', NoReverseMatch, ['il'], {'name': 'adrian'}),
|
||||||
|
('^people/(?P<state>\w\w)/(\w+)/$', 'people/il/adrian/', ['adrian'], {'state': 'il'}),
|
||||||
|
)
|
||||||
|
|
||||||
|
def run_tests(verbosity=0):
|
||||||
|
for regex, expected, args, kwargs in test_data:
|
||||||
|
passed = True
|
||||||
|
try:
|
||||||
|
got = reverse_helper(re.compile(regex), *args, **kwargs)
|
||||||
|
except NoReverseMatch, e:
|
||||||
|
if expected != NoReverseMatch:
|
||||||
|
passed, got = False, str(e)
|
||||||
|
else:
|
||||||
|
if got != expected:
|
||||||
|
passed, got = False, got
|
||||||
|
if passed and verbosity:
|
||||||
|
print "Passed: %s" % regex
|
||||||
|
elif not passed:
|
||||||
|
print "REVERSE LOOKUP FAILED: %s" % regex
|
||||||
|
print " Got: %s" % got
|
||||||
|
print " Expected: %r" % expected
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
run_tests(1)
|
Loading…
x
Reference in New Issue
Block a user