mirror of
https://github.com/django/django.git
synced 2025-07-05 02:09:13 +00:00
[soc2009/multidb] Merged up to trunk r11810. There are many conflicts in this merge, these will be resolved in a subsequent commit.
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/multidb@11812 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
353e079792
commit
c88113683d
@ -131,9 +131,12 @@ DATABASE_HOST = '' # Set to empty string for localhost. Not used wit
|
|||||||
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
||||||
DATABASE_OPTIONS = {} # Set to empty dictionary for default.
|
DATABASE_OPTIONS = {} # Set to empty dictionary for default.
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/global_settings.py
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> master:django/conf/global_settings.py
|
||||||
# The email backend to use. For possible shortcuts see django.core.mail.
|
# The email backend to use. For possible shortcuts see django.core.mail.
|
||||||
# The default is to use the SMTP backend.
|
# The default is to use the SMTP backend.
|
||||||
# Third-party backends can be specified by providing a Python path
|
# Third-party backends can be specified by providing a Python path
|
||||||
|
@ -5,7 +5,11 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Django\n"
|
"Project-Id-Version: Django\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
"POT-Creation-Date: 2009-10-25 20:56+0100\n"
|
"POT-Creation-Date: 2009-10-25 20:56+0100\n"
|
||||||
|
=======
|
||||||
|
"POT-Creation-Date: 2009-12-11 10:11+0100\n"
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
"PO-Revision-Date: 2008-02-25 15:53+0100\n"
|
"PO-Revision-Date: 2008-02-25 15:53+0100\n"
|
||||||
"Last-Translator: Jarek Zgoda <jarek.zgoda@gmail.com>\n"
|
"Last-Translator: Jarek Zgoda <jarek.zgoda@gmail.com>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
@ -223,7 +227,11 @@ msgstr "chiński tradycyjny"
|
|||||||
msgid "Successfully deleted %(count)d %(items)s."
|
msgid "Successfully deleted %(count)d %(items)s."
|
||||||
msgstr "Usunięto %(count)d %(items)s."
|
msgstr "Usunięto %(count)d %(items)s."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/actions.py:67 contrib/admin/options.py:1027
|
#: contrib/admin/actions.py:67 contrib/admin/options.py:1027
|
||||||
|
=======
|
||||||
|
#: contrib/admin/actions.py:67 contrib/admin/options.py:1034
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
msgstr "Jesteś pewien?"
|
msgstr "Jesteś pewien?"
|
||||||
|
|
||||||
@ -310,87 +318,132 @@ msgstr "log"
|
|||||||
msgid "log entries"
|
msgid "log entries"
|
||||||
msgstr "logi"
|
msgstr "logi"
|
||||||
|
|
||||||
#: contrib/admin/options.py:133 contrib/admin/options.py:147
|
#: contrib/admin/options.py:135 contrib/admin/options.py:149
|
||||||
msgid "None"
|
msgid "None"
|
||||||
msgstr "brak"
|
msgstr "brak"
|
||||||
|
|
||||||
#: contrib/admin/options.py:519
|
#: contrib/admin/options.py:522
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Changed %s."
|
msgid "Changed %s."
|
||||||
msgstr "Zmieniono %s"
|
msgstr "Zmieniono %s"
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:519 contrib/admin/options.py:529
|
#: contrib/admin/options.py:519 contrib/admin/options.py:529
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:522 contrib/admin/options.py:532
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/comments/templates/comments/preview.html:16 forms/models.py:384
|
#: contrib/comments/templates/comments/preview.html:16 forms/models.py:384
|
||||||
#: forms/models.py:596
|
#: forms/models.py:596
|
||||||
msgid "and"
|
msgid "and"
|
||||||
msgstr "i"
|
msgstr "i"
|
||||||
|
|
||||||
#: contrib/admin/options.py:524
|
#: contrib/admin/options.py:527
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Added %(name)s \"%(object)s\"."
|
msgid "Added %(name)s \"%(object)s\"."
|
||||||
msgstr "Dodano %(name)s \"%(object)s\"."
|
msgstr "Dodano %(name)s \"%(object)s\"."
|
||||||
|
|
||||||
#: contrib/admin/options.py:528
|
#: contrib/admin/options.py:531
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Changed %(list)s for %(name)s \"%(object)s\"."
|
msgid "Changed %(list)s for %(name)s \"%(object)s\"."
|
||||||
msgstr "Zmieniono %(list)s w %(name)s \"%(object)s\"."
|
msgstr "Zmieniono %(list)s w %(name)s \"%(object)s\"."
|
||||||
|
|
||||||
#: contrib/admin/options.py:533
|
#: contrib/admin/options.py:536
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Deleted %(name)s \"%(object)s\"."
|
msgid "Deleted %(name)s \"%(object)s\"."
|
||||||
msgstr "Usunięto %(name)s \"%(object)s\"."
|
msgstr "Usunięto %(name)s \"%(object)s\"."
|
||||||
|
|
||||||
#: contrib/admin/options.py:537
|
#: contrib/admin/options.py:540
|
||||||
msgid "No fields changed."
|
msgid "No fields changed."
|
||||||
msgstr "Żadne pole nie zmienione."
|
msgstr "Żadne pole nie zmienione."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:599 contrib/auth/admin.py:67
|
#: contrib/admin/options.py:599 contrib/auth/admin.py:67
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:602 contrib/auth/admin.py:68
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
||||||
msgstr "%(name)s \"%(obj)s\" dodany pomyślnie."
|
msgstr "%(name)s \"%(obj)s\" dodany pomyślnie."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:603 contrib/admin/options.py:636
|
#: contrib/admin/options.py:603 contrib/admin/options.py:636
|
||||||
#: contrib/auth/admin.py:75
|
#: contrib/auth/admin.py:75
|
||||||
msgid "You may edit it again below."
|
msgid "You may edit it again below."
|
||||||
msgstr "Możesz ponownie edytować wpis poniżej."
|
msgstr "Możesz ponownie edytować wpis poniżej."
|
||||||
|
|
||||||
#: contrib/admin/options.py:613 contrib/admin/options.py:646
|
#: contrib/admin/options.py:613 contrib/admin/options.py:646
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:606 contrib/admin/options.py:639
|
||||||
|
#: contrib/auth/admin.py:77
|
||||||
|
msgid "You may edit it again below."
|
||||||
|
msgstr "Możesz ponownie edytować wpis poniżej."
|
||||||
|
|
||||||
|
#: contrib/admin/options.py:616 contrib/admin/options.py:649
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You may add another %s below."
|
msgid "You may add another %s below."
|
||||||
msgstr "Możesz dodać nowy wpis %s poniżej."
|
msgstr "Możesz dodać nowy wpis %s poniżej."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:634
|
#: contrib/admin/options.py:634
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:637
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
||||||
msgstr "%(name)s \"%(obj)s\" zostało pomyślnie zmienione."
|
msgstr "%(name)s \"%(obj)s\" zostało pomyślnie zmienione."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:642
|
#: contrib/admin/options.py:642
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:645
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"%(name)s \"%(obj)s\" dodane pomyślnie. Możesz edytować ponownie wpis poniżej."
|
"%(name)s \"%(obj)s\" dodane pomyślnie. Możesz edytować ponownie wpis poniżej."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:773
|
#: contrib/admin/options.py:773
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:778
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Add %s"
|
msgid "Add %s"
|
||||||
msgstr "Dodaj %s"
|
msgstr "Dodaj %s"
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:804 contrib/admin/options.py:1005
|
#: contrib/admin/options.py:804 contrib/admin/options.py:1005
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:810 contrib/admin/options.py:1012
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s object with primary key %(key)r does not exist."
|
msgid "%(name)s object with primary key %(key)r does not exist."
|
||||||
msgstr "Obiekt %(name)s o kluczu głównym %(key)r nie istnieje."
|
msgstr "Obiekt %(name)s o kluczu głównym %(key)r nie istnieje."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:861
|
#: contrib/admin/options.py:861
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:867
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change %s"
|
msgid "Change %s"
|
||||||
msgstr "Zmień %s"
|
msgstr "Zmień %s"
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:905
|
#: contrib/admin/options.py:905
|
||||||
msgid "Database error"
|
msgid "Database error"
|
||||||
msgstr "Błąd bazy danych"
|
msgstr "Błąd bazy danych"
|
||||||
|
|
||||||
#: contrib/admin/options.py:941
|
#: contrib/admin/options.py:941
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:911
|
||||||
|
msgid "Database error"
|
||||||
|
msgstr "Błąd bazy danych"
|
||||||
|
|
||||||
|
#: contrib/admin/options.py:947
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(count)s %(name)s was changed successfully."
|
msgid "%(count)s %(name)s was changed successfully."
|
||||||
msgid_plural "%(count)s %(name)s were changed successfully."
|
msgid_plural "%(count)s %(name)s were changed successfully."
|
||||||
@ -398,17 +451,29 @@ msgstr[0] "%(count)s %(name)s został pomyślnie zmieniony."
|
|||||||
msgstr[1] "%(count)s %(name)s zostały pomyślnie zmienione."
|
msgstr[1] "%(count)s %(name)s zostały pomyślnie zmienione."
|
||||||
msgstr[2] "%(count)s %(name)s zostało pomyślnie zmienionych."
|
msgstr[2] "%(count)s %(name)s zostało pomyślnie zmienionych."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:1020
|
#: contrib/admin/options.py:1020
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:1027
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
||||||
msgstr "%(name)s \"%(obj)s\" usunięty pomyślnie."
|
msgstr "%(name)s \"%(obj)s\" usunięty pomyślnie."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/options.py:1057
|
#: contrib/admin/options.py:1057
|
||||||
|
=======
|
||||||
|
#: contrib/admin/options.py:1064
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change history: %s"
|
msgid "Change history: %s"
|
||||||
msgstr "Historia zmian: %s"
|
msgstr "Historia zmian: %s"
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/sites.py:21 contrib/admin/views/decorators.py:14
|
#: contrib/admin/sites.py:21 contrib/admin/views/decorators.py:14
|
||||||
|
=======
|
||||||
|
#: contrib/admin/sites.py:22 contrib/admin/views/decorators.py:14
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/auth/forms.py:80
|
#: contrib/auth/forms.py:80
|
||||||
msgid ""
|
msgid ""
|
||||||
"Please enter a correct username and password. Note that both fields are case-"
|
"Please enter a correct username and password. Note that both fields are case-"
|
||||||
@ -417,11 +482,19 @@ msgstr ""
|
|||||||
"Proszę wpisać poprawną nazwę użytkownika i hasło. Uwaga: wielkość liter ma "
|
"Proszę wpisać poprawną nazwę użytkownika i hasło. Uwaga: wielkość liter ma "
|
||||||
"znaczenie."
|
"znaczenie."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/sites.py:288 contrib/admin/views/decorators.py:40
|
#: contrib/admin/sites.py:288 contrib/admin/views/decorators.py:40
|
||||||
msgid "Please log in again, because your session has expired."
|
msgid "Please log in again, because your session has expired."
|
||||||
msgstr "Twoja sesja wygasła, zaloguj się ponownie."
|
msgstr "Twoja sesja wygasła, zaloguj się ponownie."
|
||||||
|
|
||||||
#: contrib/admin/sites.py:295 contrib/admin/views/decorators.py:47
|
#: contrib/admin/sites.py:295 contrib/admin/views/decorators.py:47
|
||||||
|
=======
|
||||||
|
#: contrib/admin/sites.py:292 contrib/admin/views/decorators.py:40
|
||||||
|
msgid "Please log in again, because your session has expired."
|
||||||
|
msgstr "Twoja sesja wygasła, zaloguj się ponownie."
|
||||||
|
|
||||||
|
#: contrib/admin/sites.py:299 contrib/admin/views/decorators.py:47
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
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."
|
||||||
@ -429,27 +502,47 @@ msgstr ""
|
|||||||
"Twoja przeglądarka nie chce akceptować ciasteczek. Zmień jej ustawienia i "
|
"Twoja przeglądarka nie chce akceptować ciasteczek. Zmień jej ustawienia i "
|
||||||
"spróbuj ponownie."
|
"spróbuj ponownie."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/sites.py:311 contrib/admin/sites.py:317
|
#: contrib/admin/sites.py:311 contrib/admin/sites.py:317
|
||||||
|
=======
|
||||||
|
#: contrib/admin/sites.py:315 contrib/admin/sites.py:321
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/views/decorators.py:66
|
#: contrib/admin/views/decorators.py:66
|
||||||
msgid "Usernames cannot contain the '@' character."
|
msgid "Usernames cannot contain the '@' character."
|
||||||
msgstr "Nazwy użytkowników nie mogą zawierać znaku '@'."
|
msgstr "Nazwy użytkowników nie mogą zawierać znaku '@'."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/sites.py:314 contrib/admin/views/decorators.py:62
|
#: contrib/admin/sites.py:314 contrib/admin/views/decorators.py:62
|
||||||
|
=======
|
||||||
|
#: contrib/admin/sites.py:318 contrib/admin/views/decorators.py:62
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your e-mail address is not your username. Try '%s' instead."
|
msgid "Your e-mail address is not your username. Try '%s' instead."
|
||||||
msgstr "Podany adres e-mail nie jest Twoją nazwą użytkownika. Spróbuj '%s'."
|
msgstr "Podany adres e-mail nie jest Twoją nazwą użytkownika. Spróbuj '%s'."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/sites.py:370
|
#: contrib/admin/sites.py:370
|
||||||
msgid "Site administration"
|
msgid "Site administration"
|
||||||
msgstr "Administracja stroną"
|
msgstr "Administracja stroną"
|
||||||
|
|
||||||
#: contrib/admin/sites.py:384 contrib/admin/templates/admin/login.html:26
|
#: contrib/admin/sites.py:384 contrib/admin/templates/admin/login.html:26
|
||||||
|
=======
|
||||||
|
#: contrib/admin/sites.py:374
|
||||||
|
msgid "Site administration"
|
||||||
|
msgstr "Administracja stroną"
|
||||||
|
|
||||||
|
#: contrib/admin/sites.py:388 contrib/admin/templates/admin/login.html:26
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/templates/registration/password_reset_complete.html:14
|
#: contrib/admin/templates/registration/password_reset_complete.html:14
|
||||||
#: contrib/admin/views/decorators.py:20
|
#: contrib/admin/views/decorators.py:20
|
||||||
msgid "Log in"
|
msgid "Log in"
|
||||||
msgstr "Zaloguj się"
|
msgstr "Zaloguj się"
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/admin/sites.py:429
|
#: contrib/admin/sites.py:429
|
||||||
|
=======
|
||||||
|
#: contrib/admin/sites.py:433
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%s administration"
|
msgid "%s administration"
|
||||||
msgstr "%s - administracja"
|
msgstr "%s - administracja"
|
||||||
@ -670,8 +763,13 @@ msgid ""
|
|||||||
"Are you sure you want to delete the selected %(object_name)s objects? All of "
|
"Are you sure you want to delete the selected %(object_name)s objects? All of "
|
||||||
"the following objects and their related items will be deleted:"
|
"the following objects and their related items will be deleted:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
"Czy chcesz skasować wybrane %(object_name)s? Następujące obiekty i zależne od "
|
"Czy chcesz skasować wybrane %(object_name)s? Następujące obiekty i zależne od "
|
||||||
"nich zostaną skasowane:"
|
"nich zostaną skasowane:"
|
||||||
|
=======
|
||||||
|
"Czy chcesz skasować wybrane %(object_name)s? Następujące obiekty i zależne "
|
||||||
|
"od nich zostaną skasowane:"
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/filter.html:2
|
#: contrib/admin/templates/admin/filter.html:2
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -977,7 +1075,7 @@ msgstr "Adres e-mail:"
|
|||||||
msgid "Reset my password"
|
msgid "Reset my password"
|
||||||
msgstr "Zresetuj moje hasło"
|
msgstr "Zresetuj moje hasło"
|
||||||
|
|
||||||
#: contrib/admin/templatetags/admin_list.py:299
|
#: contrib/admin/templatetags/admin_list.py:304
|
||||||
msgid "All dates"
|
msgid "All dates"
|
||||||
msgstr "Wszystkie daty"
|
msgstr "Wszystkie daty"
|
||||||
|
|
||||||
@ -991,11 +1089,11 @@ msgstr "Zaznacz %s"
|
|||||||
msgid "Select %s to change"
|
msgid "Select %s to change"
|
||||||
msgstr "Zaznacz %s aby zmienić"
|
msgstr "Zaznacz %s aby zmienić"
|
||||||
|
|
||||||
#: contrib/admin/views/template.py:37 contrib/sites/models.py:38
|
#: contrib/admin/views/template.py:38 contrib/sites/models.py:38
|
||||||
msgid "site"
|
msgid "site"
|
||||||
msgstr "strona"
|
msgstr "strona"
|
||||||
|
|
||||||
#: contrib/admin/views/template.py:39
|
#: contrib/admin/views/template.py:40
|
||||||
msgid "template"
|
msgid "template"
|
||||||
msgstr "szablon"
|
msgstr "szablon"
|
||||||
|
|
||||||
@ -1209,37 +1307,37 @@ msgstr "Edytuj ten obiekt (nowe okno)"
|
|||||||
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 "Jak wyżej, tyle że otwiera nowe okno."
|
msgstr "Jak wyżej, tyle że otwiera nowe okno."
|
||||||
|
|
||||||
#: contrib/auth/admin.py:21
|
#: contrib/auth/admin.py:22
|
||||||
msgid "Personal info"
|
msgid "Personal info"
|
||||||
msgstr "Dane osobowe"
|
msgstr "Dane osobowe"
|
||||||
|
|
||||||
#: contrib/auth/admin.py:22
|
#: contrib/auth/admin.py:23
|
||||||
msgid "Permissions"
|
msgid "Permissions"
|
||||||
msgstr "Uprawnienia"
|
msgstr "Uprawnienia"
|
||||||
|
|
||||||
#: contrib/auth/admin.py:23
|
#: contrib/auth/admin.py:24
|
||||||
msgid "Important dates"
|
msgid "Important dates"
|
||||||
msgstr "Ważne daty"
|
msgstr "Ważne daty"
|
||||||
|
|
||||||
#: contrib/auth/admin.py:24
|
#: contrib/auth/admin.py:25
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "Grupy"
|
msgstr "Grupy"
|
||||||
|
|
||||||
#: contrib/auth/admin.py:80
|
#: contrib/auth/admin.py:82
|
||||||
msgid "Add user"
|
msgid "Add user"
|
||||||
msgstr "Dodaj użytkownika"
|
msgstr "Dodaj użytkownika"
|
||||||
|
|
||||||
#: contrib/auth/admin.py:106
|
#: contrib/auth/admin.py:108
|
||||||
msgid "Password changed successfully."
|
msgid "Password changed successfully."
|
||||||
msgstr "Hasło zostało zmienione pomyślnie."
|
msgstr "Hasło zostało zmienione pomyślnie."
|
||||||
|
|
||||||
#: contrib/auth/admin.py:112
|
#: contrib/auth/admin.py:114
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change password: %s"
|
msgid "Change password: %s"
|
||||||
msgstr "Zmień hasło: %s"
|
msgstr "Zmień hasło: %s"
|
||||||
|
|
||||||
#: contrib/auth/forms.py:15 contrib/auth/forms.py:48
|
#: contrib/auth/forms.py:15 contrib/auth/forms.py:48
|
||||||
#: contrib/auth/models.py:128
|
#: contrib/auth/models.py:129
|
||||||
msgid ""
|
msgid ""
|
||||||
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
||||||
"digits and underscores)."
|
"digits and underscores)."
|
||||||
@ -1329,31 +1427,31 @@ msgstr "uprawnienia"
|
|||||||
msgid "group"
|
msgid "group"
|
||||||
msgstr "grupa"
|
msgstr "grupa"
|
||||||
|
|
||||||
#: contrib/auth/models.py:91 contrib/auth/models.py:138
|
#: contrib/auth/models.py:91 contrib/auth/models.py:139
|
||||||
msgid "groups"
|
msgid "groups"
|
||||||
msgstr "grupy"
|
msgstr "grupy"
|
||||||
|
|
||||||
#: contrib/auth/models.py:128
|
#: contrib/auth/models.py:129
|
||||||
msgid "username"
|
msgid "username"
|
||||||
msgstr "użytkownik"
|
msgstr "użytkownik"
|
||||||
|
|
||||||
#: contrib/auth/models.py:129
|
#: contrib/auth/models.py:130
|
||||||
msgid "first name"
|
msgid "first name"
|
||||||
msgstr "imię"
|
msgstr "imię"
|
||||||
|
|
||||||
#: contrib/auth/models.py:130
|
#: contrib/auth/models.py:131
|
||||||
msgid "last name"
|
msgid "last name"
|
||||||
msgstr "nazwisko"
|
msgstr "nazwisko"
|
||||||
|
|
||||||
#: contrib/auth/models.py:131
|
#: contrib/auth/models.py:132
|
||||||
msgid "e-mail address"
|
msgid "e-mail address"
|
||||||
msgstr "adres e-mail"
|
msgstr "adres e-mail"
|
||||||
|
|
||||||
#: contrib/auth/models.py:132
|
#: contrib/auth/models.py:133
|
||||||
msgid "password"
|
msgid "password"
|
||||||
msgstr "hasło"
|
msgstr "hasło"
|
||||||
|
|
||||||
#: contrib/auth/models.py:132
|
#: contrib/auth/models.py:133
|
||||||
msgid ""
|
msgid ""
|
||||||
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
|
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
|
||||||
"password form</a>."
|
"password form</a>."
|
||||||
@ -1361,19 +1459,19 @@ msgstr ""
|
|||||||
"Użyj '[algo]$[salt]$[hexdigest]' lub <a href=\"password/\">formularza zmiany "
|
"Użyj '[algo]$[salt]$[hexdigest]' lub <a href=\"password/\">formularza zmiany "
|
||||||
"hasła</a>."
|
"hasła</a>."
|
||||||
|
|
||||||
#: contrib/auth/models.py:133
|
#: contrib/auth/models.py:134
|
||||||
msgid "staff status"
|
msgid "staff status"
|
||||||
msgstr "w zespole"
|
msgstr "w zespole"
|
||||||
|
|
||||||
#: contrib/auth/models.py:133
|
#: contrib/auth/models.py:134
|
||||||
msgid "Designates whether the user can log into this admin site."
|
msgid "Designates whether the user can log into this admin site."
|
||||||
msgstr "Oznacza czy użytkownik może zalogować się do panelu admina."
|
msgstr "Oznacza czy użytkownik może zalogować się do panelu admina."
|
||||||
|
|
||||||
#: contrib/auth/models.py:134
|
#: contrib/auth/models.py:135
|
||||||
msgid "active"
|
msgid "active"
|
||||||
msgstr "aktywny"
|
msgstr "aktywny"
|
||||||
|
|
||||||
#: contrib/auth/models.py:134
|
#: contrib/auth/models.py:135
|
||||||
msgid ""
|
msgid ""
|
||||||
"Designates whether this user should be treated as active. Unselect this "
|
"Designates whether this user should be treated as active. Unselect this "
|
||||||
"instead of deleting accounts."
|
"instead of deleting accounts."
|
||||||
@ -1381,11 +1479,11 @@ msgstr ""
|
|||||||
"Oznacza czy użytkownika należy uważać za aktywnego. Odznacz to, zamiast "
|
"Oznacza czy użytkownika należy uważać za aktywnego. Odznacz to, zamiast "
|
||||||
"usuwać konta."
|
"usuwać konta."
|
||||||
|
|
||||||
#: contrib/auth/models.py:135
|
#: contrib/auth/models.py:136
|
||||||
msgid "superuser status"
|
msgid "superuser status"
|
||||||
msgstr "status administratora"
|
msgstr "status administratora"
|
||||||
|
|
||||||
#: contrib/auth/models.py:135
|
#: contrib/auth/models.py:136
|
||||||
msgid ""
|
msgid ""
|
||||||
"Designates that this user has all permissions without explicitly assigning "
|
"Designates that this user has all permissions without explicitly assigning "
|
||||||
"them."
|
"them."
|
||||||
@ -1393,15 +1491,15 @@ msgstr ""
|
|||||||
"Oznacza, że ten użytkownik ma wszystkie uprawnienia bez jawnego "
|
"Oznacza, że ten użytkownik ma wszystkie uprawnienia bez jawnego "
|
||||||
"przypisywania ich."
|
"przypisywania ich."
|
||||||
|
|
||||||
#: contrib/auth/models.py:136
|
#: contrib/auth/models.py:137
|
||||||
msgid "last login"
|
msgid "last login"
|
||||||
msgstr "ostatnio zalogowany"
|
msgstr "ostatnio zalogowany"
|
||||||
|
|
||||||
#: contrib/auth/models.py:137
|
#: contrib/auth/models.py:138
|
||||||
msgid "date joined"
|
msgid "date joined"
|
||||||
msgstr "data przyłączenia"
|
msgstr "data przyłączenia"
|
||||||
|
|
||||||
#: contrib/auth/models.py:139
|
#: contrib/auth/models.py:140
|
||||||
msgid ""
|
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."
|
||||||
@ -1409,24 +1507,28 @@ msgstr ""
|
|||||||
"Oprócz uprawnień przypisanych bezpośrednio użytkownikowi otrzyma on "
|
"Oprócz uprawnień przypisanych bezpośrednio użytkownikowi otrzyma on "
|
||||||
"uprawnienia grup, do których należy."
|
"uprawnienia grup, do których należy."
|
||||||
|
|
||||||
#: contrib/auth/models.py:140
|
#: contrib/auth/models.py:141
|
||||||
msgid "user permissions"
|
msgid "user permissions"
|
||||||
msgstr "uprawnienia użytkownika"
|
msgstr "uprawnienia użytkownika"
|
||||||
|
|
||||||
#: contrib/auth/models.py:144 contrib/comments/models.py:50
|
#: contrib/auth/models.py:145 contrib/comments/models.py:50
|
||||||
#: contrib/comments/models.py:168
|
#: contrib/comments/models.py:168
|
||||||
msgid "user"
|
msgid "user"
|
||||||
msgstr "użytkownik"
|
msgstr "użytkownik"
|
||||||
|
|
||||||
#: contrib/auth/models.py:145
|
#: contrib/auth/models.py:146
|
||||||
msgid "users"
|
msgid "users"
|
||||||
msgstr "użytkownicy"
|
msgstr "użytkownicy"
|
||||||
|
|
||||||
#: contrib/auth/models.py:301
|
#: contrib/auth/models.py:334
|
||||||
msgid "message"
|
msgid "message"
|
||||||
msgstr "wiadomość"
|
msgstr "wiadomość"
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: contrib/auth/views.py:58
|
#: contrib/auth/views.py:58
|
||||||
|
=======
|
||||||
|
#: contrib/auth/views.py:60
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
msgid "Logged out"
|
msgid "Logged out"
|
||||||
msgstr "Wylogowany"
|
msgstr "Wylogowany"
|
||||||
|
|
||||||
@ -1774,7 +1876,7 @@ msgstr "strona statyczna"
|
|||||||
msgid "flat pages"
|
msgid "flat pages"
|
||||||
msgstr "strony statyczne"
|
msgstr "strony statyczne"
|
||||||
|
|
||||||
#: contrib/formtools/wizard.py:130
|
#: contrib/formtools/wizard.py:132
|
||||||
msgid ""
|
msgid ""
|
||||||
"We apologize, but your form has expired. Please continue filling out the "
|
"We apologize, but your form has expired. Please continue filling out the "
|
||||||
"form from this page."
|
"form from this page."
|
||||||
@ -3811,6 +3913,10 @@ msgstr "Prowincja Północno-Zachodnia"
|
|||||||
msgid "Western Cape"
|
msgid "Western Cape"
|
||||||
msgstr "Prowincja Przylądkowa Zachodnia"
|
msgstr "Prowincja Przylądkowa Zachodnia"
|
||||||
|
|
||||||
|
#: contrib/messages/tests/base.py:97
|
||||||
|
msgid "lazy message"
|
||||||
|
msgstr "testowa wiadomość z opóźnioną ewaluacją"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:7
|
#: contrib/redirects/models.py:7
|
||||||
msgid "redirect from"
|
msgid "redirect from"
|
||||||
msgstr "przekieruj z"
|
msgstr "przekieruj z"
|
||||||
@ -3919,14 +4025,22 @@ msgstr ""
|
|||||||
msgid "Enter a valid time in HH:MM[:ss[.uuuuuu]] format."
|
msgid "Enter a valid time in HH:MM[:ss[.uuuuuu]] format."
|
||||||
msgstr "Proszę wpisać poprawną godzinę w formacie HH:MM[:ss[.uuuuuu]]."
|
msgstr "Proszę wpisać poprawną godzinę w formacie HH:MM[:ss[.uuuuuu]]."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: db/models/fields/related.py:816
|
#: db/models/fields/related.py:816
|
||||||
|
=======
|
||||||
|
#: db/models/fields/related.py:869
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
msgid ""
|
msgid ""
|
||||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Przytrzymaj wciśnięty klawisz \"Ctrl\" lub \"Command\" na Mac'u aby "
|
"Przytrzymaj wciśnięty klawisz \"Ctrl\" lub \"Command\" na Mac'u aby "
|
||||||
"zaznaczyć więcej niż jeden wybór."
|
"zaznaczyć więcej niż jeden wybór."
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#: db/models/fields/related.py:894
|
#: db/models/fields/related.py:894
|
||||||
|
=======
|
||||||
|
#: db/models/fields/related.py:930
|
||||||
|
>>>>>>> master:django/conf/locale/pl/LC_MESSAGES/django.po
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
@ -4427,17 +4541,17 @@ msgstr "Y-m"
|
|||||||
msgid "MONTH_DAY_FORMAT"
|
msgid "MONTH_DAY_FORMAT"
|
||||||
msgstr "m-d"
|
msgstr "m-d"
|
||||||
|
|
||||||
#: views/generic/create_update.py:114
|
#: views/generic/create_update.py:115
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(verbose_name)s was created successfully."
|
msgid "The %(verbose_name)s was created successfully."
|
||||||
msgstr "%(verbose_name)s zostało pomyślnie utworzone."
|
msgstr "%(verbose_name)s zostało pomyślnie utworzone."
|
||||||
|
|
||||||
#: views/generic/create_update.py:156
|
#: views/generic/create_update.py:158
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(verbose_name)s was updated successfully."
|
msgid "The %(verbose_name)s was updated successfully."
|
||||||
msgstr "%(verbose_name)s zostało pomyślnie zmienione."
|
msgstr "%(verbose_name)s zostało pomyślnie zmienione."
|
||||||
|
|
||||||
#: views/generic/create_update.py:198
|
#: views/generic/create_update.py:201
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(verbose_name)s was deleted."
|
msgid "The %(verbose_name)s was deleted."
|
||||||
msgstr "%(verbose_name)s zostało usunięte."
|
msgstr "%(verbose_name)s zostało usunięte."
|
||||||
|
@ -1059,7 +1059,7 @@ class ModelAdmin(BaseModelAdmin):
|
|||||||
content_type__id__exact = ContentType.objects.get_for_model(model).id
|
content_type__id__exact = ContentType.objects.get_for_model(model).id
|
||||||
).select_related().order_by('action_time')
|
).select_related().order_by('action_time')
|
||||||
# If no history was found, see whether this object even exists.
|
# If no history was found, see whether this object even exists.
|
||||||
obj = get_object_or_404(model, pk=object_id)
|
obj = get_object_or_404(model, pk=unquote(object_id))
|
||||||
context = {
|
context = {
|
||||||
'title': _('Change history: %s') % force_unicode(obj),
|
'title': _('Change history: %s') % force_unicode(obj),
|
||||||
'action_list': action_list,
|
'action_list': action_list,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
from warnings import warn
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils.importlib import import_module
|
from django.utils.importlib import import_module
|
||||||
|
|
||||||
@ -19,6 +20,12 @@ def load_backend(path):
|
|||||||
cls = getattr(mod, attr)
|
cls = getattr(mod, attr)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
raise ImproperlyConfigured, 'Module "%s" does not define a "%s" authentication backend' % (module, attr)
|
raise ImproperlyConfigured, 'Module "%s" does not define a "%s" authentication backend' % (module, attr)
|
||||||
|
try:
|
||||||
|
getattr(cls, 'supports_object_permissions')
|
||||||
|
except AttributeError:
|
||||||
|
warn("Authentication backends without a `supports_object_permissions` attribute are deprecated. Please define it in %s." % cls,
|
||||||
|
PendingDeprecationWarning)
|
||||||
|
cls.supports_object_permissions = False
|
||||||
return cls()
|
return cls()
|
||||||
|
|
||||||
def get_backends():
|
def get_backends():
|
||||||
|
@ -11,6 +11,8 @@ class ModelBackend(object):
|
|||||||
"""
|
"""
|
||||||
Authenticates against django.contrib.auth.models.User.
|
Authenticates against django.contrib.auth.models.User.
|
||||||
"""
|
"""
|
||||||
|
supports_object_permissions = False
|
||||||
|
|
||||||
# TODO: Model, login attribute name and password attribute name should be
|
# TODO: Model, login attribute name and password attribute name should be
|
||||||
# configurable.
|
# configurable.
|
||||||
def authenticate(self, username=None, password=None):
|
def authenticate(self, username=None, password=None):
|
||||||
|
@ -121,7 +121,8 @@ class UserManager(models.Manager):
|
|||||||
return ''.join([choice(allowed_chars) for i in range(length)])
|
return ''.join([choice(allowed_chars) for i in range(length)])
|
||||||
|
|
||||||
class User(models.Model):
|
class User(models.Model):
|
||||||
"""Users within the Django authentication system are represented by this model.
|
"""
|
||||||
|
Users within the Django authentication system are represented by this model.
|
||||||
|
|
||||||
Username and password are required. Other fields are optional.
|
Username and password are required. Other fields are optional.
|
||||||
"""
|
"""
|
||||||
@ -151,11 +152,16 @@ class User(models.Model):
|
|||||||
return "/users/%s/" % urllib.quote(smart_str(self.username))
|
return "/users/%s/" % urllib.quote(smart_str(self.username))
|
||||||
|
|
||||||
def is_anonymous(self):
|
def is_anonymous(self):
|
||||||
"Always returns False. This is a way of comparing User objects to anonymous users."
|
"""
|
||||||
|
Always returns False. This is a way of comparing User objects to
|
||||||
|
anonymous users.
|
||||||
|
"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_authenticated(self):
|
def is_authenticated(self):
|
||||||
"""Always return True. This is a way to tell if the user has been authenticated in templates.
|
"""
|
||||||
|
Always return True. This is a way to tell if the user has been
|
||||||
|
authenticated in templates.
|
||||||
"""
|
"""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -194,30 +200,41 @@ class User(models.Model):
|
|||||||
def has_usable_password(self):
|
def has_usable_password(self):
|
||||||
return self.password != UNUSABLE_PASSWORD
|
return self.password != UNUSABLE_PASSWORD
|
||||||
|
|
||||||
def get_group_permissions(self):
|
def get_group_permissions(self, obj=None):
|
||||||
"""
|
"""
|
||||||
Returns a list of permission strings that this user has through
|
Returns a list of permission strings that this user has through
|
||||||
his/her groups. This method queries all available auth backends.
|
his/her groups. This method queries all available auth backends.
|
||||||
|
If an object is passed in, only permissions matching this object
|
||||||
|
are returned.
|
||||||
"""
|
"""
|
||||||
permissions = set()
|
permissions = set()
|
||||||
for backend in auth.get_backends():
|
for backend in auth.get_backends():
|
||||||
if hasattr(backend, "get_group_permissions"):
|
if hasattr(backend, "get_group_permissions"):
|
||||||
permissions.update(backend.get_group_permissions(self))
|
if obj is not None and backend.supports_object_permissions:
|
||||||
|
group_permissions = backend.get_group_permissions(self, obj)
|
||||||
|
else:
|
||||||
|
group_permissions = backend.get_group_permissions(self)
|
||||||
|
permissions.update(group_permissions)
|
||||||
return permissions
|
return permissions
|
||||||
|
|
||||||
def get_all_permissions(self):
|
def get_all_permissions(self, obj=None):
|
||||||
permissions = set()
|
permissions = set()
|
||||||
for backend in auth.get_backends():
|
for backend in auth.get_backends():
|
||||||
if hasattr(backend, "get_all_permissions"):
|
if hasattr(backend, "get_all_permissions"):
|
||||||
permissions.update(backend.get_all_permissions(self))
|
if obj is not None and backend.supports_object_permissions:
|
||||||
|
all_permissions = backend.get_all_permissions(self, obj)
|
||||||
|
else:
|
||||||
|
all_permissions = backend.get_all_permissions(self)
|
||||||
|
permissions.update(all_permissions)
|
||||||
return permissions
|
return permissions
|
||||||
|
|
||||||
def has_perm(self, perm):
|
def has_perm(self, perm, obj=None):
|
||||||
"""
|
"""
|
||||||
Returns True if the user has the specified permission. This method
|
Returns True if the user has the specified permission. This method
|
||||||
queries all available auth backends, but returns immediately if any
|
queries all available auth backends, but returns immediately if any
|
||||||
backend returns True. Thus, a user who has permission from a single
|
backend returns True. Thus, a user who has permission from a single
|
||||||
auth backend is assumed to have permission in general.
|
auth backend is assumed to have permission in general. If an object
|
||||||
|
is provided, permissions for this specific object are checked.
|
||||||
"""
|
"""
|
||||||
# Inactive users have no permissions.
|
# Inactive users have no permissions.
|
||||||
if not self.is_active:
|
if not self.is_active:
|
||||||
@ -230,14 +247,22 @@ class User(models.Model):
|
|||||||
# Otherwise we need to check the backends.
|
# Otherwise we need to check the backends.
|
||||||
for backend in auth.get_backends():
|
for backend in auth.get_backends():
|
||||||
if hasattr(backend, "has_perm"):
|
if hasattr(backend, "has_perm"):
|
||||||
|
if obj is not None and backend.supports_object_permissions:
|
||||||
|
if backend.has_perm(self, perm, obj):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
if backend.has_perm(self, perm):
|
if backend.has_perm(self, perm):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_perms(self, perm_list):
|
def has_perms(self, perm_list, obj=None):
|
||||||
"""Returns True if the user has each of the specified permissions."""
|
"""
|
||||||
|
Returns True if the user has each of the specified permissions.
|
||||||
|
If object is passed, it checks if the user has all required perms
|
||||||
|
for this object.
|
||||||
|
"""
|
||||||
for perm in perm_list:
|
for perm in perm_list:
|
||||||
if not self.has_perm(perm):
|
if not self.has_perm(perm, obj):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -358,10 +383,10 @@ class AnonymousUser(object):
|
|||||||
return self._user_permissions
|
return self._user_permissions
|
||||||
user_permissions = property(_get_user_permissions)
|
user_permissions = property(_get_user_permissions)
|
||||||
|
|
||||||
def has_perm(self, perm):
|
def has_perm(self, perm, obj=None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_perms(self, perm_list):
|
def has_perms(self, perm_list, obj=None):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def has_module_perms(self, module):
|
def has_module_perms(self, module):
|
||||||
|
@ -4,6 +4,7 @@ from django.contrib.auth.tests.views \
|
|||||||
from django.contrib.auth.tests.forms import FORM_TESTS
|
from django.contrib.auth.tests.forms import FORM_TESTS
|
||||||
from django.contrib.auth.tests.remote_user \
|
from django.contrib.auth.tests.remote_user \
|
||||||
import RemoteUserTest, RemoteUserNoCreateTest, RemoteUserCustomTest
|
import RemoteUserTest, RemoteUserNoCreateTest, RemoteUserCustomTest
|
||||||
|
from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest
|
||||||
from django.contrib.auth.tests.tokens import TOKEN_GENERATOR_TESTS
|
from django.contrib.auth.tests.tokens import TOKEN_GENERATOR_TESTS
|
||||||
|
|
||||||
# The password for the fixture data users is 'password'
|
# The password for the fixture data users is 'password'
|
||||||
|
149
django/contrib/auth/tests/auth_backends.py
Normal file
149
django/contrib/auth/tests/auth_backends.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import User, Group, Permission, AnonymousUser
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
|
||||||
|
class BackendTest(TestCase):
|
||||||
|
|
||||||
|
backend = 'django.contrib.auth.backends.ModelBackend'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.curr_auth = settings.AUTHENTICATION_BACKENDS
|
||||||
|
settings.AUTHENTICATION_BACKENDS = (self.backend,)
|
||||||
|
User.objects.create_user('test', 'test@example.com', 'test')
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
settings.AUTHENTICATION_BACKENDS = self.curr_auth
|
||||||
|
|
||||||
|
def test_has_perm(self):
|
||||||
|
user = User.objects.get(username='test')
|
||||||
|
self.assertEqual(user.has_perm('auth.test'), False)
|
||||||
|
user.is_staff = True
|
||||||
|
user.save()
|
||||||
|
self.assertEqual(user.has_perm('auth.test'), False)
|
||||||
|
user.is_superuser = True
|
||||||
|
user.save()
|
||||||
|
self.assertEqual(user.has_perm('auth.test'), True)
|
||||||
|
user.is_staff = False
|
||||||
|
user.is_superuser = False
|
||||||
|
user.save()
|
||||||
|
self.assertEqual(user.has_perm('auth.test'), False)
|
||||||
|
|
||||||
|
def test_custom_perms(self):
|
||||||
|
user = User.objects.get(username='test')
|
||||||
|
content_type=ContentType.objects.get_for_model(Group)
|
||||||
|
perm = Permission.objects.create(name='test', content_type=content_type, codename='test')
|
||||||
|
user.user_permissions.add(perm)
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
# reloading user to purge the _perm_cache
|
||||||
|
user = User.objects.get(username='test')
|
||||||
|
self.assertEqual(user.get_all_permissions() == set([u'auth.test']), True)
|
||||||
|
self.assertEqual(user.get_group_permissions(), set([]))
|
||||||
|
self.assertEqual(user.has_module_perms('Group'), False)
|
||||||
|
self.assertEqual(user.has_module_perms('auth'), True)
|
||||||
|
perm = Permission.objects.create(name='test2', content_type=content_type, codename='test2')
|
||||||
|
user.user_permissions.add(perm)
|
||||||
|
user.save()
|
||||||
|
perm = Permission.objects.create(name='test3', content_type=content_type, codename='test3')
|
||||||
|
user.user_permissions.add(perm)
|
||||||
|
user.save()
|
||||||
|
user = User.objects.get(username='test')
|
||||||
|
self.assertEqual(user.get_all_permissions(), set([u'auth.test2', u'auth.test', u'auth.test3']))
|
||||||
|
self.assertEqual(user.has_perm('test'), False)
|
||||||
|
self.assertEqual(user.has_perm('auth.test'), True)
|
||||||
|
self.assertEqual(user.has_perms(['auth.test2', 'auth.test3']), True)
|
||||||
|
perm = Permission.objects.create(name='test_group', content_type=content_type, codename='test_group')
|
||||||
|
group = Group.objects.create(name='test_group')
|
||||||
|
group.permissions.add(perm)
|
||||||
|
group.save()
|
||||||
|
user.groups.add(group)
|
||||||
|
user = User.objects.get(username='test')
|
||||||
|
exp = set([u'auth.test2', u'auth.test', u'auth.test3', u'auth.test_group'])
|
||||||
|
self.assertEqual(user.get_all_permissions(), exp)
|
||||||
|
self.assertEqual(user.get_group_permissions(), set([u'auth.test_group']))
|
||||||
|
self.assertEqual(user.has_perms(['auth.test3', 'auth.test_group']), True)
|
||||||
|
|
||||||
|
user = AnonymousUser()
|
||||||
|
self.assertEqual(user.has_perm('test'), False)
|
||||||
|
self.assertEqual(user.has_perms(['auth.test2', 'auth.test3']), False)
|
||||||
|
|
||||||
|
|
||||||
|
class TestObj(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleRowlevelBackend(object):
|
||||||
|
supports_object_permissions = True
|
||||||
|
|
||||||
|
def has_perm(self, user, perm, obj=None):
|
||||||
|
if not obj:
|
||||||
|
return # We only support row level perms
|
||||||
|
|
||||||
|
if isinstance(obj, TestObj):
|
||||||
|
if user.username == 'test2':
|
||||||
|
return True
|
||||||
|
elif isinstance(user, AnonymousUser) and perm == 'anon':
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_all_permissions(self, user, obj=None):
|
||||||
|
if not obj:
|
||||||
|
return [] # We only support row level perms
|
||||||
|
|
||||||
|
if not isinstance(obj, TestObj):
|
||||||
|
return ['none']
|
||||||
|
|
||||||
|
if user.username == 'test2':
|
||||||
|
return ['simple', 'advanced']
|
||||||
|
else:
|
||||||
|
return ['simple']
|
||||||
|
|
||||||
|
def get_group_permissions(self, user, obj=None):
|
||||||
|
if not obj:
|
||||||
|
return # We only support row level perms
|
||||||
|
|
||||||
|
if not isinstance(obj, TestObj):
|
||||||
|
return ['none']
|
||||||
|
|
||||||
|
if 'test_group' in [group.name for group in user.groups.all()]:
|
||||||
|
return ['group_perm']
|
||||||
|
else:
|
||||||
|
return ['none']
|
||||||
|
|
||||||
|
|
||||||
|
class RowlevelBackendTest(TestCase):
|
||||||
|
|
||||||
|
backend = 'django.contrib.auth.tests.auth_backends.SimpleRowlevelBackend'
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.curr_auth = settings.AUTHENTICATION_BACKENDS
|
||||||
|
settings.AUTHENTICATION_BACKENDS = self.curr_auth + (self.backend,)
|
||||||
|
self.user1 = User.objects.create_user('test', 'test@example.com', 'test')
|
||||||
|
self.user2 = User.objects.create_user('test2', 'test2@example.com', 'test')
|
||||||
|
self.user3 = AnonymousUser()
|
||||||
|
self.user4 = User.objects.create_user('test4', 'test4@example.com', 'test')
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
settings.AUTHENTICATION_BACKENDS = self.curr_auth
|
||||||
|
|
||||||
|
def test_has_perm(self):
|
||||||
|
self.assertEqual(self.user1.has_perm('perm', TestObj()), False)
|
||||||
|
self.assertEqual(self.user2.has_perm('perm', TestObj()), True)
|
||||||
|
self.assertEqual(self.user2.has_perm('perm'), False)
|
||||||
|
self.assertEqual(self.user2.has_perms(['simple', 'advanced'], TestObj()), True)
|
||||||
|
self.assertEqual(self.user3.has_perm('perm', TestObj()), False)
|
||||||
|
self.assertEqual(self.user3.has_perm('anon', TestObj()), False)
|
||||||
|
self.assertEqual(self.user3.has_perms(['simple', 'advanced'], TestObj()), False)
|
||||||
|
|
||||||
|
def test_get_all_permissions(self):
|
||||||
|
self.assertEqual(self.user1.get_all_permissions(TestObj()), set(['simple']))
|
||||||
|
self.assertEqual(self.user2.get_all_permissions(TestObj()), set(['simple', 'advanced']))
|
||||||
|
self.assertEqual(self.user2.get_all_permissions(), set([]))
|
||||||
|
|
||||||
|
def test_get_group_permissions(self):
|
||||||
|
content_type=ContentType.objects.get_for_model(Group)
|
||||||
|
group = Group.objects.create(name='test_group')
|
||||||
|
self.user4.groups.add(group)
|
||||||
|
self.assertEqual(self.user4.get_group_permissions(TestObj()), set(['group_perm']))
|
@ -279,11 +279,19 @@ class RelatedGeoModelTest(unittest.TestCase):
|
|||||||
def test14_collect(self):
|
def test14_collect(self):
|
||||||
"Testing the `collect` GeoQuerySet method and `Collect` aggregate."
|
"Testing the `collect` GeoQuerySet method and `Collect` aggregate."
|
||||||
# Reference query:
|
# Reference query:
|
||||||
|
<<<<<<< HEAD:django/contrib/gis/tests/relatedapp/tests.py
|
||||||
# SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN
|
# SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN
|
||||||
# "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id")
|
# "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id")
|
||||||
# WHERE "relatedapp_city"."state" = 'TX';
|
# WHERE "relatedapp_city"."state" = 'TX';
|
||||||
ref_geom = fromstr('MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,-95.363151 29.763374,-96.801611 32.782057)')
|
ref_geom = fromstr('MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,-95.363151 29.763374,-96.801611 32.782057)')
|
||||||
|
|
||||||
|
=======
|
||||||
|
# SELECT AsText(ST_Collect("relatedapp_location"."point")) FROM "relatedapp_city" LEFT OUTER JOIN
|
||||||
|
# "relatedapp_location" ON ("relatedapp_city"."location_id" = "relatedapp_location"."id")
|
||||||
|
# WHERE "relatedapp_city"."state" = 'TX';
|
||||||
|
ref_geom = fromstr('MULTIPOINT(-97.516111 33.058333,-96.801611 32.782057,-95.363151 29.763374,-96.801611 32.782057)')
|
||||||
|
|
||||||
|
>>>>>>> master:django/contrib/gis/tests/relatedapp/tests.py
|
||||||
c1 = City.objects.filter(state='TX').collect(field_name='location__point')
|
c1 = City.objects.filter(state='TX').collect(field_name='location__point')
|
||||||
c2 = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect']
|
c2 = City.objects.filter(state='TX').aggregate(Collect('location__point'))['location__point__collect']
|
||||||
|
|
||||||
@ -292,7 +300,10 @@ class RelatedGeoModelTest(unittest.TestCase):
|
|||||||
# consolidate -- that's why 4 points in MultiPoint.
|
# consolidate -- that's why 4 points in MultiPoint.
|
||||||
self.assertEqual(4, len(coll))
|
self.assertEqual(4, len(coll))
|
||||||
self.assertEqual(ref_geom, coll)
|
self.assertEqual(ref_geom, coll)
|
||||||
|
<<<<<<< HEAD:django/contrib/gis/tests/relatedapp/tests.py
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> master:django/contrib/gis/tests/relatedapp/tests.py
|
||||||
|
|
||||||
# TODO: Related tests for KML, GML, and distance lookups.
|
# TODO: Related tests for KML, GML, and distance lookups.
|
||||||
|
|
||||||
|
@ -82,9 +82,14 @@ class Command(BaseCommand):
|
|||||||
model_list = get_models(app)
|
model_list = get_models(app)
|
||||||
|
|
||||||
for model in model_list:
|
for model in model_list:
|
||||||
|
<<<<<<< HEAD:django/core/management/commands/dumpdata.py
|
||||||
# Don't serialize proxy models, or models that haven't been synchronized
|
# Don't serialize proxy models, or models that haven't been synchronized
|
||||||
if not model._meta.proxy and model._meta.db_table in tables:
|
if not model._meta.proxy and model._meta.db_table in tables:
|
||||||
objects.extend(model._default_manager.using(using).all())
|
objects.extend(model._default_manager.using(using).all())
|
||||||
|
=======
|
||||||
|
if not model._meta.proxy:
|
||||||
|
objects.extend(model._default_manager.all())
|
||||||
|
>>>>>>> master:django/core/management/commands/dumpdata.py
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return serializers.serialize(format, objects, indent=indent)
|
return serializers.serialize(format, objects, indent=indent)
|
||||||
|
@ -357,7 +357,11 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||||||
cursor = None
|
cursor = None
|
||||||
if not self._valid_connection():
|
if not self._valid_connection():
|
||||||
conn_string = convert_unicode(self._connect_string())
|
conn_string = convert_unicode(self._connect_string())
|
||||||
|
<<<<<<< HEAD:django/db/backends/oracle/base.py
|
||||||
self.connection = Database.connect(conn_string, **self.settings_dict['OPTIONS'])
|
self.connection = Database.connect(conn_string, **self.settings_dict['OPTIONS'])
|
||||||
|
=======
|
||||||
|
self.connection = Database.connect(conn_string, **self.settings_dict['DATABASE_OPTIONS'])
|
||||||
|
>>>>>>> master:django/db/backends/oracle/base.py
|
||||||
cursor = FormatStylePlaceholderCursor(self.connection)
|
cursor = FormatStylePlaceholderCursor(self.connection)
|
||||||
# Set oracle date to ansi date format. This only needs to execute
|
# Set oracle date to ansi date format. This only needs to execute
|
||||||
# once when we create a new connection. We also set the Territory
|
# once when we create a new connection. We also set the Territory
|
||||||
|
@ -230,6 +230,7 @@ class ModelBase(type):
|
|||||||
|
|
||||||
signals.class_prepared.send(sender=cls)
|
signals.class_prepared.send(sender=cls)
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/db/models/base.py
|
||||||
class ModelState(object):
|
class ModelState(object):
|
||||||
"""
|
"""
|
||||||
A class for storing instance state
|
A class for storing instance state
|
||||||
@ -237,6 +238,8 @@ class ModelState(object):
|
|||||||
def __init__(self, db=None):
|
def __init__(self, db=None):
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> master:django/db/models/base.py
|
||||||
class Model(object):
|
class Model(object):
|
||||||
__metaclass__ = ModelBase
|
__metaclass__ = ModelBase
|
||||||
_deferred = False
|
_deferred = False
|
||||||
@ -488,7 +491,11 @@ class Model(object):
|
|||||||
if pk_set:
|
if pk_set:
|
||||||
# Determine whether a record with the primary key already exists.
|
# Determine whether a record with the primary key already exists.
|
||||||
if (force_update or (not force_insert and
|
if (force_update or (not force_insert and
|
||||||
|
<<<<<<< HEAD:django/db/models/base.py
|
||||||
manager.using(using).filter(pk=pk_val).exists())):
|
manager.using(using).filter(pk=pk_val).exists())):
|
||||||
|
=======
|
||||||
|
manager.filter(pk=pk_val).exists())):
|
||||||
|
>>>>>>> master:django/db/models/base.py
|
||||||
# It does already exist, so do an UPDATE.
|
# It does already exist, so do an UPDATE.
|
||||||
if force_update or non_pks:
|
if force_update or non_pks:
|
||||||
values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
|
values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
|
||||||
@ -527,7 +534,10 @@ class Model(object):
|
|||||||
# Store the database on which the object was saved
|
# Store the database on which the object was saved
|
||||||
self._state.db = using
|
self._state.db = using
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/db/models/base.py
|
||||||
# Signal that the save is complete
|
# Signal that the save is complete
|
||||||
|
=======
|
||||||
|
>>>>>>> master:django/db/models/base.py
|
||||||
if origin and not meta.auto_created:
|
if origin and not meta.auto_created:
|
||||||
signals.post_save.send(sender=origin, instance=self,
|
signals.post_save.send(sender=origin, instance=self,
|
||||||
created=(not record_exists), raw=raw)
|
created=(not record_exists), raw=raw)
|
||||||
|
@ -474,7 +474,11 @@ def create_many_related_manager(superclass, rel=False):
|
|||||||
if not rel.through._meta.auto_created:
|
if not rel.through._meta.auto_created:
|
||||||
opts = through._meta
|
opts = through._meta
|
||||||
raise AttributeError, "Cannot use create() on a ManyToManyField which specifies an intermediary model. Use %s.%s's Manager instead." % (opts.app_label, opts.object_name)
|
raise AttributeError, "Cannot use create() on a ManyToManyField which specifies an intermediary model. Use %s.%s's Manager instead." % (opts.app_label, opts.object_name)
|
||||||
|
<<<<<<< HEAD:django/db/models/fields/related.py
|
||||||
new_obj = super(ManyRelatedManager, self).using(self.instance._state.db).create(**kwargs)
|
new_obj = super(ManyRelatedManager, self).using(self.instance._state.db).create(**kwargs)
|
||||||
|
=======
|
||||||
|
new_obj = super(ManyRelatedManager, self).create(**kwargs)
|
||||||
|
>>>>>>> master:django/db/models/fields/related.py
|
||||||
self.add(new_obj)
|
self.add(new_obj)
|
||||||
return new_obj
|
return new_obj
|
||||||
create.alters_data = True
|
create.alters_data = True
|
||||||
@ -501,15 +505,22 @@ def create_many_related_manager(superclass, rel=False):
|
|||||||
new_ids = set()
|
new_ids = set()
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
if isinstance(obj, self.model):
|
if isinstance(obj, self.model):
|
||||||
|
<<<<<<< HEAD:django/db/models/fields/related.py
|
||||||
if obj._state.db != self.instance._state.db:
|
if obj._state.db != self.instance._state.db:
|
||||||
raise ValueError('Cannot add "%r": instance is on database "%s", value is is on database "%s"' %
|
raise ValueError('Cannot add "%r": instance is on database "%s", value is is on database "%s"' %
|
||||||
(obj, self.instance._state.db, obj._state.db))
|
(obj, self.instance._state.db, obj._state.db))
|
||||||
|
=======
|
||||||
|
>>>>>>> master:django/db/models/fields/related.py
|
||||||
new_ids.add(obj.pk)
|
new_ids.add(obj.pk)
|
||||||
elif isinstance(obj, Model):
|
elif isinstance(obj, Model):
|
||||||
raise TypeError, "'%s' instance expected" % self.model._meta.object_name
|
raise TypeError, "'%s' instance expected" % self.model._meta.object_name
|
||||||
else:
|
else:
|
||||||
new_ids.add(obj)
|
new_ids.add(obj)
|
||||||
|
<<<<<<< HEAD:django/db/models/fields/related.py
|
||||||
vals = self.through._default_manager.using(self.instance._state.db).values_list(target_field_name, flat=True)
|
vals = self.through._default_manager.using(self.instance._state.db).values_list(target_field_name, flat=True)
|
||||||
|
=======
|
||||||
|
vals = self.through._default_manager.values_list(target_field_name, flat=True)
|
||||||
|
>>>>>>> master:django/db/models/fields/related.py
|
||||||
vals = vals.filter(**{
|
vals = vals.filter(**{
|
||||||
source_field_name: self._pk_val,
|
source_field_name: self._pk_val,
|
||||||
'%s__in' % target_field_name: new_ids,
|
'%s__in' % target_field_name: new_ids,
|
||||||
@ -518,7 +529,11 @@ def create_many_related_manager(superclass, rel=False):
|
|||||||
|
|
||||||
# Add the ones that aren't there already
|
# Add the ones that aren't there already
|
||||||
for obj_id in (new_ids - vals):
|
for obj_id in (new_ids - vals):
|
||||||
|
<<<<<<< HEAD:django/db/models/fields/related.py
|
||||||
self.through._default_manager.using(self.instance._state.db).create(**{
|
self.through._default_manager.using(self.instance._state.db).create(**{
|
||||||
|
=======
|
||||||
|
self.through._default_manager.create(**{
|
||||||
|
>>>>>>> master:django/db/models/fields/related.py
|
||||||
'%s_id' % source_field_name: self._pk_val,
|
'%s_id' % source_field_name: self._pk_val,
|
||||||
'%s_id' % target_field_name: obj_id,
|
'%s_id' % target_field_name: obj_id,
|
||||||
})
|
})
|
||||||
@ -538,14 +553,22 @@ def create_many_related_manager(superclass, rel=False):
|
|||||||
else:
|
else:
|
||||||
old_ids.add(obj)
|
old_ids.add(obj)
|
||||||
# Remove the specified objects from the join table
|
# Remove the specified objects from the join table
|
||||||
|
<<<<<<< HEAD:django/db/models/fields/related.py
|
||||||
self.through._default_manager.using(self.instance._state.db).filter(**{
|
self.through._default_manager.using(self.instance._state.db).filter(**{
|
||||||
|
=======
|
||||||
|
self.through._default_manager.filter(**{
|
||||||
|
>>>>>>> master:django/db/models/fields/related.py
|
||||||
source_field_name: self._pk_val,
|
source_field_name: self._pk_val,
|
||||||
'%s__in' % target_field_name: old_ids
|
'%s__in' % target_field_name: old_ids
|
||||||
}).delete()
|
}).delete()
|
||||||
|
|
||||||
def _clear_items(self, source_field_name):
|
def _clear_items(self, source_field_name):
|
||||||
# source_col_name: the PK colname in join_table for the source object
|
# source_col_name: the PK colname in join_table for the source object
|
||||||
|
<<<<<<< HEAD:django/db/models/fields/related.py
|
||||||
self.through._default_manager.using(self.instance._state.db).filter(**{
|
self.through._default_manager.using(self.instance._state.db).filter(**{
|
||||||
|
=======
|
||||||
|
self.through._default_manager.filter(**{
|
||||||
|
>>>>>>> master:django/db/models/fields/related.py
|
||||||
source_field_name: self._pk_val
|
source_field_name: self._pk_val
|
||||||
}).delete()
|
}).delete()
|
||||||
|
|
||||||
|
@ -172,9 +172,12 @@ class Manager(object):
|
|||||||
def only(self, *args, **kwargs):
|
def only(self, *args, **kwargs):
|
||||||
return self.get_query_set().only(*args, **kwargs)
|
return self.get_query_set().only(*args, **kwargs)
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/db/models/manager.py
|
||||||
def using(self, *args, **kwargs):
|
def using(self, *args, **kwargs):
|
||||||
return self.get_query_set().using(*args, **kwargs)
|
return self.get_query_set().using(*args, **kwargs)
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> master:django/db/models/manager.py
|
||||||
def exists(self, *args, **kwargs):
|
def exists(self, *args, **kwargs):
|
||||||
return self.get_query_set().exists(*args, **kwargs)
|
return self.get_query_set().exists(*args, **kwargs)
|
||||||
|
|
||||||
|
@ -3,8 +3,12 @@ The main QuerySet implementation. This provides the public API for the ORM.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
<<<<<<< HEAD:django/db/models/query.py
|
||||||
|
|
||||||
from django.db import connections, transaction, IntegrityError, DEFAULT_DB_ALIAS
|
from django.db import connections, transaction, IntegrityError, DEFAULT_DB_ALIAS
|
||||||
|
=======
|
||||||
|
from django.db import connection, transaction, IntegrityError
|
||||||
|
>>>>>>> master:django/db/models/query.py
|
||||||
from django.db.models.aggregates import Aggregate
|
from django.db.models.aggregates import Aggregate
|
||||||
from django.db.models.fields import DateField
|
from django.db.models.fields import DateField
|
||||||
from django.db.models.query_utils import Q, select_related_descend, CollectedObjects, CyclicDependency, deferred_class_factory
|
from django.db.models.query_utils import Q, select_related_descend, CollectedObjects, CyclicDependency, deferred_class_factory
|
||||||
@ -476,7 +480,11 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def exists(self):
|
def exists(self):
|
||||||
if self._result_cache is None:
|
if self._result_cache is None:
|
||||||
|
<<<<<<< HEAD:django/db/models/query.py
|
||||||
return self.query.has_results(using=self.db)
|
return self.query.has_results(using=self.db)
|
||||||
|
=======
|
||||||
|
return self.query.has_results()
|
||||||
|
>>>>>>> master:django/db/models/query.py
|
||||||
return bool(self._result_cache)
|
return bool(self._result_cache)
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
|
@ -22,8 +22,12 @@ from django.db.models.sql.expressions import SQLEvaluator
|
|||||||
from django.db.models.sql.where import WhereNode, Constraint, EverythingNode, AND, OR
|
from django.db.models.sql.where import WhereNode, Constraint, EverythingNode, AND, OR
|
||||||
from django.core.exceptions import FieldError
|
from django.core.exceptions import FieldError
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/db/models/sql/query.py
|
||||||
|
|
||||||
__all__ = ['Query']
|
__all__ = ['Query']
|
||||||
|
=======
|
||||||
|
__all__ = ['Query', 'BaseQuery']
|
||||||
|
>>>>>>> master:django/db/models/sql/query.py
|
||||||
|
|
||||||
class Query(object):
|
class Query(object):
|
||||||
"""
|
"""
|
||||||
@ -337,7 +341,11 @@ class Query(object):
|
|||||||
|
|
||||||
return number
|
return number
|
||||||
|
|
||||||
|
<<<<<<< HEAD:django/db/models/sql/query.py
|
||||||
def has_results(self, using):
|
def has_results(self, using):
|
||||||
|
=======
|
||||||
|
def has_results(self):
|
||||||
|
>>>>>>> master:django/db/models/sql/query.py
|
||||||
q = self.clone()
|
q = self.clone()
|
||||||
q.add_extra({'a': 1}, None, None, None, None, None)
|
q.add_extra({'a': 1}, None, None, None, None, None)
|
||||||
q.add_fields(())
|
q.add_fields(())
|
||||||
@ -345,8 +353,104 @@ class Query(object):
|
|||||||
q.set_aggregate_mask(())
|
q.set_aggregate_mask(())
|
||||||
q.clear_ordering()
|
q.clear_ordering()
|
||||||
q.set_limits(high=1)
|
q.set_limits(high=1)
|
||||||
|
<<<<<<< HEAD:django/db/models/sql/query.py
|
||||||
compiler = q.get_compiler(using=using)
|
compiler = q.get_compiler(using=using)
|
||||||
return bool(compiler.execute_sql(SINGLE))
|
return bool(compiler.execute_sql(SINGLE))
|
||||||
|
=======
|
||||||
|
return bool(q.execute_sql(SINGLE))
|
||||||
|
|
||||||
|
def as_sql(self, with_limits=True, with_col_aliases=False):
|
||||||
|
"""
|
||||||
|
Creates the SQL for this query. Returns the SQL string and list of
|
||||||
|
parameters.
|
||||||
|
|
||||||
|
If 'with_limits' is False, any limit/offset information is not included
|
||||||
|
in the query.
|
||||||
|
"""
|
||||||
|
self.pre_sql_setup()
|
||||||
|
out_cols = self.get_columns(with_col_aliases)
|
||||||
|
ordering, ordering_group_by = self.get_ordering()
|
||||||
|
|
||||||
|
# This must come after 'select' and 'ordering' -- see docstring of
|
||||||
|
# get_from_clause() for details.
|
||||||
|
from_, f_params = self.get_from_clause()
|
||||||
|
|
||||||
|
qn = self.quote_name_unless_alias
|
||||||
|
where, w_params = self.where.as_sql(qn=qn)
|
||||||
|
having, h_params = self.having.as_sql(qn=qn)
|
||||||
|
params = []
|
||||||
|
for val in self.extra_select.itervalues():
|
||||||
|
params.extend(val[1])
|
||||||
|
|
||||||
|
result = ['SELECT']
|
||||||
|
if self.distinct:
|
||||||
|
result.append('DISTINCT')
|
||||||
|
result.append(', '.join(out_cols + self.ordering_aliases))
|
||||||
|
|
||||||
|
result.append('FROM')
|
||||||
|
result.extend(from_)
|
||||||
|
params.extend(f_params)
|
||||||
|
|
||||||
|
if where:
|
||||||
|
result.append('WHERE %s' % where)
|
||||||
|
params.extend(w_params)
|
||||||
|
if self.extra_where:
|
||||||
|
if not where:
|
||||||
|
result.append('WHERE')
|
||||||
|
else:
|
||||||
|
result.append('AND')
|
||||||
|
result.append(' AND '.join(self.extra_where))
|
||||||
|
|
||||||
|
grouping, gb_params = self.get_grouping()
|
||||||
|
if grouping:
|
||||||
|
if ordering:
|
||||||
|
# If the backend can't group by PK (i.e., any database
|
||||||
|
# other than MySQL), then any fields mentioned in the
|
||||||
|
# ordering clause needs to be in the group by clause.
|
||||||
|
if not self.connection.features.allows_group_by_pk:
|
||||||
|
for col, col_params in ordering_group_by:
|
||||||
|
if col not in grouping:
|
||||||
|
grouping.append(str(col))
|
||||||
|
gb_params.extend(col_params)
|
||||||
|
else:
|
||||||
|
ordering = self.connection.ops.force_no_ordering()
|
||||||
|
result.append('GROUP BY %s' % ', '.join(grouping))
|
||||||
|
params.extend(gb_params)
|
||||||
|
|
||||||
|
if having:
|
||||||
|
result.append('HAVING %s' % having)
|
||||||
|
params.extend(h_params)
|
||||||
|
|
||||||
|
if ordering:
|
||||||
|
result.append('ORDER BY %s' % ', '.join(ordering))
|
||||||
|
|
||||||
|
if with_limits:
|
||||||
|
if self.high_mark is not None:
|
||||||
|
result.append('LIMIT %d' % (self.high_mark - self.low_mark))
|
||||||
|
if self.low_mark:
|
||||||
|
if self.high_mark is None:
|
||||||
|
val = self.connection.ops.no_limit_value()
|
||||||
|
if val:
|
||||||
|
result.append('LIMIT %d' % val)
|
||||||
|
result.append('OFFSET %d' % self.low_mark)
|
||||||
|
|
||||||
|
params.extend(self.extra_params)
|
||||||
|
return ' '.join(result), tuple(params)
|
||||||
|
|
||||||
|
def as_nested_sql(self):
|
||||||
|
"""
|
||||||
|
Perform the same functionality as the as_sql() method, returning an
|
||||||
|
SQL string and parameters. However, the alias prefixes are bumped
|
||||||
|
beforehand (in a copy -- the current query isn't changed) and any
|
||||||
|
ordering is removed.
|
||||||
|
|
||||||
|
Used when nesting this query inside another.
|
||||||
|
"""
|
||||||
|
obj = self.clone()
|
||||||
|
obj.clear_ordering(True)
|
||||||
|
obj.bump_prefix()
|
||||||
|
return obj.as_sql()
|
||||||
|
>>>>>>> master:django/db/models/sql/query.py
|
||||||
|
|
||||||
def combine(self, rhs, connector):
|
def combine(self, rhs, connector):
|
||||||
"""
|
"""
|
||||||
|
@ -471,8 +471,12 @@ class BaseModelFormSet(BaseFormSet):
|
|||||||
pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
|
pk_key = "%s-%s" % (self.add_prefix(i), self.model._meta.pk.name)
|
||||||
pk = self.data[pk_key]
|
pk = self.data[pk_key]
|
||||||
pk_field = self.model._meta.pk
|
pk_field = self.model._meta.pk
|
||||||
|
<<<<<<< HEAD:django/forms/models.py
|
||||||
pk = pk_field.get_db_prep_lookup('exact', pk,
|
pk = pk_field.get_db_prep_lookup('exact', pk,
|
||||||
connection=connections[self.get_queryset().db])
|
connection=connections[self.get_queryset().db])
|
||||||
|
=======
|
||||||
|
pk = pk_field.get_db_prep_lookup('exact', pk)
|
||||||
|
>>>>>>> master:django/forms/models.py
|
||||||
if isinstance(pk, list):
|
if isinstance(pk, list):
|
||||||
pk = pk[0]
|
pk = pk[0]
|
||||||
kwargs['instance'] = self._existing_object(pk)
|
kwargs['instance'] = self._existing_object(pk)
|
||||||
|
@ -11,6 +11,7 @@ except NameError:
|
|||||||
from django.template import Node, NodeList, Template, Context, Variable
|
from django.template import Node, NodeList, Template, Context, Variable
|
||||||
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_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, COMMENT_TAG_START, COMMENT_TAG_END
|
||||||
from django.template import get_library, Library, InvalidTemplateLibrary
|
from django.template import get_library, Library, InvalidTemplateLibrary
|
||||||
|
from django.template.smartif import IfParser, Literal
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.encoding import smart_str, smart_unicode
|
from django.utils.encoding import smart_str, smart_unicode
|
||||||
from django.utils.itercompat import groupby
|
from django.utils.itercompat import groupby
|
||||||
@ -227,10 +228,9 @@ 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, link_type):
|
def __init__(self, var, nodelist_true, nodelist_false=None):
|
||||||
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
|
self.var = var
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<If node>"
|
return "<If node>"
|
||||||
@ -250,28 +250,10 @@ class IfNode(Node):
|
|||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
def render(self, context):
|
def render(self, context):
|
||||||
if self.link_type == IfNode.LinkTypes.or_:
|
if self.var.eval(context):
|
||||||
for ifnot, bool_expr in self.bool_exprs:
|
|
||||||
try:
|
|
||||||
value = bool_expr.resolve(context, True)
|
|
||||||
except VariableDoesNotExist:
|
|
||||||
value = None
|
|
||||||
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)
|
|
||||||
else:
|
else:
|
||||||
for ifnot, bool_expr in self.bool_exprs:
|
|
||||||
try:
|
|
||||||
value = bool_expr.resolve(context, True)
|
|
||||||
except VariableDoesNotExist:
|
|
||||||
value = None
|
|
||||||
if not ((value and not ifnot) or (ifnot and not value)):
|
|
||||||
return self.nodelist_false.render(context)
|
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):
|
||||||
@ -761,6 +743,27 @@ def ifnotequal(parser, token):
|
|||||||
return do_ifequal(parser, token, True)
|
return do_ifequal(parser, token, True)
|
||||||
ifnotequal = register.tag(ifnotequal)
|
ifnotequal = register.tag(ifnotequal)
|
||||||
|
|
||||||
|
class TemplateLiteral(Literal):
|
||||||
|
def __init__(self, value, text):
|
||||||
|
self.value = value
|
||||||
|
self.text = text # for better error messages
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
return self.text
|
||||||
|
|
||||||
|
def eval(self, context):
|
||||||
|
return self.value.resolve(context, ignore_failures=True)
|
||||||
|
|
||||||
|
class TemplateIfParser(IfParser):
|
||||||
|
error_class = TemplateSyntaxError
|
||||||
|
|
||||||
|
def __init__(self, parser, *args, **kwargs):
|
||||||
|
self.template_parser = parser
|
||||||
|
return super(TemplateIfParser, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def create_var(self, value):
|
||||||
|
return TemplateLiteral(self.template_parser.compile_filter(value), value)
|
||||||
|
|
||||||
#@register.tag(name="if")
|
#@register.tag(name="if")
|
||||||
def do_if(parser, token):
|
def do_if(parser, token):
|
||||||
"""
|
"""
|
||||||
@ -805,47 +808,21 @@ def do_if(parser, token):
|
|||||||
There are some athletes and absolutely no coaches.
|
There are some athletes and absolutely no coaches.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
``if`` tags do not allow ``and`` and ``or`` clauses with the same tag,
|
Comparison operators are also available, and the use of filters is also
|
||||||
because the order of logic would be ambigous. For example, this is
|
allowed, for example:
|
||||||
invalid::
|
|
||||||
|
|
||||||
{% if athlete_list and coach_list or cheerleader_list %}
|
{% if articles|length >= 5 %}...{% endif %}
|
||||||
|
|
||||||
If you need to combine ``and`` and ``or`` to do advanced logic, just use
|
Arguments and operators _must_ have a space between them, so
|
||||||
nested if tags. For example::
|
``{% if 1>2 %}`` is not a valid if tag.
|
||||||
|
|
||||||
{% if athlete_list %}
|
All supported operators are: ``or``, ``and``, ``in``, ``==`` (or ``=``),
|
||||||
{% if coach_list or cheerleader_list %}
|
``!=``, ``>``, ``>=``, ``<`` and ``<=``.
|
||||||
We have athletes, and either coaches or cheerleaders!
|
|
||||||
{% endif %}
|
Operator precedence follows Python.
|
||||||
{% endif %}
|
|
||||||
"""
|
"""
|
||||||
bits = token.contents.split()
|
bits = token.split_contents()[1:]
|
||||||
del bits[0]
|
var = TemplateIfParser(parser, bits).parse()
|
||||||
if not bits:
|
|
||||||
raise TemplateSyntaxError("'if' statement requires at least one argument")
|
|
||||||
# Bits now looks something like this: ['a', 'or', 'not', 'b', 'or', 'c.d']
|
|
||||||
bitstr = ' '.join(bits)
|
|
||||||
boolpairs = bitstr.split(' and ')
|
|
||||||
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:
|
|
||||||
if ' ' in boolpair:
|
|
||||||
try:
|
|
||||||
not_, boolvar = boolpair.split()
|
|
||||||
except ValueError:
|
|
||||||
raise TemplateSyntaxError, "'if' statement improperly formatted"
|
|
||||||
if not_ != 'not':
|
|
||||||
raise TemplateSyntaxError, "Expected 'not' in if statement"
|
|
||||||
boolvars.append((True, parser.compile_filter(boolvar)))
|
|
||||||
else:
|
|
||||||
boolvars.append((False, parser.compile_filter(boolpair)))
|
|
||||||
nodelist_true = parser.parse(('else', 'endif'))
|
nodelist_true = parser.parse(('else', 'endif'))
|
||||||
token = parser.next_token()
|
token = parser.next_token()
|
||||||
if token.contents == 'else':
|
if token.contents == 'else':
|
||||||
@ -853,7 +830,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, link_type)
|
return IfNode(var, nodelist_true, nodelist_false)
|
||||||
do_if = register.tag("if", do_if)
|
do_if = register.tag("if", do_if)
|
||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
|
192
django/template/smartif.py
Normal file
192
django/template/smartif.py
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
"""
|
||||||
|
Parser and utilities for the smart 'if' tag
|
||||||
|
"""
|
||||||
|
import operator
|
||||||
|
|
||||||
|
# Using a simple top down parser, as described here:
|
||||||
|
# http://effbot.org/zone/simple-top-down-parsing.htm.
|
||||||
|
# 'led' = left denotation
|
||||||
|
# 'nud' = null denotation
|
||||||
|
# 'bp' = binding power (left = lbp, right = rbp)
|
||||||
|
|
||||||
|
class TokenBase(object):
|
||||||
|
"""
|
||||||
|
Base class for operators and literals, mainly for debugging and for throwing
|
||||||
|
syntax errors.
|
||||||
|
"""
|
||||||
|
id = None # node/token type name
|
||||||
|
value = None # used by literals
|
||||||
|
first = second = None # used by tree nodes
|
||||||
|
|
||||||
|
def nud(self, parser):
|
||||||
|
# Null denotation - called in prefix context
|
||||||
|
raise parser.error_class(
|
||||||
|
"Not expecting '%s' in this position in if tag." % self.id
|
||||||
|
)
|
||||||
|
|
||||||
|
def led(self, left, parser):
|
||||||
|
# Left denotation - called in infix context
|
||||||
|
raise parser.error_class(
|
||||||
|
"Not expecting '%s' as infix operator in if tag." % self.id
|
||||||
|
)
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
"""
|
||||||
|
Returns what to display in error messages for this node
|
||||||
|
"""
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
out = [str(x) for x in [self.id, self.first, self.second] if x is not None]
|
||||||
|
return "(" + " ".join(out) + ")"
|
||||||
|
|
||||||
|
|
||||||
|
def infix(bp, func):
|
||||||
|
"""
|
||||||
|
Creates an infix operator, given a binding power and a function that
|
||||||
|
evaluates the node
|
||||||
|
"""
|
||||||
|
class Operator(TokenBase):
|
||||||
|
lbp = bp
|
||||||
|
|
||||||
|
def led(self, left, parser):
|
||||||
|
self.first = left
|
||||||
|
self.second = parser.expression(bp)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def eval(self, context):
|
||||||
|
try:
|
||||||
|
return func(self.first.eval(context), self.second.eval(context))
|
||||||
|
except Exception:
|
||||||
|
# Templates shouldn't throw exceptions when rendering. We are
|
||||||
|
# most likely to get exceptions for things like {% if foo in bar
|
||||||
|
# %} where 'bar' does not support 'in', so default to False
|
||||||
|
return False
|
||||||
|
|
||||||
|
return Operator
|
||||||
|
|
||||||
|
|
||||||
|
def prefix(bp, func):
|
||||||
|
"""
|
||||||
|
Creates a prefix operator, given a binding power and a function that
|
||||||
|
evaluates the node.
|
||||||
|
"""
|
||||||
|
class Operator(TokenBase):
|
||||||
|
lbp = bp
|
||||||
|
|
||||||
|
def nud(self, parser):
|
||||||
|
self.first = parser.expression(bp)
|
||||||
|
self.second = None
|
||||||
|
return self
|
||||||
|
|
||||||
|
def eval(self, context):
|
||||||
|
try:
|
||||||
|
return func(self.first.eval(context))
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
return Operator
|
||||||
|
|
||||||
|
|
||||||
|
# Operator precedence follows Python.
|
||||||
|
# NB - we can get slightly more accurate syntax error messages by not using the
|
||||||
|
# same object for '==' and '='.
|
||||||
|
|
||||||
|
OPERATORS = {
|
||||||
|
'or': infix(6, lambda x, y: x or y),
|
||||||
|
'and': infix(7, lambda x, y: x and y),
|
||||||
|
'not': prefix(8, operator.not_),
|
||||||
|
'in': infix(9, lambda x, y: x in y),
|
||||||
|
'=': infix(10, operator.eq),
|
||||||
|
'==': infix(10, operator.eq),
|
||||||
|
'!=': infix(10, operator.ne),
|
||||||
|
'>': infix(10, operator.gt),
|
||||||
|
'>=': infix(10, operator.ge),
|
||||||
|
'<': infix(10, operator.lt),
|
||||||
|
'<=': infix(10, operator.le),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Assign 'id' to each:
|
||||||
|
for key, op in OPERATORS.items():
|
||||||
|
op.id = key
|
||||||
|
|
||||||
|
|
||||||
|
class Literal(TokenBase):
|
||||||
|
"""
|
||||||
|
A basic self-resolvable object similar to a Django template variable.
|
||||||
|
"""
|
||||||
|
# IfParser uses Literal in create_var, but TemplateIfParser overrides
|
||||||
|
# create_var so that a proper implementation that actually resolves
|
||||||
|
# variables, filters etc is used.
|
||||||
|
id = "literal"
|
||||||
|
lbp = 0
|
||||||
|
|
||||||
|
def __init__(self, value):
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def display(self):
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
def nud(self, parser):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def eval(self, context):
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "(%s %r)" % (self.id, self.value)
|
||||||
|
|
||||||
|
|
||||||
|
class EndToken(TokenBase):
|
||||||
|
lbp = 0
|
||||||
|
|
||||||
|
def nud(self, parser):
|
||||||
|
raise parser.error_class("Unexpected end of expression in if tag.")
|
||||||
|
|
||||||
|
EndToken = EndToken()
|
||||||
|
|
||||||
|
|
||||||
|
class IfParser(object):
|
||||||
|
error_class = ValueError
|
||||||
|
|
||||||
|
def __init__(self, tokens):
|
||||||
|
self.tokens = map(self.translate_tokens, tokens)
|
||||||
|
self.pos = 0
|
||||||
|
self.current_token = self.next()
|
||||||
|
|
||||||
|
def translate_tokens(self, token):
|
||||||
|
try:
|
||||||
|
op = OPERATORS[token]
|
||||||
|
except (KeyError, TypeError):
|
||||||
|
return self.create_var(token)
|
||||||
|
else:
|
||||||
|
return op()
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
if self.pos >= len(self.tokens):
|
||||||
|
return EndToken
|
||||||
|
else:
|
||||||
|
retval = self.tokens[self.pos]
|
||||||
|
self.pos += 1
|
||||||
|
return retval
|
||||||
|
|
||||||
|
def parse(self):
|
||||||
|
retval = self.expression()
|
||||||
|
# Check that we have exhausted all the tokens
|
||||||
|
if self.current_token is not EndToken:
|
||||||
|
raise self.error_class("Unused '%s' at end of if expression." %
|
||||||
|
self.current_token.display())
|
||||||
|
return retval
|
||||||
|
|
||||||
|
def expression(self, rbp=0):
|
||||||
|
t = self.current_token
|
||||||
|
self.current_token = self.next()
|
||||||
|
left = t.nud(self)
|
||||||
|
while rbp < self.current_token.lbp:
|
||||||
|
t = self.current_token
|
||||||
|
self.current_token = self.next()
|
||||||
|
left = t.led(left, self)
|
||||||
|
return left
|
||||||
|
|
||||||
|
def create_var(self, value):
|
||||||
|
return Literal(value)
|
@ -13,6 +13,13 @@ their deprecation, as per the :ref:`Django deprecation policy
|
|||||||
hooking up admin URLs. This has been deprecated since the 1.1
|
hooking up admin URLs. This has been deprecated since the 1.1
|
||||||
release.
|
release.
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/internals/deprecation.txt
|
||||||
|
=======
|
||||||
|
* Authentication backends need to define the boolean attribute
|
||||||
|
``supports_object_permissions``. The old backend style is deprecated
|
||||||
|
since the 1.2 release.
|
||||||
|
|
||||||
|
>>>>>>> master:docs/internals/deprecation.txt
|
||||||
* 1.4
|
* 1.4
|
||||||
* ``CsrfResponseMiddleware``. This has been deprecated since the 1.2
|
* ``CsrfResponseMiddleware``. This has been deprecated since the 1.2
|
||||||
release, in favour of the template tag method for inserting the CSRF
|
release, in favour of the template tag method for inserting the CSRF
|
||||||
@ -26,6 +33,7 @@ their deprecation, as per the :ref:`Django deprecation policy
|
|||||||
class in favor of a generic E-mail backend API.
|
class in favor of a generic E-mail backend API.
|
||||||
|
|
||||||
* The many to many SQL generation functions on the database backends
|
* The many to many SQL generation functions on the database backends
|
||||||
|
<<<<<<< HEAD:docs/internals/deprecation.txt
|
||||||
will be removed.
|
will be removed.
|
||||||
|
|
||||||
* The ability to use the ``DATABASE_*`` family of top-level settings to
|
* The ability to use the ``DATABASE_*`` family of top-level settings to
|
||||||
@ -39,6 +47,9 @@ their deprecation, as per the :ref:`Django deprecation policy
|
|||||||
``get_db_prep_lookup`` methods on Field were modified in 1.2 to support
|
``get_db_prep_lookup`` methods on Field were modified in 1.2 to support
|
||||||
multiple databases. In 1.4, the support functions that allow methods
|
multiple databases. In 1.4, the support functions that allow methods
|
||||||
with the old prototype to continue working will be removed.
|
with the old prototype to continue working will be removed.
|
||||||
|
=======
|
||||||
|
will be removed. These have been deprecated since the 1.2 release.
|
||||||
|
>>>>>>> master:docs/internals/deprecation.txt
|
||||||
|
|
||||||
* The ``Message`` model (in ``django.contrib.auth``), its related
|
* The ``Message`` model (in ``django.contrib.auth``), its related
|
||||||
manager in the ``User`` model (``user.message_set``), and the
|
manager in the ``User`` model (``user.message_set``), and the
|
||||||
@ -48,6 +59,13 @@ their deprecation, as per the :ref:`Django deprecation policy
|
|||||||
:ref:`messages framework <ref-contrib-messages>` should be used
|
:ref:`messages framework <ref-contrib-messages>` should be used
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/internals/deprecation.txt
|
||||||
|
=======
|
||||||
|
* Authentication backends need to support the ``obj`` parameter for
|
||||||
|
permission checking. The ``supports_object_permissions`` variable
|
||||||
|
is not checked any longer and can be removed.
|
||||||
|
|
||||||
|
>>>>>>> master:docs/internals/deprecation.txt
|
||||||
* 2.0
|
* 2.0
|
||||||
* ``django.views.defaults.shortcut()``. This function has been moved
|
* ``django.views.defaults.shortcut()``. This function has been moved
|
||||||
to ``django.contrib.contenttypes.views.shortcut()`` as part of the
|
to ``django.contrib.contenttypes.views.shortcut()`` as part of the
|
||||||
|
@ -257,7 +257,10 @@ Here's a sample configuration which uses a MySQL option file::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/ref/databases.txt
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> master:docs/ref/databases.txt
|
||||||
# my.cnf
|
# my.cnf
|
||||||
[client]
|
[client]
|
||||||
database = NAME
|
database = NAME
|
||||||
|
@ -210,6 +210,24 @@ records to dump. If you're using a :ref:`custom manager <custom-managers>` as
|
|||||||
the default manager and it filters some of the available records, not all of the
|
the default manager and it filters some of the available records, not all of the
|
||||||
objects will be dumped.
|
objects will be dumped.
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/ref/django-admin.txt
|
||||||
|
=======
|
||||||
|
.. django-admin-option:: --exclude
|
||||||
|
|
||||||
|
.. versionadded:: 1.0
|
||||||
|
|
||||||
|
Exclude a specific application from the applications whose contents is
|
||||||
|
output. For example, to specifically exclude the `auth` application from
|
||||||
|
the output, you would call::
|
||||||
|
|
||||||
|
django-admin.py dumpdata --exclude=auth
|
||||||
|
|
||||||
|
If you want to exclude multiple applications, use multiple ``--exclude``
|
||||||
|
directives::
|
||||||
|
|
||||||
|
django-admin.py dumpdata --exclude=auth --exclude=contenttypes
|
||||||
|
|
||||||
|
>>>>>>> master:docs/ref/django-admin.txt
|
||||||
.. django-admin-option:: --format <fmt>
|
.. django-admin-option:: --format <fmt>
|
||||||
|
|
||||||
By default, ``dumpdata`` will format its output in JSON, but you can use the
|
By default, ``dumpdata`` will format its output in JSON, but you can use the
|
||||||
@ -221,11 +239,14 @@ are listed in :ref:`serialization-formats`.
|
|||||||
By default, ``dumpdata`` will output all data on a single line. This isn't
|
By default, ``dumpdata`` will output all data on a single line. This isn't
|
||||||
easy for humans to read, so you can use the ``--indent`` option to
|
easy for humans to read, so you can use the ``--indent`` option to
|
||||||
pretty-print the output with a number of indentation spaces.
|
pretty-print the output with a number of indentation spaces.
|
||||||
|
<<<<<<< HEAD:docs/ref/django-admin.txt
|
||||||
|
|
||||||
.. versionadded:: 1.0
|
.. versionadded:: 1.0
|
||||||
|
|
||||||
The :djadminopt:`--exclude` option may be provided to prevent specific
|
The :djadminopt:`--exclude` option may be provided to prevent specific
|
||||||
applications from being dumped.
|
applications from being dumped.
|
||||||
|
=======
|
||||||
|
>>>>>>> master:docs/ref/django-admin.txt
|
||||||
|
|
||||||
.. versionadded:: 1.1
|
.. versionadded:: 1.1
|
||||||
|
|
||||||
@ -252,12 +273,15 @@ fixture will be re-installed.
|
|||||||
|
|
||||||
The :djadminopt:`--noinput` option may be provided to suppress all user
|
The :djadminopt:`--noinput` option may be provided to suppress all user
|
||||||
prompts.
|
prompts.
|
||||||
|
<<<<<<< HEAD:docs/ref/django-admin.txt
|
||||||
|
|
||||||
.. versionadded:: 1.2
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
The :djadminopt:`--database` option may be used to specify the database
|
The :djadminopt:`--database` option may be used to specify the database
|
||||||
to flush.
|
to flush.
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> master:docs/ref/django-admin.txt
|
||||||
|
|
||||||
inspectdb
|
inspectdb
|
||||||
---------
|
---------
|
||||||
@ -487,6 +511,7 @@ reset <appname appname ...>
|
|||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
.. django-admin:: reset
|
.. django-admin:: reset
|
||||||
|
<<<<<<< HEAD:docs/ref/django-admin.txt
|
||||||
|
|
||||||
Executes the equivalent of ``sqlreset`` for the given app name(s).
|
Executes the equivalent of ``sqlreset`` for the given app name(s).
|
||||||
|
|
||||||
@ -497,6 +522,13 @@ prompts.
|
|||||||
|
|
||||||
The :djadminopt:`--database` option can be used to specify the alias
|
The :djadminopt:`--database` option can be used to specify the alias
|
||||||
of the database to reset.
|
of the database to reset.
|
||||||
|
=======
|
||||||
|
|
||||||
|
Executes the equivalent of ``sqlreset`` for the given app name(s).
|
||||||
|
|
||||||
|
The :djadminopt:`--noinput` option may be provided to suppress all user
|
||||||
|
prompts.
|
||||||
|
>>>>>>> master:docs/ref/django-admin.txt
|
||||||
|
|
||||||
runfcgi [options]
|
runfcgi [options]
|
||||||
-----------------
|
-----------------
|
||||||
@ -680,11 +712,14 @@ sqlflush
|
|||||||
|
|
||||||
Prints the SQL statements that would be executed for the :djadmin:`flush`
|
Prints the SQL statements that would be executed for the :djadmin:`flush`
|
||||||
command.
|
command.
|
||||||
|
<<<<<<< HEAD:docs/ref/django-admin.txt
|
||||||
|
|
||||||
.. versionadded:: 1.2
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
The :djadminopt:`--database` option can be used to specify the database for
|
The :djadminopt:`--database` option can be used to specify the database for
|
||||||
which to print the SQL.
|
which to print the SQL.
|
||||||
|
=======
|
||||||
|
>>>>>>> master:docs/ref/django-admin.txt
|
||||||
|
|
||||||
sqlindexes <appname appname ...>
|
sqlindexes <appname appname ...>
|
||||||
--------------------------------
|
--------------------------------
|
||||||
@ -784,6 +819,7 @@ with an appropriate extension (e.g. ``json`` or ``xml``). See the
|
|||||||
documentation for ``loaddata`` for details on the specification of fixture
|
documentation for ``loaddata`` for details on the specification of fixture
|
||||||
data files.
|
data files.
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/ref/django-admin.txt
|
||||||
--noinput
|
--noinput
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
The :djadminopt:`--noinput` option may be provided to suppress all user
|
The :djadminopt:`--noinput` option may be provided to suppress all user
|
||||||
@ -793,15 +829,27 @@ prompts.
|
|||||||
|
|
||||||
The :djadminopt:`--database` option can be used to specify the database to
|
The :djadminopt:`--database` option can be used to specify the database to
|
||||||
synchronize.
|
synchronize.
|
||||||
|
=======
|
||||||
|
The :djadminopt:`--noinput` option may be provided to suppress all user
|
||||||
|
prompts.
|
||||||
|
|
||||||
test <app or test identifier>
|
test <app or test identifier>
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
.. django-admin:: test
|
||||||
|
>>>>>>> master:docs/ref/django-admin.txt
|
||||||
|
|
||||||
|
test <app or test identifier>
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/ref/django-admin.txt
|
||||||
.. django-admin:: test
|
.. django-admin:: test
|
||||||
|
|
||||||
Runs tests for all installed models. See :ref:`topics-testing` for more
|
Runs tests for all installed models. See :ref:`topics-testing` for more
|
||||||
information.
|
information.
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> master:docs/ref/django-admin.txt
|
||||||
testserver <fixture fixture ...>
|
testserver <fixture fixture ...>
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
@ -935,6 +983,7 @@ Common options
|
|||||||
The following options are not available on every commands, but they are
|
The following options are not available on every commands, but they are
|
||||||
common to a number of commands.
|
common to a number of commands.
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/ref/django-admin.txt
|
||||||
.. django-admin-option:: --database
|
.. django-admin-option:: --database
|
||||||
|
|
||||||
.. versionadded:: 1.2
|
.. versionadded:: 1.2
|
||||||
@ -959,6 +1008,8 @@ directives::
|
|||||||
|
|
||||||
django-admin.py dumpdata --exclude=auth --exclude=contenttypes
|
django-admin.py dumpdata --exclude=auth --exclude=contenttypes
|
||||||
|
|
||||||
|
=======
|
||||||
|
>>>>>>> master:docs/ref/django-admin.txt
|
||||||
.. django-admin-option:: --locale
|
.. django-admin-option:: --locale
|
||||||
|
|
||||||
Use the ``--locale`` or ``-l`` option to specify the locale to process.
|
Use the ``--locale`` or ``-l`` option to specify the locale to process.
|
||||||
|
@ -145,6 +145,54 @@ The default number of seconds to cache a page when the caching middleware or
|
|||||||
``cache_page()`` decorator is used.
|
``cache_page()`` decorator is used.
|
||||||
|
|
||||||
.. setting:: CSRF_COOKIE_NAME
|
.. setting:: CSRF_COOKIE_NAME
|
||||||
|
<<<<<<< HEAD:docs/ref/settings.txt
|
||||||
|
=======
|
||||||
|
|
||||||
|
CSRF_COOKIE_NAME
|
||||||
|
----------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
|
Default: ``'csrftoken'``
|
||||||
|
|
||||||
|
The name of the cookie to use for the CSRF authentication token. This can be whatever you
|
||||||
|
want. See :ref:`ref-contrib-csrf`.
|
||||||
|
|
||||||
|
.. setting:: CSRF_COOKIE_DOMAIN
|
||||||
|
|
||||||
|
CSRF_COOKIE_DOMAIN
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
|
Default: ``None``
|
||||||
|
|
||||||
|
The domain to be used when setting the CSRF cookie. This can be useful for
|
||||||
|
allowing cross-subdomain requests to be exluded from the normal cross site
|
||||||
|
request forgery protection. It should be set to a string such as
|
||||||
|
``".lawrence.com"`` to allow a POST request from a form on one subdomain to be
|
||||||
|
accepted by accepted by a view served from another subdomain.
|
||||||
|
|
||||||
|
.. setting:: CSRF_FAILURE_VIEW
|
||||||
|
|
||||||
|
CSRF_FAILURE_VIEW
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
|
Default: ``'django.views.csrf.csrf_failure'``
|
||||||
|
|
||||||
|
A dotted path to the view function to be used when an incoming request
|
||||||
|
is rejected by the CSRF protection. The function should have this signature::
|
||||||
|
|
||||||
|
def csrf_failure(request, reason="")
|
||||||
|
|
||||||
|
where ``reason`` is a short message (intended for developers or logging, not for
|
||||||
|
end users) indicating the reason the request was rejected. See
|
||||||
|
:ref:`ref-contrib-csrf`.
|
||||||
|
|
||||||
|
.. setting:: DATABASE_ENGINE
|
||||||
|
>>>>>>> master:docs/ref/settings.txt
|
||||||
|
|
||||||
CSRF_COOKIE_NAME
|
CSRF_COOKIE_NAME
|
||||||
----------------
|
----------------
|
||||||
|
@ -313,6 +313,9 @@ displayed by the ``{{ athlete_list|length }}`` variable.
|
|||||||
As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that
|
As you can see, the ``if`` tag can take an optional ``{% else %}`` clause that
|
||||||
will be displayed if the test fails.
|
will be displayed if the test fails.
|
||||||
|
|
||||||
|
Boolean operators
|
||||||
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or
|
``if`` tags may use ``and``, ``or`` or ``not`` to test a number of variables or
|
||||||
to negate a given variable::
|
to negate a given variable::
|
||||||
|
|
||||||
@ -338,24 +341,153 @@ to negate a given variable::
|
|||||||
There are some athletes and absolutely no coaches.
|
There are some athletes and absolutely no coaches.
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
``if`` tags don't allow ``and`` and ``or`` clauses within the same tag, because
|
.. versionchanged:: 1.2
|
||||||
the order of logic would be ambiguous. For example, this is invalid::
|
|
||||||
|
Use of both ``and`` and ``or`` clauses within the same tag is allowed, with
|
||||||
|
``and`` having higher precedence than ``or`` e.g.::
|
||||||
|
|
||||||
{% if athlete_list and coach_list or cheerleader_list %}
|
{% if athlete_list and coach_list or cheerleader_list %}
|
||||||
|
|
||||||
If you need to combine ``and`` and ``or`` to do advanced logic, just use nested
|
will be interpreted like:
|
||||||
``if`` tags. For example::
|
|
||||||
|
|
||||||
{% if athlete_list %}
|
.. code-block:: python
|
||||||
{% if coach_list or cheerleader_list %}
|
|
||||||
We have athletes, and either coaches or cheerleaders!
|
if (athlete_list and coach_list) or cheerleader_list
|
||||||
{% endif %}
|
|
||||||
|
Use of actual brackets in the ``if`` tag is invalid syntax. If you need them to
|
||||||
|
indicate precedence, you should use nested ``if`` tags.
|
||||||
|
|
||||||
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
|
|
||||||
|
``if`` tags may also use the operators ``==``, ``!=``, ``<``, ``>``,
|
||||||
|
``<=``, ``>=`` and ``in`` which work as follows:
|
||||||
|
|
||||||
|
|
||||||
|
``==`` operator
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Equality. Example::
|
||||||
|
|
||||||
|
{% if somevar == "x" %}
|
||||||
|
This appears if variable somevar equals the string "x"
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
Multiple uses of the same logical operator are fine, as long as you use the
|
``!=`` operator
|
||||||
same operator. For example, this is valid::
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Inequality. Example::
|
||||||
|
|
||||||
|
{% if somevar != "x" %}
|
||||||
|
This appears if variable somevar does not equal the string "x",
|
||||||
|
or if somevar is not found in the context
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
``<`` operator
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Less than. Example::
|
||||||
|
|
||||||
|
{% if somevar < 100 %}
|
||||||
|
This appears if variable somevar is less than 100.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
``>`` operator
|
||||||
|
^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Greater than. Example::
|
||||||
|
|
||||||
|
{% if somevar > 0 %}
|
||||||
|
This appears if variable somevar is greater than 0.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
``<=`` operator
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Less than or equal to. Example::
|
||||||
|
|
||||||
|
{% if somevar <= 100 %}
|
||||||
|
This appears if variable somevar is less than 100 or equal to 100.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
``>=`` operator
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Greater than or equal to. Example::
|
||||||
|
|
||||||
|
{% if somevar >= 1 %}
|
||||||
|
This appears if variable somevar is greater than 1 or equal to 1.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
``in`` operator
|
||||||
|
^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Contained within. This operator is supported by many Python containers to test
|
||||||
|
whether the given value is in the container. The following are some examples of
|
||||||
|
how ``x in y`` will be interpreted::
|
||||||
|
|
||||||
|
{% if "bc" in "abcdef" %}
|
||||||
|
This appears since "bc" is a substring of "abcdef"
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if "hello" in greetings %}
|
||||||
|
If greetings is a list or set, one element of which is the string
|
||||||
|
"hello", this will appear.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if user in users %}
|
||||||
|
If users is a QuerySet, this will appear if user is an
|
||||||
|
instance that belongs to the QuerySet.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
The comparison operators cannot be 'chained' like in Python or in mathematical
|
||||||
|
notation. For example, instead of using::
|
||||||
|
|
||||||
|
{% if a > b > c %} (WRONG)
|
||||||
|
|
||||||
|
you should use::
|
||||||
|
|
||||||
|
{% if a > b and b > c %}
|
||||||
|
|
||||||
|
|
||||||
|
Filters
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
You can also use filters in the ``if`` expression. For example::
|
||||||
|
|
||||||
|
{% if messages|length >= 100 %}
|
||||||
|
You have lots of messages today!
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
Complex expressions
|
||||||
|
^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
All of the above can be combined to form complex expressions. For such
|
||||||
|
expressions, it can be important to know how the operators are grouped when the
|
||||||
|
expression is evaluated - that is, the precedence rules. The precedence of the
|
||||||
|
operators, from lowest to highest, is as follows:
|
||||||
|
|
||||||
|
* ``or``
|
||||||
|
* ``and``
|
||||||
|
* ``not``
|
||||||
|
* ``in``
|
||||||
|
* ``==``, ``!=``, ``<``, ``>``,``<=``, ``>=``
|
||||||
|
|
||||||
|
(This follows Python exactly). So, for example, the following complex if tag:
|
||||||
|
|
||||||
|
{% if a == b or c == d and e %}
|
||||||
|
|
||||||
|
...will be interpreted as:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
(a == b) or ((c == d) and e)
|
||||||
|
|
||||||
|
If you need different precedence, you will need to use nested if tags. Sometimes
|
||||||
|
that is better for clarity anyway, for the sake of those who do not know the
|
||||||
|
precedence rules.
|
||||||
|
|
||||||
{% if athlete_list or coach_list or parent_list or teacher_list %}
|
|
||||||
|
|
||||||
.. templatetag:: ifchanged
|
.. templatetag:: ifchanged
|
||||||
|
|
||||||
@ -427,6 +559,9 @@ You cannot check for equality with Python objects such as ``True`` or
|
|||||||
``False``. If you need to test if something is true or false, use the ``if``
|
``False``. If you need to test if something is true or false, use the ``if``
|
||||||
tag instead.
|
tag instead.
|
||||||
|
|
||||||
|
.. versionadded:: 1.2
|
||||||
|
An alternative to the ``ifequal`` tag is to use the :ttag:`if` tag and the ``==`` operator.
|
||||||
|
|
||||||
.. templatetag:: ifnotequal
|
.. templatetag:: ifnotequal
|
||||||
|
|
||||||
ifnotequal
|
ifnotequal
|
||||||
@ -434,6 +569,9 @@ ifnotequal
|
|||||||
|
|
||||||
Just like ``ifequal``, except it tests that the two arguments are not equal.
|
Just like ``ifequal``, except it tests that the two arguments are not equal.
|
||||||
|
|
||||||
|
.. versionadded:: 1.2
|
||||||
|
An alternative to the ``ifnotequal`` tag is to use the :ttag:`if` tag and the ``!=`` operator.
|
||||||
|
|
||||||
.. templatetag:: include
|
.. templatetag:: include
|
||||||
|
|
||||||
include
|
include
|
||||||
|
@ -42,6 +42,18 @@ changes that developers must be aware of:
|
|||||||
* All of the CSRF has moved from contrib to core (with backwards compatible
|
* All of the CSRF has moved from contrib to core (with backwards compatible
|
||||||
imports in the old locations, which are deprecated).
|
imports in the old locations, which are deprecated).
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/releases/1.2.txt
|
||||||
|
=======
|
||||||
|
:ttag:`if` tag changes
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
Due to new features in the :ttag:`if` template tag, it no longer accepts 'and',
|
||||||
|
'or' and 'not' as valid **variable** names. Previously that worked in some
|
||||||
|
cases even though these strings were normally treated as keywords. Now, the
|
||||||
|
keyword status is always enforced, and template code like ``{% if not %}`` or
|
||||||
|
``{% if and %}`` will throw a TemplateSyntaxError.
|
||||||
|
|
||||||
|
>>>>>>> master:docs/releases/1.2.txt
|
||||||
``LazyObject``
|
``LazyObject``
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@ -67,6 +79,7 @@ changes:
|
|||||||
|
|
||||||
__members__ = property(lambda self: self.__dir__())
|
__members__ = property(lambda self: self.__dir__())
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/releases/1.2.txt
|
||||||
Specifying databases
|
Specifying databases
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@ -208,6 +221,8 @@ connection, you should be able to upgrade by renaming
|
|||||||
database specific conversions, then you will need to provide an
|
database specific conversions, then you will need to provide an
|
||||||
implementation ``get_db_prep_*`` that uses the ``connection``
|
implementation ``get_db_prep_*`` that uses the ``connection``
|
||||||
argument to resolve database-specific values.
|
argument to resolve database-specific values.
|
||||||
|
=======
|
||||||
|
>>>>>>> master:docs/releases/1.2.txt
|
||||||
|
|
||||||
.. _deprecated-features-1.2:
|
.. _deprecated-features-1.2:
|
||||||
|
|
||||||
@ -338,6 +353,7 @@ replaces the deprecated user message API and allows you to temporarily store
|
|||||||
messages in one request and retrieve them for display in a subsequent request
|
messages in one request and retrieve them for display in a subsequent request
|
||||||
(usually the next one).
|
(usually the next one).
|
||||||
|
|
||||||
|
<<<<<<< HEAD:docs/releases/1.2.txt
|
||||||
Support for multiple databases
|
Support for multiple databases
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
@ -346,3 +362,38 @@ Django 1.2 adds the ability to use :ref:`more than one database
|
|||||||
issued at a specific database with the `using()` method on
|
issued at a specific database with the `using()` method on
|
||||||
querysets; individual objects can be saved to a specific database
|
querysets; individual objects can be saved to a specific database
|
||||||
by providing a ``using`` argument when you save the instance.
|
by providing a ``using`` argument when you save the instance.
|
||||||
|
=======
|
||||||
|
'Smart' if tag
|
||||||
|
--------------
|
||||||
|
|
||||||
|
The :ttag:`if` tag has been upgraded to be much more powerful. First, support
|
||||||
|
for comparison operators has been added. No longer will you have to type:
|
||||||
|
|
||||||
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
{% ifnotequal a b %}
|
||||||
|
...
|
||||||
|
{% endifnotequal %}
|
||||||
|
|
||||||
|
...as you can now do:
|
||||||
|
|
||||||
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
{% if a != b %}
|
||||||
|
...
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
The operators supported are ``==``, ``!=``, ``<``, ``>``, ``<=``, ``>=`` and
|
||||||
|
``in``, all of which work like the Python operators, in addition to ``and``,
|
||||||
|
``or`` and ``not`` which were already supported.
|
||||||
|
|
||||||
|
Also, filters may now be used in the ``if`` expression. For example:
|
||||||
|
|
||||||
|
.. code-block:: html+django
|
||||||
|
|
||||||
|
<div
|
||||||
|
{% if user.email|lower == message.recipient|lower %}
|
||||||
|
class="highlight"
|
||||||
|
{% endif %}
|
||||||
|
>{{ message }}</div>
|
||||||
|
>>>>>>> master:docs/releases/1.2.txt
|
||||||
|
@ -202,28 +202,51 @@ Methods
|
|||||||
:meth:`~django.contrib.auth.models.User.set_unusable_password()` has
|
:meth:`~django.contrib.auth.models.User.set_unusable_password()` has
|
||||||
been called for this user.
|
been called for this user.
|
||||||
|
|
||||||
.. method:: models.User.get_group_permissions()
|
.. method:: models.User.get_group_permissions(obj=None)
|
||||||
|
|
||||||
Returns a list of permission strings that the user has, through his/her
|
Returns a list of permission strings that the user has, through his/her
|
||||||
groups.
|
groups.
|
||||||
|
|
||||||
.. method:: models.User.get_all_permissions()
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
|
If ``obj`` is passed in, only returns the group permissions for
|
||||||
|
this specific object.
|
||||||
|
|
||||||
|
.. method:: models.User.get_all_permissions(obj=None)
|
||||||
|
|
||||||
Returns a list of permission strings that the user has, both through
|
Returns a list of permission strings that the user has, both through
|
||||||
group and user permissions.
|
group and user permissions.
|
||||||
|
|
||||||
.. method:: models.User.has_perm(perm)
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
|
If ``obj`` is passed in, only returns the permissions for this
|
||||||
|
specific object.
|
||||||
|
|
||||||
|
.. method:: models.User.has_perm(perm, obj=None)
|
||||||
|
|
||||||
Returns ``True`` if the user has the specified permission, where perm is
|
Returns ``True`` if the user has the specified permission, where perm is
|
||||||
in the format ``"<app label>.<permission codename>"``.
|
in the format ``"<app label>.<permission codename>"``.
|
||||||
If the user is inactive, this method will always return ``False``.
|
If the user is inactive, this method will always return ``False``.
|
||||||
|
|
||||||
.. method:: models.User.has_perms(perm_list)
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
|
If ``obj`` is passed in, this method won't check for a permission for
|
||||||
|
the model, but for this specific object.
|
||||||
|
|
||||||
|
.. method:: models.User.has_perms(perm_list, obj=None)
|
||||||
|
|
||||||
Returns ``True`` if the user has each of the specified permissions,
|
Returns ``True`` if the user has each of the specified permissions,
|
||||||
where each perm is in the format
|
where each perm is in the format
|
||||||
``"<app label>.<permission codename>"``. If the user is inactive,
|
``"<app label>.<permission codename>"``. If the user is inactive,
|
||||||
this method will always return ``False``.
|
this method will always return ``False``.
|
||||||
|
<<<<<<< HEAD:docs/topics/auth.txt
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. versionadded:: 1.2
|
||||||
|
|
||||||
|
If ``obj`` is passed in, this method won't check for permissions for
|
||||||
|
the model, but for the specific object.
|
||||||
|
>>>>>>> master:docs/topics/auth.txt
|
||||||
|
|
||||||
.. method:: models.User.has_module_perms(package_name)
|
.. method:: models.User.has_module_perms(package_name)
|
||||||
|
|
||||||
@ -1521,3 +1544,24 @@ A full authorization implementation can be found in
|
|||||||
the ``auth_permission`` table most of the time.
|
the ``auth_permission`` table most of the time.
|
||||||
|
|
||||||
.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py
|
.. _django/contrib/auth/backends.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/backends.py
|
||||||
|
|
||||||
|
Handling object permissions
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
Django's permission framework has a foundation for object permissions, though
|
||||||
|
there is no implementation for it in the core. That means that checking for
|
||||||
|
object permissions will always return ``False`` or an empty list (depending on
|
||||||
|
the check performed).
|
||||||
|
|
||||||
|
To enable object permissions in your own
|
||||||
|
:ref:`authentication backend <ref-authentication-backends>` you'll just have
|
||||||
|
to allow passing an ``obj`` parameter to the permission methods and set the
|
||||||
|
``supports_objects_permissions`` class attribute to ``True``.
|
||||||
|
|
||||||
|
A nonexistent ``supports_objects_permissions`` will raise a hidden
|
||||||
|
``PendingDeprecationWarning`` if used in Django 1.2. In Django 1.3, this
|
||||||
|
warning will be upgraded to a ``DeprecationWarning``, which will be displayed
|
||||||
|
loudly. Additionally ``supports_objects_permissions`` will be set to ``False``.
|
||||||
|
Django 1.4 will assume that every backend supports object permissions and
|
||||||
|
won't check for the existence of ``supports_objects_permissions``, which
|
||||||
|
means not supporting ``obj`` as a parameter will raise a ``TypeError``.
|
||||||
|
@ -188,7 +188,7 @@ tags:
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
:ttag:`if` and :ttag:`else`
|
:ttag:`if` and ``else``
|
||||||
Evaluates a variable, and if that variable is "true" the contents of the
|
Evaluates a variable, and if that variable is "true" the contents of the
|
||||||
block are displayed::
|
block are displayed::
|
||||||
|
|
||||||
@ -201,18 +201,13 @@ tags:
|
|||||||
In the above, if ``athlete_list`` is not empty, the number of athletes
|
In the above, if ``athlete_list`` is not empty, the number of athletes
|
||||||
will be displayed by the ``{{ athlete_list|length }}`` variable.
|
will be displayed by the ``{{ athlete_list|length }}`` variable.
|
||||||
|
|
||||||
:ttag:`ifequal` and :ttag:`ifnotequal`
|
You can also use filters and various operators in the ``if`` tag::
|
||||||
Display some contents if two arguments are or are not equal. For example::
|
|
||||||
|
|
||||||
{% ifequal athlete.name coach.name %}
|
{% if athlete_list|length > 1 %}
|
||||||
...
|
Team: {% for athlete in athlete_list %} ... {% endfor %}
|
||||||
{% endifequal %}
|
{% else %}
|
||||||
|
Athlete: {{ athlete_list.0.name }}
|
||||||
Or::
|
{% endif %}
|
||||||
|
|
||||||
{% ifnotequal athlete.name "Joe" %}
|
|
||||||
...
|
|
||||||
{% endifnotequal %}
|
|
||||||
|
|
||||||
:ttag:`block` and :ttag:`extends`
|
:ttag:`block` and :ttag:`extends`
|
||||||
Set up `template inheritance`_ (see below), a powerful way
|
Set up `template inheritance`_ (see below), a powerful way
|
||||||
|
@ -610,6 +610,12 @@ class AdminViewStringPrimaryKeyTest(TestCase):
|
|||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.client.logout()
|
self.client.logout()
|
||||||
|
|
||||||
|
def test_get_history_view(self):
|
||||||
|
"Retrieving the history for the object using urlencoded form of primary key should work"
|
||||||
|
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/history/' % quote(self.pk))
|
||||||
|
self.assertContains(response, escape(self.pk))
|
||||||
|
self.failUnlessEqual(response.status_code, 200)
|
||||||
|
|
||||||
def test_get_change_view(self):
|
def test_get_change_view(self):
|
||||||
"Retrieving the object using urlencoded form of primary key should work"
|
"Retrieving the object using urlencoded form of primary key should work"
|
||||||
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % quote(self.pk))
|
response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % quote(self.pk))
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
try:
|
|
||||||
set
|
|
||||||
except NameError:
|
|
||||||
from sets import Set as set # Python 2.3 fallback
|
|
||||||
|
|
||||||
__test__ = {'API_TESTS': """
|
|
||||||
>>> from django.contrib.auth.models import User, Group, Permission, AnonymousUser
|
|
||||||
>>> from django.contrib.contenttypes.models import ContentType
|
|
||||||
|
|
||||||
# No Permissions assigned yet, should return False except for superuser
|
|
||||||
|
|
||||||
>>> user = User.objects.create_user('test', 'test@example.com', 'test')
|
|
||||||
>>> user.has_perm("auth.test")
|
|
||||||
False
|
|
||||||
>>> user.is_staff=True
|
|
||||||
>>> user.save()
|
|
||||||
>>> user.has_perm("auth.test")
|
|
||||||
False
|
|
||||||
>>> user.is_superuser=True
|
|
||||||
>>> user.save()
|
|
||||||
>>> user.has_perm("auth.test")
|
|
||||||
True
|
|
||||||
>>> user.is_staff = False
|
|
||||||
>>> user.is_superuser = False
|
|
||||||
>>> user.save()
|
|
||||||
>>> user.has_perm("auth.test")
|
|
||||||
False
|
|
||||||
>>> content_type=ContentType.objects.get_for_model(Group)
|
|
||||||
>>> perm = Permission.objects.create(name="test", content_type=content_type, codename="test")
|
|
||||||
>>> user.user_permissions.add(perm)
|
|
||||||
>>> user.save()
|
|
||||||
|
|
||||||
# reloading user to purge the _perm_cache
|
|
||||||
|
|
||||||
>>> user = User.objects.get(username="test")
|
|
||||||
>>> user.get_all_permissions() == set([u'auth.test'])
|
|
||||||
True
|
|
||||||
>>> user.get_group_permissions() == set([])
|
|
||||||
True
|
|
||||||
>>> user.has_module_perms("Group")
|
|
||||||
False
|
|
||||||
>>> user.has_module_perms("auth")
|
|
||||||
True
|
|
||||||
>>> perm = Permission.objects.create(name="test2", content_type=content_type, codename="test2")
|
|
||||||
>>> user.user_permissions.add(perm)
|
|
||||||
>>> user.save()
|
|
||||||
>>> perm = Permission.objects.create(name="test3", content_type=content_type, codename="test3")
|
|
||||||
>>> user.user_permissions.add(perm)
|
|
||||||
>>> user.save()
|
|
||||||
>>> user = User.objects.get(username="test")
|
|
||||||
>>> user.get_all_permissions() == set([u'auth.test2', u'auth.test', u'auth.test3'])
|
|
||||||
True
|
|
||||||
>>> user.has_perm('test')
|
|
||||||
False
|
|
||||||
>>> user.has_perm('auth.test')
|
|
||||||
True
|
|
||||||
>>> user.has_perms(['auth.test2', 'auth.test3'])
|
|
||||||
True
|
|
||||||
>>> perm = Permission.objects.create(name="test_group", content_type=content_type, codename="test_group")
|
|
||||||
>>> group = Group.objects.create(name='test_group')
|
|
||||||
>>> group.permissions.add(perm)
|
|
||||||
>>> group.save()
|
|
||||||
>>> user.groups.add(group)
|
|
||||||
>>> user = User.objects.get(username="test")
|
|
||||||
>>> exp = set([u'auth.test2', u'auth.test', u'auth.test3', u'auth.test_group'])
|
|
||||||
>>> user.get_all_permissions() == exp
|
|
||||||
True
|
|
||||||
>>> user.get_group_permissions() == set([u'auth.test_group'])
|
|
||||||
True
|
|
||||||
>>> user.has_perms(['auth.test3', 'auth.test_group'])
|
|
||||||
True
|
|
||||||
|
|
||||||
>>> user = AnonymousUser()
|
|
||||||
>>> user.has_perm('test')
|
|
||||||
False
|
|
||||||
>>> user.has_perms(['auth.test2', 'auth.test3'])
|
|
||||||
False
|
|
||||||
"""}
|
|
@ -1,7 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Unit and doctests for specific database backends.
|
# Unit and doctests for specific database backends.
|
||||||
import unittest
|
import unittest
|
||||||
|
<<<<<<< HEAD:tests/regressiontests/backends/tests.py
|
||||||
from django.db import backend, connection, DEFAULT_DB_ALIAS
|
from django.db import backend, connection, DEFAULT_DB_ALIAS
|
||||||
|
=======
|
||||||
|
from django.db import backend, connection
|
||||||
|
>>>>>>> master:tests/regressiontests/backends/tests.py
|
||||||
from django.db.backends.signals import connection_created
|
from django.db.backends.signals import connection_created
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
@ -10,7 +14,11 @@ class Callproc(unittest.TestCase):
|
|||||||
def test_dbms_session(self):
|
def test_dbms_session(self):
|
||||||
# If the backend is Oracle, test that we can call a standard
|
# If the backend is Oracle, test that we can call a standard
|
||||||
# stored procedure through our cursor wrapper.
|
# stored procedure through our cursor wrapper.
|
||||||
|
<<<<<<< HEAD:tests/regressiontests/backends/tests.py
|
||||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle':
|
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle':
|
||||||
|
=======
|
||||||
|
if settings.DATABASE_ENGINE == 'oracle':
|
||||||
|
>>>>>>> master:tests/regressiontests/backends/tests.py
|
||||||
convert_unicode = backend.convert_unicode
|
convert_unicode = backend.convert_unicode
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.callproc(convert_unicode('DBMS_SESSION.SET_IDENTIFIER'),
|
cursor.callproc(convert_unicode('DBMS_SESSION.SET_IDENTIFIER'),
|
||||||
@ -24,7 +32,11 @@ class LongString(unittest.TestCase):
|
|||||||
def test_long_string(self):
|
def test_long_string(self):
|
||||||
# If the backend is Oracle, test that we can save a text longer
|
# If the backend is Oracle, test that we can save a text longer
|
||||||
# than 4000 chars and read it properly
|
# than 4000 chars and read it properly
|
||||||
|
<<<<<<< HEAD:tests/regressiontests/backends/tests.py
|
||||||
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle':
|
if settings.DATABASES[DEFAULT_DB_ALIAS]['ENGINE'] == 'django.db.backends.oracle':
|
||||||
|
=======
|
||||||
|
if settings.DATABASE_ENGINE == 'oracle':
|
||||||
|
>>>>>>> master:tests/regressiontests/backends/tests.py
|
||||||
c = connection.cursor()
|
c = connection.cursor()
|
||||||
c.execute('CREATE TABLE ltext ("TEXT" NCLOB)')
|
c.execute('CREATE TABLE ltext ("TEXT" NCLOB)')
|
||||||
long_str = ''.join([unicode(x) for x in xrange(4000)])
|
long_str = ''.join([unicode(x) for x in xrange(4000)])
|
||||||
|
46
tests/regressiontests/templates/smartif.py
Normal file
46
tests/regressiontests/templates/smartif.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import unittest
|
||||||
|
from django.template.smartif import IfParser, Literal
|
||||||
|
|
||||||
|
class SmartIfTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def assertCalcEqual(self, expected, tokens):
|
||||||
|
self.assertEqual(expected, IfParser(tokens).parse().eval({}))
|
||||||
|
|
||||||
|
# We only test things here that are difficult to test elsewhere
|
||||||
|
# Many other tests are found in the main tests for builtin template tags
|
||||||
|
# Test parsing via the printed parse tree
|
||||||
|
def test_not(self):
|
||||||
|
var = IfParser(["not", False]).parse()
|
||||||
|
self.assertEqual("(not (literal False))", repr(var))
|
||||||
|
self.assert_(var.eval({}))
|
||||||
|
|
||||||
|
self.assertFalse(IfParser(["not", True]).parse().eval({}))
|
||||||
|
|
||||||
|
def test_or(self):
|
||||||
|
var = IfParser([True, "or", False]).parse()
|
||||||
|
self.assertEqual("(or (literal True) (literal False))", repr(var))
|
||||||
|
self.assert_(var.eval({}))
|
||||||
|
|
||||||
|
def test_in(self):
|
||||||
|
list_ = [1,2,3]
|
||||||
|
self.assertCalcEqual(True, [1, 'in', list_])
|
||||||
|
self.assertCalcEqual(False, [1, 'in', None])
|
||||||
|
self.assertCalcEqual(False, [None, 'in', list_])
|
||||||
|
|
||||||
|
def test_precedence(self):
|
||||||
|
# (False and False) or True == True <- we want this one, like Python
|
||||||
|
# False and (False or True) == False
|
||||||
|
self.assertCalcEqual(True, [False, 'and', False, 'or', True])
|
||||||
|
|
||||||
|
# True or (False and False) == True <- we want this one, like Python
|
||||||
|
# (True or False) and False == False
|
||||||
|
self.assertCalcEqual(True, [True, 'or', False, 'and', False])
|
||||||
|
|
||||||
|
# (1 or 1) == 2 -> False
|
||||||
|
# 1 or (1 == 2) -> True <- we want this one
|
||||||
|
self.assertCalcEqual(True, [1, 'or', 1, '==', 2])
|
||||||
|
|
||||||
|
self.assertCalcEqual(True, [True, '==', True, 'or', True, '==', False])
|
||||||
|
|
||||||
|
self.assertEqual("(or (and (== (literal 1) (literal 2)) (literal 3)) (literal 4))",
|
||||||
|
repr(IfParser([1, '==', 2, 'and', 3, 'or', 4]).parse()))
|
@ -24,6 +24,7 @@ from context import context_tests
|
|||||||
from custom import custom_filters
|
from custom import custom_filters
|
||||||
from parser import filter_parsing, variable_parsing
|
from parser import filter_parsing, variable_parsing
|
||||||
from unicode import unicode_tests
|
from unicode import unicode_tests
|
||||||
|
from smartif import *
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from loaders import *
|
from loaders import *
|
||||||
@ -534,6 +535,27 @@ class Templates(unittest.TestCase):
|
|||||||
'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"),
|
||||||
|
|
||||||
|
# Filters
|
||||||
|
'if-tag-filter01': ("{% if foo|length == 5 %}yes{% else %}no{% endif %}", {'foo': 'abcde'}, "yes"),
|
||||||
|
'if-tag-filter02': ("{% if foo|upper == 'ABC' %}yes{% else %}no{% endif %}", {}, "no"),
|
||||||
|
|
||||||
|
# Equality
|
||||||
|
'if-tag-eq01': ("{% if foo == bar %}yes{% else %}no{% endif %}", {}, "yes"),
|
||||||
|
'if-tag-eq02': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1}, "no"),
|
||||||
|
'if-tag-eq03': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1, 'bar': 1}, "yes"),
|
||||||
|
'if-tag-eq04': ("{% if foo == bar %}yes{% else %}no{% endif %}", {'foo': 1, 'bar': 2}, "no"),
|
||||||
|
'if-tag-eq05': ("{% if foo == '' %}yes{% else %}no{% endif %}", {}, "no"),
|
||||||
|
|
||||||
|
# Comparison
|
||||||
|
'if-tag-gt-01': ("{% if 2 > 1 %}yes{% else %}no{% endif %}", {}, "yes"),
|
||||||
|
'if-tag-gt-02': ("{% if 1 > 1 %}yes{% else %}no{% endif %}", {}, "no"),
|
||||||
|
'if-tag-gte-01': ("{% if 1 >= 1 %}yes{% else %}no{% endif %}", {}, "yes"),
|
||||||
|
'if-tag-gte-02': ("{% if 1 >= 2 %}yes{% else %}no{% endif %}", {}, "no"),
|
||||||
|
'if-tag-lt-01': ("{% if 1 < 2 %}yes{% else %}no{% endif %}", {}, "yes"),
|
||||||
|
'if-tag-lt-02': ("{% if 1 < 1 %}yes{% else %}no{% endif %}", {}, "no"),
|
||||||
|
'if-tag-lte-01': ("{% if 1 <= 1 %}yes{% else %}no{% endif %}", {}, "yes"),
|
||||||
|
'if-tag-lte-02': ("{% if 2 <= 1 %}yes{% else %}no{% endif %}", {}, "no"),
|
||||||
|
|
||||||
# AND
|
# AND
|
||||||
'if-tag-and01': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'yes'),
|
'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-and02': ("{% if foo and bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': False}, 'no'),
|
||||||
@ -554,14 +576,13 @@ class Templates(unittest.TestCase):
|
|||||||
'if-tag-or07': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'foo': True}, 'yes'),
|
'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'),
|
'if-tag-or08': ("{% if foo or bar %}yes{% else %}no{% endif %}", {'bar': True}, 'yes'),
|
||||||
|
|
||||||
# TODO: multiple ORs
|
# multiple ORs
|
||||||
|
'if-tag-or09': ("{% if foo or bar or baz %}yes{% else %}no{% endif %}", {'baz': True}, 'yes'),
|
||||||
|
|
||||||
# NOT
|
# NOT
|
||||||
'if-tag-not01': ("{% if not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'yes'),
|
'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-not02': ("{% if not not foo %}no{% else %}yes{% endif %}", {'foo': True}, 'no'),
|
||||||
'if-tag-not03': ("{% if not %}yes{% else %}no{% endif %}", {'not': True}, 'yes'),
|
# not03 to not05 removed, now TemplateSyntaxErrors
|
||||||
'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-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-not07': ("{% if foo and not bar %}yes{% else %}no{% endif %}", {'foo': True, 'bar': True}, 'no'),
|
||||||
@ -599,12 +620,21 @@ class Templates(unittest.TestCase):
|
|||||||
'if-tag-not34': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': True}, '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'),
|
'if-tag-not35': ("{% if not foo or not bar %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, 'yes'),
|
||||||
|
|
||||||
# AND and OR raises a TemplateSyntaxError
|
# Various syntax errors
|
||||||
'if-tag-error01': ("{% if foo or bar and baz %}yes{% else %}no{% endif %}", {'foo': False, 'bar': False}, template.TemplateSyntaxError),
|
'if-tag-error01': ("{% if %}yes{% endif %}", {}, template.TemplateSyntaxError),
|
||||||
'if-tag-error02': ("{% if foo and %}yes{% else %}no{% endif %}", {'foo': True}, 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-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-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),
|
'if-tag-error05': ("{% if not foo or %}yes{% else %}no{% endif %}", {'foo': True}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error06': ("{% if abc def %}yes{% endif %}", {}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error07': ("{% if not %}yes{% endif %}", {}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error08': ("{% if and %}yes{% endif %}", {}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error09': ("{% if or %}yes{% endif %}", {}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error10': ("{% if == %}yes{% endif %}", {}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error11': ("{% if 1 == %}yes{% endif %}", {}, template.TemplateSyntaxError),
|
||||||
|
'if-tag-error12': ("{% if a not b %}yes{% endif %}", {}, template.TemplateSyntaxError),
|
||||||
|
|
||||||
|
# Additional, more precise parsing tests are in SmartIfTests
|
||||||
|
|
||||||
### IFCHANGED TAG #########################################################
|
### IFCHANGED TAG #########################################################
|
||||||
'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'),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user