mirror of
https://github.com/django/django.git
synced 2025-07-04 01:39:20 +00:00
multi-auth: Merged to [3151]
git-svn-id: http://code.djangoproject.com/svn/django/branches/multi-auth@3152 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
e976ed1f79
commit
adf4b9311d
1
AUTHORS
1
AUTHORS
@ -71,6 +71,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Russell Keith-Magee <freakboy@iinet.net.au>
|
Russell Keith-Magee <freakboy@iinet.net.au>
|
||||||
Garth Kidd <http://www.deadlybloodyserious.com/>
|
Garth Kidd <http://www.deadlybloodyserious.com/>
|
||||||
Sune Kirkeby <http://ibofobi.dk/>
|
Sune Kirkeby <http://ibofobi.dk/>
|
||||||
|
Cameron Knight (ckknight)
|
||||||
Bruce Kroeze <http://coderseye.com/>
|
Bruce Kroeze <http://coderseye.com/>
|
||||||
Joseph Kocherhans
|
Joseph Kocherhans
|
||||||
lakin.wecker@gmail.com
|
lakin.wecker@gmail.com
|
||||||
|
@ -12,7 +12,7 @@ from django.conf import global_settings
|
|||||||
|
|
||||||
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
||||||
|
|
||||||
class LazySettings:
|
class LazySettings(object):
|
||||||
"""
|
"""
|
||||||
A lazy proxy for either global Django settings or a custom settings object.
|
A lazy proxy for either global Django settings or a custom settings object.
|
||||||
The user can manually configure settings prior to using them. Otherwise,
|
The user can manually configure settings prior to using them. Otherwise,
|
||||||
@ -67,7 +67,7 @@ class LazySettings:
|
|||||||
setattr(holder, name, value)
|
setattr(holder, name, value)
|
||||||
self._target = holder
|
self._target = holder
|
||||||
|
|
||||||
class Settings:
|
class Settings(object):
|
||||||
def __init__(self, settings_module):
|
def __init__(self, settings_module):
|
||||||
# update this dict from global settings (but only for ALL_CAPS settings)
|
# update this dict from global settings (but only for ALL_CAPS settings)
|
||||||
for setting in dir(global_settings):
|
for setting in dir(global_settings):
|
||||||
@ -112,7 +112,7 @@ class Settings:
|
|||||||
def get_all_members(self):
|
def get_all_members(self):
|
||||||
return dir(self)
|
return dir(self)
|
||||||
|
|
||||||
class UserSettingsHolder:
|
class UserSettingsHolder(object):
|
||||||
"""
|
"""
|
||||||
Holder for user configured settings.
|
Holder for user configured settings.
|
||||||
"""
|
"""
|
||||||
|
Binary file not shown.
@ -12,7 +12,7 @@ msgstr ""
|
|||||||
"Last-Translator: Gaël Chardon <gael.dev_at_nospam_4now.net>\n"
|
"Last-Translator: Gaël Chardon <gael.dev_at_nospam_4now.net>\n"
|
||||||
"Language-Team: français <fr@li.org>\n"
|
"Language-Team: français <fr@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=ISO-8859-1\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -2,7 +2,6 @@
|
|||||||
# Copyright (C) 2006 THE djangojs'S COPYRIGHT HOLDER
|
# Copyright (C) 2006 THE djangojs'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the djangojs package.
|
# This file is distributed under the same license as the djangojs package.
|
||||||
# Meir Kriheli <meir@mksoft.co.il>, 2006.
|
# Meir Kriheli <meir@mksoft.co.il>, 2006.
|
||||||
# , fuzzy
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
|
Binary file not shown.
@ -11,7 +11,7 @@ msgstr ""
|
|||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2006-05-16 10:13+0200\n"
|
"POT-Creation-Date: 2006-05-16 10:13+0200\n"
|
||||||
"PO-Revision-Date: 2006-02-21 11:10+0100\n"
|
"PO-Revision-Date: 2006-02-21 11:10+0100\n"
|
||||||
"Last-Translator: GNOME PL Team <translators@gnome.pl>\n"
|
"Last-Translator: Piotr Maliński <admin@rk.edu.pl>\n"
|
||||||
"Language-Team: Polish <pl@li.org>\n"
|
"Language-Team: Polish <pl@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@ -19,7 +19,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
||||||
msgid "object ID"
|
msgid "object ID"
|
||||||
msgstr ""
|
msgstr "ID obiektu"
|
||||||
|
|
||||||
#: contrib/comments/models.py:68
|
#: contrib/comments/models.py:68
|
||||||
msgid "headline"
|
msgid "headline"
|
||||||
@ -32,43 +32,43 @@ msgstr "komentarz"
|
|||||||
|
|
||||||
#: contrib/comments/models.py:70
|
#: contrib/comments/models.py:70
|
||||||
msgid "rating #1"
|
msgid "rating #1"
|
||||||
msgstr ""
|
msgstr "ocena #1"
|
||||||
|
|
||||||
#: contrib/comments/models.py:71
|
#: contrib/comments/models.py:71
|
||||||
msgid "rating #2"
|
msgid "rating #2"
|
||||||
msgstr ""
|
msgstr "ocena #2"
|
||||||
|
|
||||||
#: contrib/comments/models.py:72
|
#: contrib/comments/models.py:72
|
||||||
msgid "rating #3"
|
msgid "rating #3"
|
||||||
msgstr ""
|
msgstr "ocena #3"
|
||||||
|
|
||||||
#: contrib/comments/models.py:73
|
#: contrib/comments/models.py:73
|
||||||
msgid "rating #4"
|
msgid "rating #4"
|
||||||
msgstr ""
|
msgstr "ocena #4"
|
||||||
|
|
||||||
#: contrib/comments/models.py:74
|
#: contrib/comments/models.py:74
|
||||||
msgid "rating #5"
|
msgid "rating #5"
|
||||||
msgstr ""
|
msgstr "ocena #5"
|
||||||
|
|
||||||
#: contrib/comments/models.py:75
|
#: contrib/comments/models.py:75
|
||||||
msgid "rating #6"
|
msgid "rating #6"
|
||||||
msgstr ""
|
msgstr "ocena #6"
|
||||||
|
|
||||||
#: contrib/comments/models.py:76
|
#: contrib/comments/models.py:76
|
||||||
msgid "rating #7"
|
msgid "rating #7"
|
||||||
msgstr ""
|
msgstr "ocena #7"
|
||||||
|
|
||||||
#: contrib/comments/models.py:77
|
#: contrib/comments/models.py:77
|
||||||
msgid "rating #8"
|
msgid "rating #8"
|
||||||
msgstr ""
|
msgstr "ocena #8"
|
||||||
|
|
||||||
#: contrib/comments/models.py:82
|
#: contrib/comments/models.py:82
|
||||||
msgid "is valid rating"
|
msgid "is valid rating"
|
||||||
msgstr ""
|
msgstr "jest poprawną oceną"
|
||||||
|
|
||||||
#: contrib/comments/models.py:83 contrib/comments/models.py:169
|
#: contrib/comments/models.py:83 contrib/comments/models.py:169
|
||||||
msgid "date/time submitted"
|
msgid "date/time submitted"
|
||||||
msgstr ""
|
msgstr "data/czas dodania"
|
||||||
|
|
||||||
#: contrib/comments/models.py:84 contrib/comments/models.py:170
|
#: contrib/comments/models.py:84 contrib/comments/models.py:170
|
||||||
msgid "is public"
|
msgid "is public"
|
||||||
@ -87,15 +87,16 @@ msgid ""
|
|||||||
"Check this box if the comment is inappropriate. A \"This comment has been "
|
"Check this box if the comment is inappropriate. A \"This comment has been "
|
||||||
"removed\" message will be displayed instead."
|
"removed\" message will be displayed instead."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Zaznacz to pole jeżeli komentarz jest nieodpowiedni. Wyświetlony zostanie tekst \"Ten "
|
||||||
|
"komentarz został usunięty\". "
|
||||||
|
|
||||||
#: contrib/comments/models.py:91
|
#: contrib/comments/models.py:91
|
||||||
#, fuzzy
|
|
||||||
msgid "comments"
|
msgid "comments"
|
||||||
msgstr "komentarz"
|
msgstr "komentarze"
|
||||||
|
|
||||||
#: contrib/comments/models.py:131 contrib/comments/models.py:207
|
#: contrib/comments/models.py:131 contrib/comments/models.py:207
|
||||||
msgid "Content object"
|
msgid "Content object"
|
||||||
msgstr ""
|
msgstr "Obiekt Treści"
|
||||||
|
|
||||||
#: contrib/comments/models.py:159
|
#: contrib/comments/models.py:159
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -106,6 +107,11 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"http://%(domain)s%(url)s"
|
"http://%(domain)s%(url)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Dodane przez %(user)s dnia %(date)s\n"
|
||||||
|
"\n"
|
||||||
|
"%(comment)y\n"
|
||||||
|
"\n"
|
||||||
|
"http://%(domain)s%(url)s"
|
||||||
|
|
||||||
#: contrib/comments/models.py:168
|
#: contrib/comments/models.py:168
|
||||||
msgid "person's name"
|
msgid "person's name"
|
||||||
@ -122,12 +128,12 @@ msgstr "zaakceptowano"
|
|||||||
#: contrib/comments/models.py:176
|
#: contrib/comments/models.py:176
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "free comment"
|
msgid "free comment"
|
||||||
msgstr "Wolny komentarz"
|
msgstr "wolny komentarz"
|
||||||
|
|
||||||
#: contrib/comments/models.py:177
|
#: contrib/comments/models.py:177
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "free comments"
|
msgid "free comments"
|
||||||
msgstr "Wolne komentarze"
|
msgstr "wolne komentarze"
|
||||||
|
|
||||||
#: contrib/comments/models.py:233
|
#: contrib/comments/models.py:233
|
||||||
msgid "score"
|
msgid "score"
|
||||||
@ -135,7 +141,7 @@ msgstr "ilość punktów"
|
|||||||
|
|
||||||
#: contrib/comments/models.py:234
|
#: contrib/comments/models.py:234
|
||||||
msgid "score date"
|
msgid "score date"
|
||||||
msgstr ""
|
msgstr "data przyznania punktów"
|
||||||
|
|
||||||
#: contrib/comments/models.py:237
|
#: contrib/comments/models.py:237
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -144,12 +150,12 @@ msgstr "ilość punktów"
|
|||||||
|
|
||||||
#: contrib/comments/models.py:238
|
#: contrib/comments/models.py:238
|
||||||
msgid "karma scores"
|
msgid "karma scores"
|
||||||
msgstr ""
|
msgstr "wyniki"
|
||||||
|
|
||||||
#: contrib/comments/models.py:242
|
#: contrib/comments/models.py:242
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(score)d rating by %(user)s"
|
msgid "%(score)d rating by %(user)s"
|
||||||
msgstr ""
|
msgstr "%(score)d ocenę przez %(user)s"
|
||||||
|
|
||||||
#: contrib/comments/models.py:258
|
#: contrib/comments/models.py:258
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -158,57 +164,62 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Komentarz oflagowany przez %(user)s:\n"
|
||||||
|
"\n"
|
||||||
|
"%(text)s"
|
||||||
|
|
||||||
#: contrib/comments/models.py:265
|
#: contrib/comments/models.py:265
|
||||||
msgid "flag date"
|
msgid "flag date"
|
||||||
msgstr ""
|
msgstr "data flagi"
|
||||||
|
|
||||||
#: contrib/comments/models.py:268
|
#: contrib/comments/models.py:268
|
||||||
msgid "user flag"
|
msgid "user flag"
|
||||||
msgstr ""
|
msgstr "flaga użytkownika"
|
||||||
|
|
||||||
#: contrib/comments/models.py:269
|
#: contrib/comments/models.py:269
|
||||||
msgid "user flags"
|
msgid "user flags"
|
||||||
msgstr ""
|
msgstr "flagi użytkownika"
|
||||||
|
|
||||||
#: contrib/comments/models.py:273
|
#: contrib/comments/models.py:273
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Flag by %r"
|
msgid "Flag by %r"
|
||||||
msgstr ""
|
msgstr "Flaga %r"
|
||||||
|
|
||||||
#: contrib/comments/models.py:278
|
#: contrib/comments/models.py:278
|
||||||
msgid "deletion date"
|
msgid "deletion date"
|
||||||
msgstr ""
|
msgstr "data skasowania"
|
||||||
|
|
||||||
#: contrib/comments/models.py:280
|
#: contrib/comments/models.py:280
|
||||||
msgid "moderator deletion"
|
msgid "moderator deletion"
|
||||||
msgstr ""
|
msgstr "usunięcie moderatora"
|
||||||
|
|
||||||
#: contrib/comments/models.py:281
|
#: contrib/comments/models.py:281
|
||||||
msgid "moderator deletions"
|
msgid "moderator deletions"
|
||||||
msgstr ""
|
msgstr "usunięcia moderatorów"
|
||||||
|
|
||||||
#: contrib/comments/models.py:285
|
#: contrib/comments/models.py:285
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Moderator deletion by %r"
|
msgid "Moderator deletion by %r"
|
||||||
msgstr ""
|
msgstr "Usunięcie moderatora przez %r"
|
||||||
|
|
||||||
#: contrib/comments/views/karma.py:19
|
#: contrib/comments/views/karma.py:19
|
||||||
msgid "Anonymous users cannot vote"
|
msgid "Anonymous users cannot vote"
|
||||||
msgstr ""
|
msgstr "Anonimowi użytkownicy nie mogą głosować"
|
||||||
|
|
||||||
#: contrib/comments/views/karma.py:23
|
#: contrib/comments/views/karma.py:23
|
||||||
msgid "Invalid comment ID"
|
msgid "Invalid comment ID"
|
||||||
msgstr ""
|
msgstr "Błędny ID komentarza"
|
||||||
|
|
||||||
#: contrib/comments/views/karma.py:25
|
#: contrib/comments/views/karma.py:25
|
||||||
msgid "No voting for yourself"
|
msgid "No voting for yourself"
|
||||||
msgstr ""
|
msgstr "Nie można głosować na siebie"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:28
|
#: contrib/comments/views/comments.py:28
|
||||||
msgid ""
|
msgid ""
|
||||||
"This rating is required because you've entered at least one other rating."
|
"This rating is required because you've entered at least one other rating."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Ta ocena jest wymagana gdyż podałeś przynajmniej jedną inną ocenę."
|
||||||
|
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:112
|
#: contrib/comments/views/comments.py:112
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -236,12 +247,12 @@ msgstr ""
|
|||||||
#: contrib/comments/views/comments.py:189
|
#: contrib/comments/views/comments.py:189
|
||||||
#: contrib/comments/views/comments.py:280
|
#: contrib/comments/views/comments.py:280
|
||||||
msgid "Only POSTs are allowed"
|
msgid "Only POSTs are allowed"
|
||||||
msgstr ""
|
msgstr "Dozwolone tylko POSTy"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:193
|
#: contrib/comments/views/comments.py:193
|
||||||
#: contrib/comments/views/comments.py:284
|
#: contrib/comments/views/comments.py:284
|
||||||
msgid "One or more of the required fields wasn't submitted"
|
msgid "One or more of the required fields wasn't submitted"
|
||||||
msgstr ""
|
msgstr "Jedno lub więcej wymaganych pól nie zostało wypełnionych"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:197
|
#: contrib/comments/views/comments.py:197
|
||||||
#: contrib/comments/views/comments.py:286
|
#: contrib/comments/views/comments.py:286
|
||||||
@ -264,17 +275,16 @@ msgstr ""
|
|||||||
#: contrib/comments/templates/comments/form.html:8
|
#: contrib/comments/templates/comments/form.html:8
|
||||||
#: contrib/admin/templates/admin/login.html:17
|
#: contrib/admin/templates/admin/login.html:17
|
||||||
msgid "Username:"
|
msgid "Username:"
|
||||||
msgstr "Nazwa użytkownika"
|
msgstr "Nazwa użytkownika:"
|
||||||
|
|
||||||
#: contrib/comments/templates/comments/form.html:6
|
#: contrib/comments/templates/comments/form.html:6
|
||||||
#: contrib/admin/templates/admin/login.html:20
|
#: contrib/admin/templates/admin/login.html:20
|
||||||
msgid "Password:"
|
msgid "Password:"
|
||||||
msgstr "Hasło"
|
msgstr "Hasło:"
|
||||||
|
|
||||||
#: contrib/comments/templates/comments/form.html:6
|
#: contrib/comments/templates/comments/form.html:6
|
||||||
#, fuzzy
|
|
||||||
msgid "Forgotten your password?"
|
msgid "Forgotten your password?"
|
||||||
msgstr "Zmień hasło"
|
msgstr "Zapomniałeś hasło?"
|
||||||
|
|
||||||
#: contrib/comments/templates/comments/form.html:8
|
#: contrib/comments/templates/comments/form.html:8
|
||||||
#: contrib/admin/templates/admin/object_history.html:3
|
#: contrib/admin/templates/admin/object_history.html:3
|
||||||
@ -385,7 +395,7 @@ msgstr "id obiektu"
|
|||||||
|
|
||||||
#: contrib/admin/models.py:20
|
#: contrib/admin/models.py:20
|
||||||
msgid "object repr"
|
msgid "object repr"
|
||||||
msgstr ""
|
msgstr "reprezentacj obiektu"
|
||||||
|
|
||||||
#: contrib/admin/models.py:21
|
#: contrib/admin/models.py:21
|
||||||
msgid "action flag"
|
msgid "action flag"
|
||||||
@ -426,12 +436,16 @@ msgid ""
|
|||||||
"Please log in again, because your session has expired. Don't worry: Your "
|
"Please log in again, because your session has expired. Don't worry: Your "
|
||||||
"submission has been saved."
|
"submission has been saved."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Zaloguj się ponownie. Twoja sesja wygasła lecz twoje zgłoszenie "
|
||||||
|
"zostało zapisane."
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:68
|
#: contrib/admin/views/decorators.py:68
|
||||||
msgid ""
|
msgid ""
|
||||||
"Looks like your browser isn't configured to accept cookies. Please enable "
|
"Looks like your browser isn't configured to accept cookies. Please enable "
|
||||||
"cookies, reload this page, and try again."
|
"cookies, reload this page, and try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Twoja przeglądarka nie chce akceptować ciasteczek. Zmień "
|
||||||
|
"jej ustawienia i spróbuj ponownie."
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:82
|
#: contrib/admin/views/decorators.py:82
|
||||||
msgid "Usernames cannot contain the '@' character."
|
msgid "Usernames cannot contain the '@' character."
|
||||||
@ -449,16 +463,16 @@ msgstr "Administracja stroną"
|
|||||||
#: contrib/admin/views/main.py:260
|
#: contrib/admin/views/main.py:260
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
||||||
msgstr ""
|
msgstr "%(name)s \"%(obj)s\" dodany pomyślnie."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
|
#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
|
||||||
msgid "You may edit it again below."
|
msgid "You may edit it again below."
|
||||||
msgstr "Możesz to ponownie edytować poniżej."
|
msgstr "Możesz ponownie edytować wpis poniżej."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
|
#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You may add another %s below."
|
msgid "You may add another %s below."
|
||||||
msgstr "Możesz dodać nowe %s poniżej."
|
msgstr "Możesz dodać nowy wpis %s poniżej."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:290
|
#: contrib/admin/views/main.py:290
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -499,6 +513,8 @@ msgstr "%(name)s \"%(obj)s\" zostało pomyślnie zmienione."
|
|||||||
msgid ""
|
msgid ""
|
||||||
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"%(name)s \"%(obj)s\" dodane pomyślnie. Możesz edytować ponownie wpis poniżej."
|
||||||
|
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:392
|
#: contrib/admin/views/main.py:392
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -508,21 +524,21 @@ msgstr "Zmień %s"
|
|||||||
#: contrib/admin/views/main.py:470
|
#: contrib/admin/views/main.py:470
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
|
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
|
||||||
msgstr ""
|
msgstr "Jedno lub więcej %(fieldname)s w %(name)s: %(obj)s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:475
|
#: contrib/admin/views/main.py:475
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "One or more %(fieldname)s in %(name)s:"
|
msgid "One or more %(fieldname)s in %(name)s:"
|
||||||
msgstr ""
|
msgstr "Jedno lub więcej %(fieldname)s w %(name)s:"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:508
|
#: contrib/admin/views/main.py:508
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
||||||
msgstr ""
|
msgstr "%(name)s \"%(obj)s\" usunięty pomyślnie."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:511
|
#: contrib/admin/views/main.py:511
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
msgstr "Czy na pewno?"
|
msgstr "Jesteś pewien?"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:533
|
#: contrib/admin/views/main.py:533
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -552,7 +568,7 @@ msgstr "Wartość logiczna (True, False - prawda lub fałsz)"
|
|||||||
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
|
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "String (up to %(maxlength)s)"
|
msgid "String (up to %(maxlength)s)"
|
||||||
msgstr ""
|
msgstr "Łańcuch (do %(maxlength)s znaków)"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:280
|
#: contrib/admin/views/doc.py:280
|
||||||
msgid "Comma-separated integers"
|
msgid "Comma-separated integers"
|
||||||
@ -604,11 +620,11 @@ msgstr "URL"
|
|||||||
|
|
||||||
#: contrib/admin/views/doc.py:301
|
#: contrib/admin/views/doc.py:301
|
||||||
msgid "U.S. state (two uppercase letters)"
|
msgid "U.S. state (two uppercase letters)"
|
||||||
msgstr ""
|
msgstr "Stan USA (dwie duże litery)"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:302
|
#: contrib/admin/views/doc.py:302
|
||||||
msgid "XML text"
|
msgid "XML text"
|
||||||
msgstr "Text XML"
|
msgstr "Tekst XML"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/object_history.html:3
|
#: contrib/admin/templates/admin/object_history.html:3
|
||||||
#: contrib/admin/templates/admin/change_list.html:5
|
#: contrib/admin/templates/admin/change_list.html:5
|
||||||
@ -682,6 +698,8 @@ msgid ""
|
|||||||
"This object doesn't have a change history. It probably wasn't added via this "
|
"This object doesn't have a change history. It probably wasn't added via this "
|
||||||
"admin site."
|
"admin site."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Ten obiekt nie ma historii zmian. Najprawdopodobniej wpis te nie "
|
||||||
|
"został dodany poprzez panel admina"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/base_site.html:4
|
#: contrib/admin/templates/admin/base_site.html:4
|
||||||
msgid "Django site admin"
|
msgid "Django site admin"
|
||||||
@ -701,13 +719,15 @@ msgstr "Bład serwera (500)"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/500.html:9
|
#: contrib/admin/templates/admin/500.html:9
|
||||||
msgid "Server Error <em>(500)</em>"
|
msgid "Server Error <em>(500)</em>"
|
||||||
msgstr ""
|
msgstr "Błąd Serwera <em>(500)</em>"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/500.html:10
|
#: contrib/admin/templates/admin/500.html:10
|
||||||
msgid ""
|
msgid ""
|
||||||
"There's been an error. It's been reported to the site administrators via e-"
|
"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."
|
"mail and should be fixed shortly. Thanks for your patience."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Wystąpił niespodziewany błąd. Raport został wysłany emailem "
|
||||||
|
"administratorowi strony."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/404.html:4
|
#: contrib/admin/templates/admin/404.html:4
|
||||||
#: contrib/admin/templates/admin/404.html:8
|
#: contrib/admin/templates/admin/404.html:8
|
||||||
@ -716,12 +736,12 @@ msgstr "Strona nie znaleziona"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/404.html:10
|
#: contrib/admin/templates/admin/404.html:10
|
||||||
msgid "We're sorry, but the requested page could not be found."
|
msgid "We're sorry, but the requested page could not be found."
|
||||||
msgstr ""
|
msgstr "Niestety nie można znaleźć rządanej strony."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:17
|
#: contrib/admin/templates/admin/index.html:17
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Models available in the %(name)s application."
|
msgid "Models available in the %(name)s application."
|
||||||
msgstr ""
|
msgstr "Modele dostępne w aplikacji %(name)s."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:28
|
#: contrib/admin/templates/admin/index.html:28
|
||||||
#: contrib/admin/templates/admin/change_form.html:15
|
#: contrib/admin/templates/admin/change_form.html:15
|
||||||
@ -734,7 +754,7 @@ msgstr "Zmień"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:44
|
#: contrib/admin/templates/admin/index.html:44
|
||||||
msgid "You don't have permission to edit anything."
|
msgid "You don't have permission to edit anything."
|
||||||
msgstr ""
|
msgstr "Nie masz uprawnień by edytować cokolwiek"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:52
|
#: contrib/admin/templates/admin/index.html:52
|
||||||
msgid "Recent Actions"
|
msgid "Recent Actions"
|
||||||
@ -746,7 +766,7 @@ msgstr "Moje akcje"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:57
|
#: contrib/admin/templates/admin/index.html:57
|
||||||
msgid "None available"
|
msgid "None available"
|
||||||
msgstr "Nic nie dostępne"
|
msgstr "Brak"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_list.html:11
|
#: contrib/admin/templates/admin/change_list.html:11
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -756,7 +776,7 @@ msgstr "Dodaj %(name)s"
|
|||||||
#: contrib/admin/templates/admin/login.html:22
|
#: contrib/admin/templates/admin/login.html:22
|
||||||
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
|
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Czy aby na pewno <a href=\"/password_reset/\">zapomniałeś/łaś</a> hasła?"
|
"Czy <a href=\"/password_reset/\">zapomniałeś/łaś</a> hasła?"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/base.html:23
|
#: contrib/admin/templates/admin/base.html:23
|
||||||
msgid "Welcome,"
|
msgid "Welcome,"
|
||||||
@ -816,11 +836,11 @@ msgstr "Porządek:"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/submit_line.html:4
|
#: contrib/admin/templates/admin/submit_line.html:4
|
||||||
msgid "Save as new"
|
msgid "Save as new"
|
||||||
msgstr "Zapisz"
|
msgstr "Zapisz jako nowe"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/submit_line.html:5
|
#: contrib/admin/templates/admin/submit_line.html:5
|
||||||
msgid "Save and add another"
|
msgid "Save and add another"
|
||||||
msgstr "Zapisz i dodaj"
|
msgstr "Zapisz i dodaj nowe"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/submit_line.html:6
|
#: contrib/admin/templates/admin/submit_line.html:6
|
||||||
msgid "Save and continue editing"
|
msgid "Save and continue editing"
|
||||||
@ -858,6 +878,8 @@ msgid ""
|
|||||||
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
||||||
"your password and e-mail the new one to you."
|
"your password and e-mail the new one to you."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Podaj swój adres email. Hasło zostanie zresetowane i wysłane na twój "
|
||||||
|
"adres email."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_form.html:16
|
#: contrib/admin/templates/registration/password_reset_form.html:16
|
||||||
msgid "E-mail address:"
|
msgid "E-mail address:"
|
||||||
@ -869,7 +891,7 @@ msgstr "Zresetuj moje hasło"
|
|||||||
|
|
||||||
#: contrib/admin/templates/registration/logged_out.html:8
|
#: contrib/admin/templates/registration/logged_out.html:8
|
||||||
msgid "Thanks for spending some quality time with the Web site today."
|
msgid "Thanks for spending some quality time with the Web site today."
|
||||||
msgstr ""
|
msgstr "Dziękujemy za odwiedzenie serwisu."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/logged_out.html:10
|
#: contrib/admin/templates/registration/logged_out.html:10
|
||||||
msgid "Log in again"
|
msgid "Log in again"
|
||||||
@ -878,19 +900,21 @@ msgstr "Zaloguj ponownie"
|
|||||||
#: contrib/admin/templates/registration/password_reset_done.html:6
|
#: contrib/admin/templates/registration/password_reset_done.html:6
|
||||||
#: contrib/admin/templates/registration/password_reset_done.html:10
|
#: contrib/admin/templates/registration/password_reset_done.html:10
|
||||||
msgid "Password reset successful"
|
msgid "Password reset successful"
|
||||||
msgstr ""
|
msgstr "Udane resetowanie hasła"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_done.html:12
|
#: contrib/admin/templates/registration/password_reset_done.html:12
|
||||||
msgid ""
|
msgid ""
|
||||||
"We've e-mailed a new password to the e-mail address you submitted. You "
|
"We've e-mailed a new password to the e-mail address you submitted. You "
|
||||||
"should be receiving it shortly."
|
"should be receiving it shortly."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Nowe hasło zostało wysłane na podany adres email. Powinieneś "
|
||||||
|
"otrzymać je niebawem."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:12
|
#: contrib/admin/templates/registration/password_change_form.html:12
|
||||||
msgid ""
|
msgid ""
|
||||||
"Please enter your old password, for security's sake, and then enter your new "
|
"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."
|
"password twice so we can verify you typed it in correctly."
|
||||||
msgstr ""
|
msgstr "Podaj swoje stare hasło i dwa razy nowe."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:17
|
#: contrib/admin/templates/registration/password_change_form.html:17
|
||||||
msgid "Old password:"
|
msgid "Old password:"
|
||||||
@ -910,12 +934,12 @@ msgstr "Zmień hasło"
|
|||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:2
|
#: contrib/admin/templates/registration/password_reset_email.html:2
|
||||||
msgid "You're receiving this e-mail because you requested a password reset"
|
msgid "You're receiving this e-mail because you requested a password reset"
|
||||||
msgstr ""
|
msgstr "Otrzymałeś email gdyż zarządałeś zresetowania hasła"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:3
|
#: contrib/admin/templates/registration/password_reset_email.html:3
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "for your user account at %(site_name)s"
|
msgid "for your user account at %(site_name)s"
|
||||||
msgstr ""
|
msgstr "dla twojego konta użytkownika na stronie %(site_name)s"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:5
|
#: contrib/admin/templates/registration/password_reset_email.html:5
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -924,11 +948,11 @@ msgstr "Twoje nowe hasło to: %(new_password)s"
|
|||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:7
|
#: contrib/admin/templates/registration/password_reset_email.html:7
|
||||||
msgid "Feel free to change this password by going to this page:"
|
msgid "Feel free to change this password by going to this page:"
|
||||||
msgstr ""
|
msgstr "Możesz zmienić je na stronie:"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:11
|
#: contrib/admin/templates/registration/password_reset_email.html:11
|
||||||
msgid "Your username, in case you've forgotten:"
|
msgid "Your username, in case you've forgotten:"
|
||||||
msgstr ""
|
msgstr "Twój login:"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:13
|
#: contrib/admin/templates/registration/password_reset_email.html:13
|
||||||
msgid "Thanks for using our site!"
|
msgid "Thanks for using our site!"
|
||||||
@ -960,7 +984,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:19
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:19
|
||||||
msgid "Documentation for this page"
|
msgid "Documentation for this page"
|
||||||
msgstr ""
|
msgstr "Dokumentacja dla tej strony"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:20
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:20
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -970,37 +994,39 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:22
|
||||||
msgid "Show object ID"
|
msgid "Show object ID"
|
||||||
msgstr ""
|
msgstr "Pokaż ID obiektu"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:23
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:23
|
||||||
msgid ""
|
msgid ""
|
||||||
"Shows the content-type and unique ID for pages that represent a single "
|
"Shows the content-type and unique ID for pages that represent a single "
|
||||||
"object."
|
"object."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Pokazuje typ i unikalne ID dla stron, które reprezentują "
|
||||||
|
"pojedynczy obiekt."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:25
|
||||||
msgid "Edit this object (current window)"
|
msgid "Edit this object (current window)"
|
||||||
msgstr ""
|
msgstr "Edytuj ten obiekt (bierzące okno)"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
|
||||||
msgid "Jumps to the admin page for pages that represent a single object."
|
msgid "Jumps to the admin page for pages that represent a single object."
|
||||||
msgstr ""
|
msgstr "Przeskok do panelu admina dla stron reprezentujących pojedynczy obiekt"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
|
||||||
msgid "Edit this object (new window)"
|
msgid "Edit this object (new window)"
|
||||||
msgstr ""
|
msgstr "Edytuj ten obiekt (nowe onko)"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:29
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:29
|
||||||
msgid "As above, but opens the admin page in a new window."
|
msgid "As above, but opens the admin page in a new window."
|
||||||
msgstr ""
|
msgstr "Jak wyżej, tyle że otwiera nowe okno."
|
||||||
|
|
||||||
#: contrib/admin/templates/widget/date_time.html:3
|
#: contrib/admin/templates/widget/date_time.html:3
|
||||||
msgid "Date:"
|
msgid "Date:"
|
||||||
msgstr "data"
|
msgstr "Data:"
|
||||||
|
|
||||||
#: contrib/admin/templates/widget/date_time.html:4
|
#: contrib/admin/templates/widget/date_time.html:4
|
||||||
msgid "Time:"
|
msgid "Time:"
|
||||||
msgstr "Czas"
|
msgstr "Czas:"
|
||||||
|
|
||||||
#: contrib/admin/templates/widget/file.html:2
|
#: contrib/admin/templates/widget/file.html:2
|
||||||
msgid "Currently:"
|
msgid "Currently:"
|
||||||
@ -1012,36 +1038,40 @@ msgstr "Zmień:"
|
|||||||
|
|
||||||
#: contrib/redirects/models.py:7
|
#: contrib/redirects/models.py:7
|
||||||
msgid "redirect from"
|
msgid "redirect from"
|
||||||
msgstr ""
|
msgstr "przekieruj z"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:8
|
#: contrib/redirects/models.py:8
|
||||||
msgid ""
|
msgid ""
|
||||||
"This should be an absolute path, excluding the domain name. Example: '/"
|
"This should be an absolute path, excluding the domain name. Example: '/"
|
||||||
"events/search/'."
|
"events/search/'."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Podaj pełną ścieżkę bez nazwy domeny. Przykład: '/"
|
||||||
|
"events/search/'."
|
||||||
|
|
||||||
#: contrib/redirects/models.py:9
|
#: contrib/redirects/models.py:9
|
||||||
msgid "redirect to"
|
msgid "redirect to"
|
||||||
msgstr ""
|
msgstr "przekierowanie do"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:10
|
#: contrib/redirects/models.py:10
|
||||||
msgid ""
|
msgid ""
|
||||||
"This can be either an absolute path (as above) or a full URL starting with "
|
"This can be either an absolute path (as above) or a full URL starting with "
|
||||||
"'http://'."
|
"'http://'."
|
||||||
msgstr ""
|
msgstr "Ścieżka jak wyżej lub pełny URL z http://"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:12
|
#: contrib/redirects/models.py:12
|
||||||
msgid "redirect"
|
msgid "redirect"
|
||||||
msgstr ""
|
msgstr "przekieruj"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:13
|
#: contrib/redirects/models.py:13
|
||||||
msgid "redirects"
|
msgid "redirects"
|
||||||
msgstr ""
|
msgstr "przekierowania"
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:8
|
#: contrib/flatpages/models.py:8
|
||||||
msgid ""
|
msgid ""
|
||||||
"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
|
"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Przykład: '/about/contact/'. Upewnij się że wpisałeś otwierający i zamykający slash."
|
||||||
|
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:9
|
#: contrib/flatpages/models.py:9
|
||||||
msgid "title"
|
msgid "title"
|
||||||
@ -1053,11 +1083,11 @@ msgstr "zawartość"
|
|||||||
|
|
||||||
#: contrib/flatpages/models.py:11
|
#: contrib/flatpages/models.py:11
|
||||||
msgid "enable comments"
|
msgid "enable comments"
|
||||||
msgstr ""
|
msgstr "włącz komentarze"
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:12
|
#: contrib/flatpages/models.py:12
|
||||||
msgid "template name"
|
msgid "template name"
|
||||||
msgstr ""
|
msgstr "nazwa szablonu"
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:13
|
#: contrib/flatpages/models.py:13
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -1067,11 +1097,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/flatpages/models.py:14
|
#: contrib/flatpages/models.py:14
|
||||||
msgid "registration required"
|
msgid "registration required"
|
||||||
msgstr ""
|
msgstr "wymagana rejestracja"
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:14
|
#: contrib/flatpages/models.py:14
|
||||||
msgid "If this is checked, only logged-in users will be able to view the page."
|
msgid "If this is checked, only logged-in users will be able to view the page."
|
||||||
msgstr ""
|
msgstr "Jeżeli zaznaczone - tylko zalogowani użytkownicy będą mogli zobaczyć stronę."
|
||||||
|
|
||||||
#: contrib/flatpages/models.py:18
|
#: contrib/flatpages/models.py:18
|
||||||
msgid "flat page"
|
msgid "flat page"
|
||||||
@ -1091,31 +1121,31 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/auth/models.py:17
|
#: contrib/auth/models.py:17
|
||||||
msgid "permission"
|
msgid "permission"
|
||||||
msgstr ""
|
msgstr "uprawnienie"
|
||||||
|
|
||||||
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
||||||
msgid "permissions"
|
msgid "permissions"
|
||||||
msgstr ""
|
msgstr "uprawnienia"
|
||||||
|
|
||||||
#: contrib/auth/models.py:29
|
#: contrib/auth/models.py:29
|
||||||
msgid "group"
|
msgid "group"
|
||||||
msgstr ""
|
msgstr "grupa"
|
||||||
|
|
||||||
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
||||||
msgid "groups"
|
msgid "groups"
|
||||||
msgstr ""
|
msgstr "grupy"
|
||||||
|
|
||||||
#: contrib/auth/models.py:55
|
#: contrib/auth/models.py:55
|
||||||
msgid "username"
|
msgid "username"
|
||||||
msgstr ""
|
msgstr "użytkownik"
|
||||||
|
|
||||||
#: contrib/auth/models.py:56
|
#: contrib/auth/models.py:56
|
||||||
msgid "first name"
|
msgid "first name"
|
||||||
msgstr ""
|
msgstr "Imię"
|
||||||
|
|
||||||
#: contrib/auth/models.py:57
|
#: contrib/auth/models.py:57
|
||||||
msgid "last name"
|
msgid "last name"
|
||||||
msgstr ""
|
msgstr "Nazwisko"
|
||||||
|
|
||||||
#: contrib/auth/models.py:58
|
#: contrib/auth/models.py:58
|
||||||
msgid "e-mail address"
|
msgid "e-mail address"
|
||||||
@ -1127,15 +1157,15 @@ msgstr "hasło"
|
|||||||
|
|
||||||
#: contrib/auth/models.py:59
|
#: contrib/auth/models.py:59
|
||||||
msgid "Use '[algo]$[salt]$[hexdigest]'"
|
msgid "Use '[algo]$[salt]$[hexdigest]'"
|
||||||
msgstr ""
|
msgstr "Użyj '[algo]$[salt]$[hexdigest]'"
|
||||||
|
|
||||||
#: contrib/auth/models.py:60
|
#: contrib/auth/models.py:60
|
||||||
msgid "staff status"
|
msgid "staff status"
|
||||||
msgstr ""
|
msgstr "stan w zespole"
|
||||||
|
|
||||||
#: contrib/auth/models.py:60
|
#: contrib/auth/models.py:60
|
||||||
msgid "Designates whether the user can log into this admin site."
|
msgid "Designates whether the user can log into this admin site."
|
||||||
msgstr ""
|
msgstr "Oznaczy czy użytkownik może zalogować się do panelu admina."
|
||||||
|
|
||||||
#: contrib/auth/models.py:61
|
#: contrib/auth/models.py:61
|
||||||
msgid "active"
|
msgid "active"
|
||||||
@ -1143,7 +1173,7 @@ msgstr "aktywny"
|
|||||||
|
|
||||||
#: contrib/auth/models.py:62
|
#: contrib/auth/models.py:62
|
||||||
msgid "superuser status"
|
msgid "superuser status"
|
||||||
msgstr ""
|
msgstr "Główny Administrator"
|
||||||
|
|
||||||
#: contrib/auth/models.py:63
|
#: contrib/auth/models.py:63
|
||||||
msgid "last login"
|
msgid "last login"
|
||||||
@ -1158,10 +1188,12 @@ msgid ""
|
|||||||
"In addition to the permissions manually assigned, this user will also get "
|
"In addition to the permissions manually assigned, this user will also get "
|
||||||
"all permissions granted to each group he/she is in."
|
"all permissions granted to each group he/she is in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Oprócz uprawnień przypisanych bezpośrednio użytkownikowi otrzyma on "
|
||||||
|
"uprawnienia grup, do których należy."
|
||||||
|
|
||||||
#: contrib/auth/models.py:67
|
#: contrib/auth/models.py:67
|
||||||
msgid "user permissions"
|
msgid "user permissions"
|
||||||
msgstr ""
|
msgstr "uprawnienia użytkownika"
|
||||||
|
|
||||||
#: contrib/auth/models.py:70
|
#: contrib/auth/models.py:70
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -1175,62 +1207,64 @@ msgstr "Uzytkownicy"
|
|||||||
|
|
||||||
#: contrib/auth/models.py:76
|
#: contrib/auth/models.py:76
|
||||||
msgid "Personal info"
|
msgid "Personal info"
|
||||||
msgstr ""
|
msgstr "Dane osobowe"
|
||||||
|
|
||||||
#: contrib/auth/models.py:77
|
#: contrib/auth/models.py:77
|
||||||
msgid "Permissions"
|
msgid "Permissions"
|
||||||
msgstr ""
|
msgstr "Uprawnienia"
|
||||||
|
|
||||||
#: contrib/auth/models.py:78
|
#: contrib/auth/models.py:78
|
||||||
msgid "Important dates"
|
msgid "Important dates"
|
||||||
msgstr ""
|
msgstr "Ważne daty"
|
||||||
|
|
||||||
#: contrib/auth/models.py:79
|
#: contrib/auth/models.py:79
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr ""
|
msgstr "Grupy"
|
||||||
|
|
||||||
#: contrib/auth/models.py:219
|
#: contrib/auth/models.py:219
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "message"
|
msgid "message"
|
||||||
msgstr "Wiadomość"
|
msgstr "wiadomość"
|
||||||
|
|
||||||
#: contrib/auth/forms.py:30
|
#: contrib/auth/forms.py:30
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
|
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
|
||||||
"required for logging in."
|
"required for logging in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Twoja przeglądarka nie chce akceptować ciasteczek. Są one "
|
||||||
|
"wymagane do zalogowania się."
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:25
|
#: contrib/contenttypes/models.py:25
|
||||||
msgid "python model class name"
|
msgid "python model class name"
|
||||||
msgstr ""
|
msgstr "nazwa pythonowa modelu klasy"
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:28
|
#: contrib/contenttypes/models.py:28
|
||||||
msgid "content type"
|
msgid "content type"
|
||||||
msgstr ""
|
msgstr "typ zawartości"
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:29
|
#: contrib/contenttypes/models.py:29
|
||||||
msgid "content types"
|
msgid "content types"
|
||||||
msgstr ""
|
msgstr "typy zawartości"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:35
|
#: contrib/sessions/models.py:35
|
||||||
msgid "session key"
|
msgid "session key"
|
||||||
msgstr ""
|
msgstr "klucz sesji"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:36
|
#: contrib/sessions/models.py:36
|
||||||
msgid "session data"
|
msgid "session data"
|
||||||
msgstr ""
|
msgstr "data sesji"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:37
|
#: contrib/sessions/models.py:37
|
||||||
msgid "expire date"
|
msgid "expire date"
|
||||||
msgstr ""
|
msgstr "data wygaśnięcia sesji"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:41
|
#: contrib/sessions/models.py:41
|
||||||
msgid "session"
|
msgid "session"
|
||||||
msgstr ""
|
msgstr "sesja"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:42
|
#: contrib/sessions/models.py:42
|
||||||
msgid "sessions"
|
msgid "sessions"
|
||||||
msgstr ""
|
msgstr "sesje"
|
||||||
|
|
||||||
#: contrib/sites/models.py:10
|
#: contrib/sites/models.py:10
|
||||||
msgid "domain name"
|
msgid "domain name"
|
||||||
@ -1250,15 +1284,15 @@ msgstr "strony"
|
|||||||
|
|
||||||
#: utils/translation.py:360
|
#: utils/translation.py:360
|
||||||
msgid "DATE_FORMAT"
|
msgid "DATE_FORMAT"
|
||||||
msgstr "FORMAT_DATY"
|
msgstr "Y-m-d"
|
||||||
|
|
||||||
#: utils/translation.py:361
|
#: utils/translation.py:361
|
||||||
msgid "DATETIME_FORMAT"
|
msgid "DATETIME_FORMAT"
|
||||||
msgstr ""
|
msgstr "Y-m-d H:i:s"
|
||||||
|
|
||||||
#: utils/translation.py:362
|
#: utils/translation.py:362
|
||||||
msgid "TIME_FORMAT"
|
msgid "TIME_FORMAT"
|
||||||
msgstr ""
|
msgstr "H:i:s"
|
||||||
|
|
||||||
#: utils/dates.py:6
|
#: utils/dates.py:6
|
||||||
msgid "Monday"
|
msgid "Monday"
|
||||||
@ -1339,52 +1373,51 @@ msgstr "Grudzień"
|
|||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "jan"
|
msgid "jan"
|
||||||
msgstr "i"
|
msgstr "sty"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "feb"
|
msgid "feb"
|
||||||
msgstr ""
|
msgstr "luty"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "mar"
|
msgid "mar"
|
||||||
msgstr ""
|
msgstr "marz"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "apr"
|
msgid "apr"
|
||||||
msgstr ""
|
msgstr "kwie"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
#, fuzzy
|
|
||||||
msgid "may"
|
msgid "may"
|
||||||
msgstr "dzień"
|
msgstr "maj"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "jun"
|
msgid "jun"
|
||||||
msgstr ""
|
msgstr "czerw"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "jul"
|
msgid "jul"
|
||||||
msgstr ""
|
msgstr "lip"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "aug"
|
msgid "aug"
|
||||||
msgstr ""
|
msgstr "sier"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "sep"
|
msgid "sep"
|
||||||
msgstr ""
|
msgstr "wrze"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "oct"
|
msgid "oct"
|
||||||
msgstr ""
|
msgstr "paź"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "nov"
|
msgid "nov"
|
||||||
msgstr ""
|
msgstr "list"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "dec"
|
msgid "dec"
|
||||||
msgstr ""
|
msgstr "gru"
|
||||||
|
|
||||||
#: utils/dates.py:27
|
#: utils/dates.py:27
|
||||||
msgid "Jan."
|
msgid "Jan."
|
||||||
@ -1396,7 +1429,7 @@ msgstr "Lut."
|
|||||||
|
|
||||||
#: utils/dates.py:28
|
#: utils/dates.py:28
|
||||||
msgid "Aug."
|
msgid "Aug."
|
||||||
msgstr "Sier.."
|
msgstr "Sier."
|
||||||
|
|
||||||
#: utils/dates.py:28
|
#: utils/dates.py:28
|
||||||
msgid "Sept."
|
msgid "Sept."
|
||||||
@ -1415,31 +1448,28 @@ msgid "Dec."
|
|||||||
msgstr "Gru."
|
msgstr "Gru."
|
||||||
|
|
||||||
#: utils/timesince.py:12
|
#: utils/timesince.py:12
|
||||||
#, fuzzy
|
|
||||||
msgid "year"
|
msgid "year"
|
||||||
msgid_plural "years"
|
msgid_plural "years"
|
||||||
msgstr[0] "rok"
|
msgstr[0] "rok"
|
||||||
msgstr[1] "rok"
|
msgstr[1] "lat"
|
||||||
|
|
||||||
#: utils/timesince.py:13
|
#: utils/timesince.py:13
|
||||||
#, fuzzy
|
|
||||||
msgid "month"
|
msgid "month"
|
||||||
msgid_plural "months"
|
msgid_plural "months"
|
||||||
msgstr[0] "miesiąc"
|
msgstr[0] "miesiąc"
|
||||||
msgstr[1] "miesiąc"
|
msgstr[1] "miesięcy"
|
||||||
|
|
||||||
#: utils/timesince.py:14
|
#: utils/timesince.py:14
|
||||||
msgid "week"
|
msgid "week"
|
||||||
msgid_plural "weeks"
|
msgid_plural "weeks"
|
||||||
msgstr[0] ""
|
msgstr[0] "tydzień"
|
||||||
msgstr[1] ""
|
msgstr[1] "tygodni"
|
||||||
|
|
||||||
#: utils/timesince.py:15
|
#: utils/timesince.py:15
|
||||||
#, fuzzy
|
|
||||||
msgid "day"
|
msgid "day"
|
||||||
msgid_plural "days"
|
msgid_plural "days"
|
||||||
msgstr[0] "dzień"
|
msgstr[0] "dzień"
|
||||||
msgstr[1] "dzień"
|
msgstr[1] "dni"
|
||||||
|
|
||||||
#: utils/timesince.py:16
|
#: utils/timesince.py:16
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -1449,11 +1479,10 @@ msgstr[0] "godzina"
|
|||||||
msgstr[1] "godzina"
|
msgstr[1] "godzina"
|
||||||
|
|
||||||
#: utils/timesince.py:17
|
#: utils/timesince.py:17
|
||||||
#, fuzzy
|
|
||||||
msgid "minute"
|
msgid "minute"
|
||||||
msgid_plural "minutes"
|
msgid_plural "minutes"
|
||||||
msgstr[0] "minuta"
|
msgstr[0] "minuta"
|
||||||
msgstr[1] "minuta"
|
msgstr[1] "minut"
|
||||||
|
|
||||||
#: conf/global_settings.py:37
|
#: conf/global_settings.py:37
|
||||||
msgid "Bengali"
|
msgid "Bengali"
|
||||||
@ -1477,7 +1506,7 @@ msgstr "Niemiecki"
|
|||||||
|
|
||||||
#: conf/global_settings.py:42
|
#: conf/global_settings.py:42
|
||||||
msgid "Greek"
|
msgid "Greek"
|
||||||
msgstr ""
|
msgstr "Grecki"
|
||||||
|
|
||||||
#: conf/global_settings.py:43
|
#: conf/global_settings.py:43
|
||||||
msgid "English"
|
msgid "English"
|
||||||
@ -1501,7 +1530,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: conf/global_settings.py:48
|
#: conf/global_settings.py:48
|
||||||
msgid "Hebrew"
|
msgid "Hebrew"
|
||||||
msgstr ""
|
msgstr "Hebrajski"
|
||||||
|
|
||||||
#: conf/global_settings.py:49
|
#: conf/global_settings.py:49
|
||||||
msgid "Icelandic"
|
msgid "Icelandic"
|
||||||
@ -1517,7 +1546,7 @@ msgstr "Japoński"
|
|||||||
|
|
||||||
#: conf/global_settings.py:52
|
#: conf/global_settings.py:52
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr ""
|
msgstr "Holenderski"
|
||||||
|
|
||||||
#: conf/global_settings.py:53
|
#: conf/global_settings.py:53
|
||||||
msgid "Norwegian"
|
msgid "Norwegian"
|
||||||
@ -1570,11 +1599,10 @@ msgid "This value must contain only letters, numbers and underscores."
|
|||||||
msgstr "To pole możei zawierać tylko litery, cyfry i podkreślenia"
|
msgstr "To pole możei zawierać tylko litery, cyfry i podkreślenia"
|
||||||
|
|
||||||
#: core/validators.py:64
|
#: core/validators.py:64
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"This value must contain only letters, numbers, underscores, dashes or "
|
"This value must contain only letters, numbers, underscores, dashes or "
|
||||||
"slashes."
|
"slashes."
|
||||||
msgstr "To pole może zawierać jedynie litery, cyfry, podkreślenia i slasze"
|
msgstr "To pole może zawierać jedynie litery, cyfry, podkreślenia i slasze."
|
||||||
|
|
||||||
#: core/validators.py:72
|
#: core/validators.py:72
|
||||||
msgid "Uppercase letters are not allowed here."
|
msgid "Uppercase letters are not allowed here."
|
||||||
@ -1606,7 +1634,7 @@ msgstr "Tu mogą być tylko cyfry"
|
|||||||
|
|
||||||
#: core/validators.py:111
|
#: core/validators.py:111
|
||||||
msgid "This value can't be comprised solely of digits."
|
msgid "This value can't be comprised solely of digits."
|
||||||
msgstr ""
|
msgstr "To pole nie może zawierać jedynie cyfr."
|
||||||
|
|
||||||
#: core/validators.py:116
|
#: core/validators.py:116
|
||||||
msgid "Enter a whole number."
|
msgid "Enter a whole number."
|
||||||
@ -1777,6 +1805,7 @@ msgid ""
|
|||||||
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
"The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
||||||
#: core/validators.py:462
|
#: core/validators.py:462
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
|
Binary file not shown.
@ -125,12 +125,10 @@ msgid "approved by staff"
|
|||||||
msgstr "одобрено администрацией"
|
msgstr "одобрено администрацией"
|
||||||
|
|
||||||
#: contrib/comments/models.py:176
|
#: contrib/comments/models.py:176
|
||||||
#, fuzzy
|
|
||||||
msgid "free comment"
|
msgid "free comment"
|
||||||
msgstr "Свободный комментарий"
|
msgstr "Свободный комментарий"
|
||||||
|
|
||||||
#: contrib/comments/models.py:177
|
#: contrib/comments/models.py:177
|
||||||
#, fuzzy
|
|
||||||
msgid "free comments"
|
msgid "free comments"
|
||||||
msgstr "Свободные комментарии"
|
msgstr "Свободные комментарии"
|
||||||
|
|
||||||
@ -143,13 +141,12 @@ msgid "score date"
|
|||||||
msgstr "счёт времени"
|
msgstr "счёт времени"
|
||||||
|
|
||||||
#: contrib/comments/models.py:237
|
#: contrib/comments/models.py:237
|
||||||
#, fuzzy
|
|
||||||
msgid "karma score"
|
msgid "karma score"
|
||||||
msgstr "счёт"
|
msgstr "Карма счёт"
|
||||||
|
|
||||||
#: contrib/comments/models.py:238
|
#: contrib/comments/models.py:238
|
||||||
msgid "karma scores"
|
msgid "karma scores"
|
||||||
msgstr ""
|
msgstr "Карма счета"
|
||||||
|
|
||||||
#: contrib/comments/models.py:242
|
#: contrib/comments/models.py:242
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -172,12 +169,10 @@ msgid "flag date"
|
|||||||
msgstr "отметка даты"
|
msgstr "отметка даты"
|
||||||
|
|
||||||
#: contrib/comments/models.py:268
|
#: contrib/comments/models.py:268
|
||||||
#, fuzzy
|
|
||||||
msgid "user flag"
|
msgid "user flag"
|
||||||
msgstr "Признак пользователя"
|
msgstr "Признак пользователя"
|
||||||
|
|
||||||
#: contrib/comments/models.py:269
|
#: contrib/comments/models.py:269
|
||||||
#, fuzzy
|
|
||||||
msgid "user flags"
|
msgid "user flags"
|
||||||
msgstr "Признаки пользователя"
|
msgstr "Признаки пользователя"
|
||||||
|
|
||||||
@ -191,14 +186,12 @@ msgid "deletion date"
|
|||||||
msgstr "дата удаления"
|
msgstr "дата удаления"
|
||||||
|
|
||||||
#: contrib/comments/models.py:280
|
#: contrib/comments/models.py:280
|
||||||
#, fuzzy
|
|
||||||
msgid "moderator deletion"
|
msgid "moderator deletion"
|
||||||
msgstr "Удалено модератором"
|
msgstr "Удаленно модератором"
|
||||||
|
|
||||||
#: contrib/comments/models.py:281
|
#: contrib/comments/models.py:281
|
||||||
#, fuzzy
|
|
||||||
msgid "moderator deletions"
|
msgid "moderator deletions"
|
||||||
msgstr "Удалено модератором"
|
msgstr "Удаления модератором"
|
||||||
|
|
||||||
#: contrib/comments/models.py:285
|
#: contrib/comments/models.py:285
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -742,7 +735,7 @@ msgstr "К сожалению, запрашиваемая вами страни
|
|||||||
#: contrib/admin/templates/admin/index.html:17
|
#: contrib/admin/templates/admin/index.html:17
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Models available in the %(name)s application."
|
msgid "Models available in the %(name)s application."
|
||||||
msgstr ""
|
msgstr "Модели доступны в %(name)s приложении."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:28
|
#: contrib/admin/templates/admin/index.html:28
|
||||||
#: contrib/admin/templates/admin/change_form.html:15
|
#: contrib/admin/templates/admin/change_form.html:15
|
||||||
@ -818,11 +811,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/search_form.html:8
|
#: contrib/admin/templates/admin/search_form.html:8
|
||||||
msgid "Go"
|
msgid "Go"
|
||||||
msgstr ""
|
msgstr "Вперёд"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:21
|
#: contrib/admin/templates/admin/change_form.html:21
|
||||||
msgid "View on site"
|
msgid "View on site"
|
||||||
msgstr ""
|
msgstr "Смотреть сайт"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:30
|
#: contrib/admin/templates/admin/change_form.html:30
|
||||||
msgid "Please correct the error below."
|
msgid "Please correct the error below."
|
||||||
@ -832,7 +825,7 @@ msgstr[1] "Пожалуйста исправьте ошибки ниже."
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:48
|
#: contrib/admin/templates/admin/change_form.html:48
|
||||||
msgid "Ordering"
|
msgid "Ordering"
|
||||||
msgstr ""
|
msgstr "Очерёдность"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:51
|
#: contrib/admin/templates/admin/change_form.html:51
|
||||||
msgid "Order:"
|
msgid "Order:"
|
||||||
@ -967,11 +960,11 @@ msgstr "Спасибо за посещение нашего сайта!"
|
|||||||
#: contrib/admin/templates/registration/password_reset_email.html:15
|
#: contrib/admin/templates/registration/password_reset_email.html:15
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(site_name)s team"
|
msgid "The %(site_name)s team"
|
||||||
msgstr "Команда сайта di %(site_name)s"
|
msgstr "Команда сайта %(site_name)s"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
|
||||||
msgid "Bookmarklets"
|
msgid "Bookmarklets"
|
||||||
msgstr ""
|
msgstr "Закладки"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:5
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:5
|
||||||
msgid "Documentation bookmarklets"
|
msgid "Documentation bookmarklets"
|
||||||
@ -1018,7 +1011,7 @@ msgstr "Редактировать данный обьект (в текущем
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:26
|
||||||
msgid "Jumps to the admin page for pages that represent a single object."
|
msgid "Jumps to the admin page for pages that represent a single object."
|
||||||
msgstr ""
|
msgstr "Перейти на страницу администратор для страниц представляющих один объект."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:28
|
||||||
msgid "Edit this object (new window)"
|
msgid "Edit this object (new window)"
|
||||||
@ -1129,22 +1122,18 @@ msgid "codename"
|
|||||||
msgstr "код"
|
msgstr "код"
|
||||||
|
|
||||||
#: contrib/auth/models.py:17
|
#: contrib/auth/models.py:17
|
||||||
#, fuzzy
|
|
||||||
msgid "permission"
|
msgid "permission"
|
||||||
msgstr "Права"
|
msgstr "Права"
|
||||||
|
|
||||||
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
||||||
#, fuzzy
|
|
||||||
msgid "permissions"
|
msgid "permissions"
|
||||||
msgstr "Права"
|
msgstr "Права"
|
||||||
|
|
||||||
#: contrib/auth/models.py:29
|
#: contrib/auth/models.py:29
|
||||||
#, fuzzy
|
|
||||||
msgid "group"
|
msgid "group"
|
||||||
msgstr "Группа"
|
msgstr "Группа"
|
||||||
|
|
||||||
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
||||||
#, fuzzy
|
|
||||||
msgid "groups"
|
msgid "groups"
|
||||||
msgstr "Группы"
|
msgstr "Группы"
|
||||||
|
|
||||||
@ -1205,17 +1194,14 @@ msgstr ""
|
|||||||
"все права группы, к которой он принадлежит."
|
"все права группы, к которой он принадлежит."
|
||||||
|
|
||||||
#: contrib/auth/models.py:67
|
#: contrib/auth/models.py:67
|
||||||
#, fuzzy
|
|
||||||
msgid "user permissions"
|
msgid "user permissions"
|
||||||
msgstr "Права"
|
msgstr "Права пользователя"
|
||||||
|
|
||||||
#: contrib/auth/models.py:70
|
#: contrib/auth/models.py:70
|
||||||
#, fuzzy
|
|
||||||
msgid "user"
|
msgid "user"
|
||||||
msgstr "Пользователь"
|
msgstr "Пользователь"
|
||||||
|
|
||||||
#: contrib/auth/models.py:71
|
#: contrib/auth/models.py:71
|
||||||
#, fuzzy
|
|
||||||
msgid "users"
|
msgid "users"
|
||||||
msgstr "Пользователи"
|
msgstr "Пользователи"
|
||||||
|
|
||||||
@ -1236,7 +1222,6 @@ msgid "Groups"
|
|||||||
msgstr "Группы"
|
msgstr "Группы"
|
||||||
|
|
||||||
#: contrib/auth/models.py:219
|
#: contrib/auth/models.py:219
|
||||||
#, fuzzy
|
|
||||||
msgid "message"
|
msgid "message"
|
||||||
msgstr "Сообщение"
|
msgstr "Сообщение"
|
||||||
|
|
||||||
@ -1247,9 +1232,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:25
|
#: contrib/contenttypes/models.py:25
|
||||||
#, fuzzy
|
|
||||||
msgid "python model class name"
|
msgid "python model class name"
|
||||||
msgstr "имя python модуля"
|
msgstr "имя класса python модуля"
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:28
|
#: contrib/contenttypes/models.py:28
|
||||||
msgid "content type"
|
msgid "content type"
|
||||||
@ -1384,54 +1368,52 @@ msgid "December"
|
|||||||
msgstr "Декабрь"
|
msgstr "Декабрь"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
#, fuzzy
|
|
||||||
msgid "jan"
|
msgid "jan"
|
||||||
msgstr "и"
|
msgstr "янв"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "feb"
|
msgid "feb"
|
||||||
msgstr ""
|
msgstr "фев"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "mar"
|
msgid "mar"
|
||||||
msgstr ""
|
msgstr "мар"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "apr"
|
msgid "apr"
|
||||||
msgstr ""
|
msgstr "апр"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
#, fuzzy
|
|
||||||
msgid "may"
|
msgid "may"
|
||||||
msgstr "Май"
|
msgstr "май"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "jun"
|
msgid "jun"
|
||||||
msgstr ""
|
msgstr "июнь"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "jul"
|
msgid "jul"
|
||||||
msgstr ""
|
msgstr "июль"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "aug"
|
msgid "aug"
|
||||||
msgstr ""
|
msgstr "авг"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "sep"
|
msgid "sep"
|
||||||
msgstr ""
|
msgstr "сен"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "oct"
|
msgid "oct"
|
||||||
msgstr ""
|
msgstr "окт"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "nov"
|
msgid "nov"
|
||||||
msgstr ""
|
msgstr "нояб"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "dec"
|
msgid "dec"
|
||||||
msgstr ""
|
msgstr "дек"
|
||||||
|
|
||||||
#: utils/dates.py:27
|
#: utils/dates.py:27
|
||||||
msgid "Jan."
|
msgid "Jan."
|
||||||
@ -1476,8 +1458,8 @@ msgstr[1] "месяцев"
|
|||||||
#: utils/timesince.py:14
|
#: utils/timesince.py:14
|
||||||
msgid "week"
|
msgid "week"
|
||||||
msgid_plural "weeks"
|
msgid_plural "weeks"
|
||||||
msgstr[0] ""
|
msgstr[0] "неделя"
|
||||||
msgstr[1] ""
|
msgstr[1] "недель"
|
||||||
|
|
||||||
#: utils/timesince.py:15
|
#: utils/timesince.py:15
|
||||||
msgid "day"
|
msgid "day"
|
||||||
@ -1610,11 +1592,11 @@ msgid "This value must contain only letters, numbers and underscores."
|
|||||||
msgstr "Значение может содержать только буквы, цифры и подчеркивания."
|
msgstr "Значение может содержать только буквы, цифры и подчеркивания."
|
||||||
|
|
||||||
#: core/validators.py:64
|
#: core/validators.py:64
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"This value must contain only letters, numbers, underscores, dashes or "
|
"This value must contain only letters, numbers, underscores, dashes or "
|
||||||
"slashes."
|
"slashes."
|
||||||
msgstr "Значение может содержать только буквы, цифры и подчеркивания."
|
msgstr "Значение может содержать только буквы, цифры, подчеркивания, дифисы или "
|
||||||
|
"тере."
|
||||||
|
|
||||||
#: core/validators.py:72
|
#: core/validators.py:72
|
||||||
msgid "Uppercase letters are not allowed here."
|
msgid "Uppercase letters are not allowed here."
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,7 @@ import datetime
|
|||||||
|
|
||||||
class FilterSpec(object):
|
class FilterSpec(object):
|
||||||
filter_specs = []
|
filter_specs = []
|
||||||
def __init__(self, f, request, params):
|
def __init__(self, f, request, params, model):
|
||||||
self.field = f
|
self.field = f
|
||||||
self.params = params
|
self.params = params
|
||||||
|
|
||||||
@ -19,10 +19,10 @@ class FilterSpec(object):
|
|||||||
cls.filter_specs.append((test, factory))
|
cls.filter_specs.append((test, factory))
|
||||||
register = classmethod(register)
|
register = classmethod(register)
|
||||||
|
|
||||||
def create(cls, f, request, params):
|
def create(cls, f, request, params, model):
|
||||||
for test, factory in cls.filter_specs:
|
for test, factory in cls.filter_specs:
|
||||||
if test(f):
|
if test(f):
|
||||||
return factory(f, request, params)
|
return factory(f, request, params, model)
|
||||||
create = classmethod(create)
|
create = classmethod(create)
|
||||||
|
|
||||||
def has_output(self):
|
def has_output(self):
|
||||||
@ -48,8 +48,8 @@ class FilterSpec(object):
|
|||||||
return "".join(t)
|
return "".join(t)
|
||||||
|
|
||||||
class RelatedFilterSpec(FilterSpec):
|
class RelatedFilterSpec(FilterSpec):
|
||||||
def __init__(self, f, request, params):
|
def __init__(self, f, request, params, model):
|
||||||
super(RelatedFilterSpec, self).__init__(f, request, params)
|
super(RelatedFilterSpec, self).__init__(f, request, params, model)
|
||||||
if isinstance(f, models.ManyToManyField):
|
if isinstance(f, models.ManyToManyField):
|
||||||
self.lookup_title = f.rel.to._meta.verbose_name
|
self.lookup_title = f.rel.to._meta.verbose_name
|
||||||
else:
|
else:
|
||||||
@ -77,8 +77,8 @@ class RelatedFilterSpec(FilterSpec):
|
|||||||
FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)
|
FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)
|
||||||
|
|
||||||
class ChoicesFilterSpec(FilterSpec):
|
class ChoicesFilterSpec(FilterSpec):
|
||||||
def __init__(self, f, request, params):
|
def __init__(self, f, request, params, model):
|
||||||
super(ChoicesFilterSpec, self).__init__(f, request, params)
|
super(ChoicesFilterSpec, self).__init__(f, request, params, model)
|
||||||
self.lookup_kwarg = '%s__exact' % f.name
|
self.lookup_kwarg = '%s__exact' % f.name
|
||||||
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
|
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
|
||||||
|
|
||||||
@ -94,8 +94,8 @@ class ChoicesFilterSpec(FilterSpec):
|
|||||||
FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec)
|
FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec)
|
||||||
|
|
||||||
class DateFieldFilterSpec(FilterSpec):
|
class DateFieldFilterSpec(FilterSpec):
|
||||||
def __init__(self, f, request, params):
|
def __init__(self, f, request, params, model):
|
||||||
super(DateFieldFilterSpec, self).__init__(f, request, params)
|
super(DateFieldFilterSpec, self).__init__(f, request, params, model)
|
||||||
|
|
||||||
self.field_generic = '%s__' % self.field.name
|
self.field_generic = '%s__' % self.field.name
|
||||||
|
|
||||||
@ -129,8 +129,8 @@ class DateFieldFilterSpec(FilterSpec):
|
|||||||
FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)
|
FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)
|
||||||
|
|
||||||
class BooleanFieldFilterSpec(FilterSpec):
|
class BooleanFieldFilterSpec(FilterSpec):
|
||||||
def __init__(self, f, request, params):
|
def __init__(self, f, request, params, model):
|
||||||
super(BooleanFieldFilterSpec, self).__init__(f, request, params)
|
super(BooleanFieldFilterSpec, self).__init__(f, request, params, model)
|
||||||
self.lookup_kwarg = '%s__exact' % f.name
|
self.lookup_kwarg = '%s__exact' % f.name
|
||||||
self.lookup_kwarg2 = '%s__isnull' % f.name
|
self.lookup_kwarg2 = '%s__isnull' % f.name
|
||||||
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
|
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
|
||||||
@ -150,3 +150,26 @@ class BooleanFieldFilterSpec(FilterSpec):
|
|||||||
'display': _('Unknown')}
|
'display': _('Unknown')}
|
||||||
|
|
||||||
FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec)
|
FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec)
|
||||||
|
|
||||||
|
# This should be registered last, because it's a last resort. For example,
|
||||||
|
# if a field is eligible to use the BooleanFieldFilterSpec, that'd be much
|
||||||
|
# more appropriate, and the AllValuesFilterSpec won't get used for it.
|
||||||
|
class AllValuesFilterSpec(FilterSpec):
|
||||||
|
def __init__(self, f, request, params, model):
|
||||||
|
super(AllValuesFilterSpec, self).__init__(f, request, params, model)
|
||||||
|
self.lookup_val = request.GET.get(f.name, None)
|
||||||
|
self.lookup_choices = model._meta.admin.manager.distinct().order_by(f.name).values(f.name)
|
||||||
|
|
||||||
|
def title(self):
|
||||||
|
return self.field.verbose_name
|
||||||
|
|
||||||
|
def choices(self, cl):
|
||||||
|
yield {'selected': self.lookup_val is None,
|
||||||
|
'query_string': cl.get_query_string({}, [self.field.name]),
|
||||||
|
'display': _('All')}
|
||||||
|
for val in self.lookup_choices:
|
||||||
|
val = str(val[self.field.name])
|
||||||
|
yield {'selected': self.lookup_val == val,
|
||||||
|
'query_string': cl.get_query_string({self.field.name: val}),
|
||||||
|
'display': val}
|
||||||
|
FilterSpec.register(lambda f: True, AllValuesFilterSpec)
|
||||||
|
46
django/contrib/admin/media/css/rtl.css
Normal file
46
django/contrib/admin/media/css/rtl.css
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
body { direction: rtl; }
|
||||||
|
|
||||||
|
/* login styles */
|
||||||
|
|
||||||
|
.login .form-row { float:right; }
|
||||||
|
.login .form-row label { float:right; padding-left:0.5em; padding-right:0; text-align:left;}
|
||||||
|
.login .submit-row { clear:both; padding:1em 9.4em 0 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/* global styles */
|
||||||
|
th { text-align: right; }
|
||||||
|
.module h2, .module caption { text-align: right; }
|
||||||
|
.addlink, .changelink { padding-left:0px; padding-right:12px; background-position:100% 0.2em; }
|
||||||
|
.deletelink { padding-left:0px; padding-right:12px; background-position:100% 0.25em; }
|
||||||
|
.object-tools { float:left; }
|
||||||
|
|
||||||
|
|
||||||
|
/* layout styles */
|
||||||
|
#user-tools { right:auto; left:0; text-align:left; }
|
||||||
|
div.breadcrumbs { text-align:right; }
|
||||||
|
#content-main { float:right;}
|
||||||
|
#content-related { float:left; margin-left:-19em; margin-right:auto;}
|
||||||
|
.colMS { margin-left:20em !important; margin-right:10px !important;}
|
||||||
|
|
||||||
|
/* dashboard styles */
|
||||||
|
.dashboard .module table td a { padding-left:.6em; padding-right:12px; }
|
||||||
|
|
||||||
|
/* changelists styles */
|
||||||
|
.change-list .filtered { background:white url(../img/admin/changelist-bg_rtl.gif) top left repeat-y !important; }
|
||||||
|
.change-list .filtered table { border-left:1px solid #ddd; border-right:0px none; }
|
||||||
|
#changelist-filter { right:auto; left:0; border-left:0px none; border-right:1px solid #ddd;}
|
||||||
|
.change-list .filtered table, .change-list .filtered .paginator, .filtered #toolbar, .filtered div.xfull { margin-right:0px !important; margin-left:160px !important; }
|
||||||
|
#changelist-filter li.selected { border-left:0px none; padding-left:0px; margin-left:0; border-right:5px solid #ccc; padding-right:5px;margin-right:-10px; }
|
||||||
|
|
||||||
|
/* fomrs styles */
|
||||||
|
.aligned label { padding:0 0 3px 1em; float:right; }
|
||||||
|
.submit-row { text-align: left }
|
||||||
|
.vDateField, .vTimeField { margin-left:2px; }
|
||||||
|
|
||||||
|
/* widget styles */
|
||||||
|
.calendarnav-previous { top:0; left:auto; right:0; }
|
||||||
|
.calendarnav-next { top:0; right:auto; left:0;}
|
||||||
|
.calendar caption, .calendarbox h2 { text-align:center; }
|
||||||
|
|
||||||
|
.selector { float: right;}
|
||||||
|
.selector .selector-filter { text-align: right;}
|
@ -31,7 +31,7 @@ var CollapsedFieldsets = {
|
|||||||
collapse_link.id = 'fieldsetcollapser' + i;
|
collapse_link.id = 'fieldsetcollapser' + i;
|
||||||
collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
|
collapse_link.onclick = new Function('CollapsedFieldsets.show('+i+'); return false;');
|
||||||
collapse_link.href = '#';
|
collapse_link.href = '#';
|
||||||
collapse_link.innerHTML = 'Show';
|
collapse_link.innerHTML = gettext('Show');
|
||||||
var h2 = fs.getElementsByTagName('h2')[0];
|
var h2 = fs.getElementsByTagName('h2')[0];
|
||||||
h2.appendChild(document.createTextNode(' ('));
|
h2.appendChild(document.createTextNode(' ('));
|
||||||
h2.appendChild(collapse_link);
|
h2.appendChild(collapse_link);
|
||||||
@ -60,7 +60,7 @@ var CollapsedFieldsets = {
|
|||||||
// Toggle the "Show" link to a "Hide" link
|
// Toggle the "Show" link to a "Hide" link
|
||||||
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
||||||
collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
|
collapse_link.onclick = new Function('CollapsedFieldsets.hide('+fieldset_index+'); return false;');
|
||||||
collapse_link.innerHTML = 'Hide';
|
collapse_link.innerHTML = gettext('Hide');
|
||||||
},
|
},
|
||||||
hide: function(fieldset_index) {
|
hide: function(fieldset_index) {
|
||||||
var fs = document.getElementsByTagName('fieldset')[fieldset_index];
|
var fs = document.getElementsByTagName('fieldset')[fieldset_index];
|
||||||
@ -69,7 +69,7 @@ var CollapsedFieldsets = {
|
|||||||
// Toggle the "Hide" link to a "Show" link
|
// Toggle the "Hide" link to a "Show" link
|
||||||
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
var collapse_link = document.getElementById('fieldsetcollapser' + fieldset_index);
|
||||||
collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
|
collapse_link.onclick = new Function('CollapsedFieldsets.show('+fieldset_index+'); return false;');
|
||||||
collapse_link.innerHTML = 'Show';
|
collapse_link.innerHTML = gettext('Show');
|
||||||
},
|
},
|
||||||
|
|
||||||
uncollapse_all: function() {
|
uncollapse_all: function() {
|
||||||
|
@ -69,7 +69,16 @@ var DateTimeShortcuts = {
|
|||||||
var clock_box = document.createElement('div');
|
var clock_box = document.createElement('div');
|
||||||
clock_box.style.display = 'none';
|
clock_box.style.display = 'none';
|
||||||
clock_box.style.position = 'absolute';
|
clock_box.style.position = 'absolute';
|
||||||
|
if (getStyle(document.body,'direction')!='rtl') {
|
||||||
clock_box.style.left = findPosX(clock_link) + 17 + 'px';
|
clock_box.style.left = findPosX(clock_link) + 17 + 'px';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// since style's width is in em, it'd be tough to calculate
|
||||||
|
// px value of it. let's use an estimated px for now
|
||||||
|
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||||
|
// (it returns as it was left aligned), needs to be fixed.
|
||||||
|
clock_box.style.left = findPosX(clock_link) - 110 + 'px';
|
||||||
|
}
|
||||||
clock_box.style.top = findPosY(clock_link) - 30 + 'px';
|
clock_box.style.top = findPosY(clock_link) - 30 + 'px';
|
||||||
clock_box.className = 'clockbox module';
|
clock_box.className = 'clockbox module';
|
||||||
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
|
clock_box.setAttribute('id', DateTimeShortcuts.clockDivName + num);
|
||||||
@ -140,7 +149,17 @@ var DateTimeShortcuts = {
|
|||||||
var cal_box = document.createElement('div');
|
var cal_box = document.createElement('div');
|
||||||
cal_box.style.display = 'none';
|
cal_box.style.display = 'none';
|
||||||
cal_box.style.position = 'absolute';
|
cal_box.style.position = 'absolute';
|
||||||
|
// is it left-to-right or right-to-left layout ?
|
||||||
|
if (getStyle(document.body,'direction')!='rtl') {
|
||||||
cal_box.style.left = findPosX(cal_link) + 17 + 'px';
|
cal_box.style.left = findPosX(cal_link) + 17 + 'px';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// since style's width is in em, it'd be tough to calculate
|
||||||
|
// px value of it. let's use an estimated px for now
|
||||||
|
// TODO: IE returns wrong value for findPosX when in rtl mode
|
||||||
|
// (it returns as it was left aligned), needs to be fixed.
|
||||||
|
cal_box.style.left = findPosX(cal_link) - 180 + 'px';
|
||||||
|
}
|
||||||
cal_box.style.top = findPosY(cal_link) - 75 + 'px';
|
cal_box.style.top = findPosY(cal_link) - 75 + 'px';
|
||||||
cal_box.className = 'calendarbox module';
|
cal_box.className = 'calendarbox module';
|
||||||
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
|
cal_box.setAttribute('id', DateTimeShortcuts.calendarDivName1 + num);
|
||||||
|
@ -136,3 +136,20 @@ String.prototype.pad_left = function(pad_length, pad_string) {
|
|||||||
}
|
}
|
||||||
return new_string;
|
return new_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Get the computed style for and element
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
function getStyle(oElm, strCssRule){
|
||||||
|
var strValue = "";
|
||||||
|
if(document.defaultView && document.defaultView.getComputedStyle){
|
||||||
|
strValue = document.defaultView.getComputedStyle(oElm, "").getPropertyValue(strCssRule);
|
||||||
|
}
|
||||||
|
else if(oElm.currentStyle){
|
||||||
|
strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
|
||||||
|
return p1.toUpperCase();
|
||||||
|
});
|
||||||
|
strValue = oElm.currentStyle[strCssRule];
|
||||||
|
}
|
||||||
|
return strValue;
|
||||||
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE }}" xml:lang="{{ LANGUAGE_CODE }}">
|
<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE }}" xml:lang="{{ LANGUAGE_CODE }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
|
||||||
<head>
|
<head>
|
||||||
<title>{% block title %}{% endblock %}</title>
|
<title>{% block title %}{% endblock %}</title>
|
||||||
<link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% load adminmedia %}{% admin_media_prefix %}css/base.css{% endblock %}" />
|
<link rel="stylesheet" type="text/css" href="{% block stylesheet %}{% load adminmedia %}{% admin_media_prefix %}css/base.css{% endblock %}" />
|
||||||
|
{% if LANGUAGE_BIDI %}<link rel="stylesheet" type="text/css" href="{% block stylesheet_rtl %}{% admin_media_prefix %}css/rtl.css{% endblock %}" />{% endif %}
|
||||||
{% block extrastyle %}{% endblock %}
|
{% block extrastyle %}{% endblock %}
|
||||||
{% block extrahead %}{% endblock %}
|
{% block extrahead %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
@ -20,7 +21,7 @@
|
|||||||
{% block branding %}{% endblock %}
|
{% block branding %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
{% if not user.is_anonymous %}{% if user.is_staff %}
|
{% if not user.is_anonymous %}{% if user.is_staff %}
|
||||||
<div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div>
|
<div id="user-tools">{% trans 'Welcome,' %} <strong>{% if user.first_name %}{{ user.first_name|escape }}{% else %}{{ user.username }}{% endif %}</strong>. {% block userlinks %}<a href="doc/">{% trans 'Documentation' %}</a> / <a href="password_change/">{% trans 'Change password' %}</a> / <a href="logout/">{% trans 'Log out' %}</a>{% endblock %}</div>
|
||||||
{% endif %}{% endif %}
|
{% endif %}{% endif %}
|
||||||
{% block nav-global %}{% endblock %}
|
{% block nav-global %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
{% load admin_list %}
|
{% load admin_list %}
|
||||||
|
{% load i18n %}
|
||||||
{% if cl.has_filters %}<div id="changelist-filter">
|
{% if cl.has_filters %}<div id="changelist-filter">
|
||||||
<h2>Filter</h2>
|
<h2>{% trans 'Filter' %}</h2>
|
||||||
{% for spec in cl.filter_specs %}
|
{% for spec in cl.filter_specs %}
|
||||||
{% filter cl spec %}
|
{% filter cl spec %}
|
||||||
{% endfor %}</div>{% endif %}
|
{% endfor %}</div>{% endif %}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{% load admin_list %}
|
{% load admin_list %}
|
||||||
|
{% load i18n %}
|
||||||
<p class="paginator">
|
<p class="paginator">
|
||||||
{% if pagination_required %}
|
{% if pagination_required %}
|
||||||
{% for i in page_range %}
|
{% for i in page_range %}
|
||||||
@ -6,5 +7,5 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %}
|
{{ cl.result_count }} {% ifequal cl.result_count 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endifequal %}
|
||||||
{% if show_all_url %} <a href="{{ show_all_url }}" class="showall">Show all</a>{% endif %}
|
{% if show_all_url %} <a href="{{ show_all_url }}" class="showall">{% trans 'Show all' %}</a>{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query|escape }}" id="searchbar" />
|
<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query|escape }}" id="searchbar" />
|
||||||
<input type="submit" value="{% trans 'Go' %}" />
|
<input type="submit" value="{% trans 'Go' %}" />
|
||||||
{% if show_result_count %}
|
{% if show_result_count %}
|
||||||
<span class="small quiet">{{ cl.result_count }} result{{ cl.result_count|pluralize }} (<a href="?">{{ cl.full_result_count }} total</a>)</span>
|
<span class="small quiet">{% blocktrans count cl.result_count as counter %}1 result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?">{% blocktrans with cl.full_result_count as full_result_count %}{{ full_result_count }} total{% endblocktrans %}</a>)</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for pair in cl.params.items %}
|
{% for pair in cl.params.items %}
|
||||||
{% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0|escape }}" value="{{ pair.1|escape }}"/>{% endifnotequal %}
|
{% ifnotequal pair.0 search_var %}<input type="hidden" name="{{ pair.0|escape }}" value="{{ pair.1|escape }}"/>{% endifnotequal %}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% trans "You're receiving this e-mail because you requested a password reset" %}
|
{% trans "You're receiving this e-mail because you requested a password reset" %}
|
||||||
{% trans "for your user account at %(site_name)s" %}.
|
{% blocktrans %}for your user account at {{ site_name }}{% endblocktrans %}.
|
||||||
|
|
||||||
{% blocktrans %}Your new password is: {{ new_password }}{% endblocktrans %}
|
{% blocktrans %}Your new password is: {{ new_password }}{% endblocktrans %}
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ def items_for_result(cl, result):
|
|||||||
|
|
||||||
if isinstance(f.rel, models.ManyToOneRel):
|
if isinstance(f.rel, models.ManyToOneRel):
|
||||||
if field_val is not None:
|
if field_val is not None:
|
||||||
result_repr = getattr(result, f.name)
|
result_repr = escape(getattr(result, f.name))
|
||||||
else:
|
else:
|
||||||
result_repr = EMPTY_CHANGELIST_VALUE
|
result_repr = EMPTY_CHANGELIST_VALUE
|
||||||
# Dates and times are special: They're formatted in a certain way.
|
# Dates and times are special: They're formatted in a certain way.
|
||||||
|
@ -18,6 +18,19 @@ def class_name_to_underscored(name):
|
|||||||
return '_'.join([s.lower() for s in word_re.findall(name)[:-1]])
|
return '_'.join([s.lower() for s in word_re.findall(name)[:-1]])
|
||||||
|
|
||||||
def include_admin_script(script_path):
|
def include_admin_script(script_path):
|
||||||
|
"""
|
||||||
|
Returns an HTML script element for including a script from the admin
|
||||||
|
media url.
|
||||||
|
|
||||||
|
Example usage::
|
||||||
|
|
||||||
|
{% include_admin_script js/calendar.js %}
|
||||||
|
|
||||||
|
could return::
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/media/admin/js/calendar.js">
|
||||||
|
"""
|
||||||
|
|
||||||
return '<script type="text/javascript" src="%s%s"></script>' % (settings.ADMIN_MEDIA_PREFIX, script_path)
|
return '<script type="text/javascript" src="%s%s"></script>' % (settings.ADMIN_MEDIA_PREFIX, script_path)
|
||||||
include_admin_script = register.simple_tag(include_admin_script)
|
include_admin_script = register.simple_tag(include_admin_script)
|
||||||
|
|
||||||
|
@ -574,7 +574,7 @@ class ChangeList(object):
|
|||||||
filter_fields = [self.lookup_opts.get_field(field_name) \
|
filter_fields = [self.lookup_opts.get_field(field_name) \
|
||||||
for field_name in self.lookup_opts.admin.list_filter]
|
for field_name in self.lookup_opts.admin.list_filter]
|
||||||
for f in filter_fields:
|
for f in filter_fields:
|
||||||
spec = FilterSpec.create(f, request, self.params)
|
spec = FilterSpec.create(f, request, self.params, self.model)
|
||||||
if spec and spec.has_output():
|
if spec and spec.has_output():
|
||||||
filter_specs.append(spec)
|
filter_specs.append(spec)
|
||||||
return filter_specs, bool(filter_specs)
|
return filter_specs, bool(filter_specs)
|
||||||
|
@ -23,8 +23,6 @@ def create_permissions(app, created_models):
|
|||||||
if not app_models:
|
if not app_models:
|
||||||
return
|
return
|
||||||
for klass in app_models:
|
for klass in app_models:
|
||||||
if not klass._meta.admin:
|
|
||||||
continue
|
|
||||||
ctype = ContentType.objects.get_for_model(klass)
|
ctype = ContentType.objects.get_for_model(klass)
|
||||||
for codename, name in _get_all_permissions(klass._meta):
|
for codename, name in _get_all_permissions(klass._meta):
|
||||||
try:
|
try:
|
||||||
|
@ -8,7 +8,7 @@ class LazyUser(object):
|
|||||||
self._user = get_user(request)
|
self._user = get_user(request)
|
||||||
return self._user
|
return self._user
|
||||||
|
|
||||||
class AuthenticationMiddleware:
|
class AuthenticationMiddleware(object):
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
|
assert hasattr(request, 'session'), "The Django authentication middleware requires session middleware to be installed. Edit your MIDDLEWARE_CLASSES setting to insert 'django.contrib.sessions.middleware.SessionMiddleware'."
|
||||||
request.__class__.user = LazyUser()
|
request.__class__.user = LazyUser()
|
||||||
|
@ -8,7 +8,7 @@ from django.http import HttpResponse, HttpResponseRedirect
|
|||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
|
from django.contrib.auth import LOGIN_URL, REDIRECT_FIELD_NAME
|
||||||
|
|
||||||
def login(request):
|
def login(request, template_name='registration/login.html'):
|
||||||
"Displays the login form and handles the login action."
|
"Displays the login form and handles the login action."
|
||||||
manipulator = AuthenticationForm(request)
|
manipulator = AuthenticationForm(request)
|
||||||
redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '')
|
redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '')
|
||||||
@ -25,19 +25,19 @@ def login(request):
|
|||||||
else:
|
else:
|
||||||
errors = {}
|
errors = {}
|
||||||
request.session.set_test_cookie()
|
request.session.set_test_cookie()
|
||||||
return render_to_response('registration/login.html', {
|
return render_to_response(template_name, {
|
||||||
'form': forms.FormWrapper(manipulator, request.POST, errors),
|
'form': forms.FormWrapper(manipulator, request.POST, errors),
|
||||||
REDIRECT_FIELD_NAME: redirect_to,
|
REDIRECT_FIELD_NAME: redirect_to,
|
||||||
'site_name': Site.objects.get_current().name,
|
'site_name': Site.objects.get_current().name,
|
||||||
}, context_instance=RequestContext(request))
|
}, context_instance=RequestContext(request))
|
||||||
|
|
||||||
def logout(request, next_page=None):
|
def logout(request, next_page=None, template_name='registration/logged_out.html'):
|
||||||
"Logs out the user and displays 'You are logged out' message."
|
"Logs out the user and displays 'You are logged out' message."
|
||||||
from django.contrib.auth import logout
|
from django.contrib.auth import logout
|
||||||
try:
|
try:
|
||||||
logout(request)
|
logout(request)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return render_to_response('registration/logged_out.html', {'title': 'Logged out'}, context_instance=RequestContext(request))
|
return render_to_response(template_name, {'title': _('Logged out')}, context_instance=RequestContext(request))
|
||||||
else:
|
else:
|
||||||
# Redirect to this page until the session has been cleared.
|
# Redirect to this page until the session has been cleared.
|
||||||
return HttpResponseRedirect(next_page or request.path)
|
return HttpResponseRedirect(next_page or request.path)
|
||||||
@ -50,7 +50,7 @@ def redirect_to_login(next, login_url=LOGIN_URL):
|
|||||||
"Redirects the user to the login page, passing the given 'next' page"
|
"Redirects the user to the login page, passing the given 'next' page"
|
||||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))
|
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))
|
||||||
|
|
||||||
def password_reset(request, is_admin_site=False):
|
def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html'):
|
||||||
new_data, errors = {}, {}
|
new_data, errors = {}, {}
|
||||||
form = PasswordResetForm()
|
form = PasswordResetForm()
|
||||||
if request.POST:
|
if request.POST:
|
||||||
@ -62,13 +62,13 @@ def password_reset(request, is_admin_site=False):
|
|||||||
else:
|
else:
|
||||||
form.save()
|
form.save()
|
||||||
return HttpResponseRedirect('%sdone/' % request.path)
|
return HttpResponseRedirect('%sdone/' % request.path)
|
||||||
return render_to_response('registration/password_reset_form.html', {'form': forms.FormWrapper(form, new_data, errors)},
|
return render_to_response(template_name, {'form': forms.FormWrapper(form, new_data, errors)},
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request))
|
||||||
|
|
||||||
def password_reset_done(request):
|
def password_reset_done(request, template_name='registration/password_reset_done.html'):
|
||||||
return render_to_response('registration/password_reset_done.html', context_instance=RequestContext(request))
|
return render_to_response(template_name, context_instance=RequestContext(request))
|
||||||
|
|
||||||
def password_change(request):
|
def password_change(request, template_name='registration/password_change_form.html'):
|
||||||
new_data, errors = {}, {}
|
new_data, errors = {}, {}
|
||||||
form = PasswordChangeForm(request.user)
|
form = PasswordChangeForm(request.user)
|
||||||
if request.POST:
|
if request.POST:
|
||||||
@ -77,9 +77,9 @@ def password_change(request):
|
|||||||
if not errors:
|
if not errors:
|
||||||
form.save(new_data)
|
form.save(new_data)
|
||||||
return HttpResponseRedirect('%sdone/' % request.path)
|
return HttpResponseRedirect('%sdone/' % request.path)
|
||||||
return render_to_response('registration/password_change_form.html', {'form': forms.FormWrapper(form, new_data, errors)},
|
return render_to_response(template_name, {'form': forms.FormWrapper(form, new_data, errors)},
|
||||||
context_instance=RequestContext(request))
|
context_instance=RequestContext(request))
|
||||||
password_change = login_required(password_change)
|
password_change = login_required(password_change)
|
||||||
|
|
||||||
def password_change_done(request):
|
def password_change_done(request, template_name='registration/password_change_done.html'):
|
||||||
return render_to_response('registration/password_change_done.html', context_instance=RequestContext(request))
|
return render_to_response(template_name, context_instance=RequestContext(request))
|
||||||
|
24
django/contrib/contenttypes/management.py
Normal file
24
django/contrib/contenttypes/management.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"""
|
||||||
|
Creates content types for all installed models.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.dispatch import dispatcher
|
||||||
|
from django.db.models import get_models, signals
|
||||||
|
|
||||||
|
def create_contenttypes(app, created_models):
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
app_models = get_models(app)
|
||||||
|
if not app_models:
|
||||||
|
return
|
||||||
|
for klass in app_models:
|
||||||
|
opts = klass._meta
|
||||||
|
try:
|
||||||
|
ContentType.objects.get(app_label=opts.app_label,
|
||||||
|
model=opts.object_name.lower())
|
||||||
|
except ContentType.DoesNotExist:
|
||||||
|
ct = ContentType(name=str(opts.verbose_name),
|
||||||
|
app_label=opts.app_label, model=opts.object_name.lower())
|
||||||
|
ct.save()
|
||||||
|
print "Adding content type '%s | %s'" % (ct.app_label, ct.model)
|
||||||
|
|
||||||
|
dispatcher.connect(create_contenttypes, signal=signals.post_syncdb)
|
@ -2,7 +2,7 @@ from django.contrib.flatpages.views import flatpage
|
|||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
class FlatpageFallbackMiddleware:
|
class FlatpageFallbackMiddleware(object):
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
if response.status_code != 404:
|
if response.status_code != 404:
|
||||||
return response # No need to check for a flatpage for non-404 responses.
|
return response # No need to check for a flatpage for non-404 responses.
|
||||||
|
@ -2,7 +2,7 @@ from django.contrib.redirects.models import Redirect
|
|||||||
from django import http
|
from django import http
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
class RedirectFallbackMiddleware:
|
class RedirectFallbackMiddleware(object):
|
||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
if response.status_code != 404:
|
if response.status_code != 404:
|
||||||
return response # No need to check for a redirect for non-404 responses.
|
return response # No need to check for a redirect for non-404 responses.
|
||||||
|
@ -8,15 +8,17 @@ class Redirect(models.Model):
|
|||||||
help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'."))
|
help_text=_("This should be an absolute path, excluding the domain name. Example: '/events/search/'."))
|
||||||
new_path = models.CharField(_('redirect to'), maxlength=200, blank=True,
|
new_path = models.CharField(_('redirect to'), maxlength=200, blank=True,
|
||||||
help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'."))
|
help_text=_("This can be either an absolute path (as above) or a full URL starting with 'http://'."))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('redirect')
|
verbose_name = _('redirect')
|
||||||
verbose_name_plural = _('redirects')
|
verbose_name_plural = _('redirects')
|
||||||
db_table = 'django_redirect'
|
db_table = 'django_redirect'
|
||||||
unique_together=(('site', 'old_path'),)
|
unique_together=(('site', 'old_path'),)
|
||||||
ordering = ('old_path',)
|
ordering = ('old_path',)
|
||||||
|
|
||||||
class Admin:
|
class Admin:
|
||||||
list_filter = ('site',)
|
list_filter = ('site',)
|
||||||
search_fields = ('old_path', 'new_path')
|
search_fields = ('old_path', 'new_path')
|
||||||
|
|
||||||
def __repr__(self):
|
def __str__(self):
|
||||||
return "%s ---> %s" % (self.old_path, self.new_path)
|
return "%s ---> %s" % (self.old_path, self.new_path)
|
||||||
|
@ -64,7 +64,7 @@ class SessionWrapper(object):
|
|||||||
|
|
||||||
_session = property(_get_session)
|
_session = property(_get_session)
|
||||||
|
|
||||||
class SessionMiddleware:
|
class SessionMiddleware(object):
|
||||||
def process_request(self, request):
|
def process_request(self, request):
|
||||||
request.session = SessionWrapper(request.COOKIES.get(settings.SESSION_COOKIE_NAME, None))
|
request.session = SessionWrapper(request.COOKIES.get(settings.SESSION_COOKIE_NAME, None))
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ def add_domain(domain, url):
|
|||||||
class FeedDoesNotExist(ObjectDoesNotExist):
|
class FeedDoesNotExist(ObjectDoesNotExist):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Feed:
|
class Feed(object):
|
||||||
item_pubdate = None
|
item_pubdate = None
|
||||||
item_enclosure_url = None
|
item_enclosure_url = None
|
||||||
feed_type = feedgenerator.DefaultFeed
|
feed_type = feedgenerator.DefaultFeed
|
||||||
@ -73,6 +73,7 @@ class Feed:
|
|||||||
author_name = self.__get_dynamic_attr('author_name', obj),
|
author_name = self.__get_dynamic_attr('author_name', obj),
|
||||||
author_link = self.__get_dynamic_attr('author_link', obj),
|
author_link = self.__get_dynamic_attr('author_link', obj),
|
||||||
author_email = self.__get_dynamic_attr('author_email', obj),
|
author_email = self.__get_dynamic_attr('author_email', obj),
|
||||||
|
categories = self.__get_dynamic_attr('categories', obj),
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -110,5 +111,6 @@ class Feed:
|
|||||||
author_name = author_name,
|
author_name = author_name,
|
||||||
author_email = author_email,
|
author_email = author_email,
|
||||||
author_link = author_link,
|
author_link = author_link,
|
||||||
|
categories = self.__get_dynamic_attr('item_categories', item),
|
||||||
)
|
)
|
||||||
return feed
|
return feed
|
||||||
|
2
django/core/cache/backends/base.py
vendored
2
django/core/cache/backends/base.py
vendored
@ -5,7 +5,7 @@ from django.core.exceptions import ImproperlyConfigured
|
|||||||
class InvalidCacheBackendError(ImproperlyConfigured):
|
class InvalidCacheBackendError(ImproperlyConfigured):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class BaseCache:
|
class BaseCache(object):
|
||||||
def __init__(self, params):
|
def __init__(self, params):
|
||||||
timeout = params.get('timeout', 300)
|
timeout = params.get('timeout', 300)
|
||||||
try:
|
try:
|
||||||
|
@ -36,6 +36,10 @@ def i18n(request):
|
|||||||
context_extras['LANGUAGE_CODE'] = request.LANGUAGE_CODE
|
context_extras['LANGUAGE_CODE'] = request.LANGUAGE_CODE
|
||||||
else:
|
else:
|
||||||
context_extras['LANGUAGE_CODE'] = settings.LANGUAGE_CODE
|
context_extras['LANGUAGE_CODE'] = settings.LANGUAGE_CODE
|
||||||
|
|
||||||
|
from django.utils import translation
|
||||||
|
context_extras['LANGUAGE_BIDI'] = translation.get_language_bidi()
|
||||||
|
|
||||||
return context_extras
|
return context_extras
|
||||||
|
|
||||||
def request(request):
|
def request(request):
|
||||||
@ -44,7 +48,7 @@ def request(request):
|
|||||||
# PermWrapper and PermLookupDict proxy the permissions system into objects that
|
# PermWrapper and PermLookupDict proxy the permissions system into objects that
|
||||||
# the template system can understand.
|
# the template system can understand.
|
||||||
|
|
||||||
class PermLookupDict:
|
class PermLookupDict(object):
|
||||||
def __init__(self, user, module_name):
|
def __init__(self, user, module_name):
|
||||||
self.user, self.module_name = user, module_name
|
self.user, self.module_name = user, module_name
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
@ -54,7 +58,7 @@ class PermLookupDict:
|
|||||||
def __nonzero__(self):
|
def __nonzero__(self):
|
||||||
return self.user.has_module_perms(self.module_name)
|
return self.user.has_module_perms(self.module_name)
|
||||||
|
|
||||||
class PermWrapper:
|
class PermWrapper(object):
|
||||||
def __init__(self, user):
|
def __init__(self, user):
|
||||||
self.user = user
|
self.user = user
|
||||||
def __getitem__(self, module_name):
|
def __getitem__(self, module_name):
|
||||||
|
@ -3,7 +3,7 @@ from django.dispatch import dispatcher
|
|||||||
from django import http
|
from django import http
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
class BaseHandler:
|
class BaseHandler(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
|
self._request_middleware = self._view_middleware = self._response_middleware = self._exception_middleware = None
|
||||||
|
|
||||||
|
@ -211,11 +211,14 @@ def _get_sql_for_pending_references(klass, pending_references):
|
|||||||
|
|
||||||
def _get_many_to_many_sql_for_model(klass):
|
def _get_many_to_many_sql_for_model(klass):
|
||||||
from django.db import backend, get_creation_module
|
from django.db import backend, get_creation_module
|
||||||
|
from django.db.models import GenericRel
|
||||||
|
|
||||||
data_types = get_creation_module().DATA_TYPES
|
data_types = get_creation_module().DATA_TYPES
|
||||||
|
|
||||||
opts = klass._meta
|
opts = klass._meta
|
||||||
final_output = []
|
final_output = []
|
||||||
for f in opts.many_to_many:
|
for f in opts.many_to_many:
|
||||||
|
if not isinstance(f.rel, GenericRel):
|
||||||
table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \
|
table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \
|
||||||
style.SQL_TABLE(backend.quote_name(f.m2m_db_table())) + ' (']
|
style.SQL_TABLE(backend.quote_name(f.m2m_db_table())) + ' (']
|
||||||
table_output.append(' %s %s %s,' % \
|
table_output.append(' %s %s %s,' % \
|
||||||
@ -815,10 +818,8 @@ def get_validation_errors(outfile, app=None):
|
|||||||
|
|
||||||
# Do field-specific validation.
|
# Do field-specific validation.
|
||||||
for f in opts.fields:
|
for f in opts.fields:
|
||||||
# Check for deprecated args
|
if f.name == 'id' and not f.primary_key and opts.pk.name == 'id':
|
||||||
dep_args = getattr(f, 'deprecated_args', None)
|
e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name)
|
||||||
if dep_args:
|
|
||||||
e.add(opts, "'%s' Initialized with deprecated args:%s" % (f.name, ",".join(dep_args)))
|
|
||||||
if isinstance(f, models.CharField) and f.maxlength in (None, 0):
|
if isinstance(f, models.CharField) and f.maxlength in (None, 0):
|
||||||
e.add(opts, '"%s": CharFields require a "maxlength" attribute.' % f.name)
|
e.add(opts, '"%s": CharFields require a "maxlength" attribute.' % f.name)
|
||||||
if isinstance(f, models.FloatField):
|
if isinstance(f, models.FloatField):
|
||||||
@ -836,8 +837,8 @@ def get_validation_errors(outfile, app=None):
|
|||||||
if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple):
|
if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple):
|
||||||
e.add(opts, '"%s": prepopulate_from should be a list or tuple.' % f.name)
|
e.add(opts, '"%s": prepopulate_from should be a list or tuple.' % f.name)
|
||||||
if f.choices:
|
if f.choices:
|
||||||
if not type(f.choices) in (tuple, list):
|
if not hasattr(f.choices, '__iter__'):
|
||||||
e.add(opts, '"%s": "choices" should be either a tuple or list.' % f.name)
|
e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name)
|
||||||
else:
|
else:
|
||||||
for c in f.choices:
|
for c in f.choices:
|
||||||
if not type(c) in (tuple, list) or len(c) != 2:
|
if not type(c) in (tuple, list) or len(c) != 2:
|
||||||
@ -923,6 +924,7 @@ def get_validation_errors(outfile, app=None):
|
|||||||
field_name = field_name[1:]
|
field_name = field_name[1:]
|
||||||
if opts.order_with_respect_to and field_name == '_order':
|
if opts.order_with_respect_to and field_name == '_order':
|
||||||
continue
|
continue
|
||||||
|
if '.' in field_name: continue # Skip ordering in the format 'table.field'.
|
||||||
try:
|
try:
|
||||||
opts.get_field(field_name, many_to_many=False)
|
opts.get_field(field_name, many_to_many=False)
|
||||||
except models.FieldDoesNotExist:
|
except models.FieldDoesNotExist:
|
||||||
|
@ -4,7 +4,7 @@ from math import ceil
|
|||||||
class InvalidPage(Exception):
|
class InvalidPage(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class ObjectPaginator:
|
class ObjectPaginator(object):
|
||||||
"""
|
"""
|
||||||
This class makes pagination easy. Feed it a QuerySet, plus the number of
|
This class makes pagination easy. Feed it a QuerySet, plus the number of
|
||||||
objects you want on each page. Then read the hits and pages properties to
|
objects you want on each page. Then read the hits and pages properties to
|
||||||
|
@ -21,7 +21,7 @@ software_version = server_version + ' ' + sys_version
|
|||||||
class WSGIServerException(Exception):
|
class WSGIServerException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class FileWrapper:
|
class FileWrapper(object):
|
||||||
"""Wrapper to convert file-like objects to iterables"""
|
"""Wrapper to convert file-like objects to iterables"""
|
||||||
|
|
||||||
def __init__(self, filelike, blksize=8192):
|
def __init__(self, filelike, blksize=8192):
|
||||||
@ -63,7 +63,7 @@ def _formatparam(param, value=None, quote=1):
|
|||||||
else:
|
else:
|
||||||
return param
|
return param
|
||||||
|
|
||||||
class Headers:
|
class Headers(object):
|
||||||
"""Manage a collection of HTTP response headers"""
|
"""Manage a collection of HTTP response headers"""
|
||||||
def __init__(self,headers):
|
def __init__(self,headers):
|
||||||
if type(headers) is not ListType:
|
if type(headers) is not ListType:
|
||||||
@ -218,7 +218,7 @@ def is_hop_by_hop(header_name):
|
|||||||
"""Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header"""
|
"""Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header"""
|
||||||
return _hoppish(header_name.lower())
|
return _hoppish(header_name.lower())
|
||||||
|
|
||||||
class ServerHandler:
|
class ServerHandler(object):
|
||||||
"""Manage the invocation of a WSGI application"""
|
"""Manage the invocation of a WSGI application"""
|
||||||
|
|
||||||
# Configuration parameters; can override per-subclass or per-instance
|
# Configuration parameters; can override per-subclass or per-instance
|
||||||
@ -591,7 +591,7 @@ class WSGIRequestHandler(BaseHTTPRequestHandler):
|
|||||||
return
|
return
|
||||||
sys.stderr.write("[%s] %s\n" % (self.log_date_time_string(), format % args))
|
sys.stderr.write("[%s] %s\n" % (self.log_date_time_string(), format % args))
|
||||||
|
|
||||||
class AdminMediaHandler:
|
class AdminMediaHandler(object):
|
||||||
"""
|
"""
|
||||||
WSGI middleware that intercepts calls to the admin media directory, as
|
WSGI middleware that intercepts calls to the admin media directory, as
|
||||||
defined by the ADMIN_MEDIA_PREFIX setting, and serves those images.
|
defined by the ADMIN_MEDIA_PREFIX setting, and serves those images.
|
||||||
|
@ -83,7 +83,7 @@ class MatchChecker(object):
|
|||||||
raise NoReverseMatch("Value %r didn't match regular expression %r" % (value, test_regex))
|
raise NoReverseMatch("Value %r didn't match regular expression %r" % (value, test_regex))
|
||||||
return str(value) # TODO: Unicode?
|
return str(value) # TODO: Unicode?
|
||||||
|
|
||||||
class RegexURLPattern:
|
class RegexURLPattern(object):
|
||||||
def __init__(self, regex, callback, default_args=None):
|
def __init__(self, regex, callback, default_args=None):
|
||||||
# regex is a string representing a regular expression.
|
# regex is a string representing a regular expression.
|
||||||
# callback is something like 'foo.views.news.stories.story_detail',
|
# callback is something like 'foo.views.news.stories.story_detail',
|
||||||
|
@ -237,7 +237,7 @@ def hasNoProfanities(field_data, all_data):
|
|||||||
"Watch your mouth! The words %s are not allowed here.", plural) % \
|
"Watch your mouth! The words %s are not allowed here.", plural) % \
|
||||||
get_text_list(['"%s%s%s"' % (i[0], '-'*(len(i)-2), i[-1]) for i in words_seen], 'and')
|
get_text_list(['"%s%s%s"' % (i[0], '-'*(len(i)-2), i[-1]) for i in words_seen], 'and')
|
||||||
|
|
||||||
class AlwaysMatchesOtherField:
|
class AlwaysMatchesOtherField(object):
|
||||||
def __init__(self, other_field_name, error_message=None):
|
def __init__(self, other_field_name, error_message=None):
|
||||||
self.other = other_field_name
|
self.other = other_field_name
|
||||||
self.error_message = error_message or lazy_inter(gettext_lazy("This field must match the '%s' field."), self.other)
|
self.error_message = error_message or lazy_inter(gettext_lazy("This field must match the '%s' field."), self.other)
|
||||||
@ -247,7 +247,7 @@ class AlwaysMatchesOtherField:
|
|||||||
if field_data != all_data[self.other]:
|
if field_data != all_data[self.other]:
|
||||||
raise ValidationError, self.error_message
|
raise ValidationError, self.error_message
|
||||||
|
|
||||||
class ValidateIfOtherFieldEquals:
|
class ValidateIfOtherFieldEquals(object):
|
||||||
def __init__(self, other_field, other_value, validator_list):
|
def __init__(self, other_field, other_value, validator_list):
|
||||||
self.other_field, self.other_value = other_field, other_value
|
self.other_field, self.other_value = other_field, other_value
|
||||||
self.validator_list = validator_list
|
self.validator_list = validator_list
|
||||||
@ -258,7 +258,7 @@ class ValidateIfOtherFieldEquals:
|
|||||||
for v in self.validator_list:
|
for v in self.validator_list:
|
||||||
v(field_data, all_data)
|
v(field_data, all_data)
|
||||||
|
|
||||||
class RequiredIfOtherFieldNotGiven:
|
class RequiredIfOtherFieldNotGiven(object):
|
||||||
def __init__(self, other_field_name, error_message=gettext_lazy("Please enter something for at least one field.")):
|
def __init__(self, other_field_name, error_message=gettext_lazy("Please enter something for at least one field.")):
|
||||||
self.other, self.error_message = other_field_name, error_message
|
self.other, self.error_message = other_field_name, error_message
|
||||||
self.always_test = True
|
self.always_test = True
|
||||||
@ -267,7 +267,7 @@ class RequiredIfOtherFieldNotGiven:
|
|||||||
if not all_data.get(self.other, False) and not field_data:
|
if not all_data.get(self.other, False) and not field_data:
|
||||||
raise ValidationError, self.error_message
|
raise ValidationError, self.error_message
|
||||||
|
|
||||||
class RequiredIfOtherFieldsGiven:
|
class RequiredIfOtherFieldsGiven(object):
|
||||||
def __init__(self, other_field_names, error_message=gettext_lazy("Please enter both fields or leave them both empty.")):
|
def __init__(self, other_field_names, error_message=gettext_lazy("Please enter both fields or leave them both empty.")):
|
||||||
self.other, self.error_message = other_field_names, error_message
|
self.other, self.error_message = other_field_names, error_message
|
||||||
self.always_test = True
|
self.always_test = True
|
||||||
@ -282,7 +282,7 @@ class RequiredIfOtherFieldGiven(RequiredIfOtherFieldsGiven):
|
|||||||
def __init__(self, other_field_name, error_message=gettext_lazy("Please enter both fields or leave them both empty.")):
|
def __init__(self, other_field_name, error_message=gettext_lazy("Please enter both fields or leave them both empty.")):
|
||||||
RequiredIfOtherFieldsGiven.__init__(self, [other_field_name], error_message)
|
RequiredIfOtherFieldsGiven.__init__(self, [other_field_name], error_message)
|
||||||
|
|
||||||
class RequiredIfOtherFieldEquals:
|
class RequiredIfOtherFieldEquals(object):
|
||||||
def __init__(self, other_field, other_value, error_message=None):
|
def __init__(self, other_field, other_value, error_message=None):
|
||||||
self.other_field = other_field
|
self.other_field = other_field
|
||||||
self.other_value = other_value
|
self.other_value = other_value
|
||||||
@ -294,7 +294,7 @@ class RequiredIfOtherFieldEquals:
|
|||||||
if all_data.has_key(self.other_field) and all_data[self.other_field] == self.other_value and not field_data:
|
if all_data.has_key(self.other_field) and all_data[self.other_field] == self.other_value and not field_data:
|
||||||
raise ValidationError(self.error_message)
|
raise ValidationError(self.error_message)
|
||||||
|
|
||||||
class RequiredIfOtherFieldDoesNotEqual:
|
class RequiredIfOtherFieldDoesNotEqual(object):
|
||||||
def __init__(self, other_field, other_value, error_message=None):
|
def __init__(self, other_field, other_value, error_message=None):
|
||||||
self.other_field = other_field
|
self.other_field = other_field
|
||||||
self.other_value = other_value
|
self.other_value = other_value
|
||||||
@ -306,7 +306,7 @@ class RequiredIfOtherFieldDoesNotEqual:
|
|||||||
if all_data.has_key(self.other_field) and all_data[self.other_field] != self.other_value and not field_data:
|
if all_data.has_key(self.other_field) and all_data[self.other_field] != self.other_value and not field_data:
|
||||||
raise ValidationError(self.error_message)
|
raise ValidationError(self.error_message)
|
||||||
|
|
||||||
class IsLessThanOtherField:
|
class IsLessThanOtherField(object):
|
||||||
def __init__(self, other_field_name, error_message):
|
def __init__(self, other_field_name, error_message):
|
||||||
self.other, self.error_message = other_field_name, error_message
|
self.other, self.error_message = other_field_name, error_message
|
||||||
|
|
||||||
@ -314,7 +314,7 @@ class IsLessThanOtherField:
|
|||||||
if field_data > all_data[self.other]:
|
if field_data > all_data[self.other]:
|
||||||
raise ValidationError, self.error_message
|
raise ValidationError, self.error_message
|
||||||
|
|
||||||
class UniqueAmongstFieldsWithPrefix:
|
class UniqueAmongstFieldsWithPrefix(object):
|
||||||
def __init__(self, field_name, prefix, error_message):
|
def __init__(self, field_name, prefix, error_message):
|
||||||
self.field_name, self.prefix = field_name, prefix
|
self.field_name, self.prefix = field_name, prefix
|
||||||
self.error_message = error_message or gettext_lazy("Duplicate values are not allowed.")
|
self.error_message = error_message or gettext_lazy("Duplicate values are not allowed.")
|
||||||
@ -324,7 +324,7 @@ class UniqueAmongstFieldsWithPrefix:
|
|||||||
if field_name != self.field_name and value == field_data:
|
if field_name != self.field_name and value == field_data:
|
||||||
raise ValidationError, self.error_message
|
raise ValidationError, self.error_message
|
||||||
|
|
||||||
class IsAPowerOf:
|
class IsAPowerOf(object):
|
||||||
"""
|
"""
|
||||||
>>> v = IsAPowerOf(2)
|
>>> v = IsAPowerOf(2)
|
||||||
>>> v(4, None)
|
>>> v(4, None)
|
||||||
@ -342,7 +342,7 @@ class IsAPowerOf:
|
|||||||
if val != int(val):
|
if val != int(val):
|
||||||
raise ValidationError, gettext("This value must be a power of %s.") % self.power_of
|
raise ValidationError, gettext("This value must be a power of %s.") % self.power_of
|
||||||
|
|
||||||
class IsValidFloat:
|
class IsValidFloat(object):
|
||||||
def __init__(self, max_digits, decimal_places):
|
def __init__(self, max_digits, decimal_places):
|
||||||
self.max_digits, self.decimal_places = max_digits, decimal_places
|
self.max_digits, self.decimal_places = max_digits, decimal_places
|
||||||
|
|
||||||
@ -355,11 +355,14 @@ class IsValidFloat:
|
|||||||
if len(data) > (self.max_digits + 1):
|
if len(data) > (self.max_digits + 1):
|
||||||
raise ValidationError, ngettext("Please enter a valid decimal number with at most %s total digit.",
|
raise ValidationError, ngettext("Please enter a valid decimal number with at most %s total digit.",
|
||||||
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
|
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
|
||||||
|
if (not '.' in data and len(data) > (self.max_digits - self.decimal_places)) or ('.' in data and len(data) > (self.max_digits - (self.decimal_places - len(data.split('.')[1])) + 1)):
|
||||||
|
raise ValidationError, ngettext( "Please enter a valid decimal number with a whole part of at most %s digit.",
|
||||||
|
"Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places)
|
||||||
if '.' in data and len(data.split('.')[1]) > self.decimal_places:
|
if '.' in data and len(data.split('.')[1]) > self.decimal_places:
|
||||||
raise ValidationError, ngettext("Please enter a valid decimal number with at most %s decimal place.",
|
raise ValidationError, ngettext("Please enter a valid decimal number with at most %s decimal place.",
|
||||||
"Please enter a valid decimal number with at most %s decimal places.", self.decimal_places) % self.decimal_places
|
"Please enter a valid decimal number with at most %s decimal places.", self.decimal_places) % self.decimal_places
|
||||||
|
|
||||||
class HasAllowableSize:
|
class HasAllowableSize(object):
|
||||||
"""
|
"""
|
||||||
Checks that the file-upload field data is a certain size. min_size and
|
Checks that the file-upload field data is a certain size. min_size and
|
||||||
max_size are measurements in bytes.
|
max_size are measurements in bytes.
|
||||||
@ -379,7 +382,7 @@ class HasAllowableSize:
|
|||||||
if self.max_size is not None and len(content) > self.max_size:
|
if self.max_size is not None and len(content) > self.max_size:
|
||||||
raise ValidationError, self.max_error_message
|
raise ValidationError, self.max_error_message
|
||||||
|
|
||||||
class MatchesRegularExpression:
|
class MatchesRegularExpression(object):
|
||||||
"""
|
"""
|
||||||
Checks that the field matches the given regular-expression. The regex
|
Checks that the field matches the given regular-expression. The regex
|
||||||
should be in string format, not already compiled.
|
should be in string format, not already compiled.
|
||||||
@ -392,7 +395,7 @@ class MatchesRegularExpression:
|
|||||||
if not self.regexp.search(field_data):
|
if not self.regexp.search(field_data):
|
||||||
raise ValidationError(self.error_message)
|
raise ValidationError(self.error_message)
|
||||||
|
|
||||||
class AnyValidator:
|
class AnyValidator(object):
|
||||||
"""
|
"""
|
||||||
This validator tries all given validators. If any one of them succeeds,
|
This validator tries all given validators. If any one of them succeeds,
|
||||||
validation passes. If none of them succeeds, the given message is thrown
|
validation passes. If none of them succeeds, the given message is thrown
|
||||||
@ -416,7 +419,7 @@ class AnyValidator:
|
|||||||
pass
|
pass
|
||||||
raise ValidationError(self.error_message)
|
raise ValidationError(self.error_message)
|
||||||
|
|
||||||
class URLMimeTypeCheck:
|
class URLMimeTypeCheck(object):
|
||||||
"Checks that the provided URL points to a document with a listed mime type"
|
"Checks that the provided URL points to a document with a listed mime type"
|
||||||
class CouldNotRetrieve(ValidationError):
|
class CouldNotRetrieve(ValidationError):
|
||||||
pass
|
pass
|
||||||
@ -441,7 +444,7 @@ class URLMimeTypeCheck:
|
|||||||
raise URLMimeTypeCheck.InvalidContentType, gettext("The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'.") % {
|
raise URLMimeTypeCheck.InvalidContentType, gettext("The URL %(url)s returned the invalid Content-Type header '%(contenttype)s'.") % {
|
||||||
'url': field_data, 'contenttype': content_type}
|
'url': field_data, 'contenttype': content_type}
|
||||||
|
|
||||||
class RelaxNGCompact:
|
class RelaxNGCompact(object):
|
||||||
"Validate against a Relax NG compact schema"
|
"Validate against a Relax NG compact schema"
|
||||||
def __init__(self, schema_path, additional_root_element=None):
|
def __init__(self, schema_path, additional_root_element=None):
|
||||||
self.schema_path = schema_path
|
self.schema_path = schema_path
|
||||||
|
@ -131,6 +131,9 @@ def get_fulltext_search_sql(field_name):
|
|||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP CONSTRAINT"
|
return "DROP CONSTRAINT"
|
||||||
|
|
||||||
|
def get_pk_default_value():
|
||||||
|
return "DEFAULT"
|
||||||
|
|
||||||
OPERATOR_MAPPING = {
|
OPERATOR_MAPPING = {
|
||||||
'exact': '= %s',
|
'exact': '= %s',
|
||||||
'iexact': 'LIKE %s',
|
'iexact': 'LIKE %s',
|
||||||
|
@ -158,6 +158,9 @@ def get_fulltext_search_sql(field_name):
|
|||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP FOREIGN KEY"
|
return "DROP FOREIGN KEY"
|
||||||
|
|
||||||
|
def get_pk_default_value():
|
||||||
|
return "DEFAULT"
|
||||||
|
|
||||||
OPERATOR_MAPPING = {
|
OPERATOR_MAPPING = {
|
||||||
'exact': '= %s',
|
'exact': '= %s',
|
||||||
'iexact': 'LIKE %s',
|
'iexact': 'LIKE %s',
|
||||||
|
@ -114,6 +114,9 @@ def get_fulltext_search_sql(field_name):
|
|||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP FOREIGN KEY"
|
return "DROP FOREIGN KEY"
|
||||||
|
|
||||||
|
def get_pk_default_value():
|
||||||
|
return "DEFAULT"
|
||||||
|
|
||||||
OPERATOR_MAPPING = {
|
OPERATOR_MAPPING = {
|
||||||
'exact': '= %s',
|
'exact': '= %s',
|
||||||
'iexact': 'LIKE %s',
|
'iexact': 'LIKE %s',
|
||||||
|
@ -108,6 +108,9 @@ def get_fulltext_search_sql(field_name):
|
|||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP CONSTRAINT"
|
return "DROP CONSTRAINT"
|
||||||
|
|
||||||
|
def get_pk_default_value():
|
||||||
|
return "DEFAULT"
|
||||||
|
|
||||||
# Register these custom typecasts, because Django expects dates/times to be
|
# Register these custom typecasts, because Django expects dates/times to be
|
||||||
# in Python's native (standard-library) datetime/time format, whereas psycopg
|
# in Python's native (standard-library) datetime/time format, whereas psycopg
|
||||||
# use mx.DateTime by default.
|
# use mx.DateTime by default.
|
||||||
|
@ -114,6 +114,9 @@ def get_fulltext_search_sql(field_name):
|
|||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP CONSTRAINT"
|
return "DROP CONSTRAINT"
|
||||||
|
|
||||||
|
def get_pk_default_value():
|
||||||
|
return "DEFAULT"
|
||||||
|
|
||||||
OPERATOR_MAPPING = {
|
OPERATOR_MAPPING = {
|
||||||
'exact': '= %s',
|
'exact': '= %s',
|
||||||
'iexact': 'ILIKE %s',
|
'iexact': 'ILIKE %s',
|
||||||
|
@ -130,6 +130,9 @@ def get_fulltext_search_sql(field_name):
|
|||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
def get_pk_default_value():
|
||||||
|
return "NULL"
|
||||||
|
|
||||||
def _sqlite_date_trunc(lookup_type, dt):
|
def _sqlite_date_trunc(lookup_type, dt):
|
||||||
try:
|
try:
|
||||||
dt = util.typecast_timestamp(dt)
|
dt = util.typecast_timestamp(dt)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
class CursorDebugWrapper:
|
class CursorDebugWrapper(object):
|
||||||
def __init__(self, cursor, db):
|
def __init__(self, cursor, db):
|
||||||
self.cursor = cursor
|
self.cursor = cursor
|
||||||
self.db = db
|
self.db = db
|
||||||
|
@ -8,6 +8,7 @@ from django.db.models.manager import Manager
|
|||||||
from django.db.models.base import Model, AdminOptions
|
from django.db.models.base import Model, AdminOptions
|
||||||
from django.db.models.fields import *
|
from django.db.models.fields import *
|
||||||
from django.db.models.fields.related import ForeignKey, OneToOneField, ManyToManyField, ManyToOneRel, ManyToManyRel, OneToOneRel, TABULAR, STACKED
|
from django.db.models.fields.related import ForeignKey, OneToOneField, ManyToManyField, ManyToOneRel, ManyToManyRel, OneToOneRel, TABULAR, STACKED
|
||||||
|
from django.db.models.fields.generic import GenericRelation, GenericRel, GenericForeignKey
|
||||||
from django.db.models import signals
|
from django.db.models import signals
|
||||||
from django.utils.functional import curry
|
from django.utils.functional import curry
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
@ -15,7 +16,7 @@ from django.utils.text import capfirst
|
|||||||
# Admin stages.
|
# Admin stages.
|
||||||
ADD, CHANGE, BOTH = 1, 2, 3
|
ADD, CHANGE, BOTH = 1, 2, 3
|
||||||
|
|
||||||
class LazyDate:
|
class LazyDate(object):
|
||||||
"""
|
"""
|
||||||
Use in limit_choices_to to compare the field to dates calculated at run time
|
Use in limit_choices_to to compare the field to dates calculated at run time
|
||||||
instead of when the model is loaded. For example::
|
instead of when the model is loaded. For example::
|
||||||
|
@ -107,6 +107,12 @@ class Model(object):
|
|||||||
else:
|
else:
|
||||||
val = kwargs.pop(f.attname, f.get_default())
|
val = kwargs.pop(f.attname, f.get_default())
|
||||||
setattr(self, f.attname, val)
|
setattr(self, f.attname, val)
|
||||||
|
for prop in kwargs.keys():
|
||||||
|
try:
|
||||||
|
if isinstance(getattr(self.__class__, prop), property):
|
||||||
|
setattr(self, prop, kwargs.pop(prop))
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
if kwargs:
|
if kwargs:
|
||||||
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
|
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
|
||||||
for i, arg in enumerate(args):
|
for i, arg in enumerate(args):
|
||||||
@ -165,7 +171,7 @@ class Model(object):
|
|||||||
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
||||||
(backend.quote_name(self._meta.db_table),
|
(backend.quote_name(self._meta.db_table),
|
||||||
','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
|
','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
|
||||||
backend.quote_name(self._meta.pk.attname)),
|
backend.quote_name(self._meta.pk.column)),
|
||||||
db_values + [pk_val])
|
db_values + [pk_val])
|
||||||
else:
|
else:
|
||||||
record_exists = False
|
record_exists = False
|
||||||
@ -183,9 +189,16 @@ class Model(object):
|
|||||||
placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \
|
placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \
|
||||||
(backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.order_with_respect_to.column)))
|
(backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.order_with_respect_to.column)))
|
||||||
db_values.append(getattr(self, self._meta.order_with_respect_to.attname))
|
db_values.append(getattr(self, self._meta.order_with_respect_to.attname))
|
||||||
|
if db_values:
|
||||||
cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
|
cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
|
||||||
(backend.quote_name(self._meta.db_table), ','.join(field_names),
|
(backend.quote_name(self._meta.db_table), ','.join(field_names),
|
||||||
','.join(placeholders)), db_values)
|
','.join(placeholders)), db_values)
|
||||||
|
else:
|
||||||
|
# Create a new record with defaults for everything.
|
||||||
|
cursor.execute("INSERT INTO %s (%s) VALUES (%s)" %
|
||||||
|
(backend.quote_name(self._meta.db_table),
|
||||||
|
backend.quote_name(self._meta.pk.column),
|
||||||
|
backend.get_pk_default_value()))
|
||||||
if self._meta.has_auto_field and not pk_set:
|
if self._meta.has_auto_field and not pk_set:
|
||||||
setattr(self, self._meta.pk.attname, backend.get_last_insert_id(cursor, self._meta.db_table, self._meta.pk.column))
|
setattr(self, self._meta.pk.attname, backend.get_last_insert_id(cursor, self._meta.db_table, self._meta.pk.column))
|
||||||
transaction.commit_unless_managed()
|
transaction.commit_unless_managed()
|
||||||
|
@ -535,7 +535,7 @@ class FileField(Field):
|
|||||||
if not self.blank:
|
if not self.blank:
|
||||||
if rel:
|
if rel:
|
||||||
# This validator makes sure FileFields work in a related context.
|
# This validator makes sure FileFields work in a related context.
|
||||||
class RequiredFileField:
|
class RequiredFileField(object):
|
||||||
def __init__(self, other_field_names, other_file_field_name):
|
def __init__(self, other_field_names, other_file_field_name):
|
||||||
self.other_field_names = other_field_names
|
self.other_field_names = other_field_names
|
||||||
self.other_file_field_name = other_file_field_name
|
self.other_file_field_name = other_file_field_name
|
||||||
|
259
django/db/models/fields/generic.py
Normal file
259
django/db/models/fields/generic.py
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
"""
|
||||||
|
Classes allowing "generic" relations through ContentType and object-id fields.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django import forms
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.db import backend
|
||||||
|
from django.db.models import signals
|
||||||
|
from django.db.models.fields.related import RelatedField, Field, ManyToManyRel
|
||||||
|
from django.db.models.loading import get_model
|
||||||
|
from django.dispatch import dispatcher
|
||||||
|
from django.utils.functional import curry
|
||||||
|
|
||||||
|
class GenericForeignKey(object):
|
||||||
|
"""
|
||||||
|
Provides a generic relation to any object through content-type/object-id
|
||||||
|
fields.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, ct_field="content_type", fk_field="object_id"):
|
||||||
|
self.ct_field = ct_field
|
||||||
|
self.fk_field = fk_field
|
||||||
|
|
||||||
|
def contribute_to_class(self, cls, name):
|
||||||
|
# Make sure the fields exist (these raise FieldDoesNotExist,
|
||||||
|
# which is a fine error to raise here)
|
||||||
|
self.name = name
|
||||||
|
self.model = cls
|
||||||
|
self.cache_attr = "_%s_cache" % name
|
||||||
|
|
||||||
|
# For some reason I don't totally understand, using weakrefs here doesn't work.
|
||||||
|
dispatcher.connect(self.instance_pre_init, signal=signals.pre_init, sender=cls, weak=False)
|
||||||
|
|
||||||
|
# Connect myself as the descriptor for this field
|
||||||
|
setattr(cls, name, self)
|
||||||
|
|
||||||
|
def instance_pre_init(self, signal, sender, args, kwargs):
|
||||||
|
# Handle initalizing an object with the generic FK instaed of
|
||||||
|
# content-type/object-id fields.
|
||||||
|
if kwargs.has_key(self.name):
|
||||||
|
value = kwargs.pop(self.name)
|
||||||
|
kwargs[self.ct_field] = self.get_content_type(value)
|
||||||
|
kwargs[self.fk_field] = value._get_pk_val()
|
||||||
|
|
||||||
|
def get_content_type(self, obj):
|
||||||
|
# Convenience function using get_model avoids a circular import when using this model
|
||||||
|
ContentType = get_model("contenttypes", "contenttype")
|
||||||
|
return ContentType.objects.get_for_model(obj)
|
||||||
|
|
||||||
|
def __get__(self, instance, instance_type=None):
|
||||||
|
if instance is None:
|
||||||
|
raise AttributeError, "%s must be accessed via instance" % self.name
|
||||||
|
|
||||||
|
try:
|
||||||
|
return getattr(instance, self.cache_attr)
|
||||||
|
except AttributeError:
|
||||||
|
rel_obj = None
|
||||||
|
ct = getattr(instance, self.ct_field)
|
||||||
|
if ct:
|
||||||
|
try:
|
||||||
|
rel_obj = ct.get_object_for_this_type(pk=getattr(instance, self.fk_field))
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
pass
|
||||||
|
setattr(instance, self.cache_attr, rel_obj)
|
||||||
|
return rel_obj
|
||||||
|
|
||||||
|
def __set__(self, instance, value):
|
||||||
|
if instance is None:
|
||||||
|
raise AttributeError, "%s must be accessed via instance" % self.related.opts.object_name
|
||||||
|
|
||||||
|
ct = None
|
||||||
|
fk = None
|
||||||
|
if value is not None:
|
||||||
|
ct = self.get_content_type(value)
|
||||||
|
fk = value._get_pk_val()
|
||||||
|
|
||||||
|
setattr(instance, self.ct_field, ct)
|
||||||
|
setattr(instance, self.fk_field, fk)
|
||||||
|
setattr(instance, self.cache_attr, value)
|
||||||
|
|
||||||
|
class GenericRelation(RelatedField, Field):
|
||||||
|
"""Provides an accessor to generic related objects (i.e. comments)"""
|
||||||
|
|
||||||
|
def __init__(self, to, **kwargs):
|
||||||
|
kwargs['verbose_name'] = kwargs.get('verbose_name', None)
|
||||||
|
kwargs['rel'] = GenericRel(to,
|
||||||
|
related_name=kwargs.pop('related_name', None),
|
||||||
|
limit_choices_to=kwargs.pop('limit_choices_to', None),
|
||||||
|
symmetrical=kwargs.pop('symmetrical', True))
|
||||||
|
|
||||||
|
# Override content-type/object-id field names on the related class
|
||||||
|
self.object_id_field_name = kwargs.pop("object_id_field", "object_id")
|
||||||
|
self.content_type_field_name = kwargs.pop("content_type_field", "content_type")
|
||||||
|
|
||||||
|
kwargs['blank'] = True
|
||||||
|
kwargs['editable'] = False
|
||||||
|
Field.__init__(self, **kwargs)
|
||||||
|
|
||||||
|
def get_manipulator_field_objs(self):
|
||||||
|
choices = self.get_choices_default()
|
||||||
|
return [curry(forms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
|
||||||
|
|
||||||
|
def get_choices_default(self):
|
||||||
|
return Field.get_choices(self, include_blank=False)
|
||||||
|
|
||||||
|
def flatten_data(self, follow, obj = None):
|
||||||
|
new_data = {}
|
||||||
|
if obj:
|
||||||
|
instance_ids = [instance._get_pk_val() for instance in getattr(obj, self.name).all()]
|
||||||
|
new_data[self.name] = instance_ids
|
||||||
|
return new_data
|
||||||
|
|
||||||
|
def m2m_db_table(self):
|
||||||
|
return self.rel.to._meta.db_table
|
||||||
|
|
||||||
|
def m2m_column_name(self):
|
||||||
|
return self.object_id_field_name
|
||||||
|
|
||||||
|
def m2m_reverse_name(self):
|
||||||
|
return self.model._meta.pk.attname
|
||||||
|
|
||||||
|
def contribute_to_class(self, cls, name):
|
||||||
|
super(GenericRelation, self).contribute_to_class(cls, name)
|
||||||
|
|
||||||
|
# Save a reference to which model this class is on for future use
|
||||||
|
self.model = cls
|
||||||
|
|
||||||
|
# Add the descriptor for the m2m relation
|
||||||
|
setattr(cls, self.name, ReverseGenericRelatedObjectsDescriptor(self))
|
||||||
|
|
||||||
|
def contribute_to_related_class(self, cls, related):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_attributes_from_rel(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_internal_type(self):
|
||||||
|
return "ManyToManyField"
|
||||||
|
|
||||||
|
class ReverseGenericRelatedObjectsDescriptor(object):
|
||||||
|
"""
|
||||||
|
This class provides the functionality that makes the related-object
|
||||||
|
managers available as attributes on a model class, for fields that have
|
||||||
|
multiple "remote" values and have a GenericRelation defined in their model
|
||||||
|
(rather than having another model pointed *at* them). In the example
|
||||||
|
"article.publications", the publications attribute is a
|
||||||
|
ReverseGenericRelatedObjectsDescriptor instance.
|
||||||
|
"""
|
||||||
|
def __init__(self, field):
|
||||||
|
self.field = field
|
||||||
|
|
||||||
|
def __get__(self, instance, instance_type=None):
|
||||||
|
if instance is None:
|
||||||
|
raise AttributeError, "Manager must be accessed via instance"
|
||||||
|
|
||||||
|
# This import is done here to avoid circular import importing this module
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
|
# Dynamically create a class that subclasses the related model's
|
||||||
|
# default manager.
|
||||||
|
rel_model = self.field.rel.to
|
||||||
|
superclass = rel_model._default_manager.__class__
|
||||||
|
RelatedManager = create_generic_related_manager(superclass)
|
||||||
|
|
||||||
|
manager = RelatedManager(
|
||||||
|
model = rel_model,
|
||||||
|
instance = instance,
|
||||||
|
symmetrical = (self.field.rel.symmetrical and instance.__class__ == rel_model),
|
||||||
|
join_table = backend.quote_name(self.field.m2m_db_table()),
|
||||||
|
source_col_name = backend.quote_name(self.field.m2m_column_name()),
|
||||||
|
target_col_name = backend.quote_name(self.field.m2m_reverse_name()),
|
||||||
|
content_type = ContentType.objects.get_for_model(self.field.model),
|
||||||
|
content_type_field_name = self.field.content_type_field_name,
|
||||||
|
object_id_field_name = self.field.object_id_field_name
|
||||||
|
)
|
||||||
|
|
||||||
|
return manager
|
||||||
|
|
||||||
|
def __set__(self, instance, value):
|
||||||
|
if instance is None:
|
||||||
|
raise AttributeError, "Manager must be accessed via instance"
|
||||||
|
|
||||||
|
manager = self.__get__(instance)
|
||||||
|
manager.clear()
|
||||||
|
for obj in value:
|
||||||
|
manager.add(obj)
|
||||||
|
|
||||||
|
def create_generic_related_manager(superclass):
|
||||||
|
"""
|
||||||
|
Factory function for a manager that subclasses 'superclass' (which is a
|
||||||
|
Manager) and adds behavior for generic related objects.
|
||||||
|
"""
|
||||||
|
|
||||||
|
class GenericRelatedObjectManager(superclass):
|
||||||
|
def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None,
|
||||||
|
join_table=None, source_col_name=None, target_col_name=None, content_type=None,
|
||||||
|
content_type_field_name=None, object_id_field_name=None):
|
||||||
|
|
||||||
|
super(GenericRelatedObjectManager, self).__init__()
|
||||||
|
self.core_filters = core_filters or {}
|
||||||
|
self.model = model
|
||||||
|
self.content_type = content_type
|
||||||
|
self.symmetrical = symmetrical
|
||||||
|
self.instance = instance
|
||||||
|
self.join_table = join_table
|
||||||
|
self.join_table = model._meta.db_table
|
||||||
|
self.source_col_name = source_col_name
|
||||||
|
self.target_col_name = target_col_name
|
||||||
|
self.content_type_field_name = content_type_field_name
|
||||||
|
self.object_id_field_name = object_id_field_name
|
||||||
|
self.pk_val = self.instance._get_pk_val()
|
||||||
|
|
||||||
|
def get_query_set(self):
|
||||||
|
query = {
|
||||||
|
'%s__pk' % self.content_type_field_name : self.content_type.id,
|
||||||
|
'%s__exact' % self.object_id_field_name : self.pk_val,
|
||||||
|
}
|
||||||
|
return superclass.get_query_set(self).filter(**query)
|
||||||
|
|
||||||
|
def add(self, *objs):
|
||||||
|
for obj in objs:
|
||||||
|
setattr(obj, self.content_type_field_name, self.content_type)
|
||||||
|
setattr(obj, self.object_id_field_name, self.pk_val)
|
||||||
|
obj.save()
|
||||||
|
add.alters_data = True
|
||||||
|
|
||||||
|
def remove(self, *objs):
|
||||||
|
for obj in objs:
|
||||||
|
obj.delete()
|
||||||
|
remove.alters_data = True
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
for obj in self.all():
|
||||||
|
obj.delete()
|
||||||
|
clear.alters_data = True
|
||||||
|
|
||||||
|
def create(self, **kwargs):
|
||||||
|
kwargs[self.content_type_field_name] = self.content_type
|
||||||
|
kwargs[self.object_id_field_name] = self.pk_val
|
||||||
|
obj = self.model(**kwargs)
|
||||||
|
obj.save()
|
||||||
|
return obj
|
||||||
|
create.alters_data = True
|
||||||
|
|
||||||
|
return GenericRelatedObjectManager
|
||||||
|
|
||||||
|
class GenericRel(ManyToManyRel):
|
||||||
|
def __init__(self, to, related_name=None, limit_choices_to=None, symmetrical=True):
|
||||||
|
self.to = to
|
||||||
|
self.num_in_admin = 0
|
||||||
|
self.related_name = related_name
|
||||||
|
self.filter_interface = None
|
||||||
|
self.limit_choices_to = limit_choices_to or {}
|
||||||
|
self.edit_inline = False
|
||||||
|
self.raw_id_admin = False
|
||||||
|
self.symmetrical = symmetrical
|
||||||
|
self.multiple = True
|
||||||
|
assert not (self.raw_id_admin and self.filter_interface), \
|
||||||
|
"Generic relations may not use both raw_id_admin and filter_interface"
|
@ -667,7 +667,7 @@ class ManyToManyField(RelatedField, Field):
|
|||||||
def set_attributes_from_rel(self):
|
def set_attributes_from_rel(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class ManyToOneRel:
|
class ManyToOneRel(object):
|
||||||
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
|
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
|
||||||
max_num_in_admin=None, num_extra_on_change=1, edit_inline=False,
|
max_num_in_admin=None, num_extra_on_change=1, edit_inline=False,
|
||||||
related_name=None, limit_choices_to=None, lookup_overrides=None, raw_id_admin=False):
|
related_name=None, limit_choices_to=None, lookup_overrides=None, raw_id_admin=False):
|
||||||
@ -704,7 +704,7 @@ class OneToOneRel(ManyToOneRel):
|
|||||||
self.raw_id_admin = raw_id_admin
|
self.raw_id_admin = raw_id_admin
|
||||||
self.multiple = False
|
self.multiple = False
|
||||||
|
|
||||||
class ManyToManyRel:
|
class ManyToManyRel(object):
|
||||||
def __init__(self, to, num_in_admin=0, related_name=None,
|
def __init__(self, to, num_in_admin=0, related_name=None,
|
||||||
filter_interface=None, limit_choices_to=None, raw_id_admin=False, symmetrical=True):
|
filter_interface=None, limit_choices_to=None, raw_id_admin=False, symmetrical=True):
|
||||||
self.to = to
|
self.to = to
|
||||||
|
@ -3,6 +3,7 @@ from django.db import backend, connection
|
|||||||
from django.db.models.query import QuerySet
|
from django.db.models.query import QuerySet
|
||||||
from django.dispatch import dispatcher
|
from django.dispatch import dispatcher
|
||||||
from django.db.models import signals
|
from django.db.models import signals
|
||||||
|
from django.db.models.fields import FieldDoesNotExist
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
|
|
||||||
# Size of each "chunk" for get_iterator calls.
|
# Size of each "chunk" for get_iterator calls.
|
||||||
@ -13,8 +14,11 @@ def ensure_default_manager(sender):
|
|||||||
cls = sender
|
cls = sender
|
||||||
if not hasattr(cls, '_default_manager'):
|
if not hasattr(cls, '_default_manager'):
|
||||||
# Create the default manager, if needed.
|
# Create the default manager, if needed.
|
||||||
if hasattr(cls, 'objects'):
|
try:
|
||||||
raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % name
|
cls._meta.get_field('objects')
|
||||||
|
raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % cls.__name__
|
||||||
|
except FieldDoesNotExist:
|
||||||
|
pass
|
||||||
cls.add_to_class('objects', Manager())
|
cls.add_to_class('objects', Manager())
|
||||||
|
|
||||||
dispatcher.connect(ensure_default_manager, signal=signals.class_prepared)
|
dispatcher.connect(ensure_default_manager, signal=signals.class_prepared)
|
||||||
@ -65,6 +69,9 @@ class Manager(object):
|
|||||||
def get(self, *args, **kwargs):
|
def get(self, *args, **kwargs):
|
||||||
return self.get_query_set().get(*args, **kwargs)
|
return self.get_query_set().get(*args, **kwargs)
|
||||||
|
|
||||||
|
def get_or_create(self, *args, **kwargs):
|
||||||
|
return self.get_query_set().get_or_create(*args, **kwargs)
|
||||||
|
|
||||||
def filter(self, *args, **kwargs):
|
def filter(self, *args, **kwargs):
|
||||||
return self.get_query_set().filter(*args, **kwargs)
|
return self.get_query_set().filter(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering',
|
|||||||
'unique_together', 'permissions', 'get_latest_by',
|
'unique_together', 'permissions', 'get_latest_by',
|
||||||
'order_with_respect_to', 'app_label')
|
'order_with_respect_to', 'app_label')
|
||||||
|
|
||||||
class Options:
|
class Options(object):
|
||||||
def __init__(self, meta):
|
def __init__(self, meta):
|
||||||
self.fields, self.many_to_many = [], []
|
self.fields, self.many_to_many = [], []
|
||||||
self.module_name, self.verbose_name = None, None
|
self.module_name, self.verbose_name = None, None
|
||||||
@ -195,7 +195,7 @@ class Options:
|
|||||||
self._field_types[field_type] = False
|
self._field_types[field_type] = False
|
||||||
return self._field_types[field_type]
|
return self._field_types[field_type]
|
||||||
|
|
||||||
class AdminOptions:
|
class AdminOptions(object):
|
||||||
def __init__(self, fields=None, js=None, list_display=None, list_filter=None,
|
def __init__(self, fields=None, js=None, list_display=None, list_filter=None,
|
||||||
date_hierarchy=None, save_as=False, ordering=None, search_fields=None,
|
date_hierarchy=None, save_as=False, ordering=None, search_fields=None,
|
||||||
save_on_top=False, list_select_related=False, manager=None, list_per_page=100):
|
save_on_top=False, list_select_related=False, manager=None, list_per_page=100):
|
||||||
|
@ -205,6 +205,23 @@ class QuerySet(object):
|
|||||||
assert len(obj_list) == 1, "get() returned more than one %s -- it returned %s! Lookup parameters were %s" % (self.model._meta.object_name, len(obj_list), kwargs)
|
assert len(obj_list) == 1, "get() returned more than one %s -- it returned %s! Lookup parameters were %s" % (self.model._meta.object_name, len(obj_list), kwargs)
|
||||||
return obj_list[0]
|
return obj_list[0]
|
||||||
|
|
||||||
|
def get_or_create(self, **kwargs):
|
||||||
|
"""
|
||||||
|
Looks up an object with the given kwargs, creating one if necessary.
|
||||||
|
Returns a tuple of (object, created), where created is a boolean
|
||||||
|
specifying whether an object was created.
|
||||||
|
"""
|
||||||
|
assert len(kwargs), 'get_or_create() must be passed at least one keyword argument'
|
||||||
|
defaults = kwargs.pop('defaults', {})
|
||||||
|
try:
|
||||||
|
return self.get(**kwargs), False
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
|
||||||
|
params.update(defaults)
|
||||||
|
obj = self.model(**params)
|
||||||
|
obj.save()
|
||||||
|
return obj, True
|
||||||
|
|
||||||
def latest(self, field_name=None):
|
def latest(self, field_name=None):
|
||||||
"""
|
"""
|
||||||
Returns the latest object, according to the model's 'get_latest_by'
|
Returns the latest object, according to the model's 'get_latest_by'
|
||||||
@ -529,7 +546,7 @@ class DateQuerySet(QuerySet):
|
|||||||
c._order = self._order
|
c._order = self._order
|
||||||
return c
|
return c
|
||||||
|
|
||||||
class QOperator:
|
class QOperator(object):
|
||||||
"Base class for QAnd and QOr"
|
"Base class for QAnd and QOr"
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
self.args = args
|
self.args = args
|
||||||
|
@ -114,7 +114,7 @@ def is_managed():
|
|||||||
def managed(flag=True):
|
def managed(flag=True):
|
||||||
"""
|
"""
|
||||||
Puts the transaction manager into a manual state: managed transactions have
|
Puts the transaction manager into a manual state: managed transactions have
|
||||||
to be committed explicitely by the user. If you switch off transaction
|
to be committed explicitly by the user. If you switch off transaction
|
||||||
management and there is a pending commit/rollback, the data will be
|
management and there is a pending commit/rollback, the data will be
|
||||||
commited.
|
commited.
|
||||||
"""
|
"""
|
||||||
|
@ -101,7 +101,7 @@ class Manipulator(object):
|
|||||||
for field in self.fields:
|
for field in self.fields:
|
||||||
field.convert_post_data(new_data)
|
field.convert_post_data(new_data)
|
||||||
|
|
||||||
class FormWrapper:
|
class FormWrapper(object):
|
||||||
"""
|
"""
|
||||||
A wrapper linking a Manipulator to the template system.
|
A wrapper linking a Manipulator to the template system.
|
||||||
This allows dictionary-style lookups of formfields. It also handles feeding
|
This allows dictionary-style lookups of formfields. It also handles feeding
|
||||||
@ -150,7 +150,7 @@ class FormWrapper:
|
|||||||
|
|
||||||
fields = property(_get_fields)
|
fields = property(_get_fields)
|
||||||
|
|
||||||
class FormFieldWrapper:
|
class FormFieldWrapper(object):
|
||||||
"A bridge between the template system and an individual form field. Used by FormWrapper."
|
"A bridge between the template system and an individual form field. Used by FormWrapper."
|
||||||
def __init__(self, formfield, data, error_list):
|
def __init__(self, formfield, data, error_list):
|
||||||
self.formfield, self.data, self.error_list = formfield, data, error_list
|
self.formfield, self.data, self.error_list = formfield, data, error_list
|
||||||
@ -211,7 +211,7 @@ class FormFieldCollection(FormFieldWrapper):
|
|||||||
def html_combined_error_list(self):
|
def html_combined_error_list(self):
|
||||||
return ''.join([field.html_error_list() for field in self.formfield_dict.values() if hasattr(field, 'errors')])
|
return ''.join([field.html_error_list() for field in self.formfield_dict.values() if hasattr(field, 'errors')])
|
||||||
|
|
||||||
class InlineObjectCollection:
|
class InlineObjectCollection(object):
|
||||||
"An object that acts like a sparse list of form field collections."
|
"An object that acts like a sparse list of form field collections."
|
||||||
def __init__(self, parent_manipulator, rel_obj, data, errors):
|
def __init__(self, parent_manipulator, rel_obj, data, errors):
|
||||||
self.parent_manipulator = parent_manipulator
|
self.parent_manipulator = parent_manipulator
|
||||||
@ -269,7 +269,7 @@ class InlineObjectCollection:
|
|||||||
self._collections = collections
|
self._collections = collections
|
||||||
|
|
||||||
|
|
||||||
class FormField:
|
class FormField(object):
|
||||||
"""Abstract class representing a form field.
|
"""Abstract class representing a form field.
|
||||||
|
|
||||||
Classes that extend FormField should define the following attributes:
|
Classes that extend FormField should define the following attributes:
|
||||||
@ -613,9 +613,10 @@ class CheckboxSelectMultipleField(SelectMultipleField):
|
|||||||
back into the single list that validators, renderers and save() expect.
|
back into the single list that validators, renderers and save() expect.
|
||||||
"""
|
"""
|
||||||
requires_data_list = True
|
requires_data_list = True
|
||||||
def __init__(self, field_name, choices=None, validator_list=None):
|
def __init__(self, field_name, choices=None, ul_class='', validator_list=None):
|
||||||
if validator_list is None: validator_list = []
|
if validator_list is None: validator_list = []
|
||||||
if choices is None: choices = []
|
if choices is None: choices = []
|
||||||
|
self.ul_class = ul_class
|
||||||
SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list)
|
SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list)
|
||||||
|
|
||||||
def prepare(self, new_data):
|
def prepare(self, new_data):
|
||||||
@ -628,7 +629,7 @@ class CheckboxSelectMultipleField(SelectMultipleField):
|
|||||||
new_data.setlist(self.field_name, data_list)
|
new_data.setlist(self.field_name, data_list)
|
||||||
|
|
||||||
def render(self, data):
|
def render(self, data):
|
||||||
output = ['<ul>']
|
output = ['<ul%s>' % (self.ul_class and ' class="%s"' % self.ul_class or '')]
|
||||||
str_data_list = map(str, data) # normalize to strings
|
str_data_list = map(str, data) # normalize to strings
|
||||||
for value, choice in self.choices:
|
for value, choice in self.choices:
|
||||||
checked_html = ''
|
checked_html = ''
|
||||||
@ -897,10 +898,11 @@ class FilePathField(SelectField):
|
|||||||
"A SelectField whose choices are the files in a given directory."
|
"A SelectField whose choices are the files in a given directory."
|
||||||
def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None):
|
def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None):
|
||||||
import os
|
import os
|
||||||
|
from django.db.models import BLANK_CHOICE_DASH
|
||||||
if match is not None:
|
if match is not None:
|
||||||
import re
|
import re
|
||||||
match_re = re.compile(match)
|
match_re = re.compile(match)
|
||||||
choices = []
|
choices = not is_required and BLANK_CHOICE_DASH[:] or []
|
||||||
if recursive:
|
if recursive:
|
||||||
for root, dirs, files in os.walk(path):
|
for root, dirs, files in os.walk(path):
|
||||||
for f in files:
|
for f in files:
|
||||||
|
@ -265,6 +265,12 @@ class HttpResponseForbidden(HttpResponse):
|
|||||||
HttpResponse.__init__(self, *args, **kwargs)
|
HttpResponse.__init__(self, *args, **kwargs)
|
||||||
self.status_code = 403
|
self.status_code = 403
|
||||||
|
|
||||||
|
class HttpResponseNotAllowed(HttpResponse):
|
||||||
|
def __init__(self, permitted_methods):
|
||||||
|
HttpResponse.__init__(self)
|
||||||
|
self['Allow'] = ', '.join(permitted_methods)
|
||||||
|
self.status_code = 405
|
||||||
|
|
||||||
class HttpResponseGone(HttpResponse):
|
class HttpResponseGone(HttpResponse):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
HttpResponse.__init__(self, *args, **kwargs)
|
HttpResponse.__init__(self, *args, **kwargs)
|
||||||
|
@ -3,7 +3,7 @@ from django.core.cache import cache
|
|||||||
from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers
|
from django.utils.cache import get_cache_key, learn_cache_key, patch_response_headers
|
||||||
from django.http import HttpResponseNotModified
|
from django.http import HttpResponseNotModified
|
||||||
|
|
||||||
class CacheMiddleware:
|
class CacheMiddleware(object):
|
||||||
"""
|
"""
|
||||||
Cache middleware. If this is enabled, each Django-powered page will be
|
Cache middleware. If this is enabled, each Django-powered page will be
|
||||||
cached for CACHE_MIDDLEWARE_SECONDS seconds. Cache is based on URLs.
|
cached for CACHE_MIDDLEWARE_SECONDS seconds. Cache is based on URLs.
|
||||||
|
@ -3,7 +3,7 @@ from django import http
|
|||||||
from django.core.mail import mail_managers
|
from django.core.mail import mail_managers
|
||||||
import md5, os
|
import md5, os
|
||||||
|
|
||||||
class CommonMiddleware:
|
class CommonMiddleware(object):
|
||||||
"""
|
"""
|
||||||
"Common" middleware for taking care of some basic operations:
|
"Common" middleware for taking care of some basic operations:
|
||||||
|
|
||||||
@ -39,6 +39,8 @@ class CommonMiddleware:
|
|||||||
# trailing slash or a file extension.
|
# trailing slash or a file extension.
|
||||||
if settings.APPEND_SLASH and (old_url[1][-1] != '/') and ('.' not in old_url[1].split('/')[-1]):
|
if settings.APPEND_SLASH and (old_url[1][-1] != '/') and ('.' not in old_url[1].split('/')[-1]):
|
||||||
new_url[1] = new_url[1] + '/'
|
new_url[1] = new_url[1] + '/'
|
||||||
|
if settings.DEBUG and request.META['REQUEST_METHOD'].lower() == 'post':
|
||||||
|
raise RuntimeError, "You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to %s%s (note the trailing slash), or set APPEND_SLASH=False in your Django settings." % (new_url[0], new_url[1])
|
||||||
if new_url != old_url:
|
if new_url != old_url:
|
||||||
# Redirect
|
# Redirect
|
||||||
if new_url[0]:
|
if new_url[0]:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django import http
|
from django import http
|
||||||
|
|
||||||
class XViewMiddleware:
|
class XViewMiddleware(object):
|
||||||
"""
|
"""
|
||||||
Adds an X-View header to internal HEAD requests -- used by the documentation system.
|
Adds an X-View header to internal HEAD requests -- used by the documentation system.
|
||||||
"""
|
"""
|
||||||
|
@ -4,7 +4,7 @@ from django.utils.cache import patch_vary_headers
|
|||||||
|
|
||||||
re_accepts_gzip = re.compile(r'\bgzip\b')
|
re_accepts_gzip = re.compile(r'\bgzip\b')
|
||||||
|
|
||||||
class GZipMiddleware:
|
class GZipMiddleware(object):
|
||||||
"""
|
"""
|
||||||
This middleware compresses content if the browser allows gzip compression.
|
This middleware compresses content if the browser allows gzip compression.
|
||||||
It sets the Vary header accordingly, so that caches will base their storage
|
It sets the Vary header accordingly, so that caches will base their storage
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
class ConditionalGetMiddleware:
|
class ConditionalGetMiddleware(object):
|
||||||
"""
|
"""
|
||||||
Handles conditional GET operations. If the response has a ETag or
|
Handles conditional GET operations. If the response has a ETag or
|
||||||
Last-Modified header, and the request has If-None-Match or
|
Last-Modified header, and the request has If-None-Match or
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
from django.utils.cache import patch_vary_headers
|
from django.utils.cache import patch_vary_headers
|
||||||
from django.utils import translation
|
from django.utils import translation
|
||||||
|
|
||||||
class LocaleMiddleware:
|
class LocaleMiddleware(object):
|
||||||
"""
|
"""
|
||||||
This is a very simple middleware that parses a request
|
This is a very simple middleware that parses a request
|
||||||
and decides what translation object to install in the current
|
and decides what translation object to install in the current
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
|
|
||||||
class TransactionMiddleware:
|
class TransactionMiddleware(object):
|
||||||
"""
|
"""
|
||||||
Transaction middleware. If this is enabled, each view function will be run
|
Transaction middleware. If this is enabled, each view function will be run
|
||||||
with commit_on_response activated - that way a save() doesn't do a direct
|
with commit_on_response activated - that way a save() doesn't do a direct
|
||||||
|
@ -56,9 +56,10 @@ times with multiple contexts)
|
|||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
from inspect import getargspec
|
from inspect import getargspec
|
||||||
from django.utils.functional import curry
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.template.context import Context, RequestContext, ContextPopException
|
from django.template.context import Context, RequestContext, ContextPopException
|
||||||
|
from django.utils.functional import curry
|
||||||
|
from django.utils.text import smart_split
|
||||||
|
|
||||||
__all__ = ('Template', 'Context', 'RequestContext', 'compile_string')
|
__all__ = ('Template', 'Context', 'RequestContext', 'compile_string')
|
||||||
|
|
||||||
@ -74,6 +75,8 @@ BLOCK_TAG_START = '{%'
|
|||||||
BLOCK_TAG_END = '%}'
|
BLOCK_TAG_END = '%}'
|
||||||
VARIABLE_TAG_START = '{{'
|
VARIABLE_TAG_START = '{{'
|
||||||
VARIABLE_TAG_END = '}}'
|
VARIABLE_TAG_END = '}}'
|
||||||
|
SINGLE_BRACE_START = '{'
|
||||||
|
SINGLE_BRACE_END = '}'
|
||||||
|
|
||||||
ALLOWED_VARIABLE_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.'
|
ALLOWED_VARIABLE_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.'
|
||||||
|
|
||||||
@ -133,7 +136,7 @@ class StringOrigin(Origin):
|
|||||||
def reload(self):
|
def reload(self):
|
||||||
return self.source
|
return self.source
|
||||||
|
|
||||||
class Template:
|
class Template(object):
|
||||||
def __init__(self, template_string, origin=None):
|
def __init__(self, template_string, origin=None):
|
||||||
"Compilation stage"
|
"Compilation stage"
|
||||||
if settings.TEMPLATE_DEBUG and origin == None:
|
if settings.TEMPLATE_DEBUG and origin == None:
|
||||||
@ -157,22 +160,18 @@ def compile_string(template_string, origin):
|
|||||||
parser = parser_factory(lexer.tokenize())
|
parser = parser_factory(lexer.tokenize())
|
||||||
return parser.parse()
|
return parser.parse()
|
||||||
|
|
||||||
class Token:
|
class Token(object):
|
||||||
def __init__(self, token_type, contents):
|
def __init__(self, token_type, contents):
|
||||||
"The token_type must be TOKEN_TEXT, TOKEN_VAR or TOKEN_BLOCK"
|
"The token_type must be TOKEN_TEXT, TOKEN_VAR or TOKEN_BLOCK"
|
||||||
self.token_type, self.contents = token_type, contents
|
self.token_type, self.contents = token_type, contents
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '<%s token: "%s...">' % (
|
return '<%s token: "%s...">' % \
|
||||||
{TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block'}[self.token_type],
|
({TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block'}[self.token_type],
|
||||||
self.contents[:20].replace('\n', '')
|
self.contents[:20].replace('\n', ''))
|
||||||
)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def split_contents(self):
|
||||||
return '<%s token: "%s">' % (
|
return smart_split(self.contents)
|
||||||
{TOKEN_TEXT: 'Text', TOKEN_VAR: 'Var', TOKEN_BLOCK: 'Block'}[self.token_type],
|
|
||||||
self.contents[:].replace('\n', '')
|
|
||||||
)
|
|
||||||
|
|
||||||
class Lexer(object):
|
class Lexer(object):
|
||||||
def __init__(self, template_string, origin):
|
def __init__(self, template_string, origin):
|
||||||
@ -367,7 +366,6 @@ class DebugParser(Parser):
|
|||||||
if not hasattr(e, 'source'):
|
if not hasattr(e, 'source'):
|
||||||
e.source = token.source
|
e.source = token.source
|
||||||
|
|
||||||
|
|
||||||
def lexer_factory(*args, **kwargs):
|
def lexer_factory(*args, **kwargs):
|
||||||
if settings.TEMPLATE_DEBUG:
|
if settings.TEMPLATE_DEBUG:
|
||||||
return DebugLexer(*args, **kwargs)
|
return DebugLexer(*args, **kwargs)
|
||||||
@ -380,8 +378,7 @@ def parser_factory(*args, **kwargs):
|
|||||||
else:
|
else:
|
||||||
return Parser(*args, **kwargs)
|
return Parser(*args, **kwargs)
|
||||||
|
|
||||||
|
class TokenParser(object):
|
||||||
class TokenParser:
|
|
||||||
"""
|
"""
|
||||||
Subclass this and implement the top() method to parse a template line. When
|
Subclass this and implement the top() method to parse a template line. When
|
||||||
instantiating the parser, pass in the line from the Django template parser.
|
instantiating the parser, pass in the line from the Django template parser.
|
||||||
@ -564,7 +561,7 @@ class FilterExpression(object):
|
|||||||
def args_check(name, func, provided):
|
def args_check(name, func, provided):
|
||||||
provided = list(provided)
|
provided = list(provided)
|
||||||
plen = len(provided)
|
plen = len(provided)
|
||||||
(args, varargs, varkw, defaults) = getargspec(func)
|
args, varargs, varkw, defaults = getargspec(func)
|
||||||
# First argument is filter input.
|
# First argument is filter input.
|
||||||
args.pop(0)
|
args.pop(0)
|
||||||
if defaults:
|
if defaults:
|
||||||
@ -614,7 +611,7 @@ def resolve_variable(path, context):
|
|||||||
|
|
||||||
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
|
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
|
||||||
"""
|
"""
|
||||||
if path[0] in '0123456789':
|
if path[0].isdigit():
|
||||||
number_type = '.' in path and float or int
|
number_type = '.' in path and float or int
|
||||||
try:
|
try:
|
||||||
current = number_type(path)
|
current = number_type(path)
|
||||||
@ -659,7 +656,7 @@ def resolve_variable(path, context):
|
|||||||
del bits[0]
|
del bits[0]
|
||||||
return current
|
return current
|
||||||
|
|
||||||
class Node:
|
class Node(object):
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
"Return the node rendered as a string"
|
"Return the node rendered as a string"
|
||||||
pass
|
pass
|
||||||
@ -820,7 +817,7 @@ class Library(object):
|
|||||||
return func
|
return func
|
||||||
|
|
||||||
def simple_tag(self,func):
|
def simple_tag(self,func):
|
||||||
(params, xx, xxx, defaults) = getargspec(func)
|
params, xx, xxx, defaults = getargspec(func)
|
||||||
|
|
||||||
class SimpleNode(Node):
|
class SimpleNode(Node):
|
||||||
def __init__(self, vars_to_resolve):
|
def __init__(self, vars_to_resolve):
|
||||||
@ -837,7 +834,7 @@ class Library(object):
|
|||||||
|
|
||||||
def inclusion_tag(self, file_name, context_class=Context, takes_context=False):
|
def inclusion_tag(self, file_name, context_class=Context, takes_context=False):
|
||||||
def dec(func):
|
def dec(func):
|
||||||
(params, xx, xxx, defaults) = getargspec(func)
|
params, xx, xxx, defaults = getargspec(func)
|
||||||
if takes_context:
|
if takes_context:
|
||||||
if params[0] == 'context':
|
if params[0] == 'context':
|
||||||
params = params[1:]
|
params = params[1:]
|
||||||
|
@ -7,7 +7,7 @@ class ContextPopException(Exception):
|
|||||||
"pop() has been called more times than push()"
|
"pop() has been called more times than push()"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Context:
|
class Context(object):
|
||||||
"A stack container for variable context"
|
"A stack container for variable context"
|
||||||
def __init__(self, dict_=None):
|
def __init__(self, dict_=None):
|
||||||
dict_ = dict_ or {}
|
dict_ = dict_ or {}
|
||||||
|
@ -330,6 +330,8 @@ def get_digit(value, arg):
|
|||||||
def date(value, arg=None):
|
def date(value, arg=None):
|
||||||
"Formats a date according to the given format"
|
"Formats a date according to the given format"
|
||||||
from django.utils.dateformat import format
|
from django.utils.dateformat import format
|
||||||
|
if not value:
|
||||||
|
return ''
|
||||||
if arg is None:
|
if arg is None:
|
||||||
arg = settings.DATE_FORMAT
|
arg = settings.DATE_FORMAT
|
||||||
return format(value, arg)
|
return format(value, arg)
|
||||||
@ -337,6 +339,8 @@ def date(value, arg=None):
|
|||||||
def time(value, arg=None):
|
def time(value, arg=None):
|
||||||
"Formats a time according to the given format"
|
"Formats a time according to the given format"
|
||||||
from django.utils.dateformat import time_format
|
from django.utils.dateformat import time_format
|
||||||
|
if not value:
|
||||||
|
return ''
|
||||||
if arg is None:
|
if arg is None:
|
||||||
arg = settings.TIME_FORMAT
|
arg = settings.TIME_FORMAT
|
||||||
return time_format(value, arg)
|
return time_format(value, arg)
|
||||||
@ -344,6 +348,8 @@ def time(value, arg=None):
|
|||||||
def timesince(value):
|
def timesince(value):
|
||||||
'Formats a date as the time since that date (i.e. "4 days, 6 hours")'
|
'Formats a date as the time since that date (i.e. "4 days, 6 hours")'
|
||||||
from django.utils.timesince import timesince
|
from django.utils.timesince import timesince
|
||||||
|
if not value:
|
||||||
|
return ''
|
||||||
return timesince(value)
|
return timesince(value)
|
||||||
|
|
||||||
###################
|
###################
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"Default tags used by the template system, available to all templates."
|
"Default tags used by the template system, available to all templates."
|
||||||
|
|
||||||
from django.template import Node, NodeList, Template, Context, resolve_variable
|
from django.template import Node, NodeList, Template, Context, resolve_variable
|
||||||
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END
|
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END
|
||||||
from django.template import get_library, Library, InvalidTemplateLibrary
|
from django.template import get_library, Library, InvalidTemplateLibrary
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
import sys
|
import sys
|
||||||
@ -149,9 +149,10 @@ class IfEqualNode(Node):
|
|||||||
return self.nodelist_false.render(context)
|
return self.nodelist_false.render(context)
|
||||||
|
|
||||||
class IfNode(Node):
|
class IfNode(Node):
|
||||||
def __init__(self, bool_exprs, nodelist_true, nodelist_false):
|
def __init__(self, bool_exprs, nodelist_true, nodelist_false, link_type):
|
||||||
self.bool_exprs = bool_exprs
|
self.bool_exprs = bool_exprs
|
||||||
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
|
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
|
||||||
|
self.link_type = link_type
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<If node>"
|
return "<If node>"
|
||||||
@ -171,6 +172,7 @@ class IfNode(Node):
|
|||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
|
if self.link_type == IfNode.LinkTypes.or_:
|
||||||
for ifnot, bool_expr in self.bool_exprs:
|
for ifnot, bool_expr in self.bool_exprs:
|
||||||
try:
|
try:
|
||||||
value = bool_expr.resolve(context)
|
value = bool_expr.resolve(context)
|
||||||
@ -179,6 +181,19 @@ class IfNode(Node):
|
|||||||
if (value and not ifnot) or (ifnot and not value):
|
if (value and not ifnot) or (ifnot and not value):
|
||||||
return self.nodelist_true.render(context)
|
return self.nodelist_true.render(context)
|
||||||
return self.nodelist_false.render(context)
|
return self.nodelist_false.render(context)
|
||||||
|
else:
|
||||||
|
for ifnot, bool_expr in self.bool_exprs:
|
||||||
|
try:
|
||||||
|
value = bool_expr.resolve(context)
|
||||||
|
except VariableDoesNotExist:
|
||||||
|
value = None
|
||||||
|
if not ((value and not ifnot) or (ifnot and not value)):
|
||||||
|
return self.nodelist_false.render(context)
|
||||||
|
return self.nodelist_true.render(context)
|
||||||
|
|
||||||
|
class LinkTypes:
|
||||||
|
and_ = 0,
|
||||||
|
or_ = 1
|
||||||
|
|
||||||
class RegroupNode(Node):
|
class RegroupNode(Node):
|
||||||
def __init__(self, target, expression, var_name):
|
def __init__(self, target, expression, var_name):
|
||||||
@ -260,7 +275,10 @@ class TemplateTagNode(Node):
|
|||||||
mapping = {'openblock': BLOCK_TAG_START,
|
mapping = {'openblock': BLOCK_TAG_START,
|
||||||
'closeblock': BLOCK_TAG_END,
|
'closeblock': BLOCK_TAG_END,
|
||||||
'openvariable': VARIABLE_TAG_START,
|
'openvariable': VARIABLE_TAG_START,
|
||||||
'closevariable': VARIABLE_TAG_END}
|
'closevariable': VARIABLE_TAG_END,
|
||||||
|
'openbrace': SINGLE_BRACE_START,
|
||||||
|
'closebrace': SINGLE_BRACE_END,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, tagtype):
|
def __init__(self, tagtype):
|
||||||
self.tagtype = tagtype
|
self.tagtype = tagtype
|
||||||
@ -487,7 +505,7 @@ def do_ifequal(parser, token, negate):
|
|||||||
...
|
...
|
||||||
{% endifnotequal %}
|
{% endifnotequal %}
|
||||||
"""
|
"""
|
||||||
bits = token.contents.split()
|
bits = list(token.split_contents())
|
||||||
if len(bits) != 3:
|
if len(bits) != 3:
|
||||||
raise TemplateSyntaxError, "%r takes two arguments" % bits[0]
|
raise TemplateSyntaxError, "%r takes two arguments" % bits[0]
|
||||||
end_tag = 'end' + bits[0]
|
end_tag = 'end' + bits[0]
|
||||||
@ -561,11 +579,22 @@ def do_if(parser, token):
|
|||||||
if not bits:
|
if not bits:
|
||||||
raise TemplateSyntaxError, "'if' statement requires at least one argument"
|
raise TemplateSyntaxError, "'if' statement requires at least one argument"
|
||||||
# bits now looks something like this: ['a', 'or', 'not', 'b', 'or', 'c.d']
|
# bits now looks something like this: ['a', 'or', 'not', 'b', 'or', 'c.d']
|
||||||
boolpairs = ' '.join(bits).split(' or ')
|
bitstr = ' '.join(bits)
|
||||||
|
boolpairs = bitstr.split(' and ')
|
||||||
boolvars = []
|
boolvars = []
|
||||||
|
if len(boolpairs) == 1:
|
||||||
|
link_type = IfNode.LinkTypes.or_
|
||||||
|
boolpairs = bitstr.split(' or ')
|
||||||
|
else:
|
||||||
|
link_type = IfNode.LinkTypes.and_
|
||||||
|
if ' or ' in bitstr:
|
||||||
|
raise TemplateSyntaxError, "'if' tags can't mix 'and' and 'or'"
|
||||||
for boolpair in boolpairs:
|
for boolpair in boolpairs:
|
||||||
if ' ' in boolpair:
|
if ' ' in boolpair:
|
||||||
|
try:
|
||||||
not_, boolvar = boolpair.split()
|
not_, boolvar = boolpair.split()
|
||||||
|
except ValueError:
|
||||||
|
raise TemplateSyntaxError, "'if' statement improperly formatted"
|
||||||
if not_ != 'not':
|
if not_ != 'not':
|
||||||
raise TemplateSyntaxError, "Expected 'not' in if statement"
|
raise TemplateSyntaxError, "Expected 'not' in if statement"
|
||||||
boolvars.append((True, parser.compile_filter(boolvar)))
|
boolvars.append((True, parser.compile_filter(boolvar)))
|
||||||
@ -578,7 +607,7 @@ def do_if(parser, token):
|
|||||||
parser.delete_first_token()
|
parser.delete_first_token()
|
||||||
else:
|
else:
|
||||||
nodelist_false = NodeList()
|
nodelist_false = NodeList()
|
||||||
return IfNode(boolvars, nodelist_true, nodelist_false)
|
return IfNode(boolvars, nodelist_true, nodelist_false, link_type)
|
||||||
do_if = register.tag("if", do_if)
|
do_if = register.tag("if", do_if)
|
||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
@ -783,6 +812,8 @@ def templatetag(parser, token):
|
|||||||
``closeblock`` ``%}``
|
``closeblock`` ``%}``
|
||||||
``openvariable`` ``{{``
|
``openvariable`` ``{{``
|
||||||
``closevariable`` ``}}``
|
``closevariable`` ``}}``
|
||||||
|
``openbrace`` ``{``
|
||||||
|
``closebrace`` ``}``
|
||||||
================== =======
|
================== =======
|
||||||
"""
|
"""
|
||||||
bits = token.contents.split()
|
bits = token.contents.split()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
class MergeDict:
|
class MergeDict(object):
|
||||||
"""
|
"""
|
||||||
A simple class for creating new "virtual" dictionaries that actualy look
|
A simple class for creating new "virtual" dictionaries that actualy look
|
||||||
up values in more than one dictionary, passed in the constructor.
|
up values in more than one dictionary, passed in the constructor.
|
||||||
|
@ -19,7 +19,7 @@ import re, time
|
|||||||
re_formatchars = re.compile(r'(?<!\\)([aABdDfFgGhHiIjlLmMnNOPrsStTUwWyYzZ])')
|
re_formatchars = re.compile(r'(?<!\\)([aABdDfFgGhHiIjlLmMnNOPrsStTUwWyYzZ])')
|
||||||
re_escaped = re.compile(r'\\(.)')
|
re_escaped = re.compile(r'\\(.)')
|
||||||
|
|
||||||
class Formatter:
|
class Formatter(object):
|
||||||
def format(self, formatstr):
|
def format(self, formatstr):
|
||||||
pieces = []
|
pieces = []
|
||||||
for i, piece in enumerate(re_formatchars.split(formatstr)):
|
for i, piece in enumerate(re_formatchars.split(formatstr)):
|
||||||
|
@ -36,7 +36,7 @@ def get_tag_uri(url, date):
|
|||||||
tag = re.sub('#', '/', tag)
|
tag = re.sub('#', '/', tag)
|
||||||
return 'tag:' + tag
|
return 'tag:' + tag
|
||||||
|
|
||||||
class SyndicationFeed:
|
class SyndicationFeed(object):
|
||||||
"Base class for all syndication feeds. Subclasses should provide write()"
|
"Base class for all syndication feeds. Subclasses should provide write()"
|
||||||
def __init__(self, title, link, description, language=None, author_email=None,
|
def __init__(self, title, link, description, language=None, author_email=None,
|
||||||
author_name=None, author_link=None, subtitle=None, categories=None,
|
author_name=None, author_link=None, subtitle=None, categories=None,
|
||||||
@ -108,7 +108,7 @@ class SyndicationFeed:
|
|||||||
else:
|
else:
|
||||||
return datetime.datetime.now()
|
return datetime.datetime.now()
|
||||||
|
|
||||||
class Enclosure:
|
class Enclosure(object):
|
||||||
"Represents an RSS enclosure"
|
"Represents an RSS enclosure"
|
||||||
def __init__(self, url, length, mime_type):
|
def __init__(self, url, length, mime_type):
|
||||||
"All args are expected to be Python Unicode objects"
|
"All args are expected to be Python Unicode objects"
|
||||||
@ -126,6 +126,8 @@ class RssFeed(SyndicationFeed):
|
|||||||
handler.addQuickElement(u"description", self.feed['description'])
|
handler.addQuickElement(u"description", self.feed['description'])
|
||||||
if self.feed['language'] is not None:
|
if self.feed['language'] is not None:
|
||||||
handler.addQuickElement(u"language", self.feed['language'])
|
handler.addQuickElement(u"language", self.feed['language'])
|
||||||
|
for cat in self.feed['categories']:
|
||||||
|
handler.addQuickElement(u"category", cat)
|
||||||
self.write_items(handler)
|
self.write_items(handler)
|
||||||
self.endChannelElement(handler)
|
self.endChannelElement(handler)
|
||||||
handler.endElement(u"rss")
|
handler.endElement(u"rss")
|
||||||
|
@ -109,3 +109,21 @@ def javascript_quote(s):
|
|||||||
s = s.replace("'", "\\'")
|
s = s.replace("'", "\\'")
|
||||||
return str(ustring_re.sub(fix, s))
|
return str(ustring_re.sub(fix, s))
|
||||||
|
|
||||||
|
smart_split_re = re.compile('("(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'|[^\\s]+)')
|
||||||
|
def smart_split(text):
|
||||||
|
"""
|
||||||
|
Generator that splits a string by spaces, leaving quoted phrases together.
|
||||||
|
Supports both single and double quotes, and supports escaping quotes with
|
||||||
|
backslashes. In the output, strings will keep their initial and trailing
|
||||||
|
quote marks.
|
||||||
|
>>> list(smart_split('This is "a person\'s" test.'))
|
||||||
|
['This', 'is', '"a person\'s"', 'test.']
|
||||||
|
"""
|
||||||
|
for bit in smart_split_re.finditer(text):
|
||||||
|
bit = bit.group(0)
|
||||||
|
if bit[0] == '"':
|
||||||
|
yield '"' + bit[1:-1].replace('\\"', '"').replace('\\\\', '\\') + '"'
|
||||||
|
elif bit[0] == "'":
|
||||||
|
yield "'" + bit[1:-1].replace("\\'", "'").replace("\\\\", "\\") + "'"
|
||||||
|
else:
|
||||||
|
yield bit
|
||||||
|
@ -111,6 +111,12 @@ def technical_500_response(request, exc_type, exc_value, tb):
|
|||||||
})
|
})
|
||||||
tb = tb.tb_next
|
tb = tb.tb_next
|
||||||
|
|
||||||
|
if not frames:
|
||||||
|
frames = [{
|
||||||
|
'filename': '<unknown>',
|
||||||
|
'function': '?',
|
||||||
|
'lineno': '?',
|
||||||
|
}]
|
||||||
t = Template(TECHNICAL_500_TEMPLATE)
|
t = Template(TECHNICAL_500_TEMPLATE)
|
||||||
c = Context({
|
c = Context({
|
||||||
'exception_type': exc_type.__name__,
|
'exception_type': exc_type.__name__,
|
||||||
|
@ -106,6 +106,8 @@ def update_object(request, model, object_id=None, slug=None,
|
|||||||
|
|
||||||
if request.POST:
|
if request.POST:
|
||||||
new_data = request.POST.copy()
|
new_data = request.POST.copy()
|
||||||
|
if model._meta.has_field_type(FileField):
|
||||||
|
new_data.update(request.FILES)
|
||||||
errors = manipulator.get_validation_errors(new_data)
|
errors = manipulator.get_validation_errors(new_data)
|
||||||
manipulator.do_html2python(new_data)
|
manipulator.do_html2python(new_data)
|
||||||
if not errors:
|
if not errors:
|
||||||
|
@ -49,8 +49,8 @@ humanize
|
|||||||
========
|
========
|
||||||
|
|
||||||
A set of Django template filters useful for adding a "human touch" to data.
|
A set of Django template filters useful for adding a "human touch" to data.
|
||||||
To activate these filters, add ``'django.contrib.english'`` to your
|
To activate these filters, add ``'django.contrib.humanize'`` to your
|
||||||
``INSTALLED_APPS`` setting. Once you've done that, use ``{% load english %}``
|
``INSTALLED_APPS`` setting. Once you've done that, use ``{% load humanize %}``
|
||||||
in a template, and you'll have access to these filters:
|
in a template, and you'll have access to these filters:
|
||||||
|
|
||||||
apnumber
|
apnumber
|
||||||
|
@ -355,8 +355,8 @@ Here's what ``django.contrib.auth.views.login`` does::
|
|||||||
form.
|
form.
|
||||||
|
|
||||||
It's your responsibility to provide the login form in a template called
|
It's your responsibility to provide the login form in a template called
|
||||||
``registration/login.html``. This template gets passed three template context
|
``registration/login.html`` by default. This template gets passed three
|
||||||
variables:
|
template context variables:
|
||||||
|
|
||||||
* ``form``: A ``FormWrapper`` object representing the login form. See the
|
* ``form``: A ``FormWrapper`` object representing the login form. See the
|
||||||
`forms documentation`_ for more on ``FormWrapper`` objects.
|
`forms documentation`_ for more on ``FormWrapper`` objects.
|
||||||
@ -365,6 +365,13 @@ variables:
|
|||||||
* ``site_name``: The name of the current ``Site``, according to the
|
* ``site_name``: The name of the current ``Site``, according to the
|
||||||
``SITE_ID`` setting. See the `site framework docs`_.
|
``SITE_ID`` setting. See the `site framework docs`_.
|
||||||
|
|
||||||
|
If you'd prefer not to call the template ``registration/login.html``, you can
|
||||||
|
pass the ``template_name`` parameter via the extra arguments to the view in
|
||||||
|
your URLconf. For example, this URLconf line would use ``myapp/login.html``
|
||||||
|
instead::
|
||||||
|
|
||||||
|
(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html'}),
|
||||||
|
|
||||||
Here's a sample ``registration/login.html`` template you can use as a starting
|
Here's a sample ``registration/login.html`` template you can use as a starting
|
||||||
point. It assumes you have a ``base.html`` template that defines a ``content``
|
point. It assumes you have a ``base.html`` template that defines a ``content``
|
||||||
block::
|
block::
|
||||||
|
@ -559,7 +559,7 @@ following models::
|
|||||||
# ...
|
# ...
|
||||||
hometown = models.ForeignKey(City)
|
hometown = models.ForeignKey(City)
|
||||||
|
|
||||||
class Book(meta.Model):
|
class Book(models.Model):
|
||||||
# ...
|
# ...
|
||||||
author = models.ForeignKey(Person)
|
author = models.ForeignKey(Person)
|
||||||
|
|
||||||
@ -705,6 +705,64 @@ The ``DoesNotExist`` exception inherits from
|
|||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
print "Either the entry or blog doesn't exist."
|
print "Either the entry or blog doesn't exist."
|
||||||
|
|
||||||
|
``get_or_create(**kwargs)``
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
A convenience method for looking up an object with the given kwargs, creating
|
||||||
|
one if necessary.
|
||||||
|
|
||||||
|
Returns a tuple of ``(object, created)``, where ``object`` is the retrieved or
|
||||||
|
created object and ``created`` is a boolean specifying whether a new object was
|
||||||
|
created.
|
||||||
|
|
||||||
|
This is meant as a shortcut to boilerplatish code and is mostly useful for
|
||||||
|
data-import scripts. For example::
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = Person.objects.get(first_name='John', last_name='Lennon')
|
||||||
|
except Person.DoesNotExist:
|
||||||
|
obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
|
||||||
|
obj.save()
|
||||||
|
|
||||||
|
This pattern gets quite unwieldy as the number of fields in a model goes up.
|
||||||
|
The above example can be rewritten using ``get_or_create()`` like so::
|
||||||
|
|
||||||
|
obj, created = Person.objects.get_or_create(first_name='John', last_name='Lennon',
|
||||||
|
defaults={'birthday': date(1940, 10, 9)})
|
||||||
|
|
||||||
|
Any keyword arguments passed to ``get_or_create()`` -- *except* an optional one
|
||||||
|
called ``defaults`` -- will be used in a ``get()`` call. If an object is found,
|
||||||
|
``get_or_create()`` returns a tuple of that object and ``False``. If an object
|
||||||
|
is *not* found, ``get_or_create()`` will instantiate and save a new object,
|
||||||
|
returning a tuple of the new object and ``True``. The new object will be
|
||||||
|
created according to this algorithm::
|
||||||
|
|
||||||
|
defaults = kwargs.pop('defaults', {})
|
||||||
|
params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
|
||||||
|
params.update(defaults)
|
||||||
|
obj = self.model(**params)
|
||||||
|
obj.save()
|
||||||
|
|
||||||
|
In English, that means start with any non-``'defaults'`` keyword argument that
|
||||||
|
doesn't contain a double underscore (which would indicate a non-exact lookup).
|
||||||
|
Then add the contents of ``defaults``, overriding any keys if necessary, and
|
||||||
|
use the result as the keyword arguments to the model class.
|
||||||
|
|
||||||
|
If you have a field named ``defaults`` and want to use it as an exact lookup in
|
||||||
|
``get_or_create()``, just use ``'defaults__exact'``, like so::
|
||||||
|
|
||||||
|
Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})
|
||||||
|
|
||||||
|
Finally, a word on using ``get_or_create()`` in Django views. As mentioned
|
||||||
|
earlier, ``get_or_create()`` is mostly useful in scripts that need to parse
|
||||||
|
data and create new records if existing ones aren't available. But if you need
|
||||||
|
to use ``get_or_create()`` in a view, please make sure to use it only in
|
||||||
|
``POST`` requests unless you have a good reason not to. ``GET`` requests
|
||||||
|
shouldn't have any effect on data; use ``POST`` whenever a request to a page
|
||||||
|
has a side effect on your data. For more, see `Safe methods`_ in the HTTP spec.
|
||||||
|
|
||||||
|
.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
|
||||||
|
|
||||||
``count()``
|
``count()``
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
|
41
docs/faq.txt
41
docs/faq.txt
@ -200,6 +200,23 @@ In the meantime, though, check out this `unofficial Django screencast`_.
|
|||||||
|
|
||||||
.. _unofficial Django screencast: http://www.throwingbeans.org/django_screencasts.html
|
.. _unofficial Django screencast: http://www.throwingbeans.org/django_screencasts.html
|
||||||
|
|
||||||
|
Is Django a content-management-system (CMS)?
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
No, Django is not a CMS, or any sort of "turnkey product" in and of itself.
|
||||||
|
It's a Web framework; it's a programming tool that lets you build Web sites.
|
||||||
|
|
||||||
|
For example, it doesn't make much sense to compare Django to something like
|
||||||
|
Drupal_, because Django is something you use to *create* things like Drupal.
|
||||||
|
|
||||||
|
Of course, Django's automatic admin site is fantastic and timesaving -- but
|
||||||
|
the admin site is one module of Django the framework. Furthermore, although
|
||||||
|
Django has special conveniences for building "CMS-y" apps, that doesn't mean
|
||||||
|
it's not just as appropriate for building "non-CMS-y" apps (whatever that
|
||||||
|
means!).
|
||||||
|
|
||||||
|
.. _Drupal: http://drupal.org/
|
||||||
|
|
||||||
When will you release Django 1.0?
|
When will you release Django 1.0?
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
@ -222,7 +239,7 @@ How can I download the Django documentation to read it offline?
|
|||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
|
|
||||||
The Django docs are available in the ``docs`` directory of each Django tarball
|
The Django docs are available in the ``docs`` directory of each Django tarball
|
||||||
release. These docs are in ReST (restructured text) format, and each text file
|
release. These docs are in ReST (ReStructured Text) format, and each text file
|
||||||
corresponds to a Web page on the official Django site.
|
corresponds to a Web page on the official Django site.
|
||||||
|
|
||||||
Because the documentation is `stored in revision control`_, you can browse
|
Because the documentation is `stored in revision control`_, you can browse
|
||||||
@ -297,13 +314,16 @@ as long as that server has WSGI_ hooks. See the `server arrangements wiki page`_
|
|||||||
How do I install mod_python on Windows?
|
How do I install mod_python on Windows?
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
* For Python 2.4, check out this `guide to mod_python & Python 2.3`_.
|
* For Python 2.4, grab mod_python from `win32 build of mod_python for
|
||||||
|
Python 2.4`_.
|
||||||
|
* For Python 2.4, check out this `Django on Windows howto`_.
|
||||||
* For Python 2.3, grab mod_python from http://www.modpython.org/ and read
|
* For Python 2.3, grab mod_python from http://www.modpython.org/ and read
|
||||||
`Running mod_python on Apache on Windows2000`_.
|
`Running mod_python on Apache on Windows2000`_.
|
||||||
* Also, try this (not Windows-specific) `guide to getting mod_python
|
* Also, try this (not Windows-specific) `guide to getting mod_python
|
||||||
working`_.
|
working`_.
|
||||||
|
|
||||||
.. _`guide to mod_python & Python 2.3`: http://www.lehuen.com/nicolas/index.php/2005/02/21/39-win32-build-of-mod_python-314-for-python-24
|
.. _`win32 build of mod_python for Python 2.4`: http://www.lehuen.com/nicolas/index.php/2005/02/21/39-win32-build-of-mod_python-314-for-python-24
|
||||||
|
.. _`Django on Windows howto`: http://thinkhole.org/wp/2006/04/03/django-on-windows-howto/
|
||||||
.. _`Running mod_python on Apache on Windows2000`: http://groups-beta.google.com/group/comp.lang.python/msg/139af8c83a5a9d4f
|
.. _`Running mod_python on Apache on Windows2000`: http://groups-beta.google.com/group/comp.lang.python/msg/139af8c83a5a9d4f
|
||||||
.. _`guide to getting mod_python working`: http://www.dscpl.com.au/articles/modpython-001.html
|
.. _`guide to getting mod_python working`: http://www.dscpl.com.au/articles/modpython-001.html
|
||||||
|
|
||||||
@ -388,19 +408,12 @@ Using a ``FileField`` or an ``ImageField`` in a model takes a few steps:
|
|||||||
If I make changes to a model, how do I update the database?
|
If I make changes to a model, how do I update the database?
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
|
|
||||||
If you don't mind clearing data, just pipe the output of the appropriate
|
If you don't mind clearing data, your project's ``manage.py`` utility has an
|
||||||
``django-admin.py sqlreset`` command into your database's command-line utility.
|
option to reset the SQL for a particular application::
|
||||||
For example::
|
|
||||||
|
|
||||||
django-admin.py sqlreset appname | psql dbname
|
manage.py reset appname
|
||||||
|
|
||||||
That "psql" assumes you're using PostgreSQL. If you're using MySQL, use the
|
This drops any tables associated with ``appname`` and recreates them.
|
||||||
appropriate command-line utility, ``mysql``.
|
|
||||||
|
|
||||||
``django-admin.py sqlreset`` outputs SQL that clears the app's database
|
|
||||||
table(s) and creates new ones. The above command uses a Unix pipe to send the
|
|
||||||
SQL directly to the PostgreSQL command-line utility, which accepts SQL as
|
|
||||||
input.
|
|
||||||
|
|
||||||
If you do care about deleting data, you'll have to execute the ``ALTER TABLE``
|
If you do care about deleting data, you'll have to execute the ``ALTER TABLE``
|
||||||
statements manually in your database. That's the way we've always done it,
|
statements manually in your database. That's the way we've always done it,
|
||||||
|
@ -15,6 +15,8 @@ We'll take a top-down approach to examining Django's form validation framework,
|
|||||||
because much of the time you won't need to use the lower-level APIs. Throughout
|
because much of the time you won't need to use the lower-level APIs. Throughout
|
||||||
this document, we'll be working with the following model, a "place" object::
|
this document, we'll be working with the following model, a "place" object::
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
PLACE_TYPES = (
|
PLACE_TYPES = (
|
||||||
(1, 'Bar'),
|
(1, 'Bar'),
|
||||||
(2, 'Restaurant'),
|
(2, 'Restaurant'),
|
||||||
@ -22,13 +24,13 @@ this document, we'll be working with the following model, a "place" object::
|
|||||||
(4, 'Secret Hideout'),
|
(4, 'Secret Hideout'),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Place(meta.Model):
|
class Place(models.Model):
|
||||||
name = meta.CharField(maxlength=100)
|
name = models.CharField(maxlength=100)
|
||||||
address = meta.CharField(maxlength=100, blank=True)
|
address = models.CharField(maxlength=100, blank=True)
|
||||||
city = meta.CharField(maxlength=50, blank=True)
|
city = models.CharField(maxlength=50, blank=True)
|
||||||
state = meta.USStateField()
|
state = models.USStateField()
|
||||||
zip_code = meta.CharField(maxlength=5, blank=True)
|
zip_code = models.CharField(maxlength=5, blank=True)
|
||||||
place_type = meta.IntegerField(choices=PLACE_TYPES)
|
place_type = models.IntegerField(choices=PLACE_TYPES)
|
||||||
|
|
||||||
class Admin:
|
class Admin:
|
||||||
pass
|
pass
|
||||||
|
@ -133,8 +133,8 @@ For example, to translate a model's ``help_text``, do the following::
|
|||||||
|
|
||||||
from django.utils.translation import gettext_lazy
|
from django.utils.translation import gettext_lazy
|
||||||
|
|
||||||
class MyThing(meta.Model):
|
class MyThing(models.Model):
|
||||||
name = meta.CharField(help_text=gettext_lazy('This is the help text'))
|
name = models.CharField(help_text=gettext_lazy('This is the help text'))
|
||||||
|
|
||||||
In this example, ``gettext_lazy()`` stores a lazy reference to the string --
|
In this example, ``gettext_lazy()`` stores a lazy reference to the string --
|
||||||
not the actual translation. The translation itself will be done when the string
|
not the actual translation. The translation itself will be done when the string
|
||||||
@ -145,8 +145,8 @@ If you don't like the verbose name ``gettext_lazy``, you can just alias it as
|
|||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
class MyThing(meta.Model):
|
class MyThing(models.Model):
|
||||||
name = meta.CharField(help_text=_('This is the help text'))
|
name = models.CharField(help_text=_('This is the help text'))
|
||||||
|
|
||||||
Always use lazy translations in `Django models`_. And it's a good idea to add
|
Always use lazy translations in `Django models`_. And it's a good idea to add
|
||||||
translations for the field names and table names, too. This means writing
|
translations for the field names and table names, too. This means writing
|
||||||
@ -155,8 +155,8 @@ class, though::
|
|||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
class MyThing(meta.Model):
|
class MyThing(models.Model):
|
||||||
name = meta.CharField(_('name'), help_text=_('This is the help text'))
|
name = models.CharField(_('name'), help_text=_('This is the help text'))
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('my thing')
|
verbose_name = _('my thing')
|
||||||
verbose_name_plural = _('mythings')
|
verbose_name_plural = _('mythings')
|
||||||
@ -230,12 +230,17 @@ Each ``RequestContext`` has access to two translation-specific variables:
|
|||||||
language code and the second is the language name (in that language).
|
language code and the second is the language name (in that language).
|
||||||
* ``LANGUAGE_CODE`` is the current user's preferred language, as a string.
|
* ``LANGUAGE_CODE`` is the current user's preferred language, as a string.
|
||||||
Example: ``en-us``. (See "How language preference is discovered", below.)
|
Example: ``en-us``. (See "How language preference is discovered", below.)
|
||||||
|
* ``LANGUAGE_BIDI`` is the current language's direction. If True, it's a
|
||||||
|
right-to-left language, e.g: Hebrew, Arabic. If False it's a
|
||||||
|
left-to-right language, e.g: English, French, German etc.
|
||||||
|
|
||||||
|
|
||||||
If you don't use the ``RequestContext`` extension, you can get those values with
|
If you don't use the ``RequestContext`` extension, you can get those values with
|
||||||
two tags::
|
three tags::
|
||||||
|
|
||||||
{% get_current_language as LANGUAGE_CODE %}
|
{% get_current_language as LANGUAGE_CODE %}
|
||||||
{% get_available_languages as LANGUAGES %}
|
{% get_available_languages as LANGUAGES %}
|
||||||
|
{% get_current_language_bidi as LANGUAGE_BIDI %}
|
||||||
|
|
||||||
These tags also require a ``{% load i18n %}``.
|
These tags also require a ``{% load i18n %}``.
|
||||||
|
|
||||||
|
@ -445,7 +445,8 @@ empty value. If a field has ``blank=False``, the field will be required.
|
|||||||
``choices``
|
``choices``
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
A list of 2-tuples to use as choices for this field.
|
An iterable (e.g., a list or tuple) of 2-tuples to use as choices for this
|
||||||
|
field.
|
||||||
|
|
||||||
If this is given, Django's admin will use a select box instead of the
|
If this is given, Django's admin will use a select box instead of the
|
||||||
standard text field and will limit choices to the choices given.
|
standard text field and will limit choices to the choices given.
|
||||||
@ -481,6 +482,12 @@ or outside your model class altogether::
|
|||||||
class Foo(models.Model):
|
class Foo(models.Model):
|
||||||
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
|
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
|
||||||
|
|
||||||
|
Finally, note that choices can be any iterable object -- not necessarily a
|
||||||
|
list or tuple. This lets you construct choices dynamically. But if you find
|
||||||
|
yourself hacking ``choices`` to be dynamic, you're probably better off using
|
||||||
|
a proper database table with a ``ForeignKey``. ``choices`` is meant for static
|
||||||
|
data that doesn't change much, if ever.
|
||||||
|
|
||||||
``core``
|
``core``
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
|
|
||||||
|
@ -400,6 +400,10 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
|
|||||||
``HttpResponseForbidden``
|
``HttpResponseForbidden``
|
||||||
Acts just like ``HttpResponse`` but uses a 403 status code.
|
Acts just like ``HttpResponse`` but uses a 403 status code.
|
||||||
|
|
||||||
|
``HttpResponseNotAllowed``
|
||||||
|
Like ``HttpResponse``, but uses a 405 status code. Takes a single,
|
||||||
|
required argument: a list of permitted methods (e.g. ``['GET', 'POST']``).
|
||||||
|
|
||||||
``HttpResponseGone``
|
``HttpResponseGone``
|
||||||
Acts just like ``HttpResponse`` but uses a 410 status code.
|
Acts just like ``HttpResponse`` but uses a 410 status code.
|
||||||
|
|
||||||
|
@ -439,6 +439,23 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
|
|||||||
|
|
||||||
author_link = 'http://www.example.com/' # Hard-coded author URL.
|
author_link = 'http://www.example.com/' # Hard-coded author URL.
|
||||||
|
|
||||||
|
# CATEGORIES -- One of the following three is optional. The framework
|
||||||
|
# looks for them in this order. In each case, the method/attribute
|
||||||
|
# should return an iterable object that returns strings.
|
||||||
|
|
||||||
|
def categories(self, obj):
|
||||||
|
"""
|
||||||
|
Takes the object returned by get_object() and returns the feed's
|
||||||
|
categories as iterable over strings.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def categories(self):
|
||||||
|
"""
|
||||||
|
Returns the feed's categories as iterable over strings.
|
||||||
|
"""
|
||||||
|
|
||||||
|
categories = ("python", "django") # Hard-coded list of categories.
|
||||||
|
|
||||||
# ITEMS -- One of the following three is required. The framework looks
|
# ITEMS -- One of the following three is required. The framework looks
|
||||||
# for them in this order.
|
# for them in this order.
|
||||||
|
|
||||||
@ -602,6 +619,25 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
|
|||||||
|
|
||||||
item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate.
|
item_pubdate = datetime.datetime(2005, 5, 3) # Hard-coded pubdate.
|
||||||
|
|
||||||
|
# ITEM CATEGORIES -- It's optional to use one of these three. This is
|
||||||
|
# a hook that specifies how to get the list of categories for a given
|
||||||
|
# item. In each case, the method/attribute should return an iterable
|
||||||
|
# object that returns strings.
|
||||||
|
|
||||||
|
def item_categories(self, item):
|
||||||
|
"""
|
||||||
|
Takes an item, as returned by items(), and returns the item's
|
||||||
|
categories.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def item_categories(self):
|
||||||
|
"""
|
||||||
|
Returns the categories for every item in the feed.
|
||||||
|
"""
|
||||||
|
|
||||||
|
item_categories = ("python", "django") # Hard-coded categories.
|
||||||
|
|
||||||
|
|
||||||
The low-level framework
|
The low-level framework
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
|
@ -454,8 +454,12 @@ displayed by the ``{{ athlete_list|length }}`` variable.
|
|||||||
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
|
As you can see, the ``if`` tag can take an option ``{% else %}`` clause that
|
||||||
will be displayed if the test fails.
|
will be displayed if the test fails.
|
||||||
|
|
||||||
``if`` tags may use ``or`` or ``not`` to test a number of variables or to negate
|
``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or
|
||||||
a given variable::
|
to negate a given variable::
|
||||||
|
|
||||||
|
{% if athlete_list and coach_list %}
|
||||||
|
Both athletes and coaches are available.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% if not athlete_list %}
|
{% if not athlete_list %}
|
||||||
There are no athletes.
|
There are no athletes.
|
||||||
@ -468,16 +472,24 @@ a given variable::
|
|||||||
{% if not athlete_list or coach_list %}
|
{% if not athlete_list or coach_list %}
|
||||||
There are no athletes or there are some coaches (OK, so
|
There are no athletes or there are some coaches (OK, so
|
||||||
writing English translations of boolean logic sounds
|
writing English translations of boolean logic sounds
|
||||||
stupid; it's not my fault).
|
stupid; it's not our fault).
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
For simplicity, ``if`` tags do not allow ``and`` clauses; use nested ``if``
|
{% if athlete_list and not coach_list %}
|
||||||
tags instead::
|
There are some athletes and absolutely no coaches.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
``if`` tags don't allow ``and`` and ``or`` clauses within the same tag, because
|
||||||
|
the order of logic would be ambiguous. For example, this is invalid::
|
||||||
|
|
||||||
|
{% if athlete_list and coach_list or cheerleader_list %}
|
||||||
|
|
||||||
|
If you need to combine ``and`` and ``or`` to do advanced logic, just use nested
|
||||||
|
``if`` tags. For example::
|
||||||
|
|
||||||
{% if athlete_list %}
|
{% if athlete_list %}
|
||||||
{% if coach_list %}
|
{% if coach_list or cheerleader_list %}
|
||||||
Number of athletes: {{ athlete_list|length }}.
|
We have athletes, and either coaches or cheerleaders!
|
||||||
Number of coaches: {{ coach_list|length }}.
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
@ -754,6 +766,8 @@ The argument tells which template bit to output:
|
|||||||
``closeblock`` ``%}``
|
``closeblock`` ``%}``
|
||||||
``openvariable`` ``{{``
|
``openvariable`` ``{{``
|
||||||
``closevariable`` ``}}``
|
``closevariable`` ``}}``
|
||||||
|
``openbrace`` ``{``
|
||||||
|
``closebrace`` ``}``
|
||||||
================== =======
|
================== =======
|
||||||
|
|
||||||
widthratio
|
widthratio
|
||||||
|
@ -502,12 +502,13 @@ Although the Django template language comes with several default tags and
|
|||||||
filters, you might want to write your own. It's easy to do.
|
filters, you might want to write your own. It's easy to do.
|
||||||
|
|
||||||
First, create a ``templatetags`` package in the appropriate Django app's
|
First, create a ``templatetags`` package in the appropriate Django app's
|
||||||
package. It should be on the same level as ``models``, ``views.py``, etc. For
|
package. It should be on the same level as ``models.py``, ``views.py``, etc. For
|
||||||
example::
|
example::
|
||||||
|
|
||||||
polls/
|
polls/
|
||||||
models/
|
models.py
|
||||||
templatetags/
|
templatetags/
|
||||||
|
views.py
|
||||||
|
|
||||||
Add two files to the ``templatetags`` package: an ``__init__.py`` file and a
|
Add two files to the ``templatetags`` package: an ``__init__.py`` file and a
|
||||||
file that will contain your custom tag/filter definitions. The name of the
|
file that will contain your custom tag/filter definitions. The name of the
|
||||||
|
@ -8,7 +8,8 @@ this behavior by explicitly adding ``primary_key=True`` to a field.
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
class Employee(models.Model):
|
class Employee(models.Model):
|
||||||
employee_code = models.CharField(maxlength=10, primary_key=True)
|
employee_code = models.CharField(maxlength=10, primary_key=True,
|
||||||
|
db_column = 'code')
|
||||||
first_name = models.CharField(maxlength=20)
|
first_name = models.CharField(maxlength=20)
|
||||||
last_name = models.CharField(maxlength=20)
|
last_name = models.CharField(maxlength=20)
|
||||||
class Meta:
|
class Meta:
|
||||||
|
0
tests/modeltests/empty/__init__.py
Normal file
0
tests/modeltests/empty/__init__.py
Normal file
24
tests/modeltests/empty/models.py
Normal file
24
tests/modeltests/empty/models.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
"""
|
||||||
|
Empty model tests
|
||||||
|
|
||||||
|
These test that things behave sensibly for the rare corner-case of a model with
|
||||||
|
no fields.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Empty(models.Model):
|
||||||
|
pass
|
||||||
|
|
||||||
|
API_TESTS = """
|
||||||
|
>>> m = Empty()
|
||||||
|
>>> m.id
|
||||||
|
>>> m.save()
|
||||||
|
>>> m2 = Empty()
|
||||||
|
>>> m2.save()
|
||||||
|
>>> len(Empty.objects.all())
|
||||||
|
2
|
||||||
|
>>> m.id is not None
|
||||||
|
True
|
||||||
|
|
||||||
|
"""
|
0
tests/modeltests/generic_relations/__init__.py
Normal file
0
tests/modeltests/generic_relations/__init__.py
Normal file
108
tests/modeltests/generic_relations/models.py
Normal file
108
tests/modeltests/generic_relations/models.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
"""
|
||||||
|
33. Generic relations
|
||||||
|
|
||||||
|
Generic relations let an object have a foreign key to any object through a
|
||||||
|
content-type/object-id field. A generic foreign key can point to any object,
|
||||||
|
be it animal, vegetable, or mineral.
|
||||||
|
|
||||||
|
The cannonical example is tags (although this example implementation is *far*
|
||||||
|
from complete).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
|
class TaggedItem(models.Model):
|
||||||
|
"""A tag on an item."""
|
||||||
|
tag = models.SlugField()
|
||||||
|
content_type = models.ForeignKey(ContentType)
|
||||||
|
object_id = models.PositiveIntegerField()
|
||||||
|
|
||||||
|
content_object = models.GenericForeignKey()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ["tag"]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.tag
|
||||||
|
|
||||||
|
class Animal(models.Model):
|
||||||
|
common_name = models.CharField(maxlength=150)
|
||||||
|
latin_name = models.CharField(maxlength=150)
|
||||||
|
|
||||||
|
tags = models.GenericRelation(TaggedItem)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.common_name
|
||||||
|
|
||||||
|
class Vegetable(models.Model):
|
||||||
|
name = models.CharField(maxlength=150)
|
||||||
|
is_yucky = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
tags = models.GenericRelation(TaggedItem)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class Mineral(models.Model):
|
||||||
|
name = models.CharField(maxlength=150)
|
||||||
|
hardness = models.PositiveSmallIntegerField()
|
||||||
|
|
||||||
|
# note the lack of an explicit GenericRelation here...
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
API_TESTS = """
|
||||||
|
# Create the world in 7 lines of code...
|
||||||
|
>>> lion = Animal(common_name="Lion", latin_name="Panthera leo")
|
||||||
|
>>> platypus = Animal(common_name="Platypus", latin_name="Ornithorhynchus anatinus")
|
||||||
|
>>> eggplant = Vegetable(name="Eggplant", is_yucky=True)
|
||||||
|
>>> bacon = Vegetable(name="Bacon", is_yucky=False)
|
||||||
|
>>> quartz = Mineral(name="Quartz", hardness=7)
|
||||||
|
>>> for o in (lion, platypus, eggplant, bacon, quartz):
|
||||||
|
... o.save()
|
||||||
|
|
||||||
|
# Objects with declared GenericRelations can be tagged directly -- the API
|
||||||
|
# mimics the many-to-many API
|
||||||
|
>>> lion.tags.create(tag="yellow")
|
||||||
|
<TaggedItem: yellow>
|
||||||
|
>>> lion.tags.create(tag="hairy")
|
||||||
|
<TaggedItem: hairy>
|
||||||
|
>>> bacon.tags.create(tag="fatty")
|
||||||
|
<TaggedItem: fatty>
|
||||||
|
>>> bacon.tags.create(tag="salty")
|
||||||
|
<TaggedItem: salty>
|
||||||
|
|
||||||
|
>>> lion.tags.all()
|
||||||
|
[<TaggedItem: hairy>, <TaggedItem: yellow>]
|
||||||
|
>>> bacon.tags.all()
|
||||||
|
[<TaggedItem: fatty>, <TaggedItem: salty>]
|
||||||
|
|
||||||
|
# You can easily access the content object like a foreign key
|
||||||
|
>>> t = TaggedItem.objects.get(tag="salty")
|
||||||
|
>>> t.content_object
|
||||||
|
<Vegetable: Bacon>
|
||||||
|
|
||||||
|
# Recall that the Mineral class doesn't have an explicit GenericRelation
|
||||||
|
# defined. That's OK since you can create TaggedItems explicitally.
|
||||||
|
>>> tag1 = TaggedItem(content_object=quartz, tag="shiny")
|
||||||
|
>>> tag2 = TaggedItem(content_object=quartz, tag="clearish")
|
||||||
|
>>> tag1.save()
|
||||||
|
>>> tag2.save()
|
||||||
|
|
||||||
|
# However, not having the convience takes a small toll when it comes
|
||||||
|
# to do lookups
|
||||||
|
>>> from django.contrib.contenttypes.models import ContentType
|
||||||
|
>>> ctype = ContentType.objects.get_for_model(quartz)
|
||||||
|
>>> TaggedItem.objects.filter(content_type__pk=ctype.id, object_id=quartz.id)
|
||||||
|
[<TaggedItem: clearish>, <TaggedItem: shiny>]
|
||||||
|
|
||||||
|
# You can set a generic foreign key in the way you'd expect
|
||||||
|
>>> tag1.content_object = platypus
|
||||||
|
>>> tag1.save()
|
||||||
|
>>> platypus.tags.all()
|
||||||
|
[<TaggedItem: shiny>]
|
||||||
|
>>> TaggedItem.objects.filter(content_type__pk=ctype.id, object_id=quartz.id)
|
||||||
|
[<TaggedItem: clearish>]
|
||||||
|
"""
|
0
tests/modeltests/get_or_create/__init__.py
Normal file
0
tests/modeltests/get_or_create/__init__.py
Normal file
52
tests/modeltests/get_or_create/models.py
Normal file
52
tests/modeltests/get_or_create/models.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
"""
|
||||||
|
32. get_or_create()
|
||||||
|
|
||||||
|
get_or_create() does what it says: it tries to look up an object with the given
|
||||||
|
parameters. If an object isn't found, it creates one with the given parameters.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
|
class Person(models.Model):
|
||||||
|
first_name = models.CharField(maxlength=100)
|
||||||
|
last_name = models.CharField(maxlength=100)
|
||||||
|
birthday = models.DateField()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '%s %s' % (self.first_name, self.last_name)
|
||||||
|
|
||||||
|
API_TESTS = """
|
||||||
|
# Acting as a divine being, create an Person.
|
||||||
|
>>> from datetime import date
|
||||||
|
>>> p = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
|
||||||
|
>>> p.save()
|
||||||
|
|
||||||
|
# Only one Person is in the database at this point.
|
||||||
|
>>> Person.objects.count()
|
||||||
|
1
|
||||||
|
|
||||||
|
# get_or_create() a person with similar first names.
|
||||||
|
>>> p, created = Person.objects.get_or_create(first_name='John', last_name='Lennon', defaults={'birthday': date(1940, 10, 9)})
|
||||||
|
|
||||||
|
# get_or_create() didn't have to create an object.
|
||||||
|
>>> created
|
||||||
|
False
|
||||||
|
|
||||||
|
# There's still only one Person in the database.
|
||||||
|
>>> Person.objects.count()
|
||||||
|
1
|
||||||
|
|
||||||
|
# get_or_create() a Person with a different name.
|
||||||
|
>>> p, created = Person.objects.get_or_create(first_name='George', last_name='Harrison', defaults={'birthday': date(1943, 2, 25)})
|
||||||
|
>>> created
|
||||||
|
True
|
||||||
|
>>> Person.objects.count()
|
||||||
|
2
|
||||||
|
|
||||||
|
# If we execute the exact same statement, it won't create a Person.
|
||||||
|
>>> p, created = Person.objects.get_or_create(first_name='George', last_name='Harrison', defaults={'birthday': date(1943, 2, 25)})
|
||||||
|
>>> created
|
||||||
|
False
|
||||||
|
>>> Person.objects.count()
|
||||||
|
2
|
||||||
|
"""
|
@ -74,7 +74,7 @@ invalid_models.fielderrors: "floatfield": FloatFields require a "decimal_places"
|
|||||||
invalid_models.fielderrors: "floatfield": FloatFields require a "max_digits" attribute.
|
invalid_models.fielderrors: "floatfield": FloatFields require a "max_digits" attribute.
|
||||||
invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute.
|
invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute.
|
||||||
invalid_models.fielderrors: "prepopulate": prepopulate_from should be a list or tuple.
|
invalid_models.fielderrors: "prepopulate": prepopulate_from should be a list or tuple.
|
||||||
invalid_models.fielderrors: "choices": "choices" should be either a tuple or list.
|
invalid_models.fielderrors: "choices": "choices" should be iterable (e.g., a tuple or list).
|
||||||
invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples.
|
invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples.
|
||||||
invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples.
|
invalid_models.fielderrors: "choices2": "choices" should be a sequence of two-tuples.
|
||||||
invalid_models.fielderrors: "index": "db_index" should be either None, True or False.
|
invalid_models.fielderrors: "index": "db_index" should be either None, True or False.
|
||||||
|
@ -12,8 +12,14 @@ class Person(models.Model):
|
|||||||
|
|
||||||
def _get_full_name(self):
|
def _get_full_name(self):
|
||||||
return "%s %s" % (self.first_name, self.last_name)
|
return "%s %s" % (self.first_name, self.last_name)
|
||||||
|
|
||||||
|
def _set_full_name(self, combined_name):
|
||||||
|
self.first_name, self.last_name = combined_name.split(' ', 1)
|
||||||
|
|
||||||
full_name = property(_get_full_name)
|
full_name = property(_get_full_name)
|
||||||
|
|
||||||
|
full_name_2 = property(_get_full_name, _set_full_name)
|
||||||
|
|
||||||
API_TESTS = """
|
API_TESTS = """
|
||||||
>>> a = Person(first_name='John', last_name='Lennon')
|
>>> a = Person(first_name='John', last_name='Lennon')
|
||||||
>>> a.save()
|
>>> a.save()
|
||||||
@ -25,4 +31,10 @@ API_TESTS = """
|
|||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
AttributeError: can't set attribute
|
AttributeError: can't set attribute
|
||||||
|
|
||||||
|
# But "full_name_2" has, and it can be used to initialise the class.
|
||||||
|
>>> a2 = Person(full_name_2 = 'Paul McCartney')
|
||||||
|
>>> a2.save()
|
||||||
|
>>> a2.first_name
|
||||||
|
'Paul'
|
||||||
"""
|
"""
|
||||||
|
@ -169,8 +169,7 @@ TEMPLATE_TESTS = {
|
|||||||
'comment-tag05': ("foo{% comment %} {% somerandomtag %} {% endcomment %}", {}, "foo"),
|
'comment-tag05': ("foo{% comment %} {% somerandomtag %} {% endcomment %}", {}, "foo"),
|
||||||
|
|
||||||
### CYCLE TAG #############################################################
|
### CYCLE TAG #############################################################
|
||||||
#'cycleXX': ('', {}, ''),
|
'cycle01': ('{% cycle a %}', {}, template.TemplateSyntaxError),
|
||||||
'cycle01': ('{% cycle a, %}', {}, 'a'),
|
|
||||||
'cycle02': ('{% cycle a,b,c as abc %}{% cycle abc %}', {}, 'ab'),
|
'cycle02': ('{% cycle a,b,c as abc %}{% cycle abc %}', {}, 'ab'),
|
||||||
'cycle03': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}', {}, 'abc'),
|
'cycle03': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}', {}, 'abc'),
|
||||||
'cycle04': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}', {}, 'abca'),
|
'cycle04': ('{% cycle a,b,c as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}', {}, 'abca'),
|
||||||
@ -193,13 +192,11 @@ TEMPLATE_TESTS = {
|
|||||||
'exception04': ("{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}", {}, template.TemplateSyntaxError),
|
'exception04': ("{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}", {}, template.TemplateSyntaxError),
|
||||||
|
|
||||||
### FILTER TAG ############################################################
|
### FILTER TAG ############################################################
|
||||||
#'filterXX': ('', {}, ''),
|
|
||||||
'filter01': ('{% filter upper %}{% endfilter %}', {}, ''),
|
'filter01': ('{% filter upper %}{% endfilter %}', {}, ''),
|
||||||
'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'),
|
'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'),
|
||||||
'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'),
|
'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'),
|
||||||
|
|
||||||
### FIRSTOF TAG ###########################################################
|
### FIRSTOF TAG ###########################################################
|
||||||
#'firstofXX': ('', {}, ''),
|
|
||||||
'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''),
|
'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''),
|
||||||
'firstof02': ('{% firstof a b c %}', {'a':1,'b':0,'c':0}, '1'),
|
'firstof02': ('{% firstof a b c %}', {'a':1,'b':0,'c':0}, '1'),
|
||||||
'firstof03': ('{% firstof a b c %}', {'a':0,'b':2,'c':0}, '2'),
|
'firstof03': ('{% firstof a b c %}', {'a':0,'b':2,'c':0}, '2'),
|
||||||
@ -220,8 +217,79 @@ TEMPLATE_TESTS = {
|
|||||||
'if-tag02': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": False}, "no"),
|
'if-tag02': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": False}, "no"),
|
||||||
'if-tag03': ("{% if foo %}yes{% else %}no{% endif %}", {}, "no"),
|
'if-tag03': ("{% if foo %}yes{% else %}no{% endif %}", {}, "no"),
|
||||||
|
|
||||||
|
# AND
|
||||||
|
'if-tag-and01': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
|
||||||
|
'if-tag-and02': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
|
||||||
|
'if-tag-and03': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
|
||||||
|
'if-tag-and04': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
|
||||||
|
'if-tag-and05': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'),
|
||||||
|
'if-tag-and06': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'),
|
||||||
|
'if-tag-and07': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True}, 'no'),
|
||||||
|
'if-tag-and08': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'bar': True}, 'no'),
|
||||||
|
|
||||||
|
# OR
|
||||||
|
'if-tag-or01': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
|
||||||
|
'if-tag-or02': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
|
||||||
|
'if-tag-or03': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
|
||||||
|
'if-tag-or04': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
|
||||||
|
'if-tag-or05': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': False}, 'no'),
|
||||||
|
'if-tag-or06': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': False}, 'no'),
|
||||||
|
'if-tag-or07': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True}, 'yes'),
|
||||||
|
'if-tag-or08': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': True}, 'yes'),
|
||||||
|
|
||||||
|
# TODO: multiple ORs
|
||||||
|
|
||||||
|
# NOT
|
||||||
|
'if-tag-not01': ("{% if not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'yes'),
|
||||||
|
'if-tag-not02': ("{% if not %}yes{% else %}no{% endif %}", {'foo': True}, 'no'),
|
||||||
|
'if-tag-not03': ("{% if not %}yes{% else %}no{% endif %}", {'not': True}, 'yes'),
|
||||||
|
'if-tag-not04': ("{% if not not %}no{% else %}yes{% endif %}", {'not': True}, 'yes'),
|
||||||
|
'if-tag-not05': ("{% if not not %}no{% else %}yes{% endif %}", {}, 'no'),
|
||||||
|
|
||||||
|
'if-tag-not06': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {}, 'no'),
|
||||||
|
'if-tag-not07': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
|
||||||
|
'if-tag-not08': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
|
||||||
|
'if-tag-not09': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
|
||||||
|
'if-tag-not10': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
|
||||||
|
|
||||||
|
'if-tag-not11': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {}, 'no'),
|
||||||
|
'if-tag-not12': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
|
||||||
|
'if-tag-not13': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
|
||||||
|
'if-tag-not14': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
|
||||||
|
'if-tag-not15': ("{% if not foo and bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'no'),
|
||||||
|
|
||||||
|
'if-tag-not16': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
|
||||||
|
'if-tag-not17': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
|
||||||
|
'if-tag-not18': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
|
||||||
|
'if-tag-not19': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
|
||||||
|
'if-tag-not20': ("{% if foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
|
||||||
|
|
||||||
|
'if-tag-not21': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {}, 'yes'),
|
||||||
|
'if-tag-not22': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
|
||||||
|
'if-tag-not23': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
|
||||||
|
'if-tag-not24': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
|
||||||
|
'if-tag-not25': ("{% if not foo or bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
|
||||||
|
|
||||||
|
'if-tag-not26': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
|
||||||
|
'if-tag-not27': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
|
||||||
|
'if-tag-not28': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
|
||||||
|
'if-tag-not29': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'no'),
|
||||||
|
'if-tag-not30': ("{% if not foo and not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
|
||||||
|
|
||||||
|
'if-tag-not31': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {}, 'yes'),
|
||||||
|
'if-tag-not32': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
|
||||||
|
'if-tag-not33': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'yes'),
|
||||||
|
'if-tag-not34': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, 'yes'),
|
||||||
|
'if-tag-not35': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
|
||||||
|
|
||||||
|
# AND and OR raises a TemplateSyntaxError
|
||||||
|
'if-tag-error01': ("{% if foo or bar and baz %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error02': ("{% if foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error03': ("{% if foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error04': ("{% if not foo and %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error05': ("{% if not foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
|
||||||
|
|
||||||
### IFCHANGED TAG #########################################################
|
### IFCHANGED TAG #########################################################
|
||||||
#'ifchangedXX': ('', {}, ''),
|
|
||||||
'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,2,3) }, '123'),
|
'ifchanged01': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,2,3) }, '123'),
|
||||||
'ifchanged02': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,3) }, '13'),
|
'ifchanged02': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,3) }, '13'),
|
||||||
'ifchanged03': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,1) }, '1'),
|
'ifchanged03': ('{% for n in num %}{% ifchanged %}{{ n }}{% endifchanged %}{% endfor %}', { 'num': (1,1,1) }, '1'),
|
||||||
@ -238,6 +306,18 @@ TEMPLATE_TESTS = {
|
|||||||
'ifequal09': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {}, "no"),
|
'ifequal09': ('{% ifequal a "test" %}yes{% else %}no{% endifequal %}', {}, "no"),
|
||||||
'ifequal10': ('{% ifequal a b %}yes{% else %}no{% endifequal %}', {}, "yes"),
|
'ifequal10': ('{% ifequal a b %}yes{% else %}no{% endifequal %}', {}, "yes"),
|
||||||
|
|
||||||
|
# SMART SPLITTING
|
||||||
|
'ifequal-split01': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {}, "no"),
|
||||||
|
'ifequal-split02': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'foo'}, "no"),
|
||||||
|
'ifequal-split03': ('{% ifequal a "test man" %}yes{% else %}no{% endifequal %}', {'a': 'test man'}, "yes"),
|
||||||
|
'ifequal-split04': ("{% ifequal a 'test man' %}yes{% else %}no{% endifequal %}", {'a': 'test man'}, "yes"),
|
||||||
|
'ifequal-split05': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': ''}, "no"),
|
||||||
|
'ifequal-split06': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i "love" you'}, "yes"),
|
||||||
|
'ifequal-split07': ("{% ifequal a 'i \"love\" you' %}yes{% else %}no{% endifequal %}", {'a': 'i love you'}, "no"),
|
||||||
|
'ifequal-split08': (r"{% ifequal a 'I\'m happy' %}yes{% else %}no{% endifequal %}", {'a': "I'm happy"}, "yes"),
|
||||||
|
'ifequal-split09': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slash\man"}, "yes"),
|
||||||
|
'ifequal-split10': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slashman"}, "no"),
|
||||||
|
|
||||||
### IFNOTEQUAL TAG ########################################################
|
### IFNOTEQUAL TAG ########################################################
|
||||||
'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
|
'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
|
||||||
'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
|
'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
|
||||||
@ -388,7 +468,6 @@ TEMPLATE_TESTS = {
|
|||||||
"""),
|
"""),
|
||||||
|
|
||||||
### REGROUP TAG ###########################################################
|
### REGROUP TAG ###########################################################
|
||||||
#'regroupXX': ('', {}, ''),
|
|
||||||
'regroup01': ('{% regroup data by bar as grouped %}' + \
|
'regroup01': ('{% regroup data by bar as grouped %}' + \
|
||||||
'{% for group in grouped %}' + \
|
'{% for group in grouped %}' + \
|
||||||
'{{ group.grouper }}:' + \
|
'{{ group.grouper }}:' + \
|
||||||
@ -414,16 +493,18 @@ TEMPLATE_TESTS = {
|
|||||||
{}, ''),
|
{}, ''),
|
||||||
|
|
||||||
### TEMPLATETAG TAG #######################################################
|
### TEMPLATETAG TAG #######################################################
|
||||||
#'templatetagXX': ('', {}, ''),
|
|
||||||
'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
|
'templatetag01': ('{% templatetag openblock %}', {}, '{%'),
|
||||||
'templatetag02': ('{% templatetag closeblock %}', {}, '%}'),
|
'templatetag02': ('{% templatetag closeblock %}', {}, '%}'),
|
||||||
'templatetag03': ('{% templatetag openvariable %}', {}, '{{'),
|
'templatetag03': ('{% templatetag openvariable %}', {}, '{{'),
|
||||||
'templatetag04': ('{% templatetag closevariable %}', {}, '}}'),
|
'templatetag04': ('{% templatetag closevariable %}', {}, '}}'),
|
||||||
'templatetag05': ('{% templatetag %}', {}, template.TemplateSyntaxError),
|
'templatetag05': ('{% templatetag %}', {}, template.TemplateSyntaxError),
|
||||||
'templatetag06': ('{% templatetag foo %}', {}, template.TemplateSyntaxError),
|
'templatetag06': ('{% templatetag foo %}', {}, template.TemplateSyntaxError),
|
||||||
|
'templatetag07': ('{% templatetag openbrace %}', {}, '{'),
|
||||||
|
'templatetag08': ('{% templatetag closebrace %}', {}, '}'),
|
||||||
|
'templatetag09': ('{% templatetag openbrace %}{% templatetag openbrace %}', {}, '{{'),
|
||||||
|
'templatetag10': ('{% templatetag closebrace %}{% templatetag closebrace %}', {}, '}}'),
|
||||||
|
|
||||||
### WIDTHRATIO TAG ########################################################
|
### WIDTHRATIO TAG ########################################################
|
||||||
#'widthratioXX': ('', {}, ''),
|
|
||||||
'widthratio01': ('{% widthratio a b 0 %}', {'a':50,'b':100}, '0'),
|
'widthratio01': ('{% widthratio a b 0 %}', {'a':50,'b':100}, '0'),
|
||||||
'widthratio02': ('{% widthratio a b 100 %}', {'a':0,'b':0}, ''),
|
'widthratio02': ('{% widthratio a b 100 %}', {'a':0,'b':0}, ''),
|
||||||
'widthratio03': ('{% widthratio a b 100 %}', {'a':0,'b':100}, '0'),
|
'widthratio03': ('{% widthratio a b 100 %}', {'a':0,'b':100}, '0'),
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user