diff --git a/AUTHORS b/AUTHORS index fb299a9e3b..fb00ca43fe 100644 --- a/AUTHORS +++ b/AUTHORS @@ -16,12 +16,23 @@ before Simon departed and currently oversees things with Adrian. Wilson Miner , who designed Django's admin 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 , who has made +significant contributions to all levels of the framework, from its database +layer to template system and documentation. Georg "Hugo" Bauer , who added internationalization support, manages i18n contributions and has made a ton of excellent tweaks, feature additions and bug fixes. +Luke Plant , who has contributed many excellent +improvements, including database-level improvements, the CSRF middleware and +unit tests. + +Russell Keith-Magee , who has contributed many excellent +improvements, including refactoring of the Django ORM code and unit tests. + Robert Wittams , who majorly refactored the Django admin application to allow for easier reuse and has made a ton of excellent tweaks, feature additions and bug fixes. @@ -49,6 +60,7 @@ answer newbie questions, and generally made Django that much better: Amit Chakradeo ChaosKCW Ian Clelland + crankycoder@gmail.com Matt Croydon Jonathan Daugherty (cygnus) Jason Davies (Esaj) @@ -59,6 +71,8 @@ answer newbie questions, and generally made Django that much better: Clint Ecker gandalf@owca.info Baishampayan Ghose + martin.glueck@gmail.com + Simon Greenhill Espen Grindhaug Brant Harris hipertracker@gmail.com @@ -70,7 +84,6 @@ answer newbie questions, and generally made Django that much better: Michael Josephson jpellerin@gmail.com junzhang.jn@gmail.com - Russell Keith-Magee Garth Kidd kilian Sune Kirkeby @@ -98,6 +111,7 @@ answer newbie questions, and generally made Django that much better: Sam Newman Neal Norwitz oggie rob + Jay Parlar pgross@thoughtworks.com phaedo phil@produxion.net @@ -112,13 +126,14 @@ answer newbie questions, and generally made Django that much better: Ivan Sagalaev (Maniac) David Schein sopel + Thomas Steinacher Radek Švarz Swaroop C H Aaron Swartz Tom Tobin Tom Insam Joe Topjian - Malcolm Tredinnick + Karen Tracey Amit Upadhyay Geert Vanderkelen Milton Waddams diff --git a/INSTALL b/INSTALL index fc21a61b47..23e24c0cdf 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,22 @@ 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. diff --git a/django/__init__.py b/django/__init__.py index 00c6f82478..5d5461c867 100644 --- a/django/__init__.py +++ b/django/__init__.py @@ -1 +1 @@ -VERSION = (0, 95, 'post-magic-removal') +VERSION = (0, 96, 'pre') diff --git a/django/bin/compile-messages.py b/django/bin/compile-messages.py index 5f653df95d..44a84de379 100755 --- a/django/bin/compile-messages.py +++ b/django/bin/compile-messages.py @@ -14,7 +14,7 @@ def compile_messages(): print "this script should be run from the django svn tree or your project or app tree" sys.exit(1) - for (dirpath, dirnames, filenames) in os.walk(basedir): + for dirpath, dirnames, filenames in os.walk(basedir): for f in filenames: if f.endswith('.po'): sys.stderr.write('processing file %s in %s\n' % (f, dirpath)) diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index a00e2ba4eb..4ea694d064 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -252,6 +252,7 @@ MIDDLEWARE_CLASSES = ( 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_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_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser. diff --git a/django/conf/locale/ru/LC_MESSAGES/django.mo b/django/conf/locale/ru/LC_MESSAGES/django.mo index 562996eee5..467c8ddb62 100644 Binary files a/django/conf/locale/ru/LC_MESSAGES/django.mo and b/django/conf/locale/ru/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/ru/LC_MESSAGES/django.po b/django/conf/locale/ru/LC_MESSAGES/django.po index 024b2bfc12..ca204d2ddf 100644 --- a/django/conf/locale/ru/LC_MESSAGES/django.po +++ b/django/conf/locale/ru/LC_MESSAGES/django.po @@ -5,17 +5,21 @@ # msgid "" msgstr "" -"Project-Id-Version: django\n" +"Project-Id-Version: django 0.95\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2006-05-16 10:11+0200\n" -"PO-Revision-Date: 2005-11-26 00:00\n" -"Last-Translator: Dmitry Sorokin \n" -"Language-Team: LANGUAGE \n" +"PO-Revision-Date: 2006-08-14 18:08+0300\n" +"Last-Translator: Grigory Fateyev \n" +"Language-Team: Dialcom Services \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\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" msgstr "ID объекта" @@ -23,7 +27,8 @@ msgstr "ID объекта" msgid "headline" msgstr "заголовок" -#: contrib/comments/models.py:69 contrib/comments/models.py:90 +#: contrib/comments/models.py:69 +#: contrib/comments/models.py:90 #: contrib/comments/models.py:167 msgid "comment" msgstr "комментарий" @@ -64,15 +69,18 @@ msgstr "рейтинг #8" msgid "is valid rating" msgstr "доступный рейтинг" -#: contrib/comments/models.py:83 contrib/comments/models.py:169 +#: contrib/comments/models.py:83 +#: contrib/comments/models.py:169 msgid "date/time submitted" msgstr "дата/время добавления" -#: contrib/comments/models.py:84 contrib/comments/models.py:170 +#: contrib/comments/models.py:84 +#: contrib/comments/models.py:170 msgid "is public" msgstr "публичный" -#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289 +#: contrib/comments/models.py:85 +#: contrib/admin/views/doc.py:289 msgid "IP address" msgstr "IP адрес" @@ -81,19 +89,15 @@ msgid "is removed" msgstr "удален" #: contrib/comments/models.py:86 -msgid "" -"Check this box if the comment is inappropriate. A \"This comment has been " -"removed\" message will be displayed instead." -msgstr "" -"Отметте, если комментарий нежелателен. Сообщение \"Этот комментарий был " -"удалён\" будет показано взамен." +msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead." +msgstr "Отметте, если комментарий нежелателен. Сообщение \"Этот комментарий был удалён\" будет показано взамен." #: contrib/comments/models.py:91 -#, fuzzy msgid "comments" -msgstr "комментарий" +msgstr "комментарии" -#: contrib/comments/models.py:131 contrib/comments/models.py:207 +#: contrib/comments/models.py:131 +#: contrib/comments/models.py:207 msgid "Content object" msgstr "Объект наполнения" @@ -151,7 +155,7 @@ msgstr "Карма счета" #: contrib/comments/models.py:242 #, python-format msgid "%(score)d rating by %(user)s" -msgstr "" +msgstr "%(score)d рейтинг %(user)s" #: contrib/comments/models.py:258 #, python-format @@ -196,7 +200,7 @@ msgstr "Удаления модератором" #: contrib/comments/models.py:285 #, python-format msgid "Moderator deletion by %r" -msgstr "" +msgstr "Удаления модератора %r" #: contrib/comments/views/karma.py:19 msgid "Anonymous users cannot vote" @@ -211,20 +215,17 @@ msgid "No voting for yourself" msgstr "Нельзя голосовать за себя" #: contrib/comments/views/comments.py:28 -msgid "" -"This rating is required because you've entered at least one other rating." -msgstr "" +msgid "This rating is required because you've entered at least one other rating." +msgstr "Этот рейтинг необходим, так как вы входили хоть однажды в другие рейтинги." #: contrib/comments/views/comments.py:112 #, python-format msgid "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comment:\n" +"This comment was posted by a user who has posted fewer than %(count)s comment:\n" "\n" "%(text)s" msgid_plural "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comments:\n" +"This comment was posted by a user who has posted fewer than %(count)s comments:\n" "\n" "%(text)s" msgstr[0] "" @@ -258,11 +259,8 @@ msgstr "Кто-то вмешивается в форму комментария #: contrib/comments/views/comments.py:207 #: contrib/comments/views/comments.py:292 -msgid "" -"The comment form had an invalid 'target' parameter -- the object ID was " -"invalid" -msgstr "" -"Форма комментария имеет неверный 'target' параметр -- ID объекта неверно" +msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid" +msgstr "Форма комментария имеет неверный 'target' параметр -- ID объекта неверно" #: contrib/comments/views/comments.py:257 #: contrib/comments/views/comments.py:321 @@ -343,8 +341,11 @@ msgid "" "

By %s:

\n" "
    \n" msgstr "" +"

    К %s:

    \n" +"
      \n" -#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 +#: contrib/admin/filterspecs.py:70 +#: contrib/admin/filterspecs.py:88 #: contrib/admin/filterspecs.py:143 msgid "All" msgstr "Все" @@ -413,14 +414,11 @@ msgstr "журнальные записи" msgid "All dates" msgstr "Все даты" -#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36 +#: contrib/admin/views/decorators.py:9 +#: contrib/auth/forms.py:36 #: contrib/auth/forms.py:41 -msgid "" -"Please enter a correct username and password. Note that both fields are case-" -"sensitive." -msgstr "" -"Пожалуйста, вводите верные данные именя пользователя и пароль. Помните, оба " -"поля чувствительны к регистру." +msgid "Please enter a correct username and password. Note that both fields are case-sensitive." +msgstr "Пожалуйста, вводите верные данные именя пользователя и пароль. Помните, оба поля чувствительны к регистру." #: contrib/admin/views/decorators.py:23 #: contrib/admin/templates/admin/login.html:25 @@ -428,20 +426,12 @@ msgid "Log in" msgstr "Вход" #: contrib/admin/views/decorators.py:61 -msgid "" -"Please log in again, because your session has expired. Don't worry: Your " -"submission has been saved." -msgstr "" -"Пожалуйста войдите снова, посколькук ваша сессия устарела. Не беспокойтесь:" -"введенные вами данные сохранены." +msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved." +msgstr "Пожалуйста войдите снова, посколькук ваша сессия устарела. Не беспокойтесь:введенные вами данные сохранены." #: contrib/admin/views/decorators.py:68 -msgid "" -"Looks like your browser isn't configured to accept cookies. Please enable " -"cookies, reload this page, and try again." -msgstr "" -"Похоже, что ваш броузер не настроен на прием cookies. Пожалуйства включите " -"cookie, перезагрузите страницу и попытайтесь снова. " +msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again." +msgstr "Похоже, что ваш броузер не настроен на прием cookies. Пожалуйства включите cookie, перезагрузите страницу и попытайтесь снова. " #: contrib/admin/views/decorators.py:82 msgid "Usernames cannot contain the '@' character." @@ -450,7 +440,7 @@ msgstr "Имя пользователя не может включать сим #: contrib/admin/views/decorators.py:84 #, python-format msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "" +msgstr "Ваш e-mail адрес не ваше имя. Попробуйте '%s' в замен." #: contrib/admin/views/main.py:226 msgid "Site administration" @@ -461,11 +451,13 @@ msgstr "Администрирование сайта" msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "%(name)s \"%(obj)s\" были успешно добавлены." -#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348 +#: contrib/admin/views/main.py:264 +#: contrib/admin/views/main.py:348 msgid "You may edit it again below." msgstr "Вы снова можете редактировать их внизу" -#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357 +#: contrib/admin/views/main.py:272 +#: contrib/admin/views/main.py:357 #, python-format msgid "You may add another %s below." msgstr "Вы можете добавить %s внизу." @@ -480,7 +472,8 @@ msgstr "Добавить %s" msgid "Added %s." msgstr "Добавлено %s" -#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338 +#: contrib/admin/views/main.py:336 +#: contrib/admin/views/main.py:338 #: contrib/admin/views/main.py:340 msgid "and" msgstr "и" @@ -497,18 +490,17 @@ msgstr "Удалено %s." #: contrib/admin/views/main.py:343 msgid "No fields changed." -msgstr "" +msgstr "Ни одно поле не изменено." #: contrib/admin/views/main.py:346 #, python-format msgid "The %(name)s \"%(obj)s\" was changed successfully." -msgstr "" +msgstr "%(name)s \"%(obj)s\" было успешно изменено" #: contrib/admin/views/main.py:354 #, python-format -msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." -msgstr "" +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "%(name)s \"%(obj)s\" было успешно изменено. Вы можете редактировать его снова." #: contrib/admin/views/main.py:392 #, python-format @@ -549,9 +541,12 @@ msgstr "Выберите %s" msgid "Select %s to change" msgstr "Выберите %s для изменения" -#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286 -#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294 -#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297 +#: contrib/admin/views/doc.py:277 +#: contrib/admin/views/doc.py:286 +#: contrib/admin/views/doc.py:288 +#: contrib/admin/views/doc.py:294 +#: contrib/admin/views/doc.py:295 +#: contrib/admin/views/doc.py:297 msgid "Integer" msgstr "Целое" @@ -559,7 +554,8 @@ msgstr "Целое" msgid "Boolean (Either True or False)" msgstr "Логическое (True или False)" -#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296 +#: contrib/admin/views/doc.py:279 +#: contrib/admin/views/doc.py:296 #, python-format msgid "String (up to %(maxlength)s)" msgstr "Строка (до %(maxlength)s символов)" @@ -580,7 +576,8 @@ msgstr "Дата (с указанием времени)" msgid "E-mail address" 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" msgstr "Путь к файлу" @@ -594,7 +591,7 @@ msgstr "Логическое (True, False или None)" #: contrib/admin/views/doc.py:292 msgid "Relation to parent model" -msgstr "" +msgstr "Зависимость на родительскую модель." #: contrib/admin/views/doc.py:293 msgid "Phone number" @@ -608,7 +605,8 @@ msgstr "Текст" msgid "Time" msgstr "Время" -#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7 +#: contrib/admin/views/doc.py:300 +#: contrib/flatpages/models.py:7 msgid "URL" msgstr "URL" @@ -688,12 +686,8 @@ msgid "DATE_WITH_TIME_FULL" msgstr "j. N Y, H:i" #: contrib/admin/templates/admin/object_history.html:36 -msgid "" -"This object doesn't have a change history. It probably wasn't added via this " -"admin site." -msgstr "" -"Данный обьект не имеет истории изменения. Возможно он не был добавлен через " -"данный административный сайт." +msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgstr "Данный обьект не имеет истории изменения. Возможно он не был добавлен через данный административный сайт." #: contrib/admin/templates/admin/base_site.html:4 msgid "Django site admin" @@ -716,12 +710,8 @@ msgid "Server Error (500)" msgstr "Ошибка сервера (500)" #: contrib/admin/templates/admin/500.html:10 -msgid "" -"There's been an error. It's been reported to the site administrators via e-" -"mail and should be fixed shortly. Thanks for your patience." -msgstr "" -"Произошла ошибка. Отчет об ошибке отправлен администраторам сайта по e-mailи " -"она должна быть вскоре исправлена. Благодарим вас на терпение и помощь." +msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." +msgstr "Произошла ошибка. Отчет об ошибке отправлен администраторам сайта по e-mailи она должна быть вскоре исправлена. Благодарим вас на терпение и помощь." #: contrib/admin/templates/admin/404.html:4 #: contrib/admin/templates/admin/404.html:8 @@ -782,23 +772,13 @@ msgstr "Удалить" #: contrib/admin/templates/admin/delete_confirmation.html:14 #, python-format -msgid "" -"Deleting the %(object_name)s '%(object)s' would result in deleting related " -"objects, but your account doesn't have permission to delete the following " -"types of objects:" -msgstr "" -"Удаление объекта %(object_name)s '%(object)s' приведет к удалению зависимых " -"элементов, но предоставленных вам прав недостаточно для удаления следующих " -"типов объектов:" +msgid "Deleting the %(object_name)s '%(object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgstr "Удаление объекта %(object_name)s '%(object)s' приведет к удалению зависимых элементов, но предоставленных вам прав недостаточно для удаления следующих типов объектов:" #: contrib/admin/templates/admin/delete_confirmation.html:21 #, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of " -"the following related items will be deleted:" -msgstr "" -"Вы уверены, что хотите удалить %(object_name)s \"%(object)s\"? Все " -"следующие объекты также будут удалены:" +msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:" +msgstr "Вы уверены, что хотите удалить %(object_name)s \"%(object)s\"? Все следующие объекты также будут удалены:" #: contrib/admin/templates/admin/delete_confirmation.html:26 msgid "Yes, I'm sure" @@ -807,7 +787,7 @@ msgstr "Да, я уверен" #: contrib/admin/templates/admin/filter.html:2 #, python-format msgid " By %(title)s " -msgstr "" +msgstr "К%(title)s " #: contrib/admin/templates/admin/search_form.html:8 msgid "Go" @@ -871,12 +851,8 @@ msgid "Password reset" msgstr "Сброс пароля" #: contrib/admin/templates/registration/password_reset_form.html:12 -msgid "" -"Forgotten your password? Enter your e-mail address below, and we'll reset " -"your password and e-mail the new one to you." -msgstr "" -"Забыли пароль? Введите ваш e-mail адрес ниже и мы очистим ваш старый пароль, " -"и вышлем вам по e-mail новый." +msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." +msgstr "Забыли пароль? Введите ваш e-mail адрес ниже и мы очистим ваш старый пароль, и вышлем вам по e-mail новый." #: contrib/admin/templates/registration/password_reset_form.html:16 msgid "E-mail address:" @@ -900,20 +876,12 @@ msgid "Password reset successful" msgstr "Успешная очистка пароля" #: contrib/admin/templates/registration/password_reset_done.html:12 -msgid "" -"We've e-mailed a new password to the e-mail address you submitted. You " -"should be receiving it shortly." -msgstr "" -"Мы отправили новый пароль по указанному вами адресу электронной почты. Вы " -"должны его вскоре получить." +msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly." +msgstr "Мы отправили новый пароль по указанному вами адресу электронной почты. Вы должны его вскоре получить." #: contrib/admin/templates/registration/password_change_form.html:12 -msgid "" -"Please enter your old password, for security's sake, and then enter your new " -"password twice so we can verify you typed it in correctly." -msgstr "" -"В целях безопасности, пожалуйста, введите ваш старый пароль, затем - новый " -"пароль дважды, с тем, чтобы мы могли убедиться в правильности написания." +msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." +msgstr "В целях безопасности, пожалуйста, введите ваш старый пароль, затем - новый пароль дважды, с тем, чтобы мы могли убедиться в правильности написания." #: contrib/admin/templates/registration/password_change_form.html:17 msgid "Old password:" @@ -986,24 +954,16 @@ msgid "Documentation for this page" msgstr "Документация по данной странице" #: contrib/admin/templates/admin_doc/bookmarklets.html:20 -msgid "" -"Jumps you from any page to the documentation for the view that generates " -"that page." -msgstr "" -"Перенаправит вас с любой страницы к просмотру документа, который генерирует " -"эту страницу." +msgid "Jumps you from any page to the documentation for the view that generates that page." +msgstr "Перенаправит вас с любой страницы к просмотру документа, который генерирует эту страницу." #: contrib/admin/templates/admin_doc/bookmarklets.html:22 msgid "Show object ID" msgstr "Показать ID обьекта" #: contrib/admin/templates/admin_doc/bookmarklets.html:23 -msgid "" -"Shows the content-type and unique ID for pages that represent a single " -"object." -msgstr "" -"Показывает тип наполнения и уникальный ID для страниц, которые означают " -"одинокий объект." +msgid "Shows the content-type and unique ID for pages that represent a single object." +msgstr "Показывает тип наполнения и уникальный ID для страниц, которые означают одинокий объект." #: contrib/admin/templates/admin_doc/bookmarklets.html:25 msgid "Edit this object (current window)" @@ -1042,24 +1002,16 @@ msgid "redirect from" msgstr "перенаправить из" #: contrib/redirects/models.py:8 -msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "" -"Это должен быть абсолютный путь, исключая доменное имя. Пример: '/events/" -"search/'." +msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'." +msgstr "Это должен быть абсолютный путь, исключая доменное имя. Пример: '/events/search/'." #: contrib/redirects/models.py:9 msgid "redirect to" msgstr "перенаправить на" #: contrib/redirects/models.py:10 -msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." -msgstr "" -"Это должен быть, либо абсолютный путь (как выше) или полный URL начинающийся " -"с 'http://'." +msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'." +msgstr "Это должен быть, либо абсолютный путь (как выше) или полный URL начинающийся с 'http://'." #: contrib/redirects/models.py:12 msgid "redirect" @@ -1070,10 +1022,8 @@ msgid "redirects" msgstr "перенаправления" #: contrib/flatpages/models.py:8 -msgid "" -"Example: '/about/contact/'. Make sure to have leading and trailing slashes." -msgstr "" -"Пример: '/about/contact/'. Будьте уверенны, что вставили завепршающий слэш." +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "Пример: '/about/contact/'. Будьте уверенны, что вставили завепршающий слэш." #: contrib/flatpages/models.py:9 msgid "title" @@ -1092,10 +1042,8 @@ msgid "template name" msgstr "имя шаблона" #: contrib/flatpages/models.py:13 -msgid "" -"Example: 'flatpages/contact_page'. If this isn't provided, the system will " -"use 'flatpages/default'." -msgstr "" +msgid "Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'." +msgstr "Пример: 'flatpages/contact_page'. Если этот файл не присутствует, система будет использовать 'flatpages/default'." #: contrib/flatpages/models.py:14 msgid "registration required" @@ -1113,7 +1061,8 @@ msgstr "простая страница" msgid "flat pages" msgstr "простые страницы" -#: contrib/auth/models.py:13 contrib/auth/models.py:26 +#: contrib/auth/models.py:13 +#: contrib/auth/models.py:26 msgid "name" msgstr "имя" @@ -1125,7 +1074,8 @@ msgstr "код" msgid "permission" msgstr "Права" -#: contrib/auth/models.py:18 contrib/auth/models.py:27 +#: contrib/auth/models.py:18 +#: contrib/auth/models.py:27 msgid "permissions" msgstr "Права" @@ -1133,7 +1083,8 @@ msgstr "Права" msgid "group" msgstr "Группа" -#: contrib/auth/models.py:30 contrib/auth/models.py:65 +#: contrib/auth/models.py:30 +#: contrib/auth/models.py:65 msgid "groups" msgstr "Группы" @@ -1159,7 +1110,7 @@ msgstr "пароль" #: contrib/auth/models.py:59 msgid "Use '[algo]$[salt]$[hexdigest]'" -msgstr "" +msgstr "Используйте '[algo]$[salt]$[hexdigest]'" #: contrib/auth/models.py:60 msgid "staff status" @@ -1186,12 +1137,8 @@ msgid "date joined" msgstr "дата регистрации" #: contrib/auth/models.py:66 -msgid "" -"In addition to the permissions manually assigned, this user will also get " -"all permissions granted to each group he/she is in." -msgstr "" -"К добавлению к перавам выбрнанным вуручную, этот пользователь может получить " -"все права группы, к которой он принадлежит." +msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in." +msgstr "К добавлению к перавам выбрнанным вуручную, этот пользователь может получить все права группы, к которой он принадлежит." #: contrib/auth/models.py:67 msgid "user permissions" @@ -1226,10 +1173,8 @@ msgid "message" msgstr "Сообщение" #: contrib/auth/forms.py:30 -msgid "" -"Your Web browser doesn't appear to have cookies enabled. Cookies are " -"required for logging in." -msgstr "" +msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in." +msgstr "У вашего браузера не включены cookies. Cookies необходимы для входа." #: contrib/contenttypes/models.py:25 msgid "python model class name" @@ -1327,23 +1272,28 @@ msgstr "Январь" msgid "February" msgstr "Февраль" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:14 +#: utils/dates.py:27 msgid "March" msgstr "Март" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:14 +#: utils/dates.py:27 msgid "April" msgstr "Апрель" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:14 +#: utils/dates.py:27 msgid "May" msgstr "Май" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:14 +#: utils/dates.py:27 msgid "June" msgstr "Июнь" -#: utils/dates.py:15 utils/dates.py:27 +#: utils/dates.py:15 +#: utils/dates.py:27 msgid "July" msgstr "Июль" @@ -1592,11 +1542,8 @@ msgid "This value must contain only letters, numbers and underscores." msgstr "Значение может содержать только буквы, цифры и подчеркивания." #: core/validators.py:64 -msgid "" -"This value must contain only letters, numbers, underscores, dashes or " -"slashes." -msgstr "Значение может содержать только буквы, цифры, подчеркивания, дифисы или " -"тере." +msgid "This value must contain only letters, numbers, underscores, dashes or slashes." +msgstr "Значение может содержать только буквы, цифры, подчеркивания, дифисы или тере." #: core/validators.py:72 msgid "Uppercase letters are not allowed here." @@ -1646,7 +1593,8 @@ msgstr "Вводите реальную дату в формате YYYY-MM-DD." msgid "Enter a valid time in HH:MM format." msgstr "Вводите реальное время в формате HH:MM." -#: core/validators.py:132 db/models/fields/__init__.py:468 +#: core/validators.py:132 +#: db/models/fields/__init__.py:468 msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." msgstr "Вводите реальные дата/время в формате YYYY-MM-DD HH:MM." @@ -1655,12 +1603,8 @@ msgid "Enter a valid e-mail address." msgstr "Укажите реальный e-mail адрес." #: core/validators.py:148 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" -"Загрузите реальное изображение. Файл, который вы загружали, не был " -"изображением или был поврежден." +msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." +msgstr "Загрузите реальное изображение. Файл, который вы загружали, не был изображением или был поврежден." #: core/validators.py:155 #, python-format @@ -1700,7 +1644,8 @@ msgstr "Неверный формат XML: %s" msgid "Invalid URL: %s" msgstr "Неверный URL: %s" -#: core/validators.py:206 core/validators.py:208 +#: core/validators.py:206 +#: core/validators.py:208 #, python-format msgid "The URL %s is a broken link." msgstr "URL %s сломанная ссылка." @@ -1725,7 +1670,8 @@ msgstr "Это поле должно совпадать с полем '%s'." msgid "Please enter something for at least one field." msgstr "Пожалуйста, заполните хотя бы одно поле." -#: core/validators.py:264 core/validators.py:275 +#: core/validators.py:264 +#: core/validators.py:275 msgid "Please enter both fields or leave them both empty." msgstr "Пожалуйста, заполните оба поля либо оставьте их пустыми." @@ -1755,26 +1701,16 @@ msgstr "Пожалуйста, вводите корректное десятич #: core/validators.py:349 #, python-format msgid "Please enter a valid decimal number with at most %s total digit." -msgid_plural "" -"Please enter a valid decimal number with at most %s total digits." -msgstr[0] "" -"Пожалуйста, вводите корректное десятичное число с максимальным количеством " -"знаков %s." -msgstr[1] "" -"Пожалуйста, вводите корректное десятичное число с максимальным количеством " -"знаков %s." +msgid_plural "Please enter a valid decimal number with at most %s total digits." +msgstr[0] "Пожалуйста, вводите корректное десятичное число с максимальным количеством знаков %s." +msgstr[1] "Пожалуйста, вводите корректное десятичное число с максимальным количеством знаков %s." #: core/validators.py:352 #, python-format msgid "Please enter a valid decimal number with at most %s decimal place." -msgid_plural "" -"Please enter a valid decimal number with at most %s decimal places." -msgstr[0] "" -"Пожалуйста, вводите корректное десятичное число с максимальным количеством " -"знаков после запятой %s." -msgstr[1] "" -"Пожалуйста, вводите корректное десятичное число с максимальным количеством " -"знаков после запятой %s." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "Пожалуйста, вводите корректное десятичное число с максимальным количеством знаков после запятой %s." +msgstr[1] "Пожалуйста, вводите корректное десятичное число с максимальным количеством знаков после запятой %s." #: core/validators.py:362 #, python-format @@ -1801,50 +1737,37 @@ msgstr "Невозможно получить что-либо с %s." #: core/validators.py:429 #, python-format -msgid "" -"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." -msgstr "URL %(url) вернул неверный заголовок Content-Type '%(contenttype)'." +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgstr "URL %(url)s вернул неверный заголовок Content-Type '%(contenttype)s'." #: core/validators.py:462 #, python-format -msgid "" -"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " -"\"%(start)s\".)" +msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)" msgstr "" #: core/validators.py:466 #, python-format -msgid "" -"Some text starting on line %(line)s is not allowed in that context. (Line " -"starts with \"%(start)s\".)" +msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)" msgstr "" #: core/validators.py:471 #, python-format -msgid "" -"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" -"(start)s\".)" +msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)" msgstr "" #: core/validators.py:476 #, python-format -msgid "" -"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" -"(start)s\".)" +msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)" msgstr "" #: core/validators.py:480 #, python-format -msgid "" -"A tag on line %(line)s is missing one or more required attributes. (Line " -"starts with \"%(start)s\".)" +msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)" msgstr "" #: core/validators.py:485 #, python-format -msgid "" -"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " -"starts with \"%(start)s\".)" +msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)" msgstr "" #: db/models/manipulators.py:302 @@ -1857,8 +1780,10 @@ msgstr "" msgid "%(optname)s with this %(fieldname)s already exists." msgstr "" -#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 -#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553 +#: db/models/fields/__init__.py:114 +#: db/models/fields/__init__.py:265 +#: db/models/fields/__init__.py:542 +#: db/models/fields/__init__.py:553 #: forms/__init__.py:346 msgid "This field is required." msgstr "Обязательное поле." @@ -1868,14 +1793,12 @@ msgid "This value must be an integer." msgstr "" #: db/models/fields/__init__.py:369 -#, fuzzy msgid "This value must be either True or False." -msgstr "Логическое (True или False)" +msgstr "Значение должно либо True либо False." #: db/models/fields/__init__.py:385 -#, fuzzy msgid "This field cannot be null." -msgstr "Это поле неверно." +msgstr "Это поле не может быть нулевым." #: db/models/fields/__init__.py:562 msgid "Enter a valid filename." @@ -1887,23 +1810,17 @@ msgid "Please enter a valid %s." msgstr "" #: db/models/fields/related.py:579 -#, fuzzy msgid "Separate multiple IDs with commas." msgstr "Несколько значений ID разделяйте запятыми." #: db/models/fields/related.py:581 -#, fuzzy -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "" -" Удерживайте \"Control\", или \"Command\" на Макинтош, для выбора больше чем " -"одного." +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr " Удерживайте \"Control\", или \"Command\" на Макинтош, для выбора больше чем одного." #: db/models/fields/related.py:625 #, python-format msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." -msgid_plural "" -"Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." msgstr[0] "" msgstr[1] "" @@ -1918,7 +1835,9 @@ msgstr[1] "" msgid "Line breaks are not allowed here." msgstr "Переносы строк не допускаются здесь." -#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589 +#: forms/__init__.py:480 +#: forms/__init__.py:551 +#: forms/__init__.py:589 #, python-format msgid "Select a valid choice; '%(data)s' is not in %(choices)s." msgstr "" @@ -1943,30 +1862,3 @@ msgstr "Введите целое число в диапазоне от 0 до 3 msgid "yes,no,maybe" 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 (500)" -#~ msgstr "Ошибка сервера (500)" diff --git a/django/conf/locale/sl/LC_MESSAGES/django.mo b/django/conf/locale/sl/LC_MESSAGES/django.mo index a7d6152411..12253610c4 100644 Binary files a/django/conf/locale/sl/LC_MESSAGES/django.mo and b/django/conf/locale/sl/LC_MESSAGES/django.mo differ diff --git a/django/conf/locale/sl/LC_MESSAGES/django.po b/django/conf/locale/sl/LC_MESSAGES/django.po index 1d9e2f4028..5a9b6d6b46 100644 --- a/django/conf/locale/sl/LC_MESSAGES/django.po +++ b/django/conf/locale/sl/LC_MESSAGES/django.po @@ -1,21 +1,25 @@ -# SOME DESCRIPTIVE TITLE. +# translation of django.po to Slovenian +# Igor Kolar , 2006. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# Igor Kolar \n" -"Language-Team: Slovenian \n" +"Language-Team: Slovenian \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" +"X-Generator: KBabel 1.11.2\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" -#: contrib/comments/models.py:67 contrib/comments/models.py:166 +#: contrib/comments/models.py:67 +#: contrib/comments/models.py:166 msgid "object ID" msgstr "ID objekta" @@ -23,7 +27,8 @@ msgstr "ID objekta" msgid "headline" msgstr "naslov" -#: contrib/comments/models.py:69 contrib/comments/models.py:90 +#: contrib/comments/models.py:69 +#: contrib/comments/models.py:90 #: contrib/comments/models.py:167 msgid "comment" msgstr "komentar" @@ -64,15 +69,18 @@ msgstr "rating #8" msgid "is valid rating" msgstr "je veljavni rating" -#: contrib/comments/models.py:83 contrib/comments/models.py:169 +#: contrib/comments/models.py:83 +#: contrib/comments/models.py:169 msgid "date/time submitted" -msgstr "podatek datum/čas poslan" +msgstr "datum/čas vnosa" -#: contrib/comments/models.py:84 contrib/comments/models.py:170 +#: contrib/comments/models.py:84 +#: contrib/comments/models.py:170 msgid "is public" msgstr "je javno" -#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289 +#: contrib/comments/models.py:85 +#: contrib/admin/views/doc.py:289 msgid "IP address" msgstr "IP naslov" @@ -81,21 +89,17 @@ msgid "is removed" msgstr "je odstranjen/-a" #: contrib/comments/models.py:86 -msgid "" -"Check this box if the comment is inappropriate. A \"This comment has been " -"removed\" message will be displayed instead." -msgstr "" -"Odkljukaj, če je komntar neprimeren. Namesto komentarja bo vidno obvestilo " -"\"Ta komentar je bil odstranjen\"." +msgid "Check this box if the comment is inappropriate. A \"This comment has been removed\" message will be displayed instead." +msgstr "Odkljukaj, če je komntar neprimeren. Namesto komentarja bo vidno obvestilo \"Ta komentar je bil odstranjen\"." #: contrib/comments/models.py:91 -#, fuzzy msgid "comments" -msgstr "komentar" +msgstr "komentarji" -#: contrib/comments/models.py:131 contrib/comments/models.py:207 +#: contrib/comments/models.py:131 +#: contrib/comments/models.py:207 msgid "Content object" -msgstr "Objekt s vsebino" +msgstr "Objekt z vsebino" #: contrib/comments/models.py:159 #, python-format @@ -125,14 +129,12 @@ msgid "approved by staff" msgstr "potrjeno s strani osebja" #: contrib/comments/models.py:176 -#, fuzzy msgid "free comment" -msgstr "Zastonj komentar" +msgstr "anonimen komentar" #: contrib/comments/models.py:177 -#, fuzzy msgid "free comments" -msgstr "Zastonj komentarji" +msgstr "anonimni komentarji" #: contrib/comments/models.py:233 msgid "score" @@ -143,14 +145,12 @@ msgid "score date" msgstr "datum ocene" #: contrib/comments/models.py:237 -#, fuzzy msgid "karma score" -msgstr "Karma" +msgstr "karma točke" #: contrib/comments/models.py:238 -#, fuzzy msgid "karma scores" -msgstr "Skrivnosti karme" +msgstr "karma točke" #: contrib/comments/models.py:242 #, python-format @@ -173,14 +173,12 @@ msgid "flag date" msgstr "datum označitve (zastavice)" #: contrib/comments/models.py:268 -#, fuzzy msgid "user flag" -msgstr "Uporabniška zastavica" +msgstr "uporabnikova zastavica" #: contrib/comments/models.py:269 -#, fuzzy msgid "user flags" -msgstr "Uporabniške zastavice" +msgstr "uporabniške zastavice" #: contrib/comments/models.py:273 #, python-format @@ -192,14 +190,12 @@ msgid "deletion date" msgstr "datum izbrisa" #: contrib/comments/models.py:280 -#, fuzzy msgid "moderator deletion" -msgstr "Izbris s strani moderatorja" +msgstr "izbris s strani moderatorja" #: contrib/comments/models.py:281 -#, fuzzy msgid "moderator deletions" -msgstr "Izbrisi s strani moderatorja" +msgstr "izbrisi s strani moderatorja" #: contrib/comments/models.py:285 #, python-format @@ -219,30 +215,33 @@ msgid "No voting for yourself" msgstr "Ni mogoče glasovati zase" #: contrib/comments/views/comments.py:28 -msgid "" -"This rating is required because you've entered at least one other rating." +msgid "This rating is required because you've entered at least one other rating." msgstr "Moraš podati tole oceno, ker si podal vsaj še eno drugo oceno." #: contrib/comments/views/comments.py:112 #, python-format msgid "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comment:\n" +"This comment was posted by a user who has posted fewer than %(count)s comment:\n" "\n" "%(text)s" msgid_plural "" -"This comment was posted by a user who has posted fewer than %(count)s " -"comments:\n" +"This comment was posted by a user who has posted fewer than %(count)s comments:\n" "\n" "%(text)s" msgstr[0] "" -"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s " -"komentarjev Komentar:\n" +"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s komentarjev:\n" "\n" "%(text)s" msgstr[1] "" -"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s " -"komentarjev Komentar:\n" +"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s komentar:\n" +"\n" +"%(text)s" +msgstr[2] "" +"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s komentarja:\n" +"\n" +"%(text)s" +msgstr[3] "" +"Ta komentar je poslal uporabnik, ki je do zdaj poslal manj kot %(count)s komentarje:\n" "\n" "%(text)s" @@ -260,12 +259,12 @@ msgstr "" #: contrib/comments/views/comments.py:189 #: contrib/comments/views/comments.py:280 msgid "Only POSTs are allowed" -msgstr "Dovoljena je le metoda HTTP POST" +msgstr "Dovoljena je le metoda POST" #: contrib/comments/views/comments.py:193 #: contrib/comments/views/comments.py:284 msgid "One or more of the required fields wasn't submitted" -msgstr "Eden ali več obveznih polj ni vpisanih" +msgstr "Eno ali več obveznih polj ni vpisanih" #: contrib/comments/views/comments.py:197 #: contrib/comments/views/comments.py:286 @@ -274,17 +273,13 @@ msgstr "Nekdo se je poigraval z obrazcem za komentarje (varnostna kršitev)" #: contrib/comments/views/comments.py:207 #: contrib/comments/views/comments.py:292 -msgid "" -"The comment form had an invalid 'target' parameter -- the object ID was " -"invalid" -msgstr "" -"Obrazec s komentarji ima neveljavni parameter 'target' -- ID objekta je " -"neveljaven." +msgid "The comment form had an invalid 'target' parameter -- the object ID was invalid" +msgstr "Obrazec s komentarji ima neveljavni parameter 'target' -- ID objekta je neveljaven." #: contrib/comments/views/comments.py:257 #: contrib/comments/views/comments.py:321 msgid "The comment form didn't provide either 'preview' or 'post'" -msgstr "Obrazec s komentarji ne zahteva niti 'preview' niti 'post' akcije." +msgstr "Obrazec s komentarji ni podal niti 'preview' niti 'post' akcije." #: contrib/comments/templates/comments/form.html:6 #: contrib/comments/templates/comments/form.html:8 @@ -363,7 +358,8 @@ msgstr "" "

      Avtor: %s

      \n" "
        \n" -#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88 +#: contrib/admin/filterspecs.py:70 +#: contrib/admin/filterspecs.py:88 #: contrib/admin/filterspecs.py:143 msgid "All" msgstr "Vse" @@ -390,7 +386,7 @@ msgstr "Letos" #: contrib/admin/filterspecs.py:143 msgid "Yes" -msgstr "Ja" +msgstr "Da" #: contrib/admin/filterspecs.py:143 msgid "No" @@ -432,46 +428,33 @@ msgstr "vnosi v dnevniku" msgid "All dates" msgstr "Vsi datumi" -#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36 +#: contrib/admin/views/decorators.py:9 +#: contrib/auth/forms.py:36 #: contrib/auth/forms.py:41 -msgid "" -"Please enter a correct username and password. Note that both fields are case-" -"sensitive." -msgstr "" -"Prosimo, vnesite veljavno uporabniško ime in geslo. Opomba: obe polji sta " -"občutljivi na velikost črk" +msgid "Please enter a correct username and password. Note that both fields are case-sensitive." +msgstr "Prosimo, vnesite veljavno uporabniško ime in geslo. Opomba: obe polji sta občutljivi na velikost črk" #: contrib/admin/views/decorators.py:23 #: contrib/admin/templates/admin/login.html:25 msgid "Log in" -msgstr "Prijate se" +msgstr "Prijavite se" #: contrib/admin/views/decorators.py:61 -msgid "" -"Please log in again, because your session has expired. Don't worry: Your " -"submission has been saved." -msgstr "" -"Vaša seja je pretekla; prosimo, prijavite se znova. Opomba: Vse vaše objave " -"so varno shranjene." +msgid "Please log in again, because your session has expired. Don't worry: Your submission has been saved." +msgstr "Vaša seja je pretekla; prosimo, prijavite se znova. Ne skrbite, vaše objave so varno shranjene." #: contrib/admin/views/decorators.py:68 -msgid "" -"Looks like your browser isn't configured to accept cookies. Please enable " -"cookies, reload this page, and try again." -msgstr "" -"Izgleda, da vaš brskalnik nima podpore za piškotke. Prosimo, vključite " -"piškotke, znova naložite to stran in poskusite še enkrat." +msgid "Looks like your browser isn't configured to accept cookies. Please enable cookies, reload this page, and try again." +msgstr "Izgleda, da vaš brskalnik nima podpore za piškotke. Prosimo, vključite piškotke, znova naložite to stran in poskusite še enkrat." #: contrib/admin/views/decorators.py:82 msgid "Usernames cannot contain the '@' character." -msgstr "Uporabniška imena ne smejo vsebovati znaka '@'" +msgstr "Uporabniška imena ne smejo vsebovati znaka '@'." #: contrib/admin/views/decorators.py:84 #, python-format msgid "Your e-mail address is not your username. Try '%s' instead." -msgstr "" -"Vaš e-mail naslov ne morete uporabljati kot uporabniško ime. Namesto tega " -"uporabite '%s'" +msgstr "Vaš e-mail naslov ne morete uporabljati kot uporabniško ime. Namesto tega uporabite '%s'." #: contrib/admin/views/main.py:226 msgid "Site administration" @@ -482,11 +465,13 @@ msgstr "Administracija strani" msgid "The %(name)s \"%(obj)s\" was added successfully." msgstr "%(name)s \"%(obj)s\" je bil uspešno dodan." -#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348 +#: contrib/admin/views/main.py:264 +#: contrib/admin/views/main.py:348 msgid "You may edit it again below." msgstr "Vsebino lahko znova uredite spodaj." -#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357 +#: contrib/admin/views/main.py:272 +#: contrib/admin/views/main.py:357 #, python-format msgid "You may add another %s below." msgstr "Spodaj lahko dodate še en %s." @@ -501,7 +486,8 @@ msgstr "Dodaj %s" msgid "Added %s." msgstr "Dodal %s." -#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338 +#: contrib/admin/views/main.py:336 +#: contrib/admin/views/main.py:338 #: contrib/admin/views/main.py:340 msgid "and" msgstr "in" @@ -509,7 +495,7 @@ msgstr "in" #: contrib/admin/views/main.py:338 #, python-format msgid "Changed %s." -msgstr "Spremenil %s" +msgstr "Spremenil %s." #: contrib/admin/views/main.py:340 #, python-format @@ -527,10 +513,8 @@ msgstr "%(name)s \"%(obj)s\" je bilo uspešno spremenjeno." #: contrib/admin/views/main.py:354 #, python-format -msgid "" -"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." -msgstr "" -"%(name)s \"%(obj)s\" je bilo uspešno dodano. Znova ga lahko urejate spodaj." +msgid "The %(name)s \"%(obj)s\" was added successfully. You may edit it again below." +msgstr "%(name)s \"%(obj)s\" je bilo uspešno dodano. Znova ga lahko urejate spodaj." #: contrib/admin/views/main.py:392 #, python-format @@ -564,24 +548,28 @@ msgstr "Zgodovina sprememb: %s" #: contrib/admin/views/main.py:565 #, python-format msgid "Select %s" -msgstr "Izberi %s" +msgstr "Izberite %s" #: contrib/admin/views/main.py:565 #, python-format msgid "Select %s to change" -msgstr "Izberi %s, ki ga želite spremeniti" +msgstr "Izberite %s, ki ga želite spremeniti" -#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286 -#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294 -#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297 +#: contrib/admin/views/doc.py:277 +#: contrib/admin/views/doc.py:286 +#: contrib/admin/views/doc.py:288 +#: contrib/admin/views/doc.py:294 +#: contrib/admin/views/doc.py:295 +#: contrib/admin/views/doc.py:297 msgid "Integer" -msgstr "Integer (število)" +msgstr "Število (integer)" #: contrib/admin/views/doc.py:278 msgid "Boolean (Either True or False)" msgstr "Boolean (ali True ali False)" -#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296 +#: contrib/admin/views/doc.py:279 +#: contrib/admin/views/doc.py:296 #, python-format msgid "String (up to %(maxlength)s)" msgstr "Niz (vse do %(maxlength)s)" @@ -602,7 +590,8 @@ msgstr "Datum (s časom)" msgid "E-mail address" msgstr "E-naslov" -#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287 +#: contrib/admin/views/doc.py:284 +#: contrib/admin/views/doc.py:287 msgid "File path" msgstr "Pot do datoteke" @@ -616,7 +605,7 @@ msgstr "Boolean (ali True ali False ali None)" #: contrib/admin/views/doc.py:292 msgid "Relation to parent model" -msgstr "Razmerje z starševskim modelom" +msgstr "Razmerje s starševskim modelom" #: contrib/admin/views/doc.py:293 msgid "Phone number" @@ -630,7 +619,8 @@ msgstr "Besedilo" msgid "Time" msgstr "Čas" -#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7 +#: contrib/admin/views/doc.py:300 +#: contrib/flatpages/models.py:7 msgid "URL" msgstr "URL (spletni naslov)" @@ -707,15 +697,11 @@ msgstr "Dejanje" #: contrib/admin/templates/admin/object_history.html:26 msgid "DATE_WITH_TIME_FULL" -msgstr "N j, Y, P" +msgstr "N j, Y, H:i" #: contrib/admin/templates/admin/object_history.html:36 -msgid "" -"This object doesn't have a change history. It probably wasn't added via this " -"admin site." -msgstr "" -"Ta objekt nima zgodovine. Verjetno ni bil dodan preko te administratorske " -"strani." +msgid "This object doesn't have a change history. It probably wasn't added via this admin site." +msgstr "Ta objekt nima zgodovine. Verjetno ni bil dodan preko te administratorske strani." #: contrib/admin/templates/admin/base_site.html:4 msgid "Django site admin" @@ -738,12 +724,8 @@ msgid "Server Error (500)" msgstr "Napaka strežnika (500)" #: contrib/admin/templates/admin/500.html:10 -msgid "" -"There's been an error. It's been reported to the site administrators via e-" -"mail and should be fixed shortly. Thanks for your patience." -msgstr "" -"Prišlo je do nepričakovane napake. Administratorji strani so že obveščeni " -"prekoe-pošte in naj bi jo v kratkem odpravili. Hvala za vaše potrpljenje." +msgid "There's been an error. It's been reported to the site administrators via e-mail and should be fixed shortly. Thanks for your patience." +msgstr "Prišlo je do nepričakovane napake. Administratorji strani so že obveščeni prekoe-pošte in naj bi jo v kratkem odpravili. Hvala za vaše potrpljenje." #: contrib/admin/templates/admin/404.html:4 #: contrib/admin/templates/admin/404.html:8 @@ -752,12 +734,12 @@ msgstr "Strani ni mogoče najti" #: contrib/admin/templates/admin/404.html:10 msgid "We're sorry, but the requested page could not be found." -msgstr "Se opraivčujemo, a zahtevane strani ni mogoče najti." +msgstr "Se opravičujemo, a zahtevane strani ni mogoče najti." #: contrib/admin/templates/admin/index.html:17 #, python-format msgid "Models available in the %(name)s application." -msgstr "" +msgstr "Modeli na voljo v %(name)s aplikaciji" #: contrib/admin/templates/admin/index.html:28 #: contrib/admin/templates/admin/change_form.html:15 @@ -776,7 +758,7 @@ msgstr "Nimate dovoljenja za urejanje česar koli." msgid "Recent Actions" msgstr "Zadnja dejanja" -#: contrib/admin/templates/admin/index.html:53 +#: contrib/admin/tempalates/admin/index.html:53 msgid "My Actions" msgstr "Moja dejanja" @@ -804,22 +786,13 @@ msgstr "Izbriši" #: contrib/admin/templates/admin/delete_confirmation.html:14 #, python-format -msgid "" -"Deleting the %(object_name)s '%(object)s' would result in deleting related " -"objects, but your account doesn't have permission to delete the following " -"types of objects:" -msgstr "" -"Izbris %(object_name)s '%(object)s' bi pomenil izbris povezanih objektov, " -"vendarvi nimate dovoljenja za izbris naslednjih tipov objektov:" +msgid "Deleting the %(object_name)s '%(object)s' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:" +msgstr "Izbris %(object_name)s '%(object)s' bi pomenil izbris povezanih objektov, vendarvi nimate dovoljenja za izbris naslednjih tipov objektov:" #: contrib/admin/templates/admin/delete_confirmation.html:21 #, python-format -msgid "" -"Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of " -"the following related items will be deleted:" -msgstr "" -"Ste prepričani, da želite izbrisati %(object_name)s \"%(object)s\"?Vsi " -"naslednji povezani elementi bodo izbrisani:" +msgid "Are you sure you want to delete the %(object_name)s \"%(object)s\"? All of the following related items will be deleted:" +msgstr "Ste prepričani, da želite izbrisati %(object_name)s \"%(object)s\"?Vsi naslednji povezani elementi bodo izbrisani:" #: contrib/admin/templates/admin/delete_confirmation.html:26 msgid "Yes, I'm sure" @@ -843,6 +816,8 @@ msgid "Please correct the error below." msgid_plural "Please correct the errors below." msgstr[0] "Prosimo, odpravite sledečo napako." msgstr[1] "Prosimo, odpravite sledeče napake." +msgstr[2] "Prosimo, odpravite sledeči napaki." +msgstr[3] "Prosimo, odpravite sledeče napake." #: contrib/admin/templates/admin/change_form.html:48 msgid "Ordering" @@ -892,12 +867,8 @@ msgid "Password reset" msgstr "Obnova gesla" #: contrib/admin/templates/registration/password_reset_form.html:12 -msgid "" -"Forgotten your password? Enter your e-mail address below, and we'll reset " -"your password and e-mail the new one to you." -msgstr "" -"Ste pozabili geslo? Vnesite vaš e-naslov spodaj in mi vam bomo poslali novo " -"geslo." +msgid "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." +msgstr "Ste pozabili geslo? Vnesite vaš e-naslov spodaj in mi vam bomo poslali novo geslo." #: contrib/admin/templates/registration/password_reset_form.html:16 msgid "E-mail address:" @@ -921,18 +892,12 @@ msgid "Password reset successful" msgstr "Geslo je bilo uspešno obnovljeno" #: contrib/admin/templates/registration/password_reset_done.html:12 -msgid "" -"We've e-mailed a new password to the e-mail address you submitted. You " -"should be receiving it shortly." +msgid "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly." msgstr "Po e-pošti smo vam poslali novo geslo.Morali bi ga prejeti v kratkem" #: contrib/admin/templates/registration/password_change_form.html:12 -msgid "" -"Please enter your old password, for security's sake, and then enter your new " -"password twice so we can verify you typed it in correctly." -msgstr "" -"Prosim, vnesite vaše staro geslo (zaradi varnosti) in nato še dvakrat novo" -"(da preverimo, da se niste zatipkali)" +msgid "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." +msgstr "Prosim, vnesite vaše staro geslo (zaradi varnosti) in nato še dvakrat novo(da preverimo, da se niste zatipkali)" #: contrib/admin/templates/registration/password_change_form.html:17 msgid "Old password:" @@ -1000,34 +965,24 @@ msgid "" "your computer is \"internal\").

        \n" msgstr "" "\n" -"

        Za inštalacijo zaznamkic povlečite povezavo v orodno " -"vrstico\n" -"z zaznamki, ali kliknite z desno miškino tipko na povezavo in jo dodajte med " -"zaznamkeZdaj lahko uporabite zaznamek s katere koli strani. Opomba: nekatere " -"teh stranilahko gledate le z internega računalnika (preverite s sistemskim " -"administratorjem)

        \n" +"

        Za inštalacijo zaznamkic povlečite povezavo v orodno vrstico\n" +"z zaznamki, ali kliknite z desno miškino tipko na povezavo in jo dodajte med zaznamkeZdaj lahko uporabite zaznamek s katere koli strani. Opomba: nekatere teh stranilahko gledate le z internega računalnika (preverite s sistemskim administratorjem)

        \n" #: contrib/admin/templates/admin_doc/bookmarklets.html:19 msgid "Documentation for this page" msgstr "Dokumentacija za to stran" #: contrib/admin/templates/admin_doc/bookmarklets.html:20 -msgid "" -"Jumps you from any page to the documentation for the view that generates " -"that page." -msgstr "" -"Skok na stran z dokumentacijo za pogled (view), ki generira trenutno stran." +msgid "Jumps you from any page to the documentation for the view that generates that page." +msgstr "Skok na stran z dokumentacijo za pogled (view), ki generira trenutno stran." #: contrib/admin/templates/admin_doc/bookmarklets.html:22 msgid "Show object ID" msgstr "Pokaži ID objekta" #: contrib/admin/templates/admin_doc/bookmarklets.html:23 -msgid "" -"Shows the content-type and unique ID for pages that represent a single " -"object." -msgstr "" -"Pokaže content-type in unikatni ID za strani, ki predstavljajo en objekt." +msgid "Shows the content-type and unique ID for pages that represent a single object." +msgstr "Pokaže content-type in unikatni ID za strani, ki predstavljajo en objekt." #: contrib/admin/templates/admin_doc/bookmarklets.html:25 msgid "Edit this object (current window)" @@ -1035,8 +990,7 @@ msgstr "Uredi trenutni objekt (v trenutnem oknu)" #: contrib/admin/templates/admin_doc/bookmarklets.html:26 msgid "Jumps to the admin page for pages that represent a single object." -msgstr "" -"Skok na administracijsko stran za vse strani, ki predstavljajo en objekt." +msgstr "Skok na administracijsko stran za vse strani, ki predstavljajo en objekt." #: contrib/admin/templates/admin_doc/bookmarklets.html:28 msgid "Edit this object (new window)" @@ -1067,23 +1021,16 @@ msgid "redirect from" msgstr "preusmeritev iz" #: contrib/redirects/models.py:8 -msgid "" -"This should be an absolute path, excluding the domain name. Example: '/" -"events/search/'." -msgstr "" -"To mora biti absolutna pot, izključujoč domeno. Primer: '/events/search'-" +msgid "This should be an absolute path, excluding the domain name. Example: '/events/search/'." +msgstr "To mora biti absolutna pot, izključujoč domeno. Primer: '/events/search'-" #: contrib/redirects/models.py:9 msgid "redirect to" msgstr "preusmeri na" #: contrib/redirects/models.py:10 -msgid "" -"This can be either an absolute path (as above) or a full URL starting with " -"'http://'." -msgstr "" -"To je ali absolutna pot (kot zgoraj) ali popoln URL naslov (začne se z " -"'http://')" +msgid "This can be either an absolute path (as above) or a full URL starting with 'http://'." +msgstr "To je ali absolutna pot (kot zgoraj) ali popoln URL naslov (začne se z 'http://')" #: contrib/redirects/models.py:12 msgid "redirect" @@ -1094,10 +1041,8 @@ msgid "redirects" msgstr "preusmeritve" #: contrib/flatpages/models.py:8 -msgid "" -"Example: '/about/contact/'. Make sure to have leading and trailing slashes." -msgstr "" -"Primer: '/about/contact/'. Mora vsebovati / (poševnico) na začetku in koncu." +msgid "Example: '/about/contact/'. Make sure to have leading and trailing slashes." +msgstr "Primer: '/about/contact/'. Mora vsebovati / (poševnico) na začetku in koncu." #: contrib/flatpages/models.py:9 msgid "title" @@ -1116,12 +1061,8 @@ msgid "template name" msgstr "ime predloge" #: contrib/flatpages/models.py:13 -msgid "" -"Example: 'flatpages/contact_page'. If this isn't provided, the system will " -"use 'flatpages/default'." -msgstr "" -"Primer: 'flatpages/contact_page'. Če to polje ni izpolnjeno, bo sistem " -"uporabil 'flatpages/default'." +msgid "Example: 'flatpages/contact_page'. If this isn't provided, the system will use 'flatpages/default'." +msgstr "Primer: 'flatpages/contact_page'. Če to polje ni izpolnjeno, bo sistem uporabil 'flatpages/default'." #: contrib/flatpages/models.py:14 msgid "registration required" @@ -1129,19 +1070,18 @@ msgstr "obvezna registracija" #: contrib/flatpages/models.py:14 msgid "If this is checked, only logged-in users will be able to view the page." -msgstr "" -"Če je to polje odkljukano, si lahko to stran ogledajo le registrirani " -"uporabniki." +msgstr "Če je to polje odkljukano, si lahko to stran ogledajo le registrirani uporabniki." #: contrib/flatpages/models.py:18 msgid "flat page" -msgstr "ploh stran :)" +msgstr "enostavna stran" #: contrib/flatpages/models.py:19 msgid "flat pages" -msgstr "ploh strani :)" +msgstr "enostavne strani" -#: contrib/auth/models.py:13 contrib/auth/models.py:26 +#: contrib/auth/models.py:13 +#: contrib/auth/models.py:26 msgid "name" msgstr "ime" @@ -1150,24 +1090,22 @@ msgid "codename" msgstr "kodno ime" #: contrib/auth/models.py:17 -#, fuzzy msgid "permission" -msgstr "Dovoljenje" +msgstr "dovoljenje" -#: contrib/auth/models.py:18 contrib/auth/models.py:27 -#, fuzzy +#: contrib/auth/models.py:18 +#: contrib/auth/models.py:27 msgid "permissions" -msgstr "Dovoljenja" +msgstr "dovoljenja" #: contrib/auth/models.py:29 -#, fuzzy msgid "group" -msgstr "Skupina" +msgstr "skupina" -#: contrib/auth/models.py:30 contrib/auth/models.py:65 -#, fuzzy +#: contrib/auth/models.py:30 +#: contrib/auth/models.py:65 msgid "groups" -msgstr "Skupine" +msgstr "skupine" #: contrib/auth/models.py:55 msgid "username" @@ -1218,27 +1156,20 @@ msgid "date joined" msgstr "član od" #: contrib/auth/models.py:66 -msgid "" -"In addition to the permissions manually assigned, this user will also get " -"all permissions granted to each group he/she is in." -msgstr "" -"Polek ročno določenih dovoljenj bo ta uporabnik dobil tudi vsa dovoljenja,ki " -"pripadajo vsem skupinah, v katerih je." +msgid "In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in." +msgstr "Polek ročno določenih dovoljenj bo ta uporabnik dobil tudi vsa dovoljenja,ki pripadajo vsem skupinah, v katerih je." #: contrib/auth/models.py:67 -#, fuzzy msgid "user permissions" -msgstr "Dovoljenja" +msgstr "uporabniška dovoljenja" #: contrib/auth/models.py:70 -#, fuzzy msgid "user" -msgstr "Uporabnik" +msgstr "uporabnik" #: contrib/auth/models.py:71 -#, fuzzy msgid "users" -msgstr "Uporabniki" +msgstr "uporabniki" #: contrib/auth/models.py:76 msgid "Personal info" @@ -1257,22 +1188,16 @@ msgid "Groups" msgstr "Skupine" #: contrib/auth/models.py:219 -#, fuzzy msgid "message" -msgstr "Sporočilo" +msgstr "sporočilo" #: contrib/auth/forms.py:30 -msgid "" -"Your Web browser doesn't appear to have cookies enabled. Cookies are " -"required for logging in." -msgstr "" -"Izgleda, da vaš brskalnik nima omogočenih piškotkov. Piškotki so potrebni za " -"prijavo." +msgid "Your Web browser doesn't appear to have cookies enabled. Cookies are required for logging in." +msgstr "Izgleda, da vaš brskalnik nima omogočenih piškotkov. Piškotki so potrebni za prijavo." #: contrib/contenttypes/models.py:25 -#, fuzzy msgid "python model class name" -msgstr "python ime modula" +msgstr "python ime razreda modela" #: contrib/contenttypes/models.py:28 msgid "content type" @@ -1366,23 +1291,28 @@ msgstr "januar" msgid "February" msgstr "februar" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:14 +#: utils/dates.py:27 msgid "March" msgstr "marec" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:14 +#: utils/dates.py:27 msgid "April" msgstr "april" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:14 +#: utils/dates.py:27 msgid "May" msgstr "maj" -#: utils/dates.py:14 utils/dates.py:27 +#: utils/dates.py:14 +#: utils/dates.py:27 msgid "June" msgstr "junij" -#: utils/dates.py:15 utils/dates.py:27 +#: utils/dates.py:15 +#: utils/dates.py:27 msgid "July" msgstr "julij" @@ -1407,62 +1337,58 @@ msgid "December" msgstr "december" #: utils/dates.py:19 -#, fuzzy msgid "jan" -msgstr "in" +msgstr "jan" #: utils/dates.py:19 -#, fuzzy msgid "feb" -msgstr "feb." +msgstr "feb" #: utils/dates.py:19 msgid "mar" -msgstr "" +msgstr "mar" #: utils/dates.py:19 msgid "apr" -msgstr "" +msgstr "apr" #: utils/dates.py:19 -#, fuzzy msgid "may" -msgstr "dan" +msgstr "maj" #: utils/dates.py:19 msgid "jun" -msgstr "" +msgstr "jun" #: utils/dates.py:20 msgid "jul" -msgstr "" +msgstr "jul" #: utils/dates.py:20 msgid "aug" -msgstr "" +msgstr "avg" #: utils/dates.py:20 msgid "sep" -msgstr "" +msgstr "sep" #: utils/dates.py:20 msgid "oct" -msgstr "" +msgstr "okt" #: utils/dates.py:20 msgid "nov" -msgstr "" +msgstr "nov" #: utils/dates.py:20 msgid "dec" -msgstr "" +msgstr "dec" #: utils/dates.py:27 msgid "Jan." msgstr "jan." #: utils/dates.py:27 -#, fuzzy msgid "Feb." msgstr "feb." @@ -1489,38 +1415,50 @@ msgstr "dec." #: utils/timesince.py:12 msgid "year" msgid_plural "years" -msgstr[0] "leto" -msgstr[1] "let" +msgstr[0] "let" +msgstr[1] "leto" +msgstr[2] "leti" +msgstr[3] "leta" #: utils/timesince.py:13 msgid "month" msgid_plural "months" -msgstr[0] "mesec" -msgstr[1] "mesecev" +msgstr[0] "mesecev" +msgstr[1] "mesec" +msgstr[2] "meseca" +msgstr[3] "meseci" #: utils/timesince.py:14 msgid "week" msgid_plural "weeks" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "tednov" +msgstr[1] "teden" +msgstr[2] "tedna" +msgstr[3] "tednov" #: utils/timesince.py:15 msgid "day" msgid_plural "days" -msgstr[0] "dan" -msgstr[1] "dni" +msgstr[0] "dni" +msgstr[1] "dan" +msgstr[2] "dneva" +msgstr[3] "dni" #: utils/timesince.py:16 msgid "hour" msgid_plural "hours" -msgstr[0] "ura" -msgstr[1] "ur" +msgstr[0] "ur" +msgstr[1] "ura" +msgstr[2] "uri" +msgstr[3] "ure" #: utils/timesince.py:17 msgid "minute" msgid_plural "minutes" -msgstr[0] "minuta" -msgstr[1] "minut" +msgstr[0] "minut" +msgstr[1] "minuta" +msgstr[2] "minuti" +msgstr[3] "minute" #: conf/global_settings.py:37 msgid "Bengali" @@ -1544,7 +1482,7 @@ msgstr "Nemški" #: conf/global_settings.py:42 msgid "Greek" -msgstr "" +msgstr "Grški" #: conf/global_settings.py:43 msgid "English" @@ -1564,11 +1502,11 @@ msgstr "Galičanski" #: conf/global_settings.py:47 msgid "Hungarian" -msgstr "" +msgstr "Madžarski" #: conf/global_settings.py:48 msgid "Hebrew" -msgstr "" +msgstr "Hebrejski" #: conf/global_settings.py:49 msgid "Icelandic" @@ -1619,9 +1557,8 @@ msgid "Swedish" msgstr "Švedski" #: conf/global_settings.py:61 -#, fuzzy msgid "Ukrainian" -msgstr "Brazilski" +msgstr "Ukrajinski" #: conf/global_settings.py:62 msgid "Simplified Chinese" @@ -1636,12 +1573,8 @@ msgid "This value must contain only letters, numbers and underscores." msgstr "To polje lahko vsebuje le črke, števila in podčrtaje (_)." #: core/validators.py:64 -#, fuzzy -msgid "" -"This value must contain only letters, numbers, underscores, dashes or " -"slashes." -msgstr "" -"To polje lahko vsebuje le črke, števila, podčrtaje (_) in poševnice (/)." +msgid "This value must contain only letters, numbers, underscores, dashes or slashes." +msgstr "To polje lahko vsebuje le črke, števila, podčrtaje, poševnice ali pomišljaje." #: core/validators.py:72 msgid "Uppercase letters are not allowed here." @@ -1691,23 +1624,18 @@ msgstr "Vnesite veljavni datum v zapisu YYYY-MM-DD (leto-mesec-dan)." msgid "Enter a valid time in HH:MM format." msgstr "Vnesite veljavni čas v zapisu HH:MM (ura:minuta)." -#: core/validators.py:132 db/models/fields/__init__.py:468 +#: core/validators.py:132 +#: db/models/fields/__init__.py:468 msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format." -msgstr "" -"Vnesite veljavni datum/čas v zapisu YYYY-MM-DD HH:MM (leto-mesec-dan ura:" -"minuta)" +msgstr "Vnesite veljavni datum/čas v zapisu YYYY-MM-DD HH:MM (leto-mesec-dan ura:minuta)" #: core/validators.py:136 msgid "Enter a valid e-mail address." msgstr "Vnesite veljavni e-naslov." #: core/validators.py:148 -msgid "" -"Upload a valid image. The file you uploaded was either not an image or a " -"corrupted image." -msgstr "" -"Uploadjate veljavno sliko. Trenutna datoteka ni bila niti slika niti " -"okvarjena slika." +msgid "Upload a valid image. The file you uploaded was either not an image or a corrupted image." +msgstr "Uploadjate veljavno sliko. Trenutna datoteka ni bila niti slika niti okvarjena slika." #: core/validators.py:155 #, python-format @@ -1747,7 +1675,8 @@ msgstr "Pokvarjen XML: %s" msgid "Invalid URL: %s" msgstr "Neveljavni URL naslov: %s" -#: core/validators.py:206 core/validators.py:208 +#: core/validators.py:206 +#: core/validators.py:208 #, python-format msgid "The URL %s is a broken link." msgstr "URL povezava %s je polomljena." @@ -1762,6 +1691,8 @@ msgid "Watch your mouth! The word %s is not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here." msgstr[0] "Pazite na jezik! Beseda %s tu ni dovoljena." msgstr[1] "Pazite na jezik! Besede %s tu niso dovoljene." +msgstr[2] "Pazite na jezik! Besede %s tu niso dovoljene." +msgstr[3] "Pazite na jezik! Besede %s tu niso dovoljene." #: core/validators.py:236 #, python-format @@ -1772,7 +1703,8 @@ msgstr "To polje mora ustrezati polju '%s'." msgid "Please enter something for at least one field." msgstr "Prosim, vnesite nekaj v vsaj eno od polj." -#: core/validators.py:264 core/validators.py:275 +#: core/validators.py:264 +#: core/validators.py:275 msgid "Please enter both fields or leave them both empty." msgstr "Prosimo, izpolnite obe polji ali ju pustite obe prazni." @@ -1802,20 +1734,20 @@ msgstr "Prosim vnesite decimalno število." #: core/validators.py:349 #, python-format msgid "Please enter a valid decimal number with at most %s total digit." -msgid_plural "" -"Please enter a valid decimal number with at most %s total digits." -msgstr[0] "Prosimo, vnesite veljavno decimalno število z največ %s števkami." -msgstr[1] "Prosimo, vnesite veljavno decimalno število z največ %s števkami." +msgid_plural "Please enter a valid decimal number with at most %s total digits." +msgstr[0] "Prosimo, vnesite veljavno decimalno število z največ %s števko." +msgstr[1] "Prosimo, vnesite veljavno decimalno število z največ %s števkama." +msgstr[2] "Prosimo, vnesite veljavno decimalno število z največ %s števkami." +msgstr[3] "Prosimo, vnesite veljavno decimalno število z največ %s števkami." #: core/validators.py:352 #, python-format msgid "Please enter a valid decimal number with at most %s decimal place." -msgid_plural "" -"Please enter a valid decimal number with at most %s decimal places." -msgstr[0] "" -"Prosimo, vnesite veljavno decimalno število z največ %s decimalnimi mesti." -msgstr[1] "" -"Prosimo, vnesite veljavno decimalno število z največ %s decimalnimi mesti." +msgid_plural "Please enter a valid decimal number with at most %s decimal places." +msgstr[0] "Prosimo, vnesite veljavno decimalno število z največ %s decimalnim mestom." +msgstr[1] "Prosimo, vnesite veljavno decimalno število z največ %s decimalnimi mesti." +msgstr[2] "Prosimo, vnesite veljavno decimalno število z največ %s decimalnimi mesti." +msgstr[3] "Prosimo, vnesite veljavno decimalno število z največ %s decimalnimi mesti." #: core/validators.py:362 #, python-format @@ -1842,94 +1774,68 @@ msgstr "Iz %s nisem mogel izločiti ničesar." #: core/validators.py:429 #, python-format -msgid "" -"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." +msgid "The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'." msgstr "URL %(url)s je vrnil neveljavni Content-Type '%(contenttype)s'." #: core/validators.py:462 #, python-format -msgid "" -"Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with " -"\"%(start)s\".)" -msgstr "" -"Prosimo, zaprite nezaprto %(tag)s oznako v vrstici %(line)s. (Vrstica se " -"začne z \"%(start)s\".)" +msgid "Please close the unclosed %(tag)s tag from line %(line)s. (Line starts with \"%(start)s\".)" +msgstr "Prosimo, zaprite nezaprto %(tag)s oznako v vrstici %(line)s. (Vrstica se začne z \"%(start)s\".)" #: core/validators.py:466 #, python-format -msgid "" -"Some text starting on line %(line)s is not allowed in that context. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"Tekst z začetka vrstice %(line)s ni dovoljen v tem kontekstu. (Vrstica se " -"začne z \"%(start)s\".)" +msgid "Some text starting on line %(line)s is not allowed in that context. (Line starts with \"%(start)s\".)" +msgstr "Tekst z začetka vrstice %(line)s ni dovoljen v tem kontekstu. (Vrstica se začne z \"%(start)s\".)" #: core/validators.py:471 -#, fuzzy, python-format -msgid "" -"\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"\"<%(tag)s>\" v vrstici %(line)s je neveljavna oznaka. (Vrstica se začne z " -"\"%(start)s\".)" +#, python-format +msgid "\"%(attr)s\" on line %(line)s is an invalid attribute. (Line starts with \"%(start)s\".)" +msgstr "\"%(attr)s\" v vrstici %(line)s je neveljavna oznaka. (Vrstica se začne z \"%(start)s\".)" #: core/validators.py:476 #, python-format -msgid "" -"\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%" -"(start)s\".)" -msgstr "" -"\"<%(tag)s>\" v vrstici %(line)s je neveljavna oznaka. (Vrstica se začne z " -"\"%(start)s\".)" +msgid "\"<%(tag)s>\" on line %(line)s is an invalid tag. (Line starts with \"%(start)s\".)" +msgstr "\"<%(tag)s>\" v vrstici %(line)s je neveljavna oznaka. (Vrstica se začne z \"%(start)s\".)" #: core/validators.py:480 #, python-format -msgid "" -"A tag on line %(line)s is missing one or more required attributes. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"Oznaki v vrstici %(line)s manjka eden ali več nujnih atributov (Vrstica se " -"začne z \"%(start)s\".)" +msgid "A tag on line %(line)s is missing one or more required attributes. (Line starts with \"%(start)s\".)" +msgstr "Oznaki na vrstici %(line)s manjka eden ali več zahtevanih parametrov. (Vrstica se začne z \"%(start)s\".)" #: core/validators.py:485 #, python-format -msgid "" -"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " -"starts with \"%(start)s\".)" -msgstr "" -"Atribut \"%(attr)s\" v vrstici %(line)s vsebuje neveljavno vrednost. " -"(Vrstica se začne z \"%(start)s\".)" +msgid "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line starts with \"%(start)s\".)" +msgstr "Atribut \"%(attr)s\" v vrstici %(line)s vsebuje neveljavno vrednost. (Vrstica se začne z \"%(start)s\".)" #: db/models/manipulators.py:302 #, python-format msgid "%(object)s with this %(type)s already exists for the given %(field)s." -msgstr "%(object)s s tem %(type)s že obstaja za veljavno (%field)s." +msgstr "%(object)s s tem %(type)s že obstaja za dane %(field)s." #: db/models/fields/__init__.py:40 #, python-format msgid "%(optname)s with this %(fieldname)s already exists." msgstr "%(optname)s s tem %(fieldname)s že obstaja." -#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 -#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553 +#: db/models/fields/__init__.py:114 +#: db/models/fields/__init__.py:265 +#: db/models/fields/__init__.py:542 +#: db/models/fields/__init__.py:553 #: forms/__init__.py:346 msgid "This field is required." msgstr "To polje je obvezno" #: db/models/fields/__init__.py:337 -#, fuzzy msgid "This value must be an integer." -msgstr "Ta vrednost mora biti potenca od %s." +msgstr "Ta vrednost mora biti število." #: db/models/fields/__init__.py:369 -#, fuzzy msgid "This value must be either True or False." -msgstr "Ta vrednost mora biti potenca od %s." +msgstr "Ta vrednost mora biti \"True\" ali \"False\"." #: db/models/fields/__init__.py:385 -#, fuzzy msgid "This field cannot be null." -msgstr "To polje ni veljavno." +msgstr "To polje ne more biti prazno." #: db/models/fields/__init__.py:562 msgid "Enter a valid filename." @@ -1941,39 +1847,38 @@ msgid "Please enter a valid %s." msgstr "Prosimo, vnesite veljaven %s." #: db/models/fields/related.py:579 -#, fuzzy msgid "Separate multiple IDs with commas." msgstr "Več ID-jev ločite z vejicami." #: db/models/fields/related.py:581 -#, fuzzy -msgid "" -"Hold down \"Control\", or \"Command\" on a Mac, to select more than one." -msgstr "" -" Stisni \"Control\" (ali \"Command\" na Mac-u), da izbereš več kot enega." +msgid "Hold down \"Control\", or \"Command\" on a Mac, to select more than one." +msgstr "Držite \"Control\" (ali \"Command\" na Mac-u), za izbiro več kot enega." #: db/models/fields/related.py:625 #, python-format msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid." -msgid_plural "" -"Please enter valid %(self)s IDs. The values %(value)r are invalid." -msgstr[0] "" -"Prosimo, vnesite veljavni %(self)s ID-je. Vrednost %(value)r ni veljavna." -msgstr[1] "" -"Prosimo, vnesite veljavni %(self)s ID-je. Vrednosti %(value)r niso veljavne." +msgid_plural "Please enter valid %(self)s IDs. The values %(value)r are invalid." +msgstr[0] "Prosimo, vnesite veljavne %(self)s ID-je. Vrednost %(value)r ni veljavna." +msgstr[1] "Prosimo, vnesite veljavni %(self)s ID. Vrednosti %(value)r niso veljavne." +msgstr[2] "Prosimo, vnesite veljavne %(self)s ID-je. Vrednosti %(value)r niso veljavne." +msgstr[3] "Prosimo, vnesite veljavne %(self)s ID-je. Vrednosti %(value)r niso veljavne." #: forms/__init__.py:380 #, python-format msgid "Ensure your text is less than %s character." msgid_plural "Ensure your text is less than %s characters." -msgstr[0] "Poskrbite, da bo tekst krajši do %s znakov." -msgstr[1] "Poskrbite, da bo tekst krajši od %s znakov." +msgstr[0] "Poskrbite, da bo tekst krajši od %s znakov." +msgstr[1] "Poskrbite, da bo tekst krajši od %s znaka." +msgstr[2] "Poskrbite, da bo tekst krajši od %s znakov." +msgstr[3] "Poskrbite, da bo tekst krajši od %s znakov." #: forms/__init__.py:385 msgid "Line breaks are not allowed here." msgstr "Prelomi vrstice tu niso dovoljeni." -#: forms/__init__.py:480 forms/__init__.py:551 forms/__init__.py:589 +#: forms/__init__.py:480 +#: forms/__init__.py:551 +#: forms/__init__.py:589 #, python-format msgid "Select a valid choice; '%(data)s' is not in %(choices)s." msgstr "Izberite veljavno možnost; '%(data)s' ni v %(choices)s." @@ -1998,23 +1903,24 @@ msgstr "Vnesite celo število med 0 in 32,767." msgid "yes,no,maybe" msgstr "ja,ne,morda" -#~ msgid "Comment" -#~ msgstr "Komentar" +msgid "Comment" +msgstr "Komentar" -#~ msgid "Comments" -#~ msgstr "Komentarji" +msgid "Comments" +msgstr "Komentarji" -#~ msgid "String (up to 50)" -#~ msgstr "Niz (do 50 znakov)" +msgid "String (up to 50)" +msgstr "Niz (do 50 znakov)" -#~ msgid "label" -#~ msgstr "oznaka" +msgid "label" +msgstr "oznaka" -#~ msgid "package" -#~ msgstr "paket" +msgid "package" +msgstr "paket" -#~ msgid "packages" -#~ msgstr "paketi" +msgid "packages" +msgstr "paketi" + +msgid "Slovene" +msgstr "Slovensko" -#~ msgid "Slovene" -#~ msgstr "Slovenski" diff --git a/django/conf/project_template/settings.py b/django/conf/project_template/settings.py index 14da715db5..63e07c061a 100644 --- a/django/conf/project_template/settings.py +++ b/django/conf/project_template/settings.py @@ -60,8 +60,9 @@ MIDDLEWARE_CLASSES = ( ROOT_URLCONF = '{{ project_name }}.urls' 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. + # Don't forget to use absolute paths, not relative paths. ) INSTALLED_APPS = ( diff --git a/django/conf/urls/defaults.py b/django/conf/urls/defaults.py index 07611c5147..17fe603d96 100644 --- a/django/conf/urls/defaults.py +++ b/django/conf/urls/defaults.py @@ -10,8 +10,10 @@ include = lambda urlconf_module: [urlconf_module] def patterns(prefix, *tuples): pattern_list = [] for t in tuples: - if type(t[1]) == list: - pattern_list.append(RegexURLResolver(t[0], t[1][0])) + regex, view_or_include = t[:2] + default_kwargs = t[2:] + if type(view_or_include) == list: + pattern_list.append(RegexURLResolver(regex, view_or_include[0], *default_kwargs)) 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 diff --git a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js index 35199baf84..3f6fb67bc7 100644 --- a/django/contrib/admin/media/js/admin/DateTimeShortcuts.js +++ b/django/contrib/admin/media/js/admin/DateTimeShortcuts.js @@ -8,7 +8,9 @@ var DateTimeShortcuts = { clockInputs: [], calendarDivName1: 'calendarbox', // name of calendar
        that gets toggled calendarDivName2: 'calendarin', // name of
        that contains calendar + calendarLinkName: 'calendarlink',// name of the link that is used to toggle clockDivName: 'clockbox', // name of clock
        that gets toggled + clockLinkName: 'clocklink', // name of the link that is used to toggle admin_media_prefix: '', init: function() { // Deduce admin_media_prefix by looking at the ' % \ + return HttpResponse('' % \ (pk_value, str(new_object).replace('"', '\\"'))) elif request.POST.has_key("_addanother"): request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name)) diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py index 6aea45feb5..0102496a33 100644 --- a/django/contrib/auth/decorators.py +++ b/django/contrib/auth/decorators.py @@ -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()))) _checklogin.__doc__ = view_func.__doc__ _checklogin.__dict__ = view_func.__dict__ - _checklogin.__name__ = view_func.__name__ return _checklogin return _dec diff --git a/django/contrib/auth/forms.py b/django/contrib/auth/forms.py index 8bd9fa44c4..ad8d423ebf 100644 --- a/django/contrib/auth/forms.py +++ b/django/contrib/auth/forms.py @@ -5,6 +5,28 @@ from django.template import Context, loader from django.core import validators 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): """ Base class for authenticating users. Extend this to get a form that accepts diff --git a/django/contrib/flatpages/README.TXT b/django/contrib/flatpages/README.TXT index e46aa1f9bf..d3071377f5 100644 --- a/django/contrib/flatpages/README.TXT +++ b/django/contrib/flatpages/README.TXT @@ -2,7 +2,7 @@ This is an optional add-on app, flatpages. 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 -Both have identical content. \ No newline at end of file +Both have identical content. diff --git a/django/contrib/sessions/middleware.py b/django/contrib/sessions/middleware.py index dde4f1a6c0..2337ad8a61 100644 --- a/django/contrib/sessions/middleware.py +++ b/django/contrib/sessions/middleware.py @@ -88,5 +88,6 @@ class SessionMiddleware(object): new_session = Session.objects.save(session_key, request.session._session, datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)) 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 diff --git a/django/core/management.py b/django/core/management.py index 14182cbdff..a469c72901 100644 --- a/django/core/management.py +++ b/django/core/management.py @@ -94,12 +94,15 @@ def get_sql_create(app): "Edit your settings file and change DATABASE_ENGINE to something like 'postgresql' or 'mysql'.\n")) 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 = [] - 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 = {} - app_models = models.get_models(app) for model in app_models: output, references = _get_sql_model_create(model, known_models) @@ -118,10 +121,13 @@ def get_sql_create(app): # but don't exist physically not_installed_models = set(pending_references.keys()) 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: - final_output.extend(['-- ' + sql for sql in + alter_sql.extend(['-- ' + sql for sql in _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 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 final_output = [] - reference_names = {} if backend.supports_constraints: opts = model._meta if model in pending_references: @@ -202,12 +207,9 @@ def _get_sql_for_pending_references(model, pending_references): r_col = f.column table = opts.db_table col = opts.get_field(f.rel.field_name).column - r_name = '%s_referencing_%s_%s' % (r_col, table, col) - if r_name in reference_names: - reference_names[r_name] += 1 - r_name += '_%s' % reference_names[r_name] - else: - reference_names[r_name] = 0 + # For MySQL, r_name must be unique in the first 64 characters. + # So we are careful with character usage here. + r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table)))) 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_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_TABLE(backend.quote_name(table)), 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] # Output DROP TABLE statements for many-to-many tables. @@ -696,9 +698,7 @@ def inspectdb(): introspection_module = get_introspection_module() - def table2model(table_name): - object_name = table_name.title().replace('_', '') - return object_name.endswith('s') and object_name[:-1] or object_name + table2model = lambda table_name: table_name.title().replace('_', '') cursor = connection.cursor() 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. 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): extra_params['db_column'] = att_name att_name += '_field' @@ -957,6 +961,12 @@ def get_validation_errors(outfile, app=None): f = opts.get_field(fn) except models.FieldDoesNotExist: 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. if opts.ordering: @@ -1132,7 +1142,14 @@ def dbshell(): dbshell.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 runfastcgi(args) 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: 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 # way. For example, if this file (manage.py) lives in a directory # "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. 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() # Remove the "startproject" command from the action_mapping, because that's diff --git a/django/core/serializers/json.py b/django/core/serializers/json.py index dd6513db57..a8b4259099 100644 --- a/django/core/serializers/json.py +++ b/django/core/serializers/json.py @@ -41,11 +41,11 @@ class DateTimeAwareJSONEncoder(simplejson.JSONEncoder): TIME_FORMAT = "%H:%M:%S" 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) elif isinstance(o, datetime.time): return o.strftime(self.TIME_FORMAT) - elif isinstance(o, datetime.datetime): - return o.strftime("%s %s" % (self.DATE_FORMAT, self.TIME_FORMAT)) else: return super(self, DateTimeAwareJSONEncoder).default(o) \ No newline at end of file diff --git a/django/core/servers/basehttp.py b/django/core/servers/basehttp.py index 7ce5706c23..4bd0e50e53 100644 --- a/django/core/servers/basehttp.py +++ b/django/core/servers/basehttp.py @@ -547,10 +547,6 @@ class WSGIRequestHandler(BaseHTTPRequestHandler): env['PATH_INFO'] = urllib.unquote(path) 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] if self.headers.typeheader is None: diff --git a/django/core/urlresolvers.py b/django/core/urlresolvers.py index 83fffacefb..2f557b90a6 100644 --- a/django/core/urlresolvers.py +++ b/django/core/urlresolvers.py @@ -86,10 +86,15 @@ class MatchChecker(object): class RegexURLPattern(object): def __init__(self, regex, callback, default_args=None): # regex is a string representing a regular expression. - # callback is something like 'foo.views.news.stories.story_detail', - # which represents the path to a module and a view function name. + # callback is either a string like 'foo.views.news.stories.story_detail' + # which represents the path to a module and a view function name, or a + # callable object (view). 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 {} def resolve(self, path): @@ -106,23 +111,28 @@ class RegexURLPattern(object): # In both cases, pass any extra_kwargs as **kwargs. kwargs.update(self.default_args) - try: # Lazily load self.func. - return self.func, args, kwargs - except AttributeError: - self.func = self.get_callback() - return self.func, args, kwargs + return self.callback, args, kwargs - def get_callback(self): - mod_name, func_name = get_mod_func(self.callback) + def _get_callback(self): + if self._callback is not None: + return self._callback + mod_name, func_name = get_mod_func(self._callback_str) try: - return getattr(__import__(mod_name, '', '', ['']), func_name) + self._callback = getattr(__import__(mod_name, '', '', ['']), func_name) except ImportError, e: raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e)) except AttributeError, e: 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): - 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 return self.reverse_helper(*args, **kwargs) @@ -130,12 +140,13 @@ class RegexURLPattern(object): return reverse_helper(self.regex, *args, **kwargs) 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. # urlconf_name is a string representing the module containing urlconfs. self.regex = re.compile(regex) self.urlconf_name = urlconf_name self.callback = None + self.default_kwargs = default_kwargs or {} def resolve(self, path): tried = [] @@ -149,7 +160,8 @@ class RegexURLResolver(object): tried.extend([(pattern.regex.pattern + ' ' + t) for t in e.args[0]['tried']]) else: 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) raise Resolver404, {'tried': tried, 'path': new_path} @@ -183,22 +195,28 @@ class RegexURLResolver(object): def resolve500(self): 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: if isinstance(pattern, RegexURLResolver): try: - return pattern.reverse_helper(viewname, *args, **kwargs) + return pattern.reverse_helper(lookup_view, *args, **kwargs) except NoReverseMatch: continue - elif pattern.callback == viewname: + elif pattern.callback == lookup_view: try: return pattern.reverse_helper(*args, **kwargs) except NoReverseMatch: continue raise NoReverseMatch - def reverse_helper(self, viewname, *args, **kwargs): - sub_match = self.reverse(viewname, *args, **kwargs) + def reverse_helper(self, lookup_view, *args, **kwargs): + sub_match = self.reverse(lookup_view, *args, **kwargs) result = reverse_helper(self.regex, *args, **kwargs) return result + sub_match @@ -209,11 +227,11 @@ def resolve(path, urlconf=None): resolver = RegexURLResolver(r'^/', urlconf) return resolver.resolve(path) -def reverse(viewname, urlconf, args=None, kwargs=None): +def reverse(viewname, urlconf=None, args=None, kwargs=None): args = args or [] kwargs = kwargs or {} if urlconf is None: from django.conf import settings urlconf = settings.ROOT_URLCONF resolver = RegexURLResolver(r'^/', urlconf) - return resolver.reverse(viewname, *args, **kwargs) + return '/' + resolver.reverse(viewname, *args, **kwargs) diff --git a/django/db/backends/postgresql_psycopg2/base.py b/django/db/backends/postgresql_psycopg2/base.py index 55cba81b70..9623e68354 100644 --- a/django/db/backends/postgresql_psycopg2/base.py +++ b/django/db/backends/postgresql_psycopg2/base.py @@ -11,6 +11,10 @@ except ImportError, e: from django.core.exceptions import ImproperlyConfigured raise ImproperlyConfigured, "Error loading psycopg2 module: %s" % e +# Register Unicode conversions +import psycopg2.extensions +psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) + DatabaseError = Database.DatabaseError try: diff --git a/django/db/models/__init__.py b/django/db/models/__init__.py index 82b1238723..0308dd047a 100644 --- a/django/db/models/__init__.py +++ b/django/db/models/__init__.py @@ -16,6 +16,18 @@ from django.utils.text import capfirst # Admin stages. 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): """ Use in limit_choices_to to compare the field to dates calculated at run time @@ -35,7 +47,7 @@ class LazyDate(object): return "" % self.delta def __get_value__(self): - return datetime.datetime.now() + self.delta + return (datetime.datetime.now() + self.delta).date() def __getattr__(self, attr): return getattr(self.__get_value__(), attr) diff --git a/django/db/models/base.py b/django/db/models/base.py index e248929ae9..b729917a57 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -44,7 +44,7 @@ class ModelBase(type): new_class._meta.app_label = model_module.__name__.split('.')[-2] # 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: return m @@ -73,7 +73,7 @@ class ModelBase(type): # 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 # registered version. - return get_model(new_class._meta.app_label, name) + return get_model(new_class._meta.app_label, name, False) class Model(object): __metaclass__ = ModelBase @@ -181,11 +181,12 @@ class Model(object): # If it does already exist, do an UPDATE. if cursor.fetchone(): db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks] - cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \ - (backend.quote_name(self._meta.db_table), - ','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]), - backend.quote_name(self._meta.pk.column)), - db_values + [pk_val]) + if db_values: + cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \ + (backend.quote_name(self._meta.db_table), + ','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]), + backend.quote_name(self._meta.pk.column)), + db_values + [pk_val]) else: record_exists = False if not pk_set or not record_exists: diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 6fba7f7876..49eb594838 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -20,7 +20,7 @@ BLANK_CHOICE_DASH = [("", "---------")] BLANK_CHOICE_NONE = [("", "None")] # 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
          class for a given radio_admin value 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 # BooleanFields (CheckboxFields) are a special case. They don't take - # is_required or validator_list. + # is_required. 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 # in the related object have core=True. If so, add a validator -- @@ -289,8 +289,11 @@ class Field(object): if self.choices: return first_choice + list(self.choices) rel_model = self.rel.to - return first_choice + [(x._get_pk_val(), str(x)) - for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)] + if hasattr(self.rel, 'get_related_field'): + 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): if self.radio_admin: diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 5dd02bccf2..aa232c07f3 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -25,7 +25,7 @@ def add_lookup(rel_cls, field): key = (module, name) # Has the model already been loaded? # 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: field.rel.to = model field.do_related_class(model, rel_cls) diff --git a/django/db/models/loading.py b/django/db/models/loading.py index c7920fa4e0..22f83bfd78 100644 --- a/django/db/models/loading.py +++ b/django/db/models/loading.py @@ -32,7 +32,7 @@ def get_apps(): _app_errors[app_name] = e return _app_list -def get_app(app_label, emptyOK = False): +def get_app(app_label, emptyOK=False): "Returns the module containing the models for the given app_label. If the app has no models in it and 'emptyOK' is True, returns None." get_apps() # Run get_apps() to populate the _app_list cache. Slightly hackish. for app_name in settings.INSTALLED_APPS: @@ -75,11 +75,15 @@ def get_models(app_mod=None): model_list.extend(get_models(app_mod)) 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. """ + if seed_cache: + get_apps() try: model_dict = _app_models[app_label] except KeyError: diff --git a/django/db/models/manipulators.py b/django/db/models/manipulators.py index 69e13dd160..b0ce48dec5 100644 --- a/django/db/models/manipulators.py +++ b/django/db/models/manipulators.py @@ -138,7 +138,7 @@ class AutomaticManipulator(forms.Manipulator): child_follow = self.follow.get(related.name, None) if child_follow: - obj_list = expanded_data[related.var_name].items() + obj_list = expanded_data.get(related.var_name, {}).items() if not obj_list: continue diff --git a/django/forms/__init__.py b/django/forms/__init__.py index 4907bd76f7..730f7a54da 100644 --- a/django/forms/__init__.py +++ b/django/forms/__init__.py @@ -434,10 +434,12 @@ class HiddenField(FormField): (self.get_id(), self.field_name, escape(data)) 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.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): checked_html = '' diff --git a/django/http/__init__.py b/django/http/__init__.py index 06f6a106ee..c4ac302ec5 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -38,7 +38,7 @@ class HttpRequest(object): def get_full_path(self): return '' - + def is_secure(self): return os.environ.get("HTTPS") == "on" @@ -203,11 +203,14 @@ class HttpResponse(object): if val is not None: self.cookies[key][var.replace('_', '-')] = val - def delete_cookie(self, key): - try: - self.cookies[key]['max_age'] = 0 - except KeyError: - pass + def delete_cookie(self, key, path='/', domain=None): + self.cookies[key] = '' + if path is not None: + self.cookies[key]['path'] = path + 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): content = ''.join(self._iterator) diff --git a/django/middleware/gzip.py b/django/middleware/gzip.py index cc8a68406c..7d860abdb1 100644 --- a/django/middleware/gzip.py +++ b/django/middleware/gzip.py @@ -12,7 +12,11 @@ class GZipMiddleware(object): """ def process_response(self, request, response): 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 ae = request.META.get('HTTP_ACCEPT_ENCODING', '') diff --git a/django/template/defaultfilters.py b/django/template/defaultfilters.py index c75f371ec8..a2e9d2f405 100644 --- a/django/template/defaultfilters.py +++ b/django/template/defaultfilters.py @@ -339,7 +339,7 @@ def date(value, arg=None): def time(value, arg=None): "Formats a time according to the given format" from django.utils.dateformat import time_format - if not value: + if value in (None, ''): return '' if arg is None: arg = settings.TIME_FORMAT @@ -437,7 +437,7 @@ def pluralize(value, arg='s'): is used instead. If the provided argument contains a comma, the text before the comma is used for the singular case. """ - if not ',' in arg: + if not ',' in arg: arg = ',' + arg bits = arg.split(',') if len(bits) > 2: diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py index f847ea123f..7f22f207b6 100644 --- a/django/template/loader_tags.py +++ b/django/template/loader_tags.py @@ -50,6 +50,8 @@ class ExtendsNode(Node): if self.parent_name_expr: error_msg += " Got this from the %r variable." % self.parent_name_expr #TODO nice repr. raise TemplateSyntaxError, error_msg + if hasattr(parent, 'render'): + return parent try: source, origin = find_template_source(parent, self.template_dirs) except TemplateDoesNotExist: @@ -137,8 +139,9 @@ def do_extends(parser, token): 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, - or ``{% extends variable %}`` uses the value of ``variable`` as the name - of the parent template to extend. + or ``{% extends variable %}`` uses the value of ``variable`` as either the + 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() if len(bits) != 2: diff --git a/django/template/loaders/filesystem.py b/django/template/loaders/filesystem.py index 0c94021fb8..d01f54c5fe 100644 --- a/django/template/loaders/filesystem.py +++ b/django/template/loaders/filesystem.py @@ -17,7 +17,7 @@ def load_template_source(template_name, template_dirs=None): return (open(filepath).read(), filepath) except IOError: tried.append(filepath) - if template_dirs: + if tried: error_msg = "Tried %s" % tried else: error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory." diff --git a/django/utils/autoreload.py b/django/utils/autoreload.py index 6363af7835..e05b7fafe1 100644 --- a/django/utils/autoreload.py +++ b/django/utils/autoreload.py @@ -35,6 +35,14 @@ try: except ImportError: 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 def reloader_thread(): diff --git a/django/views/generic/create_update.py b/django/views/generic/create_update.py index 27ba327ff5..034253a549 100644 --- a/django/views/generic/create_update.py +++ b/django/views/generic/create_update.py @@ -6,6 +6,7 @@ from django.contrib.auth.views import redirect_to_login from django.template import RequestContext from django.http import Http404, HttpResponse, HttpResponseRedirect from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured +from django.utils.translation import gettext def create_object(request, model, template_name=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) 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, # 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) 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. if post_save_redirect: @@ -180,7 +181,7 @@ def delete_object(request, model, post_delete_redirect, if request.method == 'POST': object.delete() 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) else: if not template_name: diff --git a/docs/add_ons.txt b/docs/add_ons.txt index 90c98b7176..6507f3b139 100644 --- a/docs/add_ons.txt +++ b/docs/add_ons.txt @@ -2,12 +2,15 @@ The "contrib" add-ons ===================== -Django aims to follow Python's "batteries included" philosophy. It ships with a -variety of extra, optional tools that solve common Web-development problems. +Django aims to follow Python's `"batteries included" philosophy`_. It ships +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 rundown of the packages in ``contrib``: +.. _"batteries included" philosophy: http://docs.python.org/tut/node12.html#batteries-included + admin ===== diff --git a/docs/api_stability.txt b/docs/api_stability.txt index 475a209400..a9d6904735 100644 --- a/docs/api_stability.txt +++ b/docs/api_stability.txt @@ -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 change before the 1.0 release. +What "stable" means +=================== + In this context, stable means: - 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 security hole makes it completely unavoidable. +Stable APIs +=========== + These APIs are stable: - `Caching`_. @@ -114,4 +120,4 @@ change: .. _url dispatch: http://www.djangoproject.com/documentation/url_dispatch/ .. _forms and validation: http://www.djangoproject.com/documentation/forms/ .. _serialization: http://www.djangoproject.com/documentation/serialization/ -.. _authentication: http://www.djangoproject.com/documentation/authentication/ \ No newline at end of file +.. _authentication: http://www.djangoproject.com/documentation/authentication/ diff --git a/docs/db-api.txt b/docs/db-api.txt index ce6bb0ab3b..bd178dbd7d 100644 --- a/docs/db-api.txt +++ b/docs/db-api.txt @@ -578,6 +578,9 @@ related ``Person`` *and* the related ``City``:: p = b.author # 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)`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -715,12 +718,12 @@ The ``DoesNotExist`` exception inherits from A convenience method for creating an object and saving it all in one step. Thus:: p = Person.objects.create(first_name="Bruce", last_name="Springsteen") - + and:: p = Person(first_name="Bruce", last_name="Springsteen") p.save() - + are equivalent. ``get_or_create(**kwargs)`` @@ -1468,11 +1471,12 @@ the ``ForeignKey`` ``Manager`` has these additional methods: b.entry_set.remove(e) # Disassociates Entry e from Blog b. 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 - ``None`` (``NULL``), then an object can't be removed from a relation - without being added to another. In the above example, removing ``e`` from - ``b.entry_set()`` is equivalent to doing ``e.blog = None``, and because - the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this is invalid. + ``ForeignKey`` objects where ``null=True``. If the related field can't be + set to ``None`` (``NULL``), then an object can't be removed from a + relation without being added to another. In the above example, removing + ``e`` from ``b.entry_set()`` is equivalent to doing ``e.blog = None``, + and because the ``blog`` ``ForeignKey`` doesn't have ``null=True``, this + is invalid. * ``clear()``: Removes all objects from the related object set. @@ -1556,13 +1560,13 @@ Queries over related objects ---------------------------- Queries involving related objects follow the same rules as queries involving -normal value fields. When specifying the the value for a query to match, you -may use either an object instance itself, or the primary key value for the +normal value fields. When specifying the the value for a query to match, you +may use either an object instance itself, or the primary key value for the object. For example, if you have a Blog object ``b`` with ``id=5``, the following three queries would be identical:: - + Entry.objects.filter(blog=b) # Query using object instance Entry.objects.filter(blog=b.id) # Query using id from instance Entry.objects.filter(blog=5) # Query using id directly diff --git a/docs/documentation.txt b/docs/documentation.txt new file mode 100644 index 0000000000..bacfb176b1 --- /dev/null +++ b/docs/documentation.txt @@ -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/ diff --git a/docs/faq.txt b/docs/faq.txt index b9fc282000..3cd7090583 100644 --- a/docs/faq.txt +++ b/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 +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 ====================== @@ -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? ------------------------------------------------------------- -We don't recommend you create users via the admin interface, because at the -moment it requires you to edit password hashes manually. (Passwords are hashed -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.) +If you'd like to use the admin site to create users, upgrade to the Django +development version, where this problem was fixed on Aug. 4, 2006. -To create a user, you'll have to use the Python API. See `creating users`_ for -full info. +You can also use the Python API. See `creating users`_ for full info. .. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users diff --git a/docs/forms.txt b/docs/forms.txt index 2fbe373744..67408f3c5d 100644 --- a/docs/forms.txt +++ b/docs/forms.txt @@ -404,6 +404,43 @@ Here's a simple function that might drive the above form:: errors = new_data = {} form = forms.FormWrapper(manipulator, new_data, errors) 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 ``
          `` element correctly defines +the ``enctype`` as ``"multipart/form-data"``, in order to upload files:: + + + +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:: + +

          {{ form.photo }}{{ form.photo_file }}

          + +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 ========== diff --git a/docs/generic_views.txt b/docs/generic_views.txt index aab878467f..fdab97de27 100644 --- a/docs/generic_views.txt +++ b/docs/generic_views.txt @@ -127,7 +127,7 @@ If the given URL is ``None``, Django will return an ``HttpResponseGone`` (410). This example redirects from ``/foo//`` to ``/bar//``:: urlpatterns = patterns('django.views.generic.simple', - ('^foo/(?p\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}), + ('^foo/(?P\d+)/$', 'redirect_to', {'url': '/bar/%(id)s/'}), ) This example returns a 410 HTTP error for requests to ``/bar/``:: diff --git a/docs/install.txt b/docs/install.txt index 800c49b596..fb1bd73122 100644 --- a/docs/install.txt +++ b/docs/install.txt @@ -77,9 +77,9 @@ It's easy either way. Installing the official version ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -1. Download Django-0.91.tar.gz from our `download page`_. -2. ``tar xzvf Django-0.91.tar.gz`` -3. ``cd Django-0.91`` +1. Download Django-0.95.tar.gz from our `download page`_. +2. ``tar xzvf Django-0.95.tar.gz`` +3. ``cd Django-0.95`` 4. ``sudo python setup.py install`` 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`` directory. -.. note:: - - Due to recent backwards-incompatible changes, it is strongly recommended - that you use the development version (below) for any new applications or - if you are just starting to work with Django. The 0.91 release is a - dead-end branch that is primarily of use for supporting legacy Django - applications. - .. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools Installing the development version diff --git a/docs/model-api.txt b/docs/model-api.txt index c369508c65..502ceaf7ff 100644 --- a/docs/model-api.txt +++ b/docs/model-api.txt @@ -223,6 +223,13 @@ steps: the absolute URL to your image in a template with ``{{ 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 ``FilePathField`` diff --git a/docs/release_notes_0.95.txt b/docs/release_notes_0.95.txt new file mode 100644 index 0000000000..e5b89e5a7a --- /dev/null +++ b/docs/release_notes_0.95.txt @@ -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 + diff --git a/docs/request_response.txt b/docs/request_response.txt index 7480a6d3bb..1f3b9d5804 100644 --- a/docs/request_response.txt +++ b/docs/request_response.txt @@ -149,7 +149,7 @@ Methods Returns the ``path``, plus an appended query string, if applicable. Example: ``"/music/bands/the_beatles/?print=true"`` - + ``is_secure()`` Returns ``True`` if the request is secure; that is, if it was made with HTTPS. @@ -380,10 +380,14 @@ Methods .. _`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 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`` 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`` diff --git a/docs/sessions.txt b/docs/sessions.txt index c473d0a3db..d39f42c3bf 100644 --- a/docs/sessions.txt +++ b/docs/sessions.txt @@ -245,6 +245,17 @@ Default: ``'sessionid'`` 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 ------------------------------- diff --git a/docs/settings.txt b/docs/settings.txt index 099196e56e..67e0498e1a 100644 --- a/docs/settings.txt +++ b/docs/settings.txt @@ -647,6 +647,18 @@ Default: ``'sessionid'`` The name of the cookie to use for sessions. This can be whatever you want. 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 ------------------------------- diff --git a/docs/templates.txt b/docs/templates.txt index 6117bf7b84..49d30018fe 100644 --- a/docs/templates.txt +++ b/docs/templates.txt @@ -363,10 +363,15 @@ extends Signal that this template extends a parent template. -This tag may be used in two ways: ``{% extends "base.html" %}`` (with quotes) -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 -name of the parent template to extend. +This tag can be used in two ways: + + * ``{% extends "base.html" %}`` (with quotes) uses the literal value + ``"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. @@ -493,6 +498,11 @@ If you need to combine ``and`` and ``or`` to do advanced logic, just use nested {% 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 ~~~~~~~~~ diff --git a/docs/templates_python.txt b/docs/templates_python.txt index 8a62ebebad..95ccfb3eab 100644 --- a/docs/templates_python.txt +++ b/docs/templates_python.txt @@ -198,21 +198,6 @@ some things to keep in mind: 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 ``TEMPLATE_STRING_IF_INVALID`` setting, which is set to ``''`` (the empty string) by default. diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt index 62db8ab842..1113b603da 100644 --- a/docs/tutorial01.txt +++ b/docs/tutorial01.txt @@ -81,7 +81,7 @@ the following output on the command line:: Validating models... 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/ Quit the server with CONTROL-C (Unix) or CTRL-BREAK (Windows). diff --git a/docs/url_dispatch.txt b/docs/url_dispatch.txt index 498a906d5e..00a7af027a 100644 --- a/docs/url_dispatch.txt +++ b/docs/url_dispatch.txt @@ -263,12 +263,12 @@ Here's the example URLconf from the `Django overview`_:: from django.conf.urls.defaults import * urlpatterns = patterns('', - (r'^articles/(\d{4})/$', 'myproject.news.views.year_archive'), - (r'^articles/(\d{4})/(\d{2})/$', 'myproject.news.views.month_archive'), - (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'myproject.news.views.article_detail'), + (r'^articles/(\d{4})/$', 'mysite.news.views.year_archive'), + (r'^articles/(\d{4})/(\d{2})/$', 'mysite.news.views.month_archive'), + (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 first argument to the ``patterns()`` function to specify a prefix to apply to 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 * - urlpatterns = patterns('myproject.news.views', + urlpatterns = patterns('mysite.news.views', (r'^articles/(\d{4})/$', 'year_archive'), (r'^articles/(\d{4})/(\d{2})/$', 'month_archive'), (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/ .. _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. diff --git a/setup.py b/setup.py index 845e5da3b5..1d5c5a0cda 100644 --- a/setup.py +++ b/setup.py @@ -14,38 +14,9 @@ setup( packages = find_packages(exclude=['examples', 'examples.*']), package_data = { '': ['*.TXT'], - 'django.conf': ['locale/ar/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.conf': ['locale/*/LC_MESSAGES/*'], 'django.contrib.admin': ['templates/admin/*.html', + 'templates/admin/auth/user/*.html', 'templates/admin_doc/*.html', 'templates/registration/*.html', 'templates/widget/*.html', diff --git a/tests/modeltests/empty/models.py b/tests/modeltests/empty/models.py index c50878398d..0f5a0b870f 100644 --- a/tests/modeltests/empty/models.py +++ b/tests/modeltests/empty/models.py @@ -20,5 +20,7 @@ API_TESTS = """ 2 >>> m.id is not None True +>>> existing = Empty(m.id) +>>> existing.save() """ diff --git a/tests/modeltests/lookup/models.py b/tests/modeltests/lookup/models.py index a2c0a14158..55bb373a4b 100644 --- a/tests/modeltests/lookup/models.py +++ b/tests/modeltests/lookup/models.py @@ -15,7 +15,7 @@ class Article(models.Model): def __str__(self): return self.headline -API_TESTS = """ +API_TESTS = r""" # Create a couple of Articles. >>> from datetime import datetime >>> a1 = Article(headline='Article 1', pub_date=datetime(2005, 7, 26)) @@ -161,13 +161,14 @@ DoesNotExist: Article matching query does not exist. # 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.save() >>> Article.objects.filter(headline__startswith='Article') [, , , , , , , ] >>> Article.objects.filter(headline__startswith='Article_') [] + >>> a9 = Article(headline='Article% with percent sign', pub_date=datetime(2005, 11, 21)) >>> a9.save() >>> Article.objects.filter(headline__startswith='Article') @@ -182,4 +183,12 @@ DoesNotExist: Article matching query does not exist. [, , , , , , , ] >>> Article.objects.exclude(headline="Article 7") [, , , , , , , ] + +# 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='\\') +[] + """ diff --git a/tests/othertests/defaultfilters.py b/tests/othertests/defaultfilters.py index 1636b948d0..9b1cfda833 100644 --- a/tests/othertests/defaultfilters.py +++ b/tests/othertests/defaultfilters.py @@ -231,6 +231,9 @@ False >>> time(datetime.time(13), "h") '01' +>>> time(datetime.time(0), "h") +'12' + # real testing is done in timesince.py, where we can provide our own 'now' >>> timesince(datetime.datetime.now() - datetime.timedelta(1)) '1 day' diff --git a/tests/othertests/templates.py b/tests/othertests/templates.py index 3d23d8123b..9975f3b05c 100644 --- a/tests/othertests/templates.py +++ b/tests/othertests/templates.py @@ -410,6 +410,12 @@ TEMPLATE_TESTS = { # Three-level inheritance with {{ block.super }} from parent and grandparent '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 ################################################################## # {% spaceless %} tag diff --git a/tests/othertests/urlpatterns_reverse.py b/tests/othertests/urlpatterns_reverse.py new file mode 100644 index 0000000000..236944d49f --- /dev/null +++ b/tests/othertests/urlpatterns_reverse.py @@ -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\d+)/$', 'places/3/', [], {'id': 3}), + ('^people/(?P\w+)/$', 'people/adrian/', ['adrian'], {}), + ('^people/(?P\w+)/$', 'people/adrian/', [], {'name': 'adrian'}), + ('^people/(?P\w+)/$', NoReverseMatch, ['name with spaces'], {}), + ('^people/(?P\w+)/$', NoReverseMatch, [], {'name': 'name with spaces'}), + ('^people/(?P\w+)/$', NoReverseMatch, [], {}), + ('^hardcoded/$', 'hardcoded/', [], {}), + ('^hardcoded/$', 'hardcoded/', ['any arg'], {}), + ('^hardcoded/$', 'hardcoded/', [], {'kwarg': 'foo'}), + ('^people/(?P\w\w)/(?P\w+)/$', 'people/il/adrian/', [], {'state': 'il', 'name': 'adrian'}), + ('^people/(?P\w\w)/(?P\d)/$', NoReverseMatch, [], {'state': 'il', 'name': 'adrian'}), + ('^people/(?P\w\w)/(?P\w+)/$', NoReverseMatch, [], {'state': 'il'}), + ('^people/(?P\w\w)/(?P\w+)/$', NoReverseMatch, [], {'name': 'adrian'}), + ('^people/(?P\w\w)/(\w+)/$', NoReverseMatch, ['il'], {'name': 'adrian'}), + ('^people/(?P\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)