Merge branch 'master' into schema-alteration

This commit is contained in:
Andrew Godwin 2013-05-10 12:55:30 +01:00
commit cb4b0de49e
181 changed files with 1973 additions and 1623 deletions

View File

@ -2,77 +2,77 @@
host = https://www.transifex.com host = https://www.transifex.com
lang_map = sr@latin:sr_Latn lang_map = sr@latin:sr_Latn
[django.core] [django-core.core]
file_filter = django/conf/locale/<lang>/LC_MESSAGES/django.po file_filter = django/conf/locale/<lang>/LC_MESSAGES/django.po
source_file = django/conf/locale/en/LC_MESSAGES/django.po source_file = django/conf/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-admin] [django-core.contrib-admin]
file_filter = django/contrib/admin/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/admin/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/admin/locale/en/LC_MESSAGES/django.po source_file = django/contrib/admin/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-admin-js] [django-core.contrib-admin-js]
file_filter = django/contrib/admin/locale/<lang>/LC_MESSAGES/djangojs.po file_filter = django/contrib/admin/locale/<lang>/LC_MESSAGES/djangojs.po
source_file = django/contrib/admin/locale/en/LC_MESSAGES/djangojs.po source_file = django/contrib/admin/locale/en/LC_MESSAGES/djangojs.po
source_lang = en source_lang = en
[django.contrib-admindocs] [django-core.contrib-admindocs]
file_filter = django/contrib/admindocs/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/admindocs/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/admindocs/locale/en/LC_MESSAGES/django.po source_file = django/contrib/admindocs/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-auth] [django-core.contrib-auth]
file_filter = django/contrib/auth/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/auth/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/auth/locale/en/LC_MESSAGES/django.po source_file = django/contrib/auth/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-comments] [django-core.contrib-comments]
file_filter = django/contrib/comments/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/comments/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/comments/locale/en/LC_MESSAGES/django.po source_file = django/contrib/comments/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-contenttypes] [django-core.contrib-contenttypes]
file_filter = django/contrib/contenttypes/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/contenttypes/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/contenttypes/locale/en/LC_MESSAGES/django.po source_file = django/contrib/contenttypes/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-flatpages] [django-core.contrib-flatpages]
file_filter = django/contrib/flatpages/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/flatpages/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/flatpages/locale/en/LC_MESSAGES/django.po source_file = django/contrib/flatpages/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-formtools] [django-core.contrib-formtools]
file_filter = django/contrib/formtools/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/formtools/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/formtools/locale/en/LC_MESSAGES/django.po source_file = django/contrib/formtools/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-gis] [django-core.contrib-gis]
file_filter = django/contrib/gis/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/gis/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/gis/locale/en/LC_MESSAGES/django.po source_file = django/contrib/gis/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-humanize] [django-core.contrib-humanize]
file_filter = django/contrib/humanize/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/humanize/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/humanize/locale/en/LC_MESSAGES/django.po source_file = django/contrib/humanize/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-messages] [django-core.contrib-messages]
file_filter = django/contrib/messages/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/messages/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/messages/locale/en/LC_MESSAGES/django.po source_file = django/contrib/messages/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-redirects] [django-core.contrib-redirects]
file_filter = django/contrib/redirects/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/redirects/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/redirects/locale/en/LC_MESSAGES/django.po source_file = django/contrib/redirects/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-sessions] [django-core.contrib-sessions]
file_filter = django/contrib/sessions/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/sessions/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/sessions/locale/en/LC_MESSAGES/django.po source_file = django/contrib/sessions/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-sites] [django-core.contrib-sites]
file_filter = django/contrib/sites/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/sites/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/sites/locale/en/LC_MESSAGES/django.po source_file = django/contrib/sites/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en

View File

@ -10,7 +10,9 @@ recursive-include docs *
recursive-include scripts * recursive-include scripts *
recursive-include extras * recursive-include extras *
recursive-include tests * recursive-include tests *
recursive-include django/conf/app_template *
recursive-include django/conf/locale * recursive-include django/conf/locale *
recursive-include django/conf/project_template *
recursive-include django/contrib/*/locale * recursive-include django/contrib/*/locale *
recursive-include django/contrib/admin/templates * recursive-include django/contrib/admin/templates *
recursive-include django/contrib/admin/static * recursive-include django/contrib/admin/static *

View File

View File

@ -4,7 +4,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:17+0200\n"
"PO-Revision-Date: 2010-05-13 15:35+0200\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Django team\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
@ -337,7 +337,7 @@ msgstr ""
msgid "Enter a valid value." msgid "Enter a valid value."
msgstr "" msgstr ""
#: core/validators.py:53 forms/fields.py:627 #: core/validators.py:53 forms/fields.py:640
msgid "Enter a valid URL." msgid "Enter a valid URL."
msgstr "" msgstr ""
@ -408,7 +408,7 @@ msgstr[1] ""
msgid "%(field_name)s must be unique for %(date_field)s %(lookup)s." msgid "%(field_name)s must be unique for %(date_field)s %(lookup)s."
msgstr "" msgstr ""
#: db/models/base.py:905 forms/models.py:590 #: db/models/base.py:905 forms/models.py:605
msgid "and" msgid "and"
msgstr "" msgstr ""
@ -630,46 +630,54 @@ msgstr ""
msgid "Enter a number." msgid "Enter a number."
msgstr "" msgstr ""
#: forms/fields.py:295
#, python-format
msgid "Ensure that there are no more than %s digits in total."
msgstr ""
#: forms/fields.py:296 #: forms/fields.py:296
#, python-format #, python-format
msgid "Ensure that there are no more than %s decimal places." msgid "Ensure that there are no more than %(max)s digit in total."
msgstr "" msgid_plural "Ensure that there are no more than %(max)s digits in total."
msgstr[0] ""
msgstr[1] ""
#: forms/fields.py:297 #: forms/fields.py:300
#, python-format #, python-format
msgid "Ensure that there are no more than %s digits before the decimal point." msgid "Ensure that there are no more than %(max)s decimal place."
msgstr "" msgid_plural "Ensure that there are no more than %(max)s decimal places."
msgstr[0] ""
msgstr[1] ""
#: forms/fields.py:393 forms/fields.py:1045 #: forms/fields.py:304
#, python-format
msgid ""
"Ensure that there are no more than %(max)s digit before the decimal point."
msgid_plural ""
"Ensure that there are no more than %(max)s digits before the decimal point."
msgstr[0] ""
msgstr[1] ""
#: forms/fields.py:406 forms/fields.py:1058
msgid "Enter a valid date." msgid "Enter a valid date."
msgstr "" msgstr ""
#: forms/fields.py:417 forms/fields.py:1046 #: forms/fields.py:430 forms/fields.py:1059
msgid "Enter a valid time." msgid "Enter a valid time."
msgstr "" msgstr ""
#: forms/fields.py:438 #: forms/fields.py:451
msgid "Enter a valid date/time." msgid "Enter a valid date/time."
msgstr "" msgstr ""
#: forms/fields.py:512 #: forms/fields.py:525
msgid "No file was submitted. Check the encoding type on the form." msgid "No file was submitted. Check the encoding type on the form."
msgstr "" msgstr ""
#: forms/fields.py:513 #: forms/fields.py:526
msgid "No file was submitted." msgid "No file was submitted."
msgstr "" msgstr ""
#: forms/fields.py:514 #: forms/fields.py:527
msgid "The submitted file is empty." msgid "The submitted file is empty."
msgstr "" msgstr ""
#: forms/fields.py:516 #: forms/fields.py:529
#, python-format #, python-format
msgid "Ensure this filename has at most %(max)d character (it has %(length)d)." msgid "Ensure this filename has at most %(max)d character (it has %(length)d)."
msgid_plural "" msgid_plural ""
@ -677,22 +685,22 @@ msgid_plural ""
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#: forms/fields.py:519 #: forms/fields.py:532
msgid "Please either submit a file or check the clear checkbox, not both." msgid "Please either submit a file or check the clear checkbox, not both."
msgstr "" msgstr ""
#: forms/fields.py:580 #: forms/fields.py:593
msgid "" msgid ""
"Upload a valid image. The file you uploaded was either not an image or a " "Upload a valid image. The file you uploaded was either not an image or a "
"corrupted image." "corrupted image."
msgstr "" msgstr ""
#: forms/fields.py:733 forms/fields.py:811 #: forms/fields.py:746 forms/fields.py:824 forms/models.py:1042
#, python-format #, python-format
msgid "Select a valid choice. %(value)s is not one of the available choices." msgid "Select a valid choice. %(value)s is not one of the available choices."
msgstr "" msgstr ""
#: forms/fields.py:812 forms/fields.py:915 forms/models.py:1026 #: forms/fields.py:825 forms/fields.py:928 forms/models.py:1041
msgid "Enter a list of values." msgid "Enter a list of values."
msgstr "" msgstr ""
@ -714,43 +722,38 @@ msgstr ""
msgid "Delete" msgid "Delete"
msgstr "" msgstr ""
#: forms/models.py:584 #: forms/models.py:599
#, python-format #, python-format
msgid "Please correct the duplicate data for %(field)s." msgid "Please correct the duplicate data for %(field)s."
msgstr "" msgstr ""
#: forms/models.py:588 #: forms/models.py:603
#, python-format #, python-format
msgid "Please correct the duplicate data for %(field)s, which must be unique." msgid "Please correct the duplicate data for %(field)s, which must be unique."
msgstr "" msgstr ""
#: forms/models.py:594 #: forms/models.py:609
#, python-format #, python-format
msgid "" msgid ""
"Please correct the duplicate data for %(field_name)s which must be unique " "Please correct the duplicate data for %(field_name)s which must be unique "
"for the %(lookup)s in %(date_field)s." "for the %(lookup)s in %(date_field)s."
msgstr "" msgstr ""
#: forms/models.py:602 #: forms/models.py:617
msgid "Please correct the duplicate values below." msgid "Please correct the duplicate values below."
msgstr "" msgstr ""
#: forms/models.py:868 #: forms/models.py:883
msgid "The inline foreign key did not match the parent instance primary key." msgid "The inline foreign key did not match the parent instance primary key."
msgstr "" msgstr ""
#: forms/models.py:932 #: forms/models.py:947
msgid "Select a valid choice. That choice is not one of the available choices." msgid "Select a valid choice. That choice is not one of the available choices."
msgstr "" msgstr ""
#: forms/models.py:1027 #: forms/models.py:1044
#, python-format #, python-format
msgid "Select a valid choice. %s is not one of the available choices." msgid "\"%(pk)s\" is not a valid value for a primary key."
msgstr ""
#: forms/models.py:1029
#, python-format
msgid "\"%s\" is not a valid value for a primary key."
msgstr "" msgstr ""
#: forms/util.py:84 #: forms/util.py:84
@ -760,27 +763,27 @@ msgid ""
"may be ambiguous or it may not exist." "may be ambiguous or it may not exist."
msgstr "" msgstr ""
#: forms/widgets.py:326 #: forms/widgets.py:327
msgid "Currently" msgid "Currently"
msgstr "" msgstr ""
#: forms/widgets.py:327 #: forms/widgets.py:328
msgid "Change" msgid "Change"
msgstr "" msgstr ""
#: forms/widgets.py:328 #: forms/widgets.py:329
msgid "Clear" msgid "Clear"
msgstr "" msgstr ""
#: forms/widgets.py:546 #: forms/widgets.py:547
msgid "Unknown" msgid "Unknown"
msgstr "" msgstr ""
#: forms/widgets.py:547 #: forms/widgets.py:548
msgid "Yes" msgid "Yes"
msgstr "" msgstr ""
#: forms/widgets.py:548 #: forms/widgets.py:549
msgid "No" msgid "No"
msgstr "" msgstr ""

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,22 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-03-08 10:42+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: static/admin/js/SelectFilter2.js:45 #: static/admin/js/SelectFilter2.js:45
#, c-format #, c-format
msgid "Available %s" msgid "Available %s"
msgstr "Available %s" msgstr ""
#: static/admin/js/SelectFilter2.js:46 #: static/admin/js/SelectFilter2.js:46
#, c-format #, c-format
@ -27,39 +24,37 @@ msgid ""
"This is the list of available %s. You may choose some by selecting them in " "This is the list of available %s. You may choose some by selecting them in "
"the box below and then clicking the \"Choose\" arrow between the two boxes." "the box below and then clicking the \"Choose\" arrow between the two boxes."
msgstr "" msgstr ""
"This is the list of available %s. You may choose some by selecting them in "
"the box below and then clicking the \"Choose\" arrow between the two boxes."
#: static/admin/js/SelectFilter2.js:53 #: static/admin/js/SelectFilter2.js:53
#, c-format #, c-format
msgid "Type into this box to filter down the list of available %s." msgid "Type into this box to filter down the list of available %s."
msgstr "Type into this box to filter down the list of available %s." msgstr ""
#: static/admin/js/SelectFilter2.js:57 #: static/admin/js/SelectFilter2.js:57
msgid "Filter" msgid "Filter"
msgstr "Filter" msgstr ""
#: static/admin/js/SelectFilter2.js:61 #: static/admin/js/SelectFilter2.js:61
msgid "Choose all" msgid "Choose all"
msgstr "Choose all" msgstr ""
#: static/admin/js/SelectFilter2.js:61 #: static/admin/js/SelectFilter2.js:61
#, c-format #, c-format
msgid "Click to choose all %s at once." msgid "Click to choose all %s at once."
msgstr "Click to choose all %s at once." msgstr ""
#: static/admin/js/SelectFilter2.js:67 #: static/admin/js/SelectFilter2.js:67
msgid "Choose" msgid "Choose"
msgstr "Choose" msgstr ""
#: static/admin/js/SelectFilter2.js:69 #: static/admin/js/SelectFilter2.js:69
msgid "Remove" msgid "Remove"
msgstr "Remove" msgstr ""
#: static/admin/js/SelectFilter2.js:75 #: static/admin/js/SelectFilter2.js:75
#, c-format #, c-format
msgid "Chosen %s" msgid "Chosen %s"
msgstr "Chosen %s" msgstr ""
#: static/admin/js/SelectFilter2.js:76 #: static/admin/js/SelectFilter2.js:76
#, c-format #, c-format
@ -67,31 +62,27 @@ msgid ""
"This is the list of chosen %s. You may remove some by selecting them in the " "This is the list of chosen %s. You may remove some by selecting them in the "
"box below and then clicking the \"Remove\" arrow between the two boxes." "box below and then clicking the \"Remove\" arrow between the two boxes."
msgstr "" msgstr ""
"This is the list of chosen %s. You may remove some by selecting them in the "
"box below and then clicking the \"Remove\" arrow between the two boxes."
#: static/admin/js/SelectFilter2.js:80 #: static/admin/js/SelectFilter2.js:80
msgid "Remove all" msgid "Remove all"
msgstr "Remove all" msgstr ""
#: static/admin/js/SelectFilter2.js:80 #: static/admin/js/SelectFilter2.js:80
#, c-format #, c-format
msgid "Click to remove all chosen %s at once." msgid "Click to remove all chosen %s at once."
msgstr "Click to remove all chosen %s at once." msgstr ""
#: static/admin/js/actions.js:18 static/admin/js/actions.min.js:1 #: static/admin/js/actions.js:18 static/admin/js/actions.min.js:1
msgid "%(sel)s of %(cnt)s selected" msgid "%(sel)s of %(cnt)s selected"
msgid_plural "%(sel)s of %(cnt)s selected" msgid_plural "%(sel)s of %(cnt)s selected"
msgstr[0] "%(sel)s of %(cnt)s selected" msgstr[0] ""
msgstr[1] "%(sel)s of %(cnt)s selected" msgstr[1] ""
#: static/admin/js/actions.js:109 static/admin/js/actions.min.js:5 #: static/admin/js/actions.js:109 static/admin/js/actions.min.js:5
msgid "" msgid ""
"You have unsaved changes on individual editable fields. If you run an " "You have unsaved changes on individual editable fields. If you run an "
"action, your unsaved changes will be lost." "action, your unsaved changes will be lost."
msgstr "" msgstr ""
"You have unsaved changes on individual editable fields. If you run an "
"action, your unsaved changes will be lost."
#: static/admin/js/actions.js:121 static/admin/js/actions.min.js:5 #: static/admin/js/actions.js:121 static/admin/js/actions.min.js:5
msgid "" msgid ""
@ -99,9 +90,6 @@ msgid ""
"individual fields yet. Please click OK to save. You'll need to re-run the " "individual fields yet. Please click OK to save. You'll need to re-run the "
"action." "action."
msgstr "" msgstr ""
"You have selected an action, but you haven't saved your changes to "
"individual fields yet. Please click OK to save. You'll need to re-run the "
"action."
#: static/admin/js/actions.js:123 static/admin/js/actions.min.js:6 #: static/admin/js/actions.js:123 static/admin/js/actions.min.js:6
msgid "" msgid ""
@ -109,74 +97,69 @@ msgid ""
"fields. You're probably looking for the Go button rather than the Save " "fields. You're probably looking for the Go button rather than the Save "
"button." "button."
msgstr "" msgstr ""
"You have selected an action, and you haven't made any changes on individual "
"fields. You're probably looking for the Go button rather than the Save "
"button."
#: static/admin/js/calendar.js:8 #: static/admin/js/calendar.js:8
msgid "" msgid ""
"January February March April May June July August September October November " "January February March April May June July August September October November "
"December" "December"
msgstr "" msgstr ""
"January February March April May June July August September October November "
"December"
#: static/admin/js/calendar.js:9 #: static/admin/js/calendar.js:9
msgid "S M T W T F S" msgid "S M T W T F S"
msgstr "S M T W T F S" msgstr ""
#: static/admin/js/collapse.js:8 static/admin/js/collapse.js.c:19 #: static/admin/js/collapse.js:8 static/admin/js/collapse.js.c:19
#: static/admin/js/collapse.min.js:1 #: static/admin/js/collapse.min.js:1
msgid "Show" msgid "Show"
msgstr "Show" msgstr ""
#: static/admin/js/collapse.js:16 static/admin/js/collapse.min.js:1 #: static/admin/js/collapse.js:16 static/admin/js/collapse.min.js:1
msgid "Hide" msgid "Hide"
msgstr "Hide" msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:49
#: static/admin/js/admin/DateTimeShortcuts.js:85
msgid "Now"
msgstr "Now"
#: static/admin/js/admin/DateTimeShortcuts.js:53
msgid "Clock"
msgstr "Clock"
#: static/admin/js/admin/DateTimeShortcuts.js:81
msgid "Choose a time"
msgstr "Choose a time"
#: static/admin/js/admin/DateTimeShortcuts.js:86
msgid "Midnight"
msgstr "Midnight"
#: static/admin/js/admin/DateTimeShortcuts.js:87
msgid "6 a.m."
msgstr "6 a.m."
#: static/admin/js/admin/DateTimeShortcuts.js:52
#: static/admin/js/admin/DateTimeShortcuts.js:88 #: static/admin/js/admin/DateTimeShortcuts.js:88
msgid "Now"
msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:56
msgid "Clock"
msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:84
msgid "Choose a time"
msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:89
msgid "Midnight"
msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:90
msgid "6 a.m."
msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:91
msgid "Noon" msgid "Noon"
msgstr "Noon" msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:92 #: static/admin/js/admin/DateTimeShortcuts.js:95
#: static/admin/js/admin/DateTimeShortcuts.js:204 #: static/admin/js/admin/DateTimeShortcuts.js:208
msgid "Cancel" msgid "Cancel"
msgstr "Cancel" msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:144
#: static/admin/js/admin/DateTimeShortcuts.js:197
msgid "Today"
msgstr "Today"
#: static/admin/js/admin/DateTimeShortcuts.js:148 #: static/admin/js/admin/DateTimeShortcuts.js:148
msgid "Calendar" #: static/admin/js/admin/DateTimeShortcuts.js:201
msgstr "Calendar" msgid "Today"
msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:195 #: static/admin/js/admin/DateTimeShortcuts.js:152
msgid "Yesterday" msgid "Calendar"
msgstr "Yesterday" msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:199 #: static/admin/js/admin/DateTimeShortcuts.js:199
msgid "Yesterday"
msgstr ""
#: static/admin/js/admin/DateTimeShortcuts.js:203
msgid "Tomorrow" msgid "Tomorrow"
msgstr "Tomorrow" msgstr ""

View File

@ -5,7 +5,7 @@ from django import forms
from django.conf import settings from django.conf import settings
from django.forms.formsets import all_valid, DELETION_FIELD_NAME from django.forms.formsets import all_valid, DELETION_FIELD_NAME
from django.forms.models import (modelform_factory, modelformset_factory, from django.forms.models import (modelform_factory, modelformset_factory,
inlineformset_factory, BaseInlineFormSet) inlineformset_factory, BaseInlineFormSet, modelform_defines_fields)
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.admin import widgets, helpers from django.contrib.admin import widgets, helpers
from django.contrib.admin.util import (unquote, flatten_fieldsets, get_deleted_objects, from django.contrib.admin.util import (unquote, flatten_fieldsets, get_deleted_objects,
@ -13,7 +13,7 @@ from django.contrib.admin.util import (unquote, flatten_fieldsets, get_deleted_o
from django.contrib.admin.templatetags.admin_static import static from django.contrib.admin.templatetags.admin_static import static
from django.contrib import messages from django.contrib import messages
from django.views.decorators.csrf import csrf_protect from django.views.decorators.csrf import csrf_protect
from django.core.exceptions import PermissionDenied, ValidationError from django.core.exceptions import PermissionDenied, ValidationError, FieldError
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import models, transaction, router from django.db import models, transaction, router
@ -488,7 +488,15 @@ class ModelAdmin(BaseModelAdmin):
"formfield_callback": partial(self.formfield_for_dbfield, request=request), "formfield_callback": partial(self.formfield_for_dbfield, request=request),
} }
defaults.update(kwargs) defaults.update(kwargs)
if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
defaults['fields'] = forms.ALL_FIELDS
try:
return modelform_factory(self.model, **defaults) return modelform_factory(self.model, **defaults)
except FieldError as e:
raise FieldError('%s. Check fields/fieldsets/exclude attributes of class %s.'
% (e, self.__class__.__name__))
def get_changelist(self, request, **kwargs): def get_changelist(self, request, **kwargs):
""" """
@ -519,6 +527,10 @@ class ModelAdmin(BaseModelAdmin):
"formfield_callback": partial(self.formfield_for_dbfield, request=request), "formfield_callback": partial(self.formfield_for_dbfield, request=request),
} }
defaults.update(kwargs) defaults.update(kwargs)
if (defaults.get('fields') is None
and not modelform_defines_fields(defaults.get('form'))):
defaults['fields'] = forms.ALL_FIELDS
return modelform_factory(self.model, **defaults) return modelform_factory(self.model, **defaults)
def get_changelist_formset(self, request, **kwargs): def get_changelist_formset(self, request, **kwargs):
@ -1523,6 +1535,10 @@ class InlineModelAdmin(BaseModelAdmin):
return result return result
defaults['form'] = DeleteProtectedModelForm defaults['form'] = DeleteProtectedModelForm
if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
defaults['fields'] = forms.ALL_FIELDS
return inlineformset_factory(self.parent_model, self.model, **defaults) return inlineformset_factory(self.parent_model, self.model, **defaults)
def get_fieldsets(self, request, obj=None): def get_fieldsets(self, request, obj=None):

View File

@ -246,7 +246,6 @@ def validate_fields_spec(cls, model, opts, flds, label):
# readonly_fields will handle the validation of such # readonly_fields will handle the validation of such
# things. # things.
continue continue
check_formfield(cls, model, opts, label, field)
try: try:
f = opts.get_field(field) f = opts.get_field(field)
except models.FieldDoesNotExist: except models.FieldDoesNotExist:
@ -302,14 +301,6 @@ def validate_base(cls, model):
# exclude # exclude
if cls.exclude: # default value is None if cls.exclude: # default value is None
check_isseq(cls, 'exclude', cls.exclude) check_isseq(cls, 'exclude', cls.exclude)
for field in cls.exclude:
check_formfield(cls, model, opts, 'exclude', field)
try:
f = opts.get_field(field)
except models.FieldDoesNotExist:
# If we can't find a field on the model that matches,
# it could be an extra field on the form.
continue
if len(cls.exclude) > len(set(cls.exclude)): if len(cls.exclude) > len(set(cls.exclude)):
raise ImproperlyConfigured('There are duplicate field(s) in %s.exclude' % cls.__name__) raise ImproperlyConfigured('There are duplicate field(s) in %s.exclude' % cls.__name__)
@ -380,23 +371,6 @@ def get_field(cls, model, opts, label, field):
raise ImproperlyConfigured("'%s.%s' refers to field '%s' that is missing from model '%s.%s'." raise ImproperlyConfigured("'%s.%s' refers to field '%s' that is missing from model '%s.%s'."
% (cls.__name__, label, field, model._meta.app_label, model.__name__)) % (cls.__name__, label, field, model._meta.app_label, model.__name__))
def check_formfield(cls, model, opts, label, field):
if getattr(cls.form, 'base_fields', None):
try:
cls.form.base_fields[field]
except KeyError:
raise ImproperlyConfigured("'%s.%s' refers to field '%s' that "
"is missing from the form." % (cls.__name__, label, field))
else:
get_form_is_overridden = hasattr(cls, 'get_form') and cls.get_form != ModelAdmin.get_form
if not get_form_is_overridden:
fields = fields_for_model(model)
try:
fields[field]
except KeyError:
raise ImproperlyConfigured("'%s.%s' refers to field '%s' that "
"is missing from the form." % (cls.__name__, label, field))
def fetch_attr(cls, model, opts, label, field): def fetch_attr(cls, model, opts, label, field):
try: try:
return opts.get_field(field) return opts.get_field(field)

View File

@ -1,77 +1,74 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-10-22 08:46+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: views.py:59 views.py:61 views.py:63 #: views.py:59 views.py:61 views.py:63
msgid "tag:" msgid "tag:"
msgstr "tag:" msgstr ""
#: views.py:94 views.py:96 views.py:98 #: views.py:94 views.py:96 views.py:98
msgid "filter:" msgid "filter:"
msgstr "filter:" msgstr ""
#: views.py:157 views.py:159 views.py:161 #: views.py:157 views.py:159 views.py:161
msgid "view:" msgid "view:"
msgstr "view:" msgstr ""
#: views.py:189 #: views.py:189
#, python-format #, python-format
msgid "App %r not found" msgid "App %r not found"
msgstr "App %r not found" msgstr ""
#: views.py:196 #: views.py:196
#, python-format #, python-format
msgid "Model %(model_name)r not found in app %(app_label)r" msgid "Model %(model_name)r not found in app %(app_label)r"
msgstr "Model %(model_name)r not found in app %(app_label)r" msgstr ""
#: views.py:208 #: views.py:208
#, python-format #, python-format
msgid "the related `%(app_label)s.%(data_type)s` object" msgid "the related `%(app_label)s.%(data_type)s` object"
msgstr "the related `%(app_label)s.%(data_type)s` object" msgstr ""
#: views.py:208 views.py:227 views.py:232 views.py:246 views.py:260 #: views.py:208 views.py:227 views.py:232 views.py:246 views.py:260
#: views.py:265 #: views.py:265
msgid "model:" msgid "model:"
msgstr "model:" msgstr ""
#: views.py:223 views.py:255 #: views.py:223 views.py:255
#, python-format #, python-format
msgid "related `%(app_label)s.%(object_name)s` objects" msgid "related `%(app_label)s.%(object_name)s` objects"
msgstr "related `%(app_label)s.%(object_name)s` objects" msgstr ""
#: views.py:227 views.py:260 #: views.py:227 views.py:260
#, python-format #, python-format
msgid "all %s" msgid "all %s"
msgstr "all %s" msgstr ""
#: views.py:232 views.py:265 #: views.py:232 views.py:265
#, python-format #, python-format
msgid "number of %s" msgid "number of %s"
msgstr "number of %s" msgstr ""
#: views.py:270 #: views.py:270
#, python-format #, python-format
msgid "Fields on %s objects" msgid "Fields on %s objects"
msgstr "Fields on %s objects" msgstr ""
#: views.py:362 #: views.py:362
#, python-format #, python-format
msgid "%s does not appear to be a urlpattern object" msgid "%s does not appear to be a urlpattern object"
msgstr "%s does not appear to be a urlpattern object" msgstr ""
#: templates/admin_doc/bookmarklets.html:6 templates/admin_doc/index.html:6 #: templates/admin_doc/bookmarklets.html:6 templates/admin_doc/index.html:6
#: templates/admin_doc/missing_docutils.html:6 #: templates/admin_doc/missing_docutils.html:6
@ -83,7 +80,7 @@ msgstr "%s does not appear to be a urlpattern object"
#: templates/admin_doc/view_detail.html:6 #: templates/admin_doc/view_detail.html:6
#: templates/admin_doc/view_index.html:7 #: templates/admin_doc/view_index.html:7
msgid "Home" msgid "Home"
msgstr "Home" msgstr ""
#: templates/admin_doc/bookmarklets.html:7 templates/admin_doc/index.html:7 #: templates/admin_doc/bookmarklets.html:7 templates/admin_doc/index.html:7
#: templates/admin_doc/missing_docutils.html:7 #: templates/admin_doc/missing_docutils.html:7
@ -95,15 +92,15 @@ msgstr "Home"
#: templates/admin_doc/view_detail.html:7 #: templates/admin_doc/view_detail.html:7
#: templates/admin_doc/view_index.html:8 #: templates/admin_doc/view_index.html:8
msgid "Documentation" msgid "Documentation"
msgstr "Documentation" msgstr ""
#: templates/admin_doc/bookmarklets.html:8 #: templates/admin_doc/bookmarklets.html:8
msgid "Bookmarklets" msgid "Bookmarklets"
msgstr "Bookmarklets" msgstr ""
#: templates/admin_doc/bookmarklets.html:11 #: templates/admin_doc/bookmarklets.html:11
msgid "Documentation bookmarklets" msgid "Documentation bookmarklets"
msgstr "Documentation bookmarklets" msgstr ""
#: templates/admin_doc/bookmarklets.html:15 #: templates/admin_doc/bookmarklets.html:15
msgid "" msgid ""
@ -115,81 +112,70 @@ msgid ""
"as \"internal\" (talk to your system administrator if you aren't sure if\n" "as \"internal\" (talk to your system administrator if you aren't sure if\n"
"your computer is \"internal\").</p>\n" "your computer is \"internal\").</p>\n"
msgstr "" msgstr ""
"\n"
"<p class=\"help\">To install bookmarklets, drag the link to your bookmarks\n"
"toolbar, or right-click the link and add it to your bookmarks. Now you can\n"
"select the bookmarklet from any page in the site. Note that some of these\n"
"bookmarklets require you to be viewing the site from a computer designated\n"
"as \"internal\" (talk to your system administrator if you aren't sure if\n"
"your computer is \"internal\").</p>\n"
#: templates/admin_doc/bookmarklets.html:25 #: templates/admin_doc/bookmarklets.html:25
msgid "Documentation for this page" msgid "Documentation for this page"
msgstr "Documentation for this page" msgstr ""
#: templates/admin_doc/bookmarklets.html:26 #: templates/admin_doc/bookmarklets.html:26
msgid "" msgid ""
"Jumps you from any page to the documentation for the view that generates " "Jumps you from any page to the documentation for the view that generates "
"that page." "that page."
msgstr "" msgstr ""
"Jumps you from any page to the documentation for the view that generates "
"that page."
#: templates/admin_doc/bookmarklets.html:28 #: templates/admin_doc/bookmarklets.html:28
msgid "Show object ID" msgid "Show object ID"
msgstr "Show object ID" msgstr ""
#: templates/admin_doc/bookmarklets.html:29 #: templates/admin_doc/bookmarklets.html:29
msgid "" msgid ""
"Shows the content-type and unique ID for pages that represent a single " "Shows the content-type and unique ID for pages that represent a single "
"object." "object."
msgstr "" msgstr ""
"Shows the content-type and unique ID for pages that represent a single "
"object."
#: templates/admin_doc/bookmarklets.html:31 #: templates/admin_doc/bookmarklets.html:31
msgid "Edit this object (current window)" msgid "Edit this object (current window)"
msgstr "Edit this object (current window)" msgstr ""
#: templates/admin_doc/bookmarklets.html:32 #: templates/admin_doc/bookmarklets.html:32
msgid "Jumps to the admin page for pages that represent a single object." msgid "Jumps to the admin page for pages that represent a single object."
msgstr "Jumps to the admin page for pages that represent a single object." msgstr ""
#: templates/admin_doc/bookmarklets.html:34 #: templates/admin_doc/bookmarklets.html:34
msgid "Edit this object (new window)" msgid "Edit this object (new window)"
msgstr "Edit this object (new window)" msgstr ""
#: templates/admin_doc/bookmarklets.html:35 #: templates/admin_doc/bookmarklets.html:35
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 "As above, but opens the admin page in a new window." msgstr ""
#: templates/admin_doc/model_detail.html:16 #: templates/admin_doc/model_detail.html:16
#: templates/admin_doc/model_index.html:10 #: templates/admin_doc/model_index.html:10
msgid "Models" msgid "Models"
msgstr "Models" msgstr ""
#: templates/admin_doc/template_detail.html:8 #: templates/admin_doc/template_detail.html:8
msgid "Templates" msgid "Templates"
msgstr "Templates" msgstr ""
#: templates/admin_doc/template_filter_index.html:9 #: templates/admin_doc/template_filter_index.html:9
msgid "Filters" msgid "Filters"
msgstr "Filters" msgstr ""
#: templates/admin_doc/template_tag_index.html:9 #: templates/admin_doc/template_tag_index.html:9
msgid "Tags" msgid "Tags"
msgstr "Tags" msgstr ""
#: templates/admin_doc/view_detail.html:8 #: templates/admin_doc/view_detail.html:8
#: templates/admin_doc/view_index.html:9 #: templates/admin_doc/view_index.html:9
msgid "Views" msgid "Views"
msgstr "Views" msgstr ""
#: tests/__init__.py:23 #: tests/test_fields.py:29
msgid "Boolean (Either True or False)" msgid "Boolean (Either True or False)"
msgstr "Boolean (Either True or False)" msgstr ""
#: tests/__init__.py:33 #: tests/test_fields.py:39
#, python-format #, python-format
msgid "Field of type: %(field_type)s" msgid "Field of type: %(field_type)s"
msgstr "Field of type: %(field_type)s" msgstr ""

View File

@ -130,6 +130,7 @@ class UserChangeForm(forms.ModelForm):
class Meta: class Meta:
model = User model = User
fields = '__all__'
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(UserChangeForm, self).__init__(*args, **kwargs) super(UserChangeForm, self).__init__(*args, **kwargs)

View File

@ -1,81 +1,79 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-12-16 08:51+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: admin.py:41 #: admin.py:41
msgid "Personal info" msgid "Personal info"
msgstr "Personal info" msgstr ""
#: admin.py:42 #: admin.py:42
msgid "Permissions" msgid "Permissions"
msgstr "Permissions" msgstr ""
#: admin.py:44 #: admin.py:44
msgid "Important dates" msgid "Important dates"
msgstr "Important dates" msgstr ""
#: admin.py:132 #: admin.py:132
msgid "Password changed successfully." msgid "Password changed successfully."
msgstr "Password changed successfully." msgstr ""
#: admin.py:142 #: admin.py:142
#, python-format #, python-format
msgid "Change password: %s" msgid "Change password: %s"
msgstr "Change password: %s" msgstr ""
#: forms.py:33 tests/forms.py:261 tests/forms.py:266 tests/forms.py:407 #: forms.py:33 tests/test_forms.py:261 tests/test_forms.py:266
#: tests/test_forms.py:407
msgid "No password set." msgid "No password set."
msgstr "No password set." msgstr ""
#: forms.py:39 tests/forms.py:271 tests/forms.py:277 #: forms.py:39 tests/test_forms.py:271 tests/test_forms.py:277
msgid "Invalid password format or unknown hashing algorithm." msgid "Invalid password format or unknown hashing algorithm."
msgstr "Invalid password format or unknown hashing algorithm." msgstr ""
#: forms.py:72 #: forms.py:72
msgid "A user with that username already exists." msgid "A user with that username already exists."
msgstr "A user with that username already exists." msgstr ""
#: forms.py:73 forms.py:254 forms.py:314 #: forms.py:73 forms.py:254 forms.py:314
msgid "The two password fields didn't match." msgid "The two password fields didn't match."
msgstr "The two password fields didn't match." msgstr ""
#: forms.py:75 forms.py:120 #: forms.py:75 forms.py:120
msgid "Username" msgid "Username"
msgstr "Username" msgstr ""
#: forms.py:77 forms.py:121 #: forms.py:77 forms.py:121
msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." msgid "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only."
msgstr "Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only." msgstr ""
#: forms.py:80 forms.py:124 #: forms.py:80 forms.py:124
msgid "This value may contain only letters, numbers and @/./+/-/_ characters." msgid "This value may contain only letters, numbers and @/./+/-/_ characters."
msgstr "This value may contain only letters, numbers and @/./+/-/_ characters." msgstr ""
#: forms.py:82 forms.py:126 forms.py:153 forms.py:316 #: forms.py:82 forms.py:126 forms.py:153 forms.py:316
msgid "Password" msgid "Password"
msgstr "Password" msgstr ""
#: forms.py:84 #: forms.py:84
msgid "Password confirmation" msgid "Password confirmation"
msgstr "Password confirmation" msgstr ""
#: forms.py:86 #: forms.py:86
msgid "Enter the same password as above, for verification." msgid "Enter the same password as above, for verification."
msgstr "Enter the same password as above, for verification." msgstr ""
#: forms.py:127 #: forms.py:127
msgid "" msgid ""
@ -83,9 +81,6 @@ msgid ""
"password, but you can change the password using <a href=\"password/\">this " "password, but you can change the password using <a href=\"password/\">this "
"form</a>." "form</a>."
msgstr "" msgstr ""
"Raw passwords are not stored, so there is no way to see this user's "
"password, but you can change the password using <a href=\"password/\">this "
"form</a>."
#: forms.py:156 #: forms.py:156
#, python-format #, python-format
@ -93,208 +88,177 @@ msgid ""
"Please enter a correct %(username)s and password. Note that both fields may " "Please enter a correct %(username)s and password. Note that both fields may "
"be case-sensitive." "be case-sensitive."
msgstr "" msgstr ""
"Please enter a correct %(username)s and password. Note that both fields may "
"be case-sensitive."
#: forms.py:158 #: forms.py:158
msgid "This account is inactive." msgid "This account is inactive."
msgstr "This account is inactive." msgstr ""
#: forms.py:206 #: forms.py:206
msgid "Email" msgid "Email"
msgstr "Email" msgstr ""
#: forms.py:256 #: forms.py:256
msgid "New password" msgid "New password"
msgstr "New password" msgstr ""
#: forms.py:258 #: forms.py:258
msgid "New password confirmation" msgid "New password confirmation"
msgstr "New password confirmation" msgstr ""
#: forms.py:287 #: forms.py:287
msgid "Your old password was entered incorrectly. Please enter it again." msgid "Your old password was entered incorrectly. Please enter it again."
msgstr "Your old password was entered incorrectly. Please enter it again." msgstr ""
#: forms.py:290 #: forms.py:290
msgid "Old password" msgid "Old password"
msgstr "Old password" msgstr ""
#: forms.py:318 #: forms.py:318
msgid "Password (again)" msgid "Password (again)"
msgstr "Password (again)" msgstr ""
#: hashers.py:243 hashers.py:317 hashers.py:365 hashers.py:393 hashers.py:426 #: hashers.py:243 hashers.py:317 hashers.py:365 hashers.py:393 hashers.py:426
#: hashers.py:459 hashers.py:493 #: hashers.py:459 hashers.py:493
msgid "algorithm" msgid "algorithm"
msgstr "algorithm" msgstr ""
#: hashers.py:244 #: hashers.py:244
msgid "iterations" msgid "iterations"
msgstr "iterations" msgstr ""
#: hashers.py:245 hashers.py:319 hashers.py:366 hashers.py:394 hashers.py:494 #: hashers.py:245 hashers.py:319 hashers.py:366 hashers.py:394 hashers.py:494
msgid "salt" msgid "salt"
msgstr "salt" msgstr ""
#: hashers.py:246 hashers.py:367 hashers.py:395 hashers.py:427 hashers.py:460 #: hashers.py:246 hashers.py:367 hashers.py:395 hashers.py:427 hashers.py:460
#: hashers.py:495 #: hashers.py:495
msgid "hash" msgid "hash"
msgstr "hash" msgstr ""
#: hashers.py:318 #: hashers.py:318
msgid "work factor" msgid "work factor"
msgstr "work factor" msgstr ""
#: hashers.py:320 #: hashers.py:320
msgid "checksum" msgid "checksum"
msgstr "checksum" msgstr ""
#: models.py:72 models.py:121 #: models.py:72 models.py:121
msgid "name" msgid "name"
msgstr "name" msgstr ""
#: models.py:74 #: models.py:74
msgid "codename" msgid "codename"
msgstr "codename" msgstr ""
#: models.py:78 #: models.py:78
msgid "permission" msgid "permission"
msgstr "permission" msgstr ""
#: models.py:79 models.py:123 #: models.py:79 models.py:123
msgid "permissions" msgid "permissions"
msgstr "permissions" msgstr ""
#: models.py:128 #: models.py:128
msgid "group" msgid "group"
msgstr "group" msgstr ""
#: models.py:129 models.py:301 #: models.py:129 models.py:294
msgid "groups" msgid "groups"
msgstr "groups" msgstr ""
#: models.py:200 #: models.py:200
msgid "password" msgid "password"
msgstr "password" msgstr ""
#: models.py:201 #: models.py:201
msgid "last login" msgid "last login"
msgstr "last login" msgstr ""
#: models.py:298 #: models.py:291
msgid "superuser status" msgid "superuser status"
msgstr "superuser status" msgstr ""
#: models.py:292
msgid ""
"Designates that this user has all permissions without explicitly assigning "
"them."
msgstr ""
#: models.py:295
msgid ""
"The groups this user belongs to. A user will get all permissions granted to "
"each of his/her group."
msgstr ""
#: models.py:299 #: models.py:299
msgid ""
"Designates that this user has all permissions without explicitly assigning "
"them."
msgstr ""
"Designates that this user has all permissions without explicitly assigning "
"them."
#: models.py:302
msgid ""
"The groups this user belongs to. A user will get all permissions granted to "
"each of his/her group."
msgstr ""
"The groups this user belongs to. A user will get all permissions granted to "
"each of his/her group."
#: models.py:306
msgid "user permissions" msgid "user permissions"
msgstr "user permissions" msgstr ""
#: models.py:377 #: models.py:366
msgid "username" msgid "username"
msgstr "username" msgstr ""
#: models.py:367
msgid ""
"Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"
msgstr ""
#: models.py:370
msgid "Enter a valid username."
msgstr ""
#: models.py:372
msgid "first name"
msgstr ""
#: models.py:373
msgid "last name"
msgstr ""
#: models.py:374
msgid "email address"
msgstr ""
#: models.py:375
msgid "staff status"
msgstr ""
#: models.py:376
msgid "Designates whether the user can log into this admin site."
msgstr ""
#: models.py:378 #: models.py:378
msgid "" msgid "active"
"Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters" msgstr ""
#: models.py:379
msgid ""
"Designates whether this user should be treated as active. Unselect this "
"instead of deleting accounts."
msgstr "" msgstr ""
"Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters"
#: models.py:381 #: models.py:381
msgid "Enter a valid username." msgid "date joined"
msgstr "Enter a valid username." msgstr ""
#: models.py:383
msgid "first name"
msgstr "first name"
#: models.py:384
msgid "last name"
msgstr "last name"
#: models.py:385
msgid "email address"
msgstr "email address"
#: models.py:386
msgid "staff status"
msgstr "staff status"
#: models.py:387
msgid "Designates whether the user can log into this admin site."
msgstr "Designates whether the user can log into this admin site."
#: models.py:389 #: models.py:389
msgid "active" msgid "user"
msgstr "active" msgstr ""
#: models.py:390 #: models.py:390
msgid ""
"Designates whether this user should be treated as active. Unselect this "
"instead of deleting accounts."
msgstr ""
"Designates whether this user should be treated as active. Unselect this "
"instead of deleting accounts."
#: models.py:392
msgid "date joined"
msgstr "date joined"
#: models.py:400
msgid "user"
msgstr "user"
#: models.py:401
msgid "users" msgid "users"
msgstr "users" msgstr ""
#: views.py:89 #: views.py:89
msgid "Logged out" msgid "Logged out"
msgstr "Logged out" msgstr ""
#: templates/registration/password_reset_subject.txt:2 #: templates/registration/password_reset_subject.txt:2
#, python-format #, python-format
msgid "Password reset on %(site_name)s" msgid "Password reset on %(site_name)s"
msgstr "Password reset on %(site_name)s" msgstr ""
#: tests/forms.py:325 #: tests/test_forms.py:325
#, fuzzy
msgid "Enter a valid email address." msgid "Enter a valid email address."
msgstr "Enter a valid username." msgstr ""
#~ msgid ""
#~ "Your Web browser doesn't appear to have cookies enabled. Cookies are "
#~ "required for logging in."
#~ msgstr ""
#~ "Your Web browser doesn't appear to have cookies enabled. Cookies are "
#~ "required for logging in."
#~ msgid ""
#~ "That email address doesn't have an associated user account. Are you sure "
#~ "you've registered?"
#~ msgstr ""
#~ "That email address doesn't have an associated user account. Are you sure "
#~ "you've registered?"
#~ msgid ""
#~ "The user account associated with this email address cannot reset the "
#~ "password."
#~ msgstr ""
#~ "The user account associated with this email address cannot reset the "
#~ "password."

View File

@ -1,182 +1,171 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-02-14 13:24+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: admin.py:25 #: admin.py:25
msgid "Content" msgid "Content"
msgstr "Content" msgstr ""
#: admin.py:28 #: admin.py:28
msgid "Metadata" msgid "Metadata"
msgstr "Metadata" msgstr ""
#: admin.py:55 #: admin.py:55
#, fuzzy, python-format #, python-format
msgid "%d comment was successfully flagged" msgid "%d comment was successfully flagged"
msgid_plural "%d comments were successfully flagged" msgid_plural "%d comments were successfully flagged"
msgstr[0] "1 comment was successfully %(action)s." msgstr[0] ""
msgstr[1] "%(count)s comments were successfully %(action)s." msgstr[1] ""
#: admin.py:57 #: admin.py:57
msgid "Flag selected comments" msgid "Flag selected comments"
msgstr "Flag selected comments" msgstr ""
#: admin.py:61 #: admin.py:61
#, fuzzy, python-format #, python-format
msgid "%d comment was successfully approved" msgid "%d comment was successfully approved"
msgid_plural "%d comments were successfully approved" msgid_plural "%d comments were successfully approved"
msgstr[0] "1 comment was successfully %(action)s." msgstr[0] ""
msgstr[1] "%(count)s comments were successfully %(action)s." msgstr[1] ""
#: admin.py:63 #: admin.py:63
msgid "Approve selected comments" msgid "Approve selected comments"
msgstr "Approve selected comments" msgstr ""
#: admin.py:67 #: admin.py:67
#, fuzzy, python-format #, python-format
msgid "%d comment was successfully removed" msgid "%d comment was successfully removed"
msgid_plural "%d comments were successfully removed" msgid_plural "%d comments were successfully removed"
msgstr[0] "1 comment was successfully %(action)s." msgstr[0] ""
msgstr[1] "%(count)s comments were successfully %(action)s." msgstr[1] ""
#: admin.py:69 #: admin.py:69
msgid "Remove selected comments" msgid "Remove selected comments"
msgstr "Remove selected comments" msgstr ""
#: feeds.py:14 #: feeds.py:14
#, python-format #, python-format
msgid "%(site_name)s comments" msgid "%(site_name)s comments"
msgstr "%(site_name)s comments" msgstr ""
#: feeds.py:20 #: feeds.py:20
#, python-format #, python-format
msgid "Latest comments on %(site_name)s" msgid "Latest comments on %(site_name)s"
msgstr "Latest comments on %(site_name)s" msgstr ""
#: forms.py:96 #: forms.py:96
msgid "Name" msgid "Name"
msgstr "Name" msgstr ""
#: forms.py:97 #: forms.py:97
msgid "Email address" msgid "Email address"
msgstr "Email address" msgstr ""
#: forms.py:98 #: forms.py:98
msgid "URL" msgid "URL"
msgstr "URL" msgstr ""
#: forms.py:99 #: forms.py:99
msgid "Comment" msgid "Comment"
msgstr "Comment" msgstr ""
#: forms.py:177 #: forms.py:177
#, python-format #, python-format
msgid "Watch your mouth! The word %s is not allowed here." msgid "Watch your mouth! The word %s is not allowed here."
msgid_plural "Watch your mouth! The words %s are not allowed here." msgid_plural "Watch your mouth! The words %s are not allowed here."
msgstr[0] "Watch your mouth! The word %s is not allowed here." msgstr[0] ""
msgstr[1] "Watch your mouth! The words %s are not allowed here." msgstr[1] ""
#: forms.py:181 templates/comments/preview.html:16 #: forms.py:181 templates/comments/preview.html:16
msgid "and" msgid "and"
msgstr "and" msgstr ""
#: forms.py:186 #: forms.py:186
msgid "" msgid ""
"If you enter anything in this field your comment will be treated as spam" "If you enter anything in this field your comment will be treated as spam"
msgstr "" msgstr ""
"If you enter anything in this field your comment will be treated as spam"
#: models.py:23 #: models.py:23
msgid "content type" msgid "content type"
msgstr "content type" msgstr ""
#: models.py:25 #: models.py:25
msgid "object ID" msgid "object ID"
msgstr "object ID" msgstr ""
#: models.py:53 models.py:177 #: models.py:53 models.py:177
msgid "user" msgid "user"
msgstr "user" msgstr ""
#: models.py:55 #: models.py:55
msgid "user's name" msgid "user's name"
msgstr "user's name" msgstr ""
#: models.py:56 #: models.py:56
msgid "user's email address" msgid "user's email address"
msgstr "user's email address" msgstr ""
#: models.py:57 #: models.py:57
msgid "user's URL" msgid "user's URL"
msgstr "user's URL" msgstr ""
#: models.py:59 models.py:79 models.py:178 #: models.py:59 models.py:79 models.py:178
msgid "comment" msgid "comment"
msgstr "comment" msgstr ""
#: models.py:62 #: models.py:62
msgid "date/time submitted" msgid "date/time submitted"
msgstr "date/time submitted" msgstr ""
#: models.py:63 #: models.py:63
msgid "IP address" msgid "IP address"
msgstr "IP address" msgstr ""
#: models.py:64 #: models.py:64
msgid "is public" msgid "is public"
msgstr "is public" msgstr ""
#: models.py:65 #: models.py:65
msgid "" msgid ""
"Uncheck this box to make the comment effectively disappear from the site." "Uncheck this box to make the comment effectively disappear from the site."
msgstr "" msgstr ""
"Uncheck this box to make the comment effectively disappear from the site."
#: models.py:67 #: models.py:67
msgid "is removed" msgid "is removed"
msgstr "is removed" msgstr ""
#: models.py:68 #: models.py:68
msgid "" msgid ""
"Check this box if the comment is inappropriate. A \"This comment has been " "Check this box if the comment is inappropriate. A \"This comment has been "
"removed\" message will be displayed instead." "removed\" message will be displayed instead."
msgstr "" msgstr ""
"Check this box if the comment is inappropriate. A \"This comment has been "
"removed\" message will be displayed instead."
#: models.py:80 #: models.py:80
msgid "comments" msgid "comments"
msgstr "comments" msgstr ""
#: models.py:124 #: models.py:124
msgid "" msgid ""
"This comment was posted by an authenticated user and thus the name is read-" "This comment was posted by an authenticated user and thus the name is read-"
"only." "only."
msgstr "" msgstr ""
"This comment was posted by an authenticated user and thus the name is read-"
"only."
#: models.py:134 #: models.py:134
msgid "" msgid ""
"This comment was posted by an authenticated user and thus the email is read-" "This comment was posted by an authenticated user and thus the email is read-"
"only." "only."
msgstr "" msgstr ""
"This comment was posted by an authenticated user and thus the email is read-"
"only."
#: models.py:160 #: models.py:160
#, python-format #, python-format
@ -187,128 +176,107 @@ msgid ""
"\n" "\n"
"http://%(domain)s%(url)s" "http://%(domain)s%(url)s"
msgstr "" msgstr ""
"Posted by %(user)s at %(date)s\n"
"\n"
"%(comment)s\n"
"\n"
"http://%(domain)s%(url)s"
#: models.py:179 #: models.py:179
msgid "flag" msgid "flag"
msgstr "flag" msgstr ""
#: models.py:180 #: models.py:180
msgid "date" msgid "date"
msgstr "date" msgstr ""
#: models.py:190 #: models.py:190
msgid "comment flag" msgid "comment flag"
msgstr "comment flag" msgstr ""
#: models.py:191 #: models.py:191
msgid "comment flags" msgid "comment flags"
msgstr "comment flags" msgstr ""
#: templates/comments/approve.html:4 #: templates/comments/approve.html:4
msgid "Approve a comment" msgid "Approve a comment"
msgstr "Approve a comment" msgstr ""
#: templates/comments/approve.html:7 #: templates/comments/approve.html:7
msgid "Really make this comment public?" msgid "Really make this comment public?"
msgstr "Really make this comment public?" msgstr ""
#: templates/comments/approve.html:12 #: templates/comments/approve.html:12
msgid "Approve" msgid "Approve"
msgstr "Approve" msgstr ""
#: templates/comments/approved.html:4 #: templates/comments/approved.html:4
msgid "Thanks for approving" msgid "Thanks for approving"
msgstr "Thanks for approving" msgstr ""
#: templates/comments/approved.html:7 templates/comments/deleted.html:7 #: templates/comments/approved.html:7 templates/comments/deleted.html:7
#: templates/comments/flagged.html:7 #: templates/comments/flagged.html:7
msgid "" msgid ""
"Thanks for taking the time to improve the quality of discussion on our site" "Thanks for taking the time to improve the quality of discussion on our site"
msgstr "" msgstr ""
"Thanks for taking the time to improve the quality of discussion on our site"
#: templates/comments/delete.html:4 #: templates/comments/delete.html:4
msgid "Remove a comment" msgid "Remove a comment"
msgstr "Remove a comment" msgstr ""
#: templates/comments/delete.html:7 #: templates/comments/delete.html:7
msgid "Really remove this comment?" msgid "Really remove this comment?"
msgstr "Really remove this comment?" msgstr ""
#: templates/comments/delete.html:12 #: templates/comments/delete.html:12
msgid "Remove" msgid "Remove"
msgstr "Remove" msgstr ""
#: templates/comments/deleted.html:4 #: templates/comments/deleted.html:4
msgid "Thanks for removing" msgid "Thanks for removing"
msgstr "Thanks for removing" msgstr ""
#: templates/comments/flag.html:4 #: templates/comments/flag.html:4
msgid "Flag this comment" msgid "Flag this comment"
msgstr "Flag this comment" msgstr ""
#: templates/comments/flag.html:7 #: templates/comments/flag.html:7
msgid "Really flag this comment?" msgid "Really flag this comment?"
msgstr "Really flag this comment?" msgstr ""
#: templates/comments/flag.html:12 #: templates/comments/flag.html:12
msgid "Flag" msgid "Flag"
msgstr "Flag" msgstr ""
#: templates/comments/flagged.html:4 #: templates/comments/flagged.html:4
msgid "Thanks for flagging" msgid "Thanks for flagging"
msgstr "Thanks for flagging" msgstr ""
#: templates/comments/form.html:17 templates/comments/preview.html:32 #: templates/comments/form.html:17 templates/comments/preview.html:32
msgid "Post" msgid "Post"
msgstr "Post" msgstr ""
#: templates/comments/form.html:18 templates/comments/preview.html:33 #: templates/comments/form.html:18 templates/comments/preview.html:33
msgid "Preview" msgid "Preview"
msgstr "Preview" msgstr ""
#: templates/comments/posted.html:4 #: templates/comments/posted.html:4
msgid "Thanks for commenting" msgid "Thanks for commenting"
msgstr "Thanks for commenting" msgstr ""
#: templates/comments/posted.html:7 #: templates/comments/posted.html:7
msgid "Thank you for your comment" msgid "Thank you for your comment"
msgstr "Thank you for your comment" msgstr ""
#: templates/comments/preview.html:4 templates/comments/preview.html.py:13 #: templates/comments/preview.html:4 templates/comments/preview.html.py:13
msgid "Preview your comment" msgid "Preview your comment"
msgstr "Preview your comment" msgstr ""
#: templates/comments/preview.html:11 #: templates/comments/preview.html:11
msgid "Please correct the error below" msgid "Please correct the error below"
msgid_plural "Please correct the errors below" msgid_plural "Please correct the errors below"
msgstr[0] "Please correct the error below" msgstr[0] ""
msgstr[1] "Please correct the errors below" msgstr[1] ""
#: templates/comments/preview.html:16 #: templates/comments/preview.html:16
msgid "Post your comment" msgid "Post your comment"
msgstr "Post your comment" msgstr ""
#: templates/comments/preview.html:16 #: templates/comments/preview.html:16
msgid "or make changes" msgid "or make changes"
msgstr "or make changes" msgstr ""
#~ msgid "flagged"
#~ msgid_plural "flagged"
#~ msgstr[0] "flagged"
#~ msgstr[1] "flagged"
#~ msgid "approved"
#~ msgid_plural "approved"
#~ msgstr[0] "approved"
#~ msgstr[1] "approved"
#~ msgid "removed"
#~ msgid_plural "removed"
#~ msgstr[0] "removed"
#~ msgstr[1] "removed"

View File

@ -13,8 +13,9 @@ from django.db.models import signals
from django.db.models.fields.related import ForeignObject, ForeignObjectRel from django.db.models.fields.related import ForeignObject, ForeignObjectRel
from django.db.models.related import PathInfo from django.db.models.related import PathInfo
from django.db.models.sql.where import Constraint from django.db.models.sql.where import Constraint
from django.forms import ModelForm from django.forms import ModelForm, ALL_FIELDS
from django.forms.models import BaseModelFormSet, modelformset_factory, save_instance from django.forms.models import (BaseModelFormSet, modelformset_factory, save_instance,
modelform_defines_fields)
from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets from django.contrib.admin.options import InlineModelAdmin, flatten_fieldsets
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils import six from django.utils import six
@ -137,9 +138,6 @@ class GenericForeignKey(six.with_metaclass(RenameGenericForeignKeyMethods)):
return rel_obj return rel_obj
def __set__(self, instance, value): def __set__(self, instance, value):
if instance is None:
raise AttributeError("%s must be accessed via instance" % self.related.opts.object_name)
ct = None ct = None
fk = None fk = None
if value is not None: if value is not None:
@ -280,9 +278,6 @@ class ReverseGenericRelatedObjectsDescriptor(object):
return manager return manager
def __set__(self, instance, value): def __set__(self, instance, value):
if instance is None:
raise AttributeError("Manager must be accessed via instance")
manager = self.__get__(instance) manager = self.__get__(instance)
manager.clear() manager.clear()
for obj in value: for obj in value:
@ -486,6 +481,10 @@ class GenericInlineModelAdmin(InlineModelAdmin):
"exclude": exclude "exclude": exclude
} }
defaults.update(kwargs) defaults.update(kwargs)
if defaults['fields'] is None and not modelform_defines_fields(defaults['form']):
defaults['fields'] = ALL_FIELDS
return generic_inlineformset_factory(self.model, **defaults) return generic_inlineformset_factory(self.model, **defaults)
class GenericStackedInline(GenericInlineModelAdmin): class GenericStackedInline(GenericInlineModelAdmin):

View File

@ -1,44 +1,41 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-03-08 11:45+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: models.py:130 #: models.py:130
msgid "python model class name" msgid "python model class name"
msgstr "python model class name" msgstr ""
#: models.py:134 #: models.py:134
msgid "content type" msgid "content type"
msgstr "content type" msgstr ""
#: models.py:135 #: models.py:135
msgid "content types" msgid "content types"
msgstr "content types" msgstr ""
#: views.py:17 #: views.py:17
#, python-format #, python-format
msgid "Content type %(ct_id)s object has no associated model" msgid "Content type %(ct_id)s object has no associated model"
msgstr "Content type %(ct_id)s object has no associated model" msgstr ""
#: views.py:21 #: views.py:21
#, python-format #, python-format
msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist" msgid "Content type %(ct_id)s object %(obj_id)s doesn't exist"
msgstr "Content type %(ct_id)s object %(obj_id)s doesn't exist" msgstr ""
#: views.py:27 #: views.py:27
#, python-format #, python-format
msgid "%(ct_name)s objects don't have a get_absolute_url() method" msgid "%(ct_name)s objects don't have a get_absolute_url() method"
msgstr "%(ct_name)s objects don't have a get_absolute_url() method" msgstr ""

View File

@ -12,6 +12,7 @@ class FlatpageForm(forms.ModelForm):
class Meta: class Meta:
model = FlatPage model = FlatPage
fields = '__all__'
def clean_url(self): def clean_url(self):
url = self.cleaned_data['url'] url = self.cleaned_data['url']

View File

@ -1,97 +1,88 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-10-18 10:56+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: admin.py:10 #: admin.py:10
msgid "Advanced options" msgid "Advanced options"
msgstr "Advanced options" msgstr ""
#: forms.py:7 models.py:11 #: forms.py:7 models.py:11
msgid "URL" msgid "URL"
msgstr "URL" msgstr ""
#: forms.py:8 #: forms.py:8
msgid "" msgid ""
"Example: '/about/contact/'. Make sure to have leading and trailing slashes." "Example: '/about/contact/'. Make sure to have leading and trailing slashes."
msgstr "" msgstr ""
"Example: '/about/contact/'. Make sure to have leading and trailing slashes."
#: forms.py:10 #: forms.py:10
msgid "" msgid ""
"This value must contain only letters, numbers, dots, underscores, dashes, " "This value must contain only letters, numbers, dots, underscores, dashes, "
"slashes or tildes." "slashes or tildes."
msgstr "" msgstr ""
"This value must contain only letters, numbers, dots, underscores, dashes, "
"slashes or tildes."
#: forms.py:19 #: forms.py:19
msgid "URL is missing a leading slash." msgid "URL is missing a leading slash."
msgstr "URL is missing a leading slash." msgstr ""
#: forms.py:23 #: forms.py:23
msgid "URL is missing a trailing slash." msgid "URL is missing a trailing slash."
msgstr "URL is missing a trailing slash." msgstr ""
#: forms.py:38 #: forms.py:38
#, python-format #, python-format
msgid "Flatpage with url %(url)s already exists for site %(site)s" msgid "Flatpage with url %(url)s already exists for site %(site)s"
msgstr "Flatpage with url %(url)s already exists for site %(site)s" msgstr ""
#: models.py:12 #: models.py:12
msgid "title" msgid "title"
msgstr "title" msgstr ""
#: models.py:13 #: models.py:13
msgid "content" msgid "content"
msgstr "content" msgstr ""
#: models.py:14 #: models.py:14
msgid "enable comments" msgid "enable comments"
msgstr "enable comments" msgstr ""
#: models.py:15 #: models.py:15
msgid "template name" msgid "template name"
msgstr "template name" msgstr ""
#: models.py:16 #: models.py:16
msgid "" msgid ""
"Example: 'flatpages/contact_page.html'. If this isn't provided, the system " "Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
"will use 'flatpages/default.html'." "will use 'flatpages/default.html'."
msgstr "" msgstr ""
"Example: 'flatpages/contact_page.html'. If this isn't provided, the system "
"will use 'flatpages/default.html'."
#: models.py:17 #: models.py:17
msgid "registration required" msgid "registration required"
msgstr "registration required" msgstr ""
#: models.py:18 #: models.py:18
msgid "If this is checked, only logged-in users will be able to view the page." msgid "If this is checked, only logged-in users will be able to view the page."
msgstr "" msgstr ""
"If this is checked, only logged-in users will be able to view the page."
#: models.py:24 #: models.py:24
msgid "flat page" msgid "flat page"
msgstr "flat page" msgstr ""
#: models.py:25 #: models.py:25
msgid "flat pages" msgid "flat pages"
msgstr "flat pages" msgstr ""
#: tests/forms.py:98 #: tests/test_forms.py:98
msgid "This field is required." msgid "This field is required."
msgstr "This field is required." msgstr ""

View File

@ -1,36 +1,26 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-02-14 13:42+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: templates/formtools/wizard/wizard_form.html:15 #: templates/formtools/wizard/wizard_form.html:15
msgid "first step" msgid "first step"
msgstr "first step" msgstr ""
#: templates/formtools/wizard/wizard_form.html:16 #: templates/formtools/wizard/wizard_form.html:16
msgid "prev step" msgid "prev step"
msgstr "prev step" msgstr ""
#: templates/formtools/wizard/wizard_form.html:18 #: templates/formtools/wizard/wizard_form.html:18
msgid "submit" msgid "submit"
msgstr "submit" msgstr ""
#~ msgid ""
#~ "We apologize, but your form has expired. Please continue filling out the "
#~ "form from this page."
#~ msgstr ""
#~ "We apologize, but your form has expired. Please continue filling out the "
#~ "form from this page."

View File

@ -60,9 +60,11 @@ class TestModel(models.Model):
class TestModelForm(forms.ModelForm): class TestModelForm(forms.ModelForm):
class Meta: class Meta:
model = TestModel model = TestModel
fields = '__all__'
TestModelFormSet = forms.models.modelformset_factory(TestModel, form=TestModelForm, extra=2) TestModelFormSet = forms.models.modelformset_factory(TestModel, form=TestModelForm, extra=2,
fields='__all__')
class TestWizard(WizardView): class TestWizard(WizardView):

View File

@ -15,6 +15,7 @@ from django.utils._os import upath
class UserForm(forms.ModelForm): class UserForm(forms.ModelForm):
class Meta: class Meta:
model = User model = User
fields = '__all__'
UserFormSet = forms.models.modelformset_factory(User, form=UserForm, extra=2) UserFormSet = forms.models.modelformset_factory(User, form=UserForm, extra=2)

View File

@ -3,10 +3,12 @@ Base/mixin classes for the spatial backend database operations and the
`SpatialRefSys` model the backend. `SpatialRefSys` model the backend.
""" """
import re import re
from django.contrib.gis import gdal from django.contrib.gis import gdal
from django.utils import six from django.utils import six
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
class BaseSpatialOperations(object): class BaseSpatialOperations(object):
""" """
This module holds the base `BaseSpatialBackend` object, which is This module holds the base `BaseSpatialBackend` object, which is
@ -18,7 +20,7 @@ class BaseSpatialOperations(object):
geometry_operators = {} geometry_operators = {}
geography_operators = {} geography_operators = {}
geography_functions = {} geography_functions = {}
gis_terms = {} gis_terms = set()
truncate_params = {} truncate_params = {}
# Quick booleans for the type of this spatial backend, and # Quick booleans for the type of this spatial backend, and

View File

@ -3,7 +3,6 @@ from django.db.backends.mysql.base import DatabaseOperations
from django.contrib.gis.db.backends.adapter import WKTAdapter from django.contrib.gis.db.backends.adapter import WKTAdapter
from django.contrib.gis.db.backends.base import BaseSpatialOperations from django.contrib.gis.db.backends.base import BaseSpatialOperations
from django.utils import six
class MySQLOperations(DatabaseOperations, BaseSpatialOperations): class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
@ -32,7 +31,7 @@ class MySQLOperations(DatabaseOperations, BaseSpatialOperations):
'within': 'MBRWithin', 'within': 'MBRWithin',
} }
gis_terms = dict([(term, None) for term in list(geometry_functions) + ['isnull']]) gis_terms = set(geometry_functions) | set(['isnull'])
def geo_db_type(self, f): def geo_db_type(self, f):
return f.geom_type return f.geom_type

View File

@ -18,6 +18,7 @@ from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.measure import Distance from django.contrib.gis.measure import Distance
from django.utils import six from django.utils import six
class SDOOperation(SpatialFunction): class SDOOperation(SpatialFunction):
"Base class for SDO* Oracle operations." "Base class for SDO* Oracle operations."
sql_template = "%(function)s(%(geo_col)s, %(geometry)s) %(operator)s '%(result)s'" sql_template = "%(function)s(%(geo_col)s, %(geometry)s) %(operator)s '%(result)s'"
@ -32,6 +33,7 @@ class SDODistance(SpatialFunction):
sql_template = ('%(function)s(%(geo_col)s, %(geometry)s, %(tolerance)s) ' sql_template = ('%(function)s(%(geo_col)s, %(geometry)s, %(tolerance)s) '
'%(operator)s %(result)s') '%(operator)s %(result)s')
dist_func = 'SDO_GEOM.SDO_DISTANCE' dist_func = 'SDO_GEOM.SDO_DISTANCE'
def __init__(self, op, tolerance=0.05): def __init__(self, op, tolerance=0.05):
super(SDODistance, self).__init__(self.dist_func, super(SDODistance, self).__init__(self.dist_func,
tolerance=tolerance, tolerance=tolerance,
@ -40,6 +42,7 @@ class SDODistance(SpatialFunction):
class SDODWithin(SpatialFunction): class SDODWithin(SpatialFunction):
dwithin_func = 'SDO_WITHIN_DISTANCE' dwithin_func = 'SDO_WITHIN_DISTANCE'
sql_template = "%(function)s(%(geo_col)s, %(geometry)s, %%s) = 'TRUE'" sql_template = "%(function)s(%(geo_col)s, %(geometry)s, %%s) = 'TRUE'"
def __init__(self): def __init__(self):
super(SDODWithin, self).__init__(self.dwithin_func) super(SDODWithin, self).__init__(self.dwithin_func)
@ -48,6 +51,7 @@ class SDOGeomRelate(SpatialFunction):
relate_func = 'SDO_GEOM.RELATE' relate_func = 'SDO_GEOM.RELATE'
sql_template = ("%(function)s(%(geo_col)s, '%(mask)s', %(geometry)s, " sql_template = ("%(function)s(%(geo_col)s, '%(mask)s', %(geometry)s, "
"%(tolerance)s) %(operator)s '%(mask)s'") "%(tolerance)s) %(operator)s '%(mask)s'")
def __init__(self, mask, tolerance=0.05): def __init__(self, mask, tolerance=0.05):
# SDO_GEOM.RELATE(...) has a peculiar argument order: column, mask, geom, tolerance. # SDO_GEOM.RELATE(...) has a peculiar argument order: column, mask, geom, tolerance.
# Moreover, the runction result is the mask (e.g., 'DISJOINT' instead of 'TRUE'). # Moreover, the runction result is the mask (e.g., 'DISJOINT' instead of 'TRUE').
@ -60,6 +64,7 @@ class SDORelate(SpatialFunction):
mask_regex = re.compile(r'^(%s)(\+(%s))*$' % (masks, masks), re.I) mask_regex = re.compile(r'^(%s)(\+(%s))*$' % (masks, masks), re.I)
sql_template = "%(function)s(%(geo_col)s, %(geometry)s, 'mask=%(mask)s') = 'TRUE'" sql_template = "%(function)s(%(geo_col)s, %(geometry)s, 'mask=%(mask)s') = 'TRUE'"
relate_func = 'SDO_RELATE' relate_func = 'SDO_RELATE'
def __init__(self, mask): def __init__(self, mask):
if not self.mask_regex.match(mask): if not self.mask_regex.match(mask):
raise ValueError('Invalid %s mask: "%s"' % (self.relate_func, mask)) raise ValueError('Invalid %s mask: "%s"' % (self.relate_func, mask))
@ -127,9 +132,8 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
} }
geometry_functions.update(distance_functions) geometry_functions.update(distance_functions)
gis_terms = ['isnull'] gis_terms = set(['isnull'])
gis_terms += list(geometry_functions) gis_terms.update(geometry_functions)
gis_terms = dict([(term, None) for term in gis_terms])
truncate_params = {'relate' : None} truncate_params = {'relate' : None}
@ -272,7 +276,8 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
given Aggregate instance. given Aggregate instance.
""" """
agg_name = agg.__class__.__name__.lower() agg_name = agg.__class__.__name__.lower()
if agg_name == 'union' : agg_name += 'agg' if agg_name == 'union':
agg_name += 'agg'
if agg.is_extent: if agg.is_extent:
sql_template = '%(function)s(%(field)s)' sql_template = '%(function)s(%(field)s)'
else: else:

View File

@ -221,10 +221,9 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
self.geometry = True self.geometry = True
# Creating a dictionary lookup of all GIS terms for PostGIS. # Creating a dictionary lookup of all GIS terms for PostGIS.
gis_terms = ['isnull'] self.gis_terms = set(['isnull'])
gis_terms += list(self.geometry_operators) self.gis_terms.update(self.geometry_operators)
gis_terms += list(self.geometry_functions) self.gis_terms.update(self.geometry_functions)
self.gis_terms = dict([(term, None) for term in gis_terms])
self.area = prefix + 'Area' self.area = prefix + 'Area'
self.bounding_circle = BOUNDINGCIRCLE self.bounding_circle = BOUNDINGCIRCLE
@ -565,7 +564,8 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
if not self.check_aggregate_support(agg): if not self.check_aggregate_support(agg):
raise NotImplementedError('%s spatial aggregate is not implmented for this backend.' % agg_name) raise NotImplementedError('%s spatial aggregate is not implmented for this backend.' % agg_name)
agg_name = agg_name.lower() agg_name = agg_name.lower()
if agg_name == 'union': agg_name += 'agg' if agg_name == 'union':
agg_name += 'agg'
sql_template = '%(function)s(%(field)s)' sql_template = '%(function)s(%(field)s)'
sql_function = getattr(self, agg_name) sql_function = getattr(self, agg_name)
return sql_template, sql_function return sql_template, sql_function

View File

@ -117,9 +117,8 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations):
super(DatabaseOperations, self).__init__(connection) super(DatabaseOperations, self).__init__(connection)
# Creating the GIS terms dictionary. # Creating the GIS terms dictionary.
gis_terms = ['isnull'] self.gis_terms = set(['isnull'])
gis_terms += self.geometry_functions.keys() self.gis_terms.update(self.geometry_functions)
self.gis_terms = dict([(term, None) for term in gis_terms])
@cached_property @cached_property
def spatial_version(self): def spatial_version(self):

View File

@ -11,6 +11,7 @@ from django.contrib.gis.geoip.prototypes import (
GeoIP_country_name_by_addr, GeoIP_country_name_by_name) GeoIP_country_name_by_addr, GeoIP_country_name_by_name)
from django.utils import six from django.utils import six
from django.utils.encoding import force_bytes
# Regular expressions for recognizing the GeoIP free database editions. # Regular expressions for recognizing the GeoIP free database editions.
free_regex = re.compile(r'^GEO-\d{3}FREE') free_regex = re.compile(r'^GEO-\d{3}FREE')
@ -97,18 +98,18 @@ class GeoIP(object):
# and/or city datasets exist, then try and open them. # and/or city datasets exist, then try and open them.
country_db = os.path.join(path, country or GEOIP_SETTINGS.get('GEOIP_COUNTRY', 'GeoIP.dat')) country_db = os.path.join(path, country or GEOIP_SETTINGS.get('GEOIP_COUNTRY', 'GeoIP.dat'))
if os.path.isfile(country_db): if os.path.isfile(country_db):
self._country = GeoIP_open(country_db, cache) self._country = GeoIP_open(force_bytes(country_db), cache)
self._country_file = country_db self._country_file = country_db
city_db = os.path.join(path, city or GEOIP_SETTINGS.get('GEOIP_CITY', 'GeoLiteCity.dat')) city_db = os.path.join(path, city or GEOIP_SETTINGS.get('GEOIP_CITY', 'GeoLiteCity.dat'))
if os.path.isfile(city_db): if os.path.isfile(city_db):
self._city = GeoIP_open(city_db, cache) self._city = GeoIP_open(force_bytes(city_db), cache)
self._city_file = city_db self._city_file = city_db
elif os.path.isfile(path): elif os.path.isfile(path):
# Otherwise, some detective work will be needed to figure # Otherwise, some detective work will be needed to figure
# out whether the given database path is for the GeoIP country # out whether the given database path is for the GeoIP country
# or city databases. # or city databases.
ptr = GeoIP_open(path, cache) ptr = GeoIP_open(force_bytes(path), cache)
info = GeoIP_database_info(ptr) info = GeoIP_database_info(ptr)
if lite_regex.match(info): if lite_regex.match(info):
# GeoLite City database detected. # GeoLite City database detected.
@ -136,9 +137,6 @@ class GeoIP(object):
if not isinstance(query, six.string_types): if not isinstance(query, six.string_types):
raise TypeError('GeoIP query must be a string, not type %s' % type(query).__name__) raise TypeError('GeoIP query must be a string, not type %s' % type(query).__name__)
# GeoIP only takes ASCII-encoded strings.
query = query.encode('ascii')
# Extra checks for the existence of country and city databases. # Extra checks for the existence of country and city databases.
if city_or_country and not (self._country or self._city): if city_or_country and not (self._country or self._city):
raise GeoIPException('Invalid GeoIP country and city data files.') raise GeoIPException('Invalid GeoIP country and city data files.')
@ -147,8 +145,8 @@ class GeoIP(object):
elif city and not self._city: elif city and not self._city:
raise GeoIPException('Invalid GeoIP city data file: %s' % self._city_file) raise GeoIPException('Invalid GeoIP city data file: %s' % self._city_file)
# Return the query string back to the caller. # Return the query string back to the caller. GeoIP only takes bytestrings.
return query return force_bytes(query)
def city(self, query): def city(self, query):
""" """
@ -156,33 +154,33 @@ class GeoIP(object):
Fully Qualified Domain Name (FQDN). Some information in the dictionary Fully Qualified Domain Name (FQDN). Some information in the dictionary
may be undefined (None). may be undefined (None).
""" """
query = self._check_query(query, city=True) enc_query = self._check_query(query, city=True)
if ipv4_re.match(query): if ipv4_re.match(query):
# If an IP address was passed in # If an IP address was passed in
return GeoIP_record_by_addr(self._city, c_char_p(query)) return GeoIP_record_by_addr(self._city, c_char_p(enc_query))
else: else:
# If a FQDN was passed in. # If a FQDN was passed in.
return GeoIP_record_by_name(self._city, c_char_p(query)) return GeoIP_record_by_name(self._city, c_char_p(enc_query))
def country_code(self, query): def country_code(self, query):
"Returns the country code for the given IP Address or FQDN." "Returns the country code for the given IP Address or FQDN."
query = self._check_query(query, city_or_country=True) enc_query = self._check_query(query, city_or_country=True)
if self._country: if self._country:
if ipv4_re.match(query): if ipv4_re.match(query):
return GeoIP_country_code_by_addr(self._country, query) return GeoIP_country_code_by_addr(self._country, enc_query)
else: else:
return GeoIP_country_code_by_name(self._country, query) return GeoIP_country_code_by_name(self._country, enc_query)
else: else:
return self.city(query)['country_code'] return self.city(query)['country_code']
def country_name(self, query): def country_name(self, query):
"Returns the country name for the given IP Address or FQDN." "Returns the country name for the given IP Address or FQDN."
query = self._check_query(query, city_or_country=True) enc_query = self._check_query(query, city_or_country=True)
if self._country: if self._country:
if ipv4_re.match(query): if ipv4_re.match(query):
return GeoIP_country_name_by_addr(self._country, query) return GeoIP_country_name_by_addr(self._country, enc_query)
else: else:
return GeoIP_country_name_by_name(self._country, query) return GeoIP_country_name_by_name(self._country, enc_query)
else: else:
return self.city(query)['country_name'] return self.city(query)['country_name']

View File

@ -92,7 +92,7 @@ def check_string(result, func, cargs):
free(result) free(result)
else: else:
s = '' s = ''
return s return s.decode()
GeoIP_database_info = lgeoip.GeoIP_database_info GeoIP_database_info = lgeoip.GeoIP_database_info
GeoIP_database_info.restype = geoip_char_p GeoIP_database_info.restype = geoip_char_p
@ -100,7 +100,12 @@ GeoIP_database_info.errcheck = check_string
# String output routines. # String output routines.
def string_output(func): def string_output(func):
def _err_check(result, func, cargs):
if result:
return result.decode()
return result
func.restype = c_char_p func.restype = c_char_p
func.errcheck = _err_check
return func return func
GeoIP_country_code_by_addr = string_output(lgeoip.GeoIP_country_code_by_addr) GeoIP_country_code_by_addr = string_output(lgeoip.GeoIP_country_code_by_addr)

View File

@ -103,14 +103,8 @@ class GeoIPTest(unittest.TestCase):
def test05_unicode_response(self): def test05_unicode_response(self):
"Testing that GeoIP strings are properly encoded, see #16553." "Testing that GeoIP strings are properly encoded, see #16553."
g = GeoIP() g = GeoIP()
d = g.city('62.224.93.23') d = g.city("www.osnabrueck.de")
self.assertEqual('Schümberg', d['city']) self.assertEqual('Osnabrück', d['city'])
def test06_unicode_query(self):
"Testing that GeoIP accepts unicode string queries, see #17059."
g = GeoIP()
d = g.country('whitehouse.gov')
self.assertEqual('US', d['country_code'])
def suite(): def suite():

View File

@ -1,93 +1,88 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-03-08 12:32+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: views.py:9 #: views.py:9
msgid "No feeds are registered." msgid "No feeds are registered."
msgstr "No feeds are registered." msgstr ""
#: views.py:19 #: views.py:19
#, python-format #, python-format
msgid "Slug %r isn't registered." msgid "Slug %r isn't registered."
msgstr "Slug %r isn't registered." msgstr ""
#: db/models/fields.py:51 #: db/models/fields.py:51
msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type." msgid "The base GIS field -- maps to the OpenGIS Specification Geometry type."
msgstr "The base GIS field -- maps to the OpenGIS Specification Geometry type." msgstr ""
#: db/models/fields.py:270 #: db/models/fields.py:270
msgid "Point" msgid "Point"
msgstr "Point" msgstr ""
#: db/models/fields.py:274 #: db/models/fields.py:274
msgid "Line string" msgid "Line string"
msgstr "Line string" msgstr ""
#: db/models/fields.py:278 #: db/models/fields.py:278
msgid "Polygon" msgid "Polygon"
msgstr "Polygon" msgstr ""
#: db/models/fields.py:282 #: db/models/fields.py:282
msgid "Multi-point" msgid "Multi-point"
msgstr "Multi-point" msgstr ""
#: db/models/fields.py:286 #: db/models/fields.py:286
msgid "Multi-line string" msgid "Multi-line string"
msgstr "Multi-line string" msgstr ""
#: db/models/fields.py:290 #: db/models/fields.py:290
msgid "Multi polygon" msgid "Multi polygon"
msgstr "Multi polygon" msgstr ""
#: db/models/fields.py:294 #: db/models/fields.py:294
msgid "Geometry collection" msgid "Geometry collection"
msgstr "Geometry collection" msgstr ""
#: forms/fields.py:23 #: forms/fields.py:23
msgid "No geometry value provided." msgid "No geometry value provided."
msgstr "No geometry value provided." msgstr ""
#: forms/fields.py:24 #: forms/fields.py:24
msgid "Invalid geometry value." msgid "Invalid geometry value."
msgstr "Invalid geometry value." msgstr ""
#: forms/fields.py:25 #: forms/fields.py:25
msgid "Invalid geometry type." msgid "Invalid geometry type."
msgstr "Invalid geometry type." msgstr ""
#: forms/fields.py:26 #: forms/fields.py:26
msgid "" msgid ""
"An error occurred when transforming the geometry to the SRID of the geometry " "An error occurred when transforming the geometry to the SRID of the geometry "
"form field." "form field."
msgstr "" msgstr ""
"An error occurred when transforming the geometry to the SRID of the geometry "
"form field."
#: sitemaps/views.py:46 #: sitemaps/views.py:46
#, python-format #, python-format
msgid "No sitemap available for section: %r" msgid "No sitemap available for section: %r"
msgstr "No sitemap available for section: %r" msgstr ""
#: sitemaps/views.py:60 #: sitemaps/views.py:60
#, python-format #, python-format
msgid "Page %s empty" msgid "Page %s empty"
msgstr "Page %s empty" msgstr ""
#: sitemaps/views.py:62 #: sitemaps/views.py:62
#, python-format #, python-format
msgid "No page '%s'" msgid "No page '%s'"
msgstr "No page '%s'" msgstr ""

View File

@ -297,7 +297,7 @@ class GeoLookupTest(TestCase):
# The left/right lookup tests are known failures on PostGIS 2.0/2.0.1 # The left/right lookup tests are known failures on PostGIS 2.0/2.0.1
# http://trac.osgeo.org/postgis/ticket/2035 # http://trac.osgeo.org/postgis/ticket/2035
if (2, 0, 0) <= connection.ops.spatial_version <= (2, 0, 1): if connection.ops.postgis and (2, 0, 0) <= connection.ops.spatial_version <= (2, 0, 1):
test_left_right_lookups = unittest.expectedFailure(test_left_right_lookups) test_left_right_lookups = unittest.expectedFailure(test_left_right_lookups)
def test_equals_lookups(self): def test_equals_lookups(self):

View File

@ -1,293 +1,290 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-02-14 13:08+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: tests.py:131 templatetags/humanize.py:168 #: tests.py:135 templatetags/humanize.py:168
msgid "today" msgid "today"
msgstr "today" msgstr ""
#: tests.py:131 templatetags/humanize.py:172 #: tests.py:135 templatetags/humanize.py:172
msgid "yesterday" msgid "yesterday"
msgstr "yesterday" msgstr ""
#: tests.py:131 templatetags/humanize.py:170 #: tests.py:135 templatetags/humanize.py:170
msgid "tomorrow" msgid "tomorrow"
msgstr "tomorrow" msgstr ""
#: templatetags/humanize.py:26 #: templatetags/humanize.py:26
msgid "th" msgid "th"
msgstr "th" msgstr ""
#: templatetags/humanize.py:26 #: templatetags/humanize.py:26
msgid "st" msgid "st"
msgstr "st" msgstr ""
#: templatetags/humanize.py:26 #: templatetags/humanize.py:26
msgid "nd" msgid "nd"
msgstr "nd" msgstr ""
#: templatetags/humanize.py:26 #: templatetags/humanize.py:26
msgid "rd" msgid "rd"
msgstr "rd" msgstr ""
#: templatetags/humanize.py:55 #: templatetags/humanize.py:55
#, python-format #, python-format
msgid "%(value).1f million" msgid "%(value).1f million"
msgid_plural "%(value).1f million" msgid_plural "%(value).1f million"
msgstr[0] "%(value).1f million" msgstr[0] ""
msgstr[1] "%(value).1f million" msgstr[1] ""
#: templatetags/humanize.py:56 #: templatetags/humanize.py:56
#, python-format #, python-format
msgid "%(value)s million" msgid "%(value)s million"
msgid_plural "%(value)s million" msgid_plural "%(value)s million"
msgstr[0] "%(value)s million" msgstr[0] ""
msgstr[1] "%(value)s million" msgstr[1] ""
#: templatetags/humanize.py:59 #: templatetags/humanize.py:59
#, python-format #, python-format
msgid "%(value).1f billion" msgid "%(value).1f billion"
msgid_plural "%(value).1f billion" msgid_plural "%(value).1f billion"
msgstr[0] "%(value).1f billion" msgstr[0] ""
msgstr[1] "%(value).1f billion" msgstr[1] ""
#: templatetags/humanize.py:60 #: templatetags/humanize.py:60
#, python-format #, python-format
msgid "%(value)s billion" msgid "%(value)s billion"
msgid_plural "%(value)s billion" msgid_plural "%(value)s billion"
msgstr[0] "%(value)s billion" msgstr[0] ""
msgstr[1] "%(value)s billion" msgstr[1] ""
#: templatetags/humanize.py:63 #: templatetags/humanize.py:63
#, python-format #, python-format
msgid "%(value).1f trillion" msgid "%(value).1f trillion"
msgid_plural "%(value).1f trillion" msgid_plural "%(value).1f trillion"
msgstr[0] "%(value).1f trillion" msgstr[0] ""
msgstr[1] "%(value).1f trillion" msgstr[1] ""
#: templatetags/humanize.py:64 #: templatetags/humanize.py:64
#, python-format #, python-format
msgid "%(value)s trillion" msgid "%(value)s trillion"
msgid_plural "%(value)s trillion" msgid_plural "%(value)s trillion"
msgstr[0] "%(value)s trillion" msgstr[0] ""
msgstr[1] "%(value)s trillion" msgstr[1] ""
#: templatetags/humanize.py:67 #: templatetags/humanize.py:67
#, python-format #, python-format
msgid "%(value).1f quadrillion" msgid "%(value).1f quadrillion"
msgid_plural "%(value).1f quadrillion" msgid_plural "%(value).1f quadrillion"
msgstr[0] "%(value).1f quadrillion" msgstr[0] ""
msgstr[1] "%(value).1f quadrillion" msgstr[1] ""
#: templatetags/humanize.py:68 #: templatetags/humanize.py:68
#, python-format #, python-format
msgid "%(value)s quadrillion" msgid "%(value)s quadrillion"
msgid_plural "%(value)s quadrillion" msgid_plural "%(value)s quadrillion"
msgstr[0] "%(value)s quadrillion" msgstr[0] ""
msgstr[1] "%(value)s quadrillion" msgstr[1] ""
#: templatetags/humanize.py:71 #: templatetags/humanize.py:71
#, python-format #, python-format
msgid "%(value).1f quintillion" msgid "%(value).1f quintillion"
msgid_plural "%(value).1f quintillion" msgid_plural "%(value).1f quintillion"
msgstr[0] "%(value).1f quintillion" msgstr[0] ""
msgstr[1] "%(value).1f quintillion" msgstr[1] ""
#: templatetags/humanize.py:72 #: templatetags/humanize.py:72
#, python-format #, python-format
msgid "%(value)s quintillion" msgid "%(value)s quintillion"
msgid_plural "%(value)s quintillion" msgid_plural "%(value)s quintillion"
msgstr[0] "%(value)s quintillion" msgstr[0] ""
msgstr[1] "%(value)s quintillion" msgstr[1] ""
#: templatetags/humanize.py:75 #: templatetags/humanize.py:75
#, python-format #, python-format
msgid "%(value).1f sextillion" msgid "%(value).1f sextillion"
msgid_plural "%(value).1f sextillion" msgid_plural "%(value).1f sextillion"
msgstr[0] "%(value).1f sextillion" msgstr[0] ""
msgstr[1] "%(value).1f sextillion" msgstr[1] ""
#: templatetags/humanize.py:76 #: templatetags/humanize.py:76
#, python-format #, python-format
msgid "%(value)s sextillion" msgid "%(value)s sextillion"
msgid_plural "%(value)s sextillion" msgid_plural "%(value)s sextillion"
msgstr[0] "%(value)s sextillion" msgstr[0] ""
msgstr[1] "%(value)s sextillion" msgstr[1] ""
#: templatetags/humanize.py:79 #: templatetags/humanize.py:79
#, python-format #, python-format
msgid "%(value).1f septillion" msgid "%(value).1f septillion"
msgid_plural "%(value).1f septillion" msgid_plural "%(value).1f septillion"
msgstr[0] "%(value).1f septillion" msgstr[0] ""
msgstr[1] "%(value).1f septillion" msgstr[1] ""
#: templatetags/humanize.py:80 #: templatetags/humanize.py:80
#, python-format #, python-format
msgid "%(value)s septillion" msgid "%(value)s septillion"
msgid_plural "%(value)s septillion" msgid_plural "%(value)s septillion"
msgstr[0] "%(value)s septillion" msgstr[0] ""
msgstr[1] "%(value)s septillion" msgstr[1] ""
#: templatetags/humanize.py:83 #: templatetags/humanize.py:83
#, python-format #, python-format
msgid "%(value).1f octillion" msgid "%(value).1f octillion"
msgid_plural "%(value).1f octillion" msgid_plural "%(value).1f octillion"
msgstr[0] "%(value).1f octillion" msgstr[0] ""
msgstr[1] "%(value).1f octillion" msgstr[1] ""
#: templatetags/humanize.py:84 #: templatetags/humanize.py:84
#, python-format #, python-format
msgid "%(value)s octillion" msgid "%(value)s octillion"
msgid_plural "%(value)s octillion" msgid_plural "%(value)s octillion"
msgstr[0] "%(value)s octillion" msgstr[0] ""
msgstr[1] "%(value)s octillion" msgstr[1] ""
#: templatetags/humanize.py:87 #: templatetags/humanize.py:87
#, python-format #, python-format
msgid "%(value).1f nonillion" msgid "%(value).1f nonillion"
msgid_plural "%(value).1f nonillion" msgid_plural "%(value).1f nonillion"
msgstr[0] "%(value).1f nonillion" msgstr[0] ""
msgstr[1] "%(value).1f nonillion" msgstr[1] ""
#: templatetags/humanize.py:88 #: templatetags/humanize.py:88
#, python-format #, python-format
msgid "%(value)s nonillion" msgid "%(value)s nonillion"
msgid_plural "%(value)s nonillion" msgid_plural "%(value)s nonillion"
msgstr[0] "%(value)s nonillion" msgstr[0] ""
msgstr[1] "%(value)s nonillion" msgstr[1] ""
#: templatetags/humanize.py:91 #: templatetags/humanize.py:91
#, python-format #, python-format
msgid "%(value).1f decillion" msgid "%(value).1f decillion"
msgid_plural "%(value).1f decillion" msgid_plural "%(value).1f decillion"
msgstr[0] "%(value).1f decillion" msgstr[0] ""
msgstr[1] "%(value).1f decillion" msgstr[1] ""
#: templatetags/humanize.py:92 #: templatetags/humanize.py:92
#, python-format #, python-format
msgid "%(value)s decillion" msgid "%(value)s decillion"
msgid_plural "%(value)s decillion" msgid_plural "%(value)s decillion"
msgstr[0] "%(value)s decillion" msgstr[0] ""
msgstr[1] "%(value)s decillion" msgstr[1] ""
#: templatetags/humanize.py:95 #: templatetags/humanize.py:95
#, python-format #, python-format
msgid "%(value).1f googol" msgid "%(value).1f googol"
msgid_plural "%(value).1f googol" msgid_plural "%(value).1f googol"
msgstr[0] "%(value).1f googol" msgstr[0] ""
msgstr[1] "%(value).1f googol" msgstr[1] ""
#: templatetags/humanize.py:96 #: templatetags/humanize.py:96
#, python-format #, python-format
msgid "%(value)s googol" msgid "%(value)s googol"
msgid_plural "%(value)s googol" msgid_plural "%(value)s googol"
msgstr[0] "%(value)s googol" msgstr[0] ""
msgstr[1] "%(value)s googol" msgstr[1] ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "one" msgid "one"
msgstr "one" msgstr ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "two" msgid "two"
msgstr "two" msgstr ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "three" msgid "three"
msgstr "three" msgstr ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "four" msgid "four"
msgstr "four" msgstr ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "five" msgid "five"
msgstr "five" msgstr ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "six" msgid "six"
msgstr "six" msgstr ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "seven" msgid "seven"
msgstr "seven" msgstr ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "eight" msgid "eight"
msgstr "eight" msgstr ""
#: templatetags/humanize.py:145 #: templatetags/humanize.py:145
msgid "nine" msgid "nine"
msgstr "nine" msgstr ""
#: templatetags/humanize.py:191 #: templatetags/humanize.py:191
#, python-format #, python-format
msgctxt "naturaltime" msgctxt "naturaltime"
msgid "%(delta)s ago" msgid "%(delta)s ago"
msgstr "%(delta)s ago" msgstr ""
#: templatetags/humanize.py:194 templatetags/humanize.py:216 #: templatetags/humanize.py:194 templatetags/humanize.py:216
msgid "now" msgid "now"
msgstr "now" msgstr ""
#: templatetags/humanize.py:197 #: templatetags/humanize.py:197
#, python-format #, python-format
msgid "a second ago" msgid "a second ago"
msgid_plural "%(count)s seconds ago" msgid_plural "%(count)s seconds ago"
msgstr[0] "a second ago" msgstr[0] ""
msgstr[1] "%(count)s seconds ago" msgstr[1] ""
#: templatetags/humanize.py:202 #: templatetags/humanize.py:202
#, python-format #, python-format
msgid "a minute ago" msgid "a minute ago"
msgid_plural "%(count)s minutes ago" msgid_plural "%(count)s minutes ago"
msgstr[0] "a minute ago" msgstr[0] ""
msgstr[1] "%(count)s minutes ago" msgstr[1] ""
#: templatetags/humanize.py:207 #: templatetags/humanize.py:207
#, python-format #, python-format
msgid "an hour ago" msgid "an hour ago"
msgid_plural "%(count)s hours ago" msgid_plural "%(count)s hours ago"
msgstr[0] "an hour ago" msgstr[0] ""
msgstr[1] "%(count)s hours ago" msgstr[1] ""
#: templatetags/humanize.py:213 #: templatetags/humanize.py:213
#, python-format #, python-format
msgctxt "naturaltime" msgctxt "naturaltime"
msgid "%(delta)s from now" msgid "%(delta)s from now"
msgstr "%(delta)s from now" msgstr ""
#: templatetags/humanize.py:219 #: templatetags/humanize.py:219
#, python-format #, python-format
msgid "a second from now" msgid "a second from now"
msgid_plural "%(count)s seconds from now" msgid_plural "%(count)s seconds from now"
msgstr[0] "a second from now" msgstr[0] ""
msgstr[1] "%(count)s seconds from now" msgstr[1] ""
#: templatetags/humanize.py:224 #: templatetags/humanize.py:224
#, python-format #, python-format
msgid "a minute from now" msgid "a minute from now"
msgid_plural "%(count)s minutes from now" msgid_plural "%(count)s minutes from now"
msgstr[0] "a minute from now" msgstr[0] ""
msgstr[1] "%(count)s minutes from now" msgstr[1] ""
#: templatetags/humanize.py:229 #: templatetags/humanize.py:229
#, python-format #, python-format
msgid "an hour from now" msgid "an hour from now"
msgid_plural "%(count)s hours from now" msgid_plural "%(count)s hours from now"
msgstr[0] "an hour from now" msgstr[0] ""
msgstr[1] "%(count)s hours from now" msgstr[1] ""

View File

@ -1,21 +1,18 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-02-14 13:16+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: tests/base.py:101 #: tests/base.py:100
msgid "lazy message" msgid "lazy message"
msgstr "lazy message" msgstr ""

View File

@ -1,49 +1,42 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-02-14 13:39+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: models.py:9 #: models.py:9
msgid "redirect from" msgid "redirect from"
msgstr "redirect from" msgstr ""
#: models.py:10 #: models.py:10
msgid "" msgid ""
"This should be an absolute path, excluding the domain name. Example: '/" "This should be an absolute path, excluding the domain name. Example: '/"
"events/search/'." "events/search/'."
msgstr "" msgstr ""
"This should be an absolute path, excluding the domain name. Example: '/"
"events/search/'."
#: models.py:11 #: models.py:11
msgid "redirect to" msgid "redirect to"
msgstr "redirect to" msgstr ""
#: models.py:12 #: models.py:12
msgid "" msgid ""
"This can be either an absolute path (as above) or a full URL starting with " "This can be either an absolute path (as above) or a full URL starting with "
"'http://'." "'http://'."
msgstr "" msgstr ""
"This can be either an absolute path (as above) or a full URL starting with "
"'http://'."
#: models.py:15 #: models.py:15
msgid "redirect" msgid "redirect"
msgstr "redirect" msgstr ""
#: models.py:16 #: models.py:16
msgid "redirects" msgid "redirects"
msgstr "redirects" msgstr ""

View File

@ -1,37 +1,34 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-02-14 13:40+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: models.py:38 #: models.py:38
msgid "session key" msgid "session key"
msgstr "session key" msgstr ""
#: models.py:40 #: models.py:40
msgid "session data" msgid "session data"
msgstr "session data" msgstr ""
#: models.py:41 #: models.py:41
msgid "expire date" msgid "expire date"
msgstr "expire date" msgstr ""
#: models.py:46 #: models.py:46
msgid "session" msgid "session"
msgstr "session" msgstr ""
#: models.py:47 #: models.py:47
msgid "sessions" msgid "sessions"
msgstr "sessions" msgstr ""

View File

@ -144,3 +144,10 @@ class HTTPSitemapTests(SitemapTestsBase):
</sitemapindex> </sitemapindex>
""" % self.base_url """ % self.base_url
self.assertXMLEqual(response.content.decode('utf-8'), expected_content) self.assertXMLEqual(response.content.decode('utf-8'), expected_content)
def test_x_robots_sitemap(self):
response = self.client.get('/simple/index.xml')
self.assertEqual(response['X-Robots-Tag'], 'noindex, noodp, noarchive')
response = self.client.get('/simple/sitemap.xml')
self.assertEqual(response['X-Robots-Tag'], 'noindex, noodp, noarchive')

View File

@ -1,4 +1,5 @@
import warnings import warnings
from functools import wraps
from django.contrib.sites.models import get_current_site from django.contrib.sites.models import get_current_site
from django.core import urlresolvers from django.core import urlresolvers
@ -7,6 +8,15 @@ from django.http import Http404
from django.template.response import TemplateResponse from django.template.response import TemplateResponse
from django.utils import six from django.utils import six
def x_robots_tag(func):
@wraps(func)
def inner(request, *args, **kwargs):
response = func(request, *args, **kwargs)
response['X-Robots-Tag'] = 'noindex, noodp, noarchive'
return response
return inner
@x_robots_tag
def index(request, sitemaps, def index(request, sitemaps,
template_name='sitemap_index.xml', content_type='application/xml', template_name='sitemap_index.xml', content_type='application/xml',
sitemap_url_name='django.contrib.sitemaps.views.sitemap', sitemap_url_name='django.contrib.sitemaps.views.sitemap',
@ -35,6 +45,7 @@ def index(request, sitemaps,
return TemplateResponse(request, template_name, {'sitemaps': sites}, return TemplateResponse(request, template_name, {'sitemaps': sites},
content_type=content_type) content_type=content_type)
@x_robots_tag
def sitemap(request, sitemaps, section=None, def sitemap(request, sitemaps, section=None,
template_name='sitemap.xml', content_type='application/xml', template_name='sitemap.xml', content_type='application/xml',
mimetype=None): mimetype=None):

View File

@ -1,20 +1,17 @@
# This file is distributed under the same license as the Django package. # This file is distributed under the same license as the Django package.
# #
# Translators:
# Jannis Leidel <jannis@leidel.info>, 2011.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Django\n" "Project-Id-Version: Django\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-28 10:04+0100\n" "POT-Creation-Date: 2013-05-02 16:18+0200\n"
"PO-Revision-Date: 2012-02-14 13:49+0000\n" "PO-Revision-Date: 2010-05-13 15:35+0200\n"
"Last-Translator: Jannis Leidel <jannis@leidel.info>\n" "Last-Translator: Django team\n"
"Language-Team: English <en@li.org>\n" "Language-Team: English <en@li.org>\n"
"Language: en\n" "Language: en\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: models.py:25 #: models.py:25
msgid "The domain name cannot contain any spaces or tabs." msgid "The domain name cannot contain any spaces or tabs."
@ -22,16 +19,16 @@ msgstr ""
#: models.py:58 #: models.py:58
msgid "domain name" msgid "domain name"
msgstr "domain name" msgstr ""
#: models.py:60 #: models.py:60
msgid "display name" msgid "display name"
msgstr "display name" msgstr ""
#: models.py:65 #: models.py:65
msgid "site" msgid "site"
msgstr "site" msgstr ""
#: models.py:66 #: models.py:66
msgid "sites" msgid "sites"
msgstr "sites" msgstr ""

View File

@ -116,6 +116,12 @@ class Command(NoArgsCommand):
processor = self.storage.post_process(found_files, processor = self.storage.post_process(found_files,
dry_run=self.dry_run) dry_run=self.dry_run)
for original_path, processed_path, processed in processor: for original_path, processed_path, processed in processor:
if isinstance(processed, Exception):
self.stderr.write("Post-processing '%s' failed!" % original_path)
# Add a blank line before the traceback, otherwise it's
# too easy to miss the relevant part of the error message.
self.stderr.write("")
raise processed
if processed: if processed:
self.log("Post-processed '%s' as '%s'" % self.log("Post-processed '%s' as '%s'" %
(original_path, processed_path), level=1) (original_path, processed_path), level=1)

View File

@ -251,7 +251,10 @@ class CachedFilesMixin(object):
for patterns in self._patterns.values(): for patterns in self._patterns.values():
for pattern, template in patterns: for pattern, template in patterns:
converter = self.url_converter(name, template) converter = self.url_converter(name, template)
try:
content = pattern.sub(converter, content) content = pattern.sub(converter, content)
except ValueError as exc:
yield name, None, exc
if hashed_file_exists: if hashed_file_exists:
self.delete(hashed_name) self.delete(hashed_name)
# then save the processed result # then save the processed result

View File

@ -57,6 +57,7 @@ STATUS_CODE_TEXT = {
415: 'UNSUPPORTED MEDIA TYPE', 415: 'UNSUPPORTED MEDIA TYPE',
416: 'REQUESTED RANGE NOT SATISFIABLE', 416: 'REQUESTED RANGE NOT SATISFIABLE',
417: 'EXPECTATION FAILED', 417: 'EXPECTATION FAILED',
418: "I'M A TEAPOT",
422: 'UNPROCESSABLE ENTITY', 422: 'UNPROCESSABLE ENTITY',
423: 'LOCKED', 423: 'LOCKED',
424: 'FAILED DEPENDENCY', 424: 'FAILED DEPENDENCY',

View File

@ -294,7 +294,10 @@ class Command(NoArgsCommand):
os.unlink(potfile) os.unlink(potfile)
for f in file_list: for f in file_list:
try:
f.process(self, potfile, self.domain, self.keep_pot) f.process(self, potfile, self.domain, self.keep_pot)
except UnicodeDecodeError:
self.stdout.write("UnicodeDecodeError: skipped file %s in %s" % (f.file, f.dirpath))
return potfile return potfile
def find_files(self, root): def find_files(self, root):

View File

@ -43,7 +43,7 @@ class TemplateCommand(BaseCommand):
option_list = BaseCommand.option_list + ( option_list = BaseCommand.option_list + (
make_option('--template', make_option('--template',
action='store', dest='template', action='store', dest='template',
help='The dotted import path to load the template from.'), help='The path or URL to load the template from.'),
make_option('--extension', '-e', dest='extensions', make_option('--extension', '-e', dest='extensions',
action='append', default=['py'], action='append', default=['py'],
help='The file extension(s) to render (default: "py"). ' help='The file extension(s) to render (default: "py"). '

View File

@ -108,6 +108,8 @@ class ServerHandler(simple_server.ServerHandler, object):
class WSGIServer(simple_server.WSGIServer, object): class WSGIServer(simple_server.WSGIServer, object):
"""BaseHTTPServer that implements the Python WSGI protocol""" """BaseHTTPServer that implements the Python WSGI protocol"""
request_queue_size = 10
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if kwargs.pop('ipv6', False): if kwargs.pop('ipv6', False):
self.address_family = socket.AF_INET6 self.address_family = socket.AF_INET6

View File

@ -30,6 +30,11 @@ if (version < (1, 2, 1) or (version[:3] == (1, 2, 1) and
from MySQLdb.converters import conversions, Thing2Literal from MySQLdb.converters import conversions, Thing2Literal
from MySQLdb.constants import FIELD_TYPE, CLIENT from MySQLdb.constants import FIELD_TYPE, CLIENT
try:
import pytz
except ImportError:
pytz = None
from django.conf import settings from django.conf import settings
from django.db import utils from django.db import utils
from django.db.backends import * from django.db.backends import *
@ -123,7 +128,7 @@ class CursorWrapper(object):
except Database.OperationalError as e: except Database.OperationalError as e:
# Map some error codes to IntegrityError, since they seem to be # Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place. # misclassified and Django would prefer the more logical place.
if e[0] in self.codes_for_integrityerror: if e.args[0] in self.codes_for_integrityerror:
six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2]) six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
raise raise
@ -133,7 +138,7 @@ class CursorWrapper(object):
except Database.OperationalError as e: except Database.OperationalError as e:
# Map some error codes to IntegrityError, since they seem to be # Map some error codes to IntegrityError, since they seem to be
# misclassified and Django would prefer the more logical place. # misclassified and Django would prefer the more logical place.
if e[0] in self.codes_for_integrityerror: if e.args[0] in self.codes_for_integrityerror:
six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2]) six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
raise raise
@ -190,6 +195,15 @@ class DatabaseFeatures(BaseDatabaseFeatures):
@cached_property @cached_property
def has_zoneinfo_database(self): def has_zoneinfo_database(self):
# MySQL accepts full time zones names (eg. Africa/Nairobi) but rejects
# abbreviations (eg. EAT). When pytz isn't installed and the current
# time zone is LocalTimezone (the only sensible value in this
# context), the current time zone name will be an abbreviation. As a
# consequence, MySQL cannot perform time zone conversions reliably.
if pytz is None:
return False
# Test if the time zone definitions are installed.
cursor = self.connection.cursor() cursor = self.connection.cursor()
cursor.execute("SELECT 1 FROM mysql.time_zone LIMIT 1") cursor.execute("SELECT 1 FROM mysql.time_zone LIMIT 1")
return cursor.fetchone() is not None return cursor.fetchone() is not None
@ -395,8 +409,9 @@ class DatabaseWrapper(BaseDatabaseWrapper):
kwargs = { kwargs = {
'conv': django_conversions, 'conv': django_conversions,
'charset': 'utf8', 'charset': 'utf8',
'use_unicode': True,
} }
if not six.PY3:
kwargs['use_unicode'] = True
settings_dict = self.settings_dict settings_dict = self.settings_dict
if settings_dict['USER']: if settings_dict['USER']:
kwargs['user'] = settings_dict['USER'] kwargs['user'] = settings_dict['USER']

View File

@ -10,6 +10,7 @@ class DatabaseValidation(BaseDatabaseValidation):
from django.db import models from django.db import models
varchar_fields = (models.CharField, models.CommaSeparatedIntegerField, varchar_fields = (models.CharField, models.CommaSeparatedIntegerField,
models.SlugField) models.SlugField)
if isinstance(f, varchar_fields) and f.max_length > 255 and f.unique: if (isinstance(f, varchar_fields) and f.unique
and (f.max_length is None or int(f.max_length) > 255)):
msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when using "unique=True".' msg = '"%(name)s": %(cls)s cannot have a "max_length" greater than 255 when using "unique=True".'
errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__}) errors.add(opts, msg % {'name': f.name, 'cls': f.__class__.__name__})

View File

@ -1,3 +1,5 @@
from functools import wraps
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
from django.db.models.loading import get_apps, get_app, get_models, get_model, register_models from django.db.models.loading import get_apps, get_app, get_models, get_model, register_models
from django.db.models.query import Q from django.db.models.query import Q
@ -11,7 +13,6 @@ from django.db.models.fields.files import FileField, ImageField
from django.db.models.fields.related import ForeignKey, ForeignObject, OneToOneField, ManyToManyField, ManyToOneRel, ManyToManyRel, OneToOneRel from django.db.models.fields.related import ForeignKey, ForeignObject, OneToOneField, ManyToManyField, ManyToOneRel, ManyToManyRel, OneToOneRel
from django.db.models.deletion import CASCADE, PROTECT, SET, SET_NULL, SET_DEFAULT, DO_NOTHING, ProtectedError from django.db.models.deletion import CASCADE, PROTECT, SET, SET_NULL, SET_DEFAULT, DO_NOTHING, ProtectedError
from django.db.models import signals from django.db.models import signals
from django.utils.decorators import wraps
def permalink(func): def permalink(func):

View File

@ -204,9 +204,6 @@ class SingleRelatedObjectDescriptor(six.with_metaclass(RenameRelatedObjectDescri
return rel_obj return rel_obj
def __set__(self, instance, value): def __set__(self, instance, value):
if instance is None:
raise AttributeError("%s must be accessed via instance" % self.related.opts.object_name)
# The similarity of the code below to the code in # The similarity of the code below to the code in
# ReverseSingleRelatedObjectDescriptor is annoying, but there's a bunch # ReverseSingleRelatedObjectDescriptor is annoying, but there's a bunch
# of small differences that would make a common base class convoluted. # of small differences that would make a common base class convoluted.
@ -310,9 +307,6 @@ class ReverseSingleRelatedObjectDescriptor(six.with_metaclass(RenameRelatedObjec
return rel_obj return rel_obj
def __set__(self, instance, value): def __set__(self, instance, value):
if instance is None:
raise AttributeError("%s must be accessed via instance" % self.field.name)
# If null=True, we can assign null here, but otherwise the value needs # If null=True, we can assign null here, but otherwise the value needs
# to be an instance of the related class. # to be an instance of the related class.
if value is None and self.field.null == False: if value is None and self.field.null == False:
@ -382,9 +376,6 @@ class ForeignRelatedObjectsDescriptor(object):
return self.related_manager_cls(instance) return self.related_manager_cls(instance)
def __set__(self, instance, value): def __set__(self, instance, value):
if instance is None:
raise AttributeError("Manager must be accessed via instance")
manager = self.__get__(instance) manager = self.__get__(instance)
# If the foreign key can support nulls, then completely clear the related set. # If the foreign key can support nulls, then completely clear the related set.
# Otherwise, just move the named objects into the set. # Otherwise, just move the named objects into the set.
@ -765,9 +756,6 @@ class ManyRelatedObjectsDescriptor(object):
return manager return manager
def __set__(self, instance, value): def __set__(self, instance, value):
if instance is None:
raise AttributeError("Manager must be accessed via instance")
if not self.related.field.rel.through._meta.auto_created: if not self.related.field.rel.through._meta.auto_created:
opts = self.related.field.rel.through._meta opts = self.related.field.rel.through._meta
raise AttributeError("Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s.%s's Manager instead." % (opts.app_label, opts.object_name)) raise AttributeError("Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s.%s's Manager instead." % (opts.app_label, opts.object_name))
@ -822,9 +810,6 @@ class ReverseManyRelatedObjectsDescriptor(object):
return manager return manager
def __set__(self, instance, value): def __set__(self, instance, value):
if instance is None:
raise AttributeError("Manager must be accessed via instance")
if not self.field.rel.through._meta.auto_created: if not self.field.rel.through._meta.auto_created:
opts = self.field.rel.through._meta opts = self.field.rel.through._meta
raise AttributeError("Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s.%s's Manager instead." % (opts.app_label, opts.object_name)) raise AttributeError("Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s.%s's Manager instead." % (opts.app_label, opts.object_name))

View File

@ -312,11 +312,7 @@ class QuerySet(object):
if skip: if skip:
obj = model_cls(**dict(zip(init_list, row_data))) obj = model_cls(**dict(zip(init_list, row_data)))
else: else:
try:
obj = model(*row_data) obj = model(*row_data)
except IndexError:
import ipdb; ipdb.set_trace()
pass
# Store the source database of the object # Store the source database of the object
obj._state.db = db obj._state.db = db

View File

@ -102,7 +102,7 @@ class DeferredAttribute(object):
f = [f for f in opts.fields f = [f for f in opts.fields
if f.attname == self.field_name][0] if f.attname == self.field_name][0]
name = f.name name = f.name
# Lets see if the field is part of the parent chain. If so we # Let's see if the field is part of the parent chain. If so we
# might be able to reuse the already loaded value. Refs #18343. # might be able to reuse the already loaded value. Refs #18343.
val = self._check_parent_chain(instance, name) val = self._check_parent_chain(instance, name)
if val is None: if val is None:
@ -194,8 +194,7 @@ def deferred_class_factory(model, attrs):
name = "%s_Deferred_%s" % (model.__name__, '_'.join(sorted(list(attrs)))) name = "%s_Deferred_%s" % (model.__name__, '_'.join(sorted(list(attrs))))
name = util.truncate_name(name, 80, 32) name = util.truncate_name(name, 80, 32)
overrides = dict([(attr, DeferredAttribute(attr, model)) overrides = dict((attr, DeferredAttribute(attr, model)) for attr in attrs)
for attr in attrs])
overrides["Meta"] = Meta overrides["Meta"] = Meta
overrides["__module__"] = model.__module__ overrides["__module__"] = model.__module__
overrides["_deferred"] = True overrides["_deferred"] = True

View File

@ -1092,7 +1092,7 @@ class SQLDateTimeCompiler(SQLCompiler):
if datetime is None: if datetime is None:
raise ValueError("Database returned an invalid value " raise ValueError("Database returned an invalid value "
"in QuerySet.dates(). Are time zone " "in QuerySet.dates(). Are time zone "
"definitions installed?") "definitions and pytz installed?")
datetime = datetime.replace(tzinfo=None) datetime = datetime.replace(tzinfo=None)
datetime = timezone.make_aware(datetime, self.query.tzinfo) datetime = timezone.make_aware(datetime, self.query.tzinfo)
yield datetime yield datetime

View File

@ -169,7 +169,7 @@ class ConnectionHandler(object):
conn.setdefault('ENGINE', 'django.db.backends.dummy') conn.setdefault('ENGINE', 'django.db.backends.dummy')
if conn['ENGINE'] == 'django.db.backends.' or not conn['ENGINE']: if conn['ENGINE'] == 'django.db.backends.' or not conn['ENGINE']:
conn['ENGINE'] = 'django.db.backends.dummy' conn['ENGINE'] = 'django.db.backends.dummy'
conn.setdefault('CONN_MAX_AGE', 600) conn.setdefault('CONN_MAX_AGE', 0)
conn.setdefault('OPTIONS', {}) conn.setdefault('OPTIONS', {})
conn.setdefault('TIME_ZONE', 'UTC' if settings.USE_TZ else settings.TIME_ZONE) conn.setdefault('TIME_ZONE', 'UTC' if settings.USE_TZ else settings.TIME_ZONE)
for setting in ['NAME', 'USER', 'PASSWORD', 'HOST', 'PORT']: for setting in ['NAME', 'USER', 'PASSWORD', 'HOST', 'PORT']:

View File

@ -9,7 +9,7 @@ from django.utils.encoding import python_2_unicode_compatible
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils import six from django.utils import six
from django.utils.six.moves import xrange from django.utils.six.moves import xrange
from django.utils.translation import ugettext as _ from django.utils.translation import ungettext, ugettext as _
__all__ = ('BaseFormSet', 'all_valid') __all__ = ('BaseFormSet', 'all_valid')
@ -302,7 +302,9 @@ class BaseFormSet(object):
try: try:
if (self.validate_max and self.total_form_count() > self.max_num) or \ if (self.validate_max and self.total_form_count() > self.max_num) or \
self.management_form.cleaned_data[TOTAL_FORM_COUNT] > self.absolute_max: self.management_form.cleaned_data[TOTAL_FORM_COUNT] > self.absolute_max:
raise ValidationError(_("Please submit %s or fewer forms." % self.max_num)) raise ValidationError(ungettext(
"Please submit %d or fewer forms.",
"Please submit %d or fewer forms.", self.max_num) % self.max_num)
# Give self.clean() a chance to do cross-form validation. # Give self.clean() a chance to do cross-form validation.
self.clean() self.clean()
except ValidationError as e: except ValidationError as e:

View File

@ -5,6 +5,8 @@ and database field objects.
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
import warnings
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS, FieldError from django.core.exceptions import ValidationError, NON_FIELD_ERRORS, FieldError
from django.forms.fields import Field, ChoiceField from django.forms.fields import Field, ChoiceField
from django.forms.forms import BaseForm, get_declared_fields from django.forms.forms import BaseForm, get_declared_fields
@ -22,8 +24,12 @@ from django.utils.translation import ugettext_lazy as _, ugettext
__all__ = ( __all__ = (
'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model', 'ModelForm', 'BaseModelForm', 'model_to_dict', 'fields_for_model',
'save_instance', 'ModelChoiceField', 'ModelMultipleChoiceField', 'save_instance', 'ModelChoiceField', 'ModelMultipleChoiceField',
'ALL_FIELDS',
) )
ALL_FIELDS = '__all__'
def construct_instance(form, instance, fields=None, exclude=None): def construct_instance(form, instance, fields=None, exclude=None):
""" """
Constructs and returns a model instance from the bound ``form``'s Constructs and returns a model instance from the bound ``form``'s
@ -211,7 +217,7 @@ class ModelFormMetaclass(type):
# of ('foo',) # of ('foo',)
for opt in ['fields', 'exclude']: for opt in ['fields', 'exclude']:
value = getattr(opts, opt) value = getattr(opts, opt)
if isinstance(value, six.string_types): if isinstance(value, six.string_types) and value != ALL_FIELDS:
msg = ("%(model)s.Meta.%(opt)s cannot be a string. " msg = ("%(model)s.Meta.%(opt)s cannot be a string. "
"Did you mean to type: ('%(value)s',)?" % { "Did you mean to type: ('%(value)s',)?" % {
'model': new_class.__name__, 'model': new_class.__name__,
@ -222,6 +228,20 @@ class ModelFormMetaclass(type):
if opts.model: if opts.model:
# If a model is defined, extract form fields from it. # If a model is defined, extract form fields from it.
if opts.fields is None and opts.exclude is None:
# This should be some kind of assertion error once deprecation
# cycle is complete.
warnings.warn("Creating a ModelForm without either the 'fields' attribute "
"or the 'exclude' attribute is deprecated - form %s "
"needs updating" % name,
PendingDeprecationWarning)
if opts.fields == ALL_FIELDS:
# sentinel for fields_for_model to indicate "get the list of
# fields from the model"
opts.fields = None
fields = fields_for_model(opts.model, opts.fields, fields = fields_for_model(opts.model, opts.fields,
opts.exclude, opts.widgets, formfield_callback) opts.exclude, opts.widgets, formfield_callback)
# make sure opts.fields doesn't specify an invalid field # make sure opts.fields doesn't specify an invalid field
@ -394,7 +414,8 @@ def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
Returns a ModelForm containing form fields for the given model. Returns a ModelForm containing form fields for the given model.
``fields`` is an optional list of field names. If provided, only the named ``fields`` is an optional list of field names. If provided, only the named
fields will be included in the returned fields. fields will be included in the returned fields. If omitted or '__all__',
all fields will be used.
``exclude`` is an optional list of field names. If provided, the named ``exclude`` is an optional list of field names. If provided, the named
fields will be excluded from the returned fields, even if they are listed fields will be excluded from the returned fields, even if they are listed
@ -434,6 +455,15 @@ def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
'formfield_callback': formfield_callback 'formfield_callback': formfield_callback
} }
# The ModelFormMetaclass will trigger a similar warning/error, but this will
# be difficult to debug for code that needs updating, so we produce the
# warning here too.
if (getattr(Meta, 'fields', None) is None and
getattr(Meta, 'exclude', None) is None):
warnings.warn("Calling modelform_factory without defining 'fields' or "
"'exclude' explicitly is deprecated",
PendingDeprecationWarning, stacklevel=2)
# Instatiate type(form) in order to use the same metaclass as form. # Instatiate type(form) in order to use the same metaclass as form.
return type(form)(class_name, (form,), form_class_attrs) return type(form)(class_name, (form,), form_class_attrs)
@ -701,6 +731,21 @@ def modelformset_factory(model, form=ModelForm, formfield_callback=None,
""" """
Returns a FormSet class for the given Django model class. Returns a FormSet class for the given Django model class.
""" """
# modelform_factory will produce the same warning/error, but that will be
# difficult to debug for code that needs upgrading, so we produce the
# warning here too. This logic is reproducing logic inside
# modelform_factory, but it can be removed once the deprecation cycle is
# complete, since the validation exception will produce a helpful
# stacktrace.
meta = getattr(form, 'Meta', None)
if meta is None:
meta = type(str('Meta'), (object,), {})
if (getattr(meta, 'fields', fields) is None and
getattr(meta, 'exclude', exclude) is None):
warnings.warn("Calling modelformset_factory without defining 'fields' or "
"'exclude' explicitly is deprecated",
PendingDeprecationWarning, stacklevel=2)
form = modelform_factory(model, form=form, fields=fields, exclude=exclude, form = modelform_factory(model, form=form, fields=fields, exclude=exclude,
formfield_callback=formfield_callback, formfield_callback=formfield_callback,
widgets=widgets) widgets=widgets)
@ -1091,3 +1136,11 @@ class ModelMultipleChoiceField(ModelChoiceField):
initial_set = set([force_text(value) for value in self.prepare_value(initial)]) initial_set = set([force_text(value) for value in self.prepare_value(initial)])
data_set = set([force_text(value) for value in data]) data_set = set([force_text(value) for value in data])
return data_set != initial_set return data_set != initial_set
def modelform_defines_fields(form_class):
return (form_class is not None and (
hasattr(form_class, '_meta') and
(form_class._meta.fields is not None or
form_class._meta.exclude is not None)
))

View File

@ -1,5 +1,6 @@
import re import re
import warnings import warnings
from functools import wraps
from xml.dom.minidom import parseString, Node from xml.dom.minidom import parseString, Node
from django.conf import settings, UserSettingsHolder from django.conf import settings, UserSettingsHolder
@ -10,7 +11,6 @@ from django.template import Template, loader, TemplateDoesNotExist
from django.template.loaders import cached from django.template.loaders import cached
from django.test.signals import template_rendered, setting_changed from django.test.signals import template_rendered, setting_changed
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.functional import wraps
from django.utils import six from django.utils import six
from django.utils.translation import deactivate from django.utils.translation import deactivate

View File

@ -14,13 +14,19 @@ class MergeDict(object):
def __init__(self, *dicts): def __init__(self, *dicts):
self.dicts = dicts self.dicts = dicts
def __bool__(self):
return any(self.dicts)
def __nonzero__(self):
return type(self).__bool__(self)
def __getitem__(self, key): def __getitem__(self, key):
for dict_ in self.dicts: for dict_ in self.dicts:
try: try:
return dict_[key] return dict_[key]
except KeyError: except KeyError:
pass pass
raise KeyError raise KeyError(key)
def __copy__(self): def __copy__(self):
return self.__class__(*self.dicts) return self.__class__(*self.dicts)

View File

@ -346,6 +346,7 @@ class SimpleLazyObject(LazyObject):
# care about this (especially in equality tests) # care about this (especially in equality tests)
__class__ = property(new_method_proxy(operator.attrgetter("__class__"))) __class__ = property(new_method_proxy(operator.attrgetter("__class__")))
__eq__ = new_method_proxy(operator.eq) __eq__ = new_method_proxy(operator.eq)
__ne__ = new_method_proxy(operator.ne)
__hash__ = new_method_proxy(hash) __hash__ = new_method_proxy(hash)
__bool__ = new_method_proxy(bool) # Python 3 __bool__ = new_method_proxy(bool) # Python 3
__nonzero__ = __bool__ # Python 2 __nonzero__ = __bool__ # Python 2

View File

@ -1,3 +1,5 @@
import warnings
from django.forms import models as model_forms from django.forms import models as model_forms
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
@ -95,7 +97,14 @@ class ModelFormMixin(FormMixin, SingleObjectMixin):
# Try to get a queryset and extract the model class # Try to get a queryset and extract the model class
# from that # from that
model = self.get_queryset().model model = self.get_queryset().model
return model_forms.modelform_factory(model)
fields = getattr(self, 'fields', None)
if fields is None:
warnings.warn("Using ModelFormMixin (base class of %s) without "
"the 'fields' attribute is deprecated." % self.__class__.__name__,
PendingDeprecationWarning)
return model_forms.modelform_factory(model, fields=fields)
def get_form_kwargs(self): def get_form_kwargs(self):
""" """

View File

@ -6,7 +6,7 @@ from django import http
from django.conf import settings from django.conf import settings
from django.template import Context, Template from django.template import Context, Template
from django.utils import importlib from django.utils import importlib
from django.utils.translation import check_for_language, activate, to_locale, get_language from django.utils.translation import check_for_language, to_locale, get_language
from django.utils.encoding import smart_text from django.utils.encoding import smart_text
from django.utils.formats import get_format_modules, get_format from django.utils.formats import get_format_modules, get_format
from django.utils._os import upath from django.utils._os import upath
@ -205,17 +205,18 @@ def javascript_catalog(request, domain='djangojs', packages=None):
go to the djangojs domain. But this might be needed if you go to the djangojs domain. But this might be needed if you
deliver your JavaScript source from Django templates. deliver your JavaScript source from Django templates.
""" """
if request.GET: default_locale = to_locale(settings.LANGUAGE_CODE)
if 'language' in request.GET: locale = to_locale(get_language())
if request.GET and 'language' in request.GET:
if check_for_language(request.GET['language']): if check_for_language(request.GET['language']):
activate(request.GET['language']) locale = to_locale(request.GET['language'])
if packages is None: if packages is None:
packages = ['django.conf'] packages = ['django.conf']
if isinstance(packages, six.string_types): if isinstance(packages, six.string_types):
packages = packages.split('+') packages = packages.split('+')
packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS] packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS]
default_locale = to_locale(settings.LANGUAGE_CODE)
locale = to_locale(get_language())
t = {} t = {}
paths = [] paths = []
en_selected = locale.startswith('en') en_selected = locale.startswith('en')

View File

@ -5,9 +5,7 @@ import json
import os import os
import re import re
from docutils import nodes, transforms from sphinx import addnodes, __version__ as sphinx_ver
from sphinx import addnodes, roles, __version__ as sphinx_ver
from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.writers.html import SmartyPantsHTMLTranslator from sphinx.writers.html import SmartyPantsHTMLTranslator
from sphinx.util.console import bold from sphinx.util.console import bold
@ -64,21 +62,25 @@ class VersionDirective(Directive):
option_spec = {} option_spec = {}
def run(self): def run(self):
if len(self.arguments) > 1:
msg = """Only one argument accepted for directive '{directive_name}::'.
Comments should be provided as content,
not as an extra argument.""".format(directive_name=self.name)
raise self.error(msg)
env = self.state.document.settings.env env = self.state.document.settings.env
ret = [] ret = []
node = addnodes.versionmodified() node = addnodes.versionmodified()
ret.append(node) ret.append(node)
if self.arguments[0] == env.config.django_next_version: if self.arguments[0] == env.config.django_next_version:
node['version'] = "Development version" node['version'] = "Development version"
else: else:
node['version'] = self.arguments[0] node['version'] = self.arguments[0]
node['type'] = self.name node['type'] = self.name
if len(self.arguments) == 2:
inodes, messages = self.state.inline_text(self.arguments[1], self.lineno+1)
node.extend(inodes)
if self.content: if self.content:
self.state.nested_parse(self.content, self.content_offset, node) self.state.nested_parse(self.content, self.content_offset, node)
ret = ret + messages
env.note_versionchange(node['type'], node['version'], node, self.lineno) env.note_versionchange(node['type'], node['version'], node, self.lineno)
return ret return ret

View File

@ -157,6 +157,15 @@ Performance optimizations
Setting :setting:`DEBUG = False <DEBUG>` disables several features that are Setting :setting:`DEBUG = False <DEBUG>` disables several features that are
only useful in development. In addition, you can tune the following settings. only useful in development. In addition, you can tune the following settings.
:setting:`CONN_MAX_AGE`
-----------------------
Enabling `persistent database connections <persistent-database-connections>`_
can result in a nice speed-up when connecting to the database accounts for a
significant part of the request processing time.
This helps a lot on virtualized hosts with limited network performance.
:setting:`TEMPLATE_LOADERS` :setting:`TEMPLATE_LOADERS`
--------------------------- ---------------------------

View File

@ -61,7 +61,7 @@ this generated model definition:
class Person(models.Model): class Person(models.Model):
id = models.IntegerField(primary_key=True) id = models.IntegerField(primary_key=True)
first_name = models.ChaField(max_length=70) first_name = models.CharField(max_length=70)
class Meta: class Meta:
**managed = False** **managed = False**
db_table = 'CENSUS_PERSONS' db_table = 'CENSUS_PERSONS'

View File

@ -32,7 +32,7 @@ Configuring static files
{% load staticfiles %} {% load staticfiles %}
<img src="{% static "my_app/myexample.jpg" %}" alt="My image"/> <img src="{% static "my_app/myexample.jpg" %}" alt="My image"/>
3. Store your static files in a folder called ``static`` in your app. For 4. Store your static files in a folder called ``static`` in your app. For
example ``my_app/static/my_app/myimage.jpg``. example ``my_app/static/my_app/myimage.jpg``.
Now, if you use ``./manage.py runserver``, all static files should be served Now, if you use ``./manage.py runserver``, all static files should be served

View File

@ -441,6 +441,20 @@ Jeremy Dunck
.. _Ultimate Frisbee: http://www.montrealultimate.ca .. _Ultimate Frisbee: http://www.montrealultimate.ca
.. _Reptiletech: http://www.reptiletech.com .. _Reptiletech: http://www.reptiletech.com
`Daniel Lindsley`_
Pythonista since 2003, Djangonaut since 2006. Daniel started with Django
just after the v0.90 release (back when ``Manipulators`` looked good) & fell
in love. Since then, he wrote third-party apps like Haystack & Tastypie
& has run the annual Django Dash since 2007. One of the testing faithful,
Daniel's contributions include rewriting the ``Forms`` test suite & the
addition of ``request.is_ajax``. Daniel currently works as a Python
developer at `Amazon Web Services`_ on the ``boto`` library.
Daniel lives in Seattle, WA, USA.
.. _`Daniel Lindsley`: http://toastdriven.com/
.. _`Amazon Web Services`: https://aws.amazon.com/
Specialists Specialists
----------- -----------

View File

@ -62,5 +62,5 @@ Django source tree, as for any code change:
.. _Transifex: https://www.transifex.com/ .. _Transifex: https://www.transifex.com/
.. _Django i18n mailing list: http://groups.google.com/group/django-i18n/ .. _Django i18n mailing list: http://groups.google.com/group/django-i18n/
.. _Django project page: https://www.transifex.com/projects/p/django/ .. _Django project page: https://www.transifex.com/projects/p/django-core/
.. _Transifex User Guide: http://help.transifex.com/ .. _Transifex User Guide: http://help.transifex.com/

View File

@ -188,8 +188,8 @@ Our policy for new features is:
release, not the development version. release, not the development version.
Our preferred way for marking new features is by prefacing the features' Our preferred way for marking new features is by prefacing the features'
documentation with: "``.. versionadded:: X.Y``", followed by an optional one documentation with: "``.. versionadded:: X.Y``", followed by a a mandatory
line comment and a mandatory blank line. blank line and an optional content (indented).
General improvements, or other changes to the APIs that should be emphasized General improvements, or other changes to the APIs that should be emphasized
should use the "``.. versionchanged:: X.Y``" directive (with the same format should use the "``.. versionchanged:: X.Y``" directive (with the same format

View File

@ -175,13 +175,13 @@ OK, this is the fun part, where we actually push out a release!
#. Make sure you have an absolutely clean tree by running ``git clean -dfx``. #. Make sure you have an absolutely clean tree by running ``git clean -dfx``.
#. Run ``python setup.py sdist`` to generate the release package. This will #. Run ``make -f extras/Makefile`` to generate the release packages. This will
create the release package in a ``dist/`` directory. create the release packages in a ``dist/`` directory.
#. Generate the hashes of the release package:: #. Generate the hashes of the release packages::
$ md5sum dist/Django-<version>.tar.gz $ md5sum dist/Django-*
$ sha1sum dist/Django-<version>.tar.gz $ sha1sum dist/Django-*
*FIXME: perhaps we should switch to sha256?* *FIXME: perhaps we should switch to sha256?*
@ -221,6 +221,9 @@ Now you're ready to actually put the release out there. To do this:
$ mktmpenv $ mktmpenv
$ pip install https://www.djangoproject.com/m/releases/1.5/Django-1.5.1.tar.gz $ pip install https://www.djangoproject.com/m/releases/1.5/Django-1.5.1.tar.gz
$ deactivate $ deactivate
$ mktmpenv
$ pip install https://www.djangoproject.com/m/releases/1.5/Django-1.5.1-py2.py3-none-any.whl
$ deactivate
This just tests that the tarballs are available (i.e. redirects are up) and This just tests that the tarballs are available (i.e. redirects are up) and
that they install correctly, but it'll catch silly mistakes. that they install correctly, but it'll catch silly mistakes.

View File

@ -66,16 +66,17 @@ After the previous tutorials, our project should look like this::
__init__.py __init__.py
admin.py admin.py
models.py models.py
tests.py
static/ static/
style.css polls
images/ images/
background.gif background.gif
style.css
templates/ templates/
polls/ polls/
detail.html detail.html
index.html index.html
results.html results.html
tests.py
urls.py urls.py
views.py views.py
templates/ templates/
@ -129,7 +130,7 @@ this. For a small app like polls, this process isn't too difficult.
2. Move the ``polls`` directory into the ``django-polls`` directory. 2. Move the ``polls`` directory into the ``django-polls`` directory.
3. Create a file ``django-polls/README.txt`` with the following contents:: 3. Create a file ``django-polls/README.rst`` with the following contents::
===== =====
Polls Polls
@ -177,7 +178,7 @@ Create a file ``django-polls/setup.py`` with the following contents::
import os import os
from setuptools import setup from setuptools import setup
README = open(os.path.join(os.path.dirname(__file__), 'README.txt')).read() README = open(os.path.join(os.path.dirname(__file__), 'README.rst')).read()
# allow setup.py to be run from any path # allow setup.py to be run from any path
os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir))) os.chdir(os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir)))
@ -216,10 +217,13 @@ Create a file ``django-polls/setup.py`` with the following contents::
6. Only Python modules and packages are included in the package by default. To 6. Only Python modules and packages are included in the package by default. To
include additional files, we'll need to create a ``MANIFEST.in`` file. The include additional files, we'll need to create a ``MANIFEST.in`` file. The
distribute docs referred to in the previous step discuss this file in more distribute docs referred to in the previous step discuss this file in more
details. To include the templates and our LICENSE file, create a file details. To include the templates, the ``README.rst`` and our ``LICENSE``
``django-polls/MANIFEST.in`` with the following contents:: file, create a file ``django-polls/MANIFEST.in`` with the following
contents::
include LICENSE include LICENSE
include README.rst
recursive-include polls/static *
recursive-include polls/templates * recursive-include polls/templates *
7. It's optional, but recommended, to include detailed documentation with your 7. It's optional, but recommended, to include detailed documentation with your

View File

@ -23,7 +23,8 @@ If Django is installed, you should see the version of your installation. If it
isn't, you'll get an error telling "No module named django". isn't, you'll get an error telling "No module named django".
This tutorial is written for Django |version| and Python 2.x. If the Django This tutorial is written for Django |version| and Python 2.x. If the Django
version doesn't match, you can refer to the tutorial for your version of Django version doesn't match, you can refer to the tutorial for your version of
Django by using the version switcher at the bottom right corner of this page,
or update Django to the newest version. If you are using Python 3.x, be aware or update Django to the newest version. If you are using Python 3.x, be aware
that your code may need to differ from what is in the tutorial and you should that your code may need to differ from what is in the tutorial and you should
continue using the tutorial only if you know what you are doing with Python continue using the tutorial only if you know what you are doing with Python
@ -242,9 +243,6 @@ come with Django:
* :mod:`django.contrib.sessions` -- A session framework. * :mod:`django.contrib.sessions` -- A session framework.
* :mod:`django.contrib.sites` -- A framework for managing multiple sites
with one Django installation.
* :mod:`django.contrib.messages` -- A messaging framework. * :mod:`django.contrib.messages` -- A messaging framework.
* :mod:`django.contrib.staticfiles` -- A framework for managing * :mod:`django.contrib.staticfiles` -- A framework for managing
@ -252,7 +250,7 @@ come with Django:
These applications are included by default as a convenience for the common case. These applications are included by default as a convenience for the common case.
Each of these applications makes use of at least one database table, though, Some of these applications makes use of at least one database table, though,
so we need to create the tables in the database before we can use them. To do so we need to create the tables in the database before we can use them. To do
that, run the following command: that, run the following command:
@ -581,27 +579,32 @@ Wait a minute. ``<Poll: Poll object>`` is, utterly, an unhelpful representation
of this object. Let's fix that by editing the polls model (in the of this object. Let's fix that by editing the polls model (in the
``polls/models.py`` file) and adding a ``polls/models.py`` file) and adding a
:meth:`~django.db.models.Model.__unicode__` method to both ``Poll`` and :meth:`~django.db.models.Model.__unicode__` method to both ``Poll`` and
``Choice``:: ``Choice``. On Python 3, simply replace ``__unicode__`` by ``__str__`` in the
following example::
class Poll(models.Model): class Poll(models.Model):
# ... # ...
def __unicode__(self): def __unicode__(self): # Python 3: def __str__(self):
return self.question return self.question
class Choice(models.Model): class Choice(models.Model):
# ... # ...
def __unicode__(self): def __unicode__(self): # Python 3: def __str__(self):
return self.choice_text return self.choice_text
It's important to add :meth:`~django.db.models.Model.__unicode__` methods to It's important to add :meth:`~django.db.models.Model.__unicode__` methods (or
your models, not only for your own sanity when dealing with the interactive :meth:`~django.db.models.Model.__str__` on Python 3) to your models, not only
prompt, but also because objects' representations are used throughout Django's for your own sanity when dealing with the interactive prompt, but also because
automatically-generated admin. objects' representations are used throughout Django's automatically-generated
admin.
.. admonition:: Why :meth:`~django.db.models.Model.__unicode__` and not .. admonition:: `__unicode__` or `__str__`?
:meth:`~django.db.models.Model.__str__`?
If you're familiar with Python, you might be in the habit of adding On Python 3, things are simpler, just use
:meth:`~django.db.models.Model.__str__` and forget about
:meth:`~django.db.models.Model.__unicode__`.
If you're familiar with Python 2, you might be in the habit of adding
:meth:`~django.db.models.Model.__str__` methods to your classes, not :meth:`~django.db.models.Model.__str__` methods to your classes, not
:meth:`~django.db.models.Model.__unicode__` methods. We use :meth:`~django.db.models.Model.__unicode__` methods. We use
:meth:`~django.db.models.Model.__unicode__` here because Django models deal :meth:`~django.db.models.Model.__unicode__` here because Django models deal

View File

@ -15,9 +15,9 @@ What are automated tests?
Tests are simple routines that check the operation of your code. Tests are simple routines that check the operation of your code.
Testing operates at different levels. Some tests might apply to a tiny detail Testing operates at different levels. Some tests might apply to a tiny detail
- *does a particular model method return values as expected?*, while others (*does a particular model method return values as expected?*) while others
examine the overall operation of the software - *does a sequence of user inputs examine the overall operation of the software (*does a sequence of user inputs
on the site produce the desired result?* That's no different from the kind of on the site produce the desired result?*). That's no different from the kind of
testing you did earlier in :doc:`Tutorial 1 </intro/tutorial01>`, using the testing you did earlier in :doc:`Tutorial 1 </intro/tutorial01>`, using the
shell to examine the behavior of a method, or running the application and shell to examine the behavior of a method, or running the application and
entering data to check how it behaves. entering data to check how it behaves.
@ -326,6 +326,13 @@ in the shell::
>>> from django.test.utils import setup_test_environment >>> from django.test.utils import setup_test_environment
>>> setup_test_environment() >>> setup_test_environment()
:meth:`~django.test.utils.setup_test_environment` installs a template renderer
which will allow us to examine some additional attributes on responses such as
``response.context`` that otherwise wouldn't be available. Note that this
method *does not* setup a test database, so the following will be run against
the existing database and the output may differ slightly depending on what
polls you already created.
Next we need to import the test client class (later in ``tests.py`` we will use Next we need to import the test client class (later in ``tests.py`` we will use
the :class:`django.test.TestCase` class, which comes with its own client, so the :class:`django.test.TestCase` class, which comes with its own client, so
this won't be required):: this won't be required)::

View File

@ -108,7 +108,7 @@ loaded in the bottom right of the screen.
These are the **basics**. For more details on settings and other bits included These are the **basics**. For more details on settings and other bits included
with the framework see with the framework see
:doc:`the static files howto </howto/static-files/index>` and the :doc:`the static files howto </howto/static-files/index>` and
:doc:`the staticfiles reference </ref/contrib/staticfiles>`. :doc:`Deploying :doc:`the staticfiles reference </ref/contrib/staticfiles>`. :doc:`Deploying
static files </howto/static-files/deployment>` discusses how to use static static files </howto/static-files/deployment>` discusses how to use static
files on a real server. files on a real server.

View File

@ -105,6 +105,7 @@ TemplateView
in the URL. in the URL.
.. versionchanged:: 1.5 .. versionchanged:: 1.5
The context used to be populated with a ``{{ params }}`` dictionary of The context used to be populated with a ``{{ params }}`` dictionary of
the parameters captured in the URL. Now those parameters are first-level the parameters captured in the URL. Now those parameters are first-level
context variables. context variables.

View File

@ -110,6 +110,7 @@ CreateView
class AuthorCreate(CreateView): class AuthorCreate(CreateView):
model = Author model = Author
fields = ['name']
UpdateView UpdateView
---------- ----------
@ -152,6 +153,7 @@ UpdateView
class AuthorUpdate(UpdateView): class AuthorUpdate(UpdateView):
model = Author model = Author
fields = ['name']
DeleteView DeleteView
---------- ----------

View File

@ -330,5 +330,6 @@ BaseDateListView
:meth:`QuerySet.dates()<django.db.models.query.QuerySet.dates>`. :meth:`QuerySet.dates()<django.db.models.query.QuerySet.dates>`.
.. versionchanged:: 1.5 .. versionchanged:: 1.5
The ``ordering`` parameter was added, and the default order was The ``ordering`` parameter was added, and the default order was
changed to ascending. changed to ascending.

View File

@ -116,6 +116,18 @@ ModelFormMixin
by examining ``self.object`` or by examining ``self.object`` or
:attr:`~django.views.generic.detail.SingleObjectMixin.queryset`. :attr:`~django.views.generic.detail.SingleObjectMixin.queryset`.
.. attribute:: fields
.. versionadded:: 1.6
A list of names of fields. This is interpreted the same way as the
``Meta.fields`` attribute of :class:`~django.forms.ModelForm`.
This is a required attribute if you are generating the form class
automatically (e.g. using ``model``). Omitting this attribute will
result in all fields being used, but this behaviour is deprecated
and will be removed in Django 1.8.
.. attribute:: success_url .. attribute:: success_url
The URL to redirect to when the form is successfully processed. The URL to redirect to when the form is successfully processed.

View File

@ -67,7 +67,6 @@ TemplateResponseMixin
.. attribute:: content_type .. attribute:: content_type
.. versionadded:: 1.5 .. versionadded:: 1.5
The ``content_type`` attribute was added.
The content type to use for the response. ``content_type`` is passed The content type to use for the response. ``content_type`` is passed
as a keyword argument to ``response_class``. Default is ``None`` -- as a keyword argument to ``response_class``. Default is ``None`` --

View File

@ -62,6 +62,7 @@ To set the same ``X-Frame-Options`` value for all responses in your site, put
) )
.. versionchanged:: 1.6 .. versionchanged:: 1.6
This middleware is enabled in the settings file generated by This middleware is enabled in the settings file generated by
:djadmin:`startproject`. :djadmin:`startproject`.

View File

@ -18,6 +18,7 @@ The admin is enabled in the default project template used by
:djadmin:`startproject`. :djadmin:`startproject`.
.. versionchanged:: 1.6 .. versionchanged:: 1.6
In previous versions, the admin wasn't enabled by default. In previous versions, the admin wasn't enabled by default.
For reference, here are the requirements: For reference, here are the requirements:
@ -334,6 +335,22 @@ subclass::
For an example see the section `Adding custom validation to the admin`_. For an example see the section `Adding custom validation to the admin`_.
.. admonition:: Note
.. versionchanged:: 1.6
If you define the ``Meta.model`` attribute on a
:class:`~django.forms.ModelForm`, you must also define the
``Meta.fields`` attribute (or the ``Meta.exclude`` attribute). However,
since the admin has its own way of defining fields, the ``Meta.fields``
attribute will be ignored.
If the ``ModelForm`` is only going to be used for the admin, the easiest
solution is to omit the ``Meta.model`` attribute, since ``ModelAdmin``
will provide the correct model to use. Alternatively, you can set
``fields = []`` in the ``Meta`` class to satisfy the validation on the
``ModelForm``.
.. admonition:: Note .. admonition:: Note
If your ``ModelForm`` and ``ModelAdmin`` both define an ``exclude`` If your ``ModelForm`` and ``ModelAdmin`` both define an ``exclude``
@ -1282,13 +1299,24 @@ templates used by the :class:`ModelAdmin` views:
on the changelist page. To use a custom form, for example:: on the changelist page. To use a custom form, for example::
class MyForm(forms.ModelForm): class MyForm(forms.ModelForm):
class Meta: pass
model = MyModel
class MyModelAdmin(admin.ModelAdmin): class MyModelAdmin(admin.ModelAdmin):
def get_changelist_form(self, request, **kwargs): def get_changelist_form(self, request, **kwargs):
return MyForm return MyForm
.. admonition:: Note
.. versionchanged:: 1.6
If you define the ``Meta.model`` attribute on a
:class:`~django.forms.ModelForm`, you must also define the
``Meta.fields`` attribute (or the ``Meta.exclude`` attribute). However,
``ModelAdmin`` ignores this value, overriding it with the
:attr:`ModelAdmin.list_editable` attribute. The easiest solution is to
omit the ``Meta.model`` attribute, since ``ModelAdmin`` will provide the
correct model to use.
.. method:: ModelAdmin.get_changelist_formset(self, request, **kwargs) .. method:: ModelAdmin.get_changelist_formset(self, request, **kwargs)
Returns a :ref:`ModelFormSet <model-formsets>` class for use on the Returns a :ref:`ModelFormSet <model-formsets>` class for use on the
@ -1341,6 +1369,7 @@ templates used by the :class:`ModelAdmin` views:
return qs.filter(author=request.user) return qs.filter(author=request.user)
.. versionchanged:: 1.6 .. versionchanged:: 1.6
The ``get_queryset`` method was previously named ``queryset``. The ``get_queryset`` method was previously named ``queryset``.
.. method:: ModelAdmin.message_user(request, message, level=messages.INFO, extra_tags='', fail_silently=False) .. method:: ModelAdmin.message_user(request, message, level=messages.INFO, extra_tags='', fail_silently=False)
@ -1348,7 +1377,9 @@ templates used by the :class:`ModelAdmin` views:
Sends a message to the user using the :mod:`django.contrib.messages` Sends a message to the user using the :mod:`django.contrib.messages`
backend. See the :ref:`custom ModelAdmin example <custom-admin-action>`. backend. See the :ref:`custom ModelAdmin example <custom-admin-action>`.
.. versionadded:: 1.5 .. versionchanged:: 1.5
Keyword arguments were added in Django 1.5.
Keyword arguments allow you to change the message level, add extra CSS Keyword arguments allow you to change the message level, add extra CSS
tags, or fail silently if the ``contrib.messages`` framework is not tags, or fail silently if the ``contrib.messages`` framework is not
@ -1451,6 +1482,7 @@ in your own admin JavaScript without including a second copy, you can use the
``django.jQuery`` object on changelist and add/edit views. ``django.jQuery`` object on changelist and add/edit views.
.. versionchanged:: 1.6 .. versionchanged:: 1.6
The embedded jQuery has been upgraded from 1.4.2 to 1.9.1. The embedded jQuery has been upgraded from 1.4.2 to 1.9.1.
The :class:`ModelAdmin` class requires jQuery by default, so there is no need The :class:`ModelAdmin` class requires jQuery by default, so there is no need
@ -1485,9 +1517,6 @@ needed. Now within your form you can add your own custom validation for
any field:: any field::
class MyArticleAdminForm(forms.ModelForm): class MyArticleAdminForm(forms.ModelForm):
class Meta:
model = Article
def clean_name(self): def clean_name(self):
# do something that validates your data # do something that validates your data
return self.cleaned_data["name"] return self.cleaned_data["name"]

View File

@ -950,6 +950,7 @@ __ http://geohash.org/
*Availability*: PostGIS, SpatiaLite *Availability*: PostGIS, SpatiaLite
.. versionchanged:: 1.5 .. versionchanged:: 1.5
``geojson`` support for Spatialite > 3.0 has been added. ``geojson`` support for Spatialite > 3.0 has been added.
Attaches a ``geojson`` attribute to every model in the queryset that contains the Attaches a ``geojson`` attribute to every model in the queryset that contains the

View File

@ -845,7 +845,7 @@ include the SRID value (in other words, EWKB).
.. class:: WKBWriter .. class:: WKBWriter
``WKBWriter`` provides the most control over its output. By default it ``WKBWriter`` provides the most control over its output. By default it
returns OGC-compliant WKB when it's ``write`` method is called. However, returns OGC-compliant WKB when its ``write`` method is called. However,
it has properties that allow for the creation of EWKB, a superset of the it has properties that allow for the creation of EWKB, a superset of the
WKB standard that includes additional information. WKB standard that includes additional information.

View File

@ -194,7 +194,7 @@ Configure, make and install::
.. note:: .. note::
Because GeoDjango has it's own Python interface, the preceding instructions Because GeoDjango has its own Python interface, the preceding instructions
do not build GDAL's own Python bindings. The bindings may be built by do not build GDAL's own Python bindings. The bindings may be built by
adding the ``--with-python`` flag when running ``configure``. See adding the ``--with-python`` flag when running ``configure``. See
`GDAL/OGR In Python`__ for more information on GDAL's bindings. `GDAL/OGR In Python`__ for more information on GDAL's bindings.

View File

@ -252,6 +252,7 @@ Enabling the sites framework
============================ ============================
.. versionchanged:: 1.6 .. versionchanged:: 1.6
In previous versions, the sites framework was enabled by default. In previous versions, the sites framework was enabled by default.
To enable the sites framework, follow these steps: To enable the sites framework, follow these steps:

View File

@ -22,14 +22,14 @@ Persistent connections
.. versionadded:: 1.6 .. versionadded:: 1.6
Persistent connections avoid the overhead of re-establishing a connection to Persistent connections avoid the overhead of re-establishing a connection to
the database in each request. By default, connections are kept open for up 10 the database in each request. They're controlled by the
minutes — if not specified, :setting:`CONN_MAX_AGE` defaults to 600 seconds. :setting:`CONN_MAX_AGE` parameter which defines the maximum lifetime of a
connection. It can be set independently for each database.
Django 1.5 and earlier didn't have persistent connections. To restore the The default value is ``0``, preserving the historical behavior of closing the
legacy behavior of closing the connection at the end of every request, set database connection at the end of each request. To enable persistent
:setting:`CONN_MAX_AGE` to ``0``. connections, set :setting:`CONN_MAX_AGE` to a positive number of seconds. For
unlimited persistent connections, set it to ``None``.
For unlimited persistent connections, set :setting:`CONN_MAX_AGE` to ``None``.
Connection management Connection management
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
@ -64,13 +64,22 @@ least as many simultaneous connections as you have worker threads.
Sometimes a database won't be accessed by the majority of your views, for Sometimes a database won't be accessed by the majority of your views, for
example because it's the database of an external system, or thanks to caching. example because it's the database of an external system, or thanks to caching.
In such cases, you should set :setting:`CONN_MAX_AGE` to a lower value, or In such cases, you should set :setting:`CONN_MAX_AGE` to a low value or even
even ``0``, because it doesn't make sense to maintain a connection that's ``0``, because it doesn't make sense to maintain a connection that's unlikely
unlikely to be reused. This will help keep the number of simultaneous to be reused. This will help keep the number of simultaneous connections to
connections to this database small. this database small.
The development server creates a new thread for each request it handles, The development server creates a new thread for each request it handles,
negating the effect of persistent connections. negating the effect of persistent connections. Don't enable them during
development.
When Django establishes a connection to the database, it sets up appropriate
parameters, depending on the backend being used. If you enable persistent
connections, this setup is no longer repeated every request. If you modify
parameters such as the connection's isolation level or time zone, you should
either restore Django's defaults at the end of each request, force an
appropriate value at the beginning of each request, or disable persistent
connections.
.. _postgresql-notes: .. _postgresql-notes:
@ -182,6 +191,7 @@ Django supports MySQL 5.0.3 and higher.
data on all database schema. Django's ``inspectdb`` feature uses it. data on all database schema. Django's ``inspectdb`` feature uses it.
.. versionchanged:: 1.5 .. versionchanged:: 1.5
The minimum version requirement of MySQL 5.0.3 was set in Django 1.5. The minimum version requirement of MySQL 5.0.3 was set in Django 1.5.
Django expects the database to support Unicode (UTF-8 encoding) and delegates to Django expects the database to support Unicode (UTF-8 encoding) and delegates to
@ -251,6 +261,18 @@ required for full MySQL support in Django.
.. _MySQLdb: http://sourceforge.net/projects/mysql-python .. _MySQLdb: http://sourceforge.net/projects/mysql-python
Python 3
--------
At the time of writing, the latest release of MySQLdb (1.2.4) doesn't support
Python 3. In order to use MySQL under Python 3, you'll have to install an
unofficial fork, such as `MySQL-for-Python-3`_.
This port is still in alpha. In particular, it doesn't support binary data,
making it impossible to use :class:`django.db.models.BinaryField`.
.. _MySQL-for-Python-3: https://github.com/clelland/MySQL-for-Python-3
Creating your database Creating your database
---------------------- ----------------------
@ -360,8 +382,8 @@ Here's a sample configuration which uses a MySQL option file::
default-character-set = utf8 default-character-set = utf8
Several other MySQLdb connection options may be useful, such as ``ssl``, Several other MySQLdb connection options may be useful, such as ``ssl``,
``use_unicode``, ``init_command``, and ``sql_mode``. Consult the ``init_command``, and ``sql_mode``. Consult the `MySQLdb documentation`_ for
`MySQLdb documentation`_ for more details. more details.
.. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html .. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html
.. _MySQLdb documentation: http://mysql-python.sourceforge.net/ .. _MySQLdb documentation: http://mysql-python.sourceforge.net/

View File

@ -98,6 +98,7 @@ Can be run as a cronjob or directly to clean out old data from the database
(only expired sessions at the moment). (only expired sessions at the moment).
.. versionchanged:: 1.5 .. versionchanged:: 1.5
:djadmin:`cleanup` is deprecated. Use :djadmin:`clearsessions` instead. :djadmin:`cleanup` is deprecated. Use :djadmin:`clearsessions` instead.
compilemessages compilemessages
@ -173,6 +174,7 @@ The :djadminopt:`--all` option may be provided to display all settings, even
if they have Django's default value. Such settings are prefixed by ``"###"``. if they have Django's default value. Such settings are prefixed by ``"###"``.
.. versionadded:: 1.6 .. versionadded:: 1.6
The :djadminopt:`--all` option was added. The :djadminopt:`--all` option was added.
dumpdata <appname appname appname.Model ...> dumpdata <appname appname appname.Model ...>
@ -778,8 +780,6 @@ use the ``--plain`` option, like so::
django-admin.py shell --plain django-admin.py shell --plain
.. versionchanged:: 1.5
If you would like to specify either IPython or bpython as your interpreter if If you would like to specify either IPython or bpython as your interpreter if
you have both installed you can specify an alternative interpreter interface you have both installed you can specify an alternative interpreter interface
with the ``-i`` or ``--interface`` options like so: with the ``-i`` or ``--interface`` options like so:
@ -807,6 +807,10 @@ behavior you can use the ``--no-startup`` option. e.g.::
django-admin.py shell --plain --no-startup django-admin.py shell --plain --no-startup
.. versionadded:: 1.5
The ``--interface`` option was added in Django 1.5.
.. versionadded:: 1.6 .. versionadded:: 1.6
The ``--no-startup`` option was added in Django 1.6. The ``--no-startup`` option was added in Django 1.6.
@ -1353,6 +1357,7 @@ for any other exception. If you specify ``--traceback``, ``django-admin.py``
will also output a full stack trace when a ``CommandError`` is raised. will also output a full stack trace when a ``CommandError`` is raised.
.. versionchanged:: 1.6 .. versionchanged:: 1.6
Previously, Django didn't show a full stack trace by default for exceptions Previously, Django didn't show a full stack trace by default for exceptions
other than ``CommandError``. other than ``CommandError``.

View File

@ -138,6 +138,7 @@ the underlying database exceptions. See :pep:`249`, the Python Database API
Specification v2.0, for further information. Specification v2.0, for further information.
.. versionchanged:: 1.6 .. versionchanged:: 1.6
Previous version of Django only wrapped ``DatabaseError`` and Previous version of Django only wrapped ``DatabaseError`` and
``IntegrityError``. ``IntegrityError``.

View File

@ -467,6 +467,11 @@ For each field, we describe the default widget used if you don't specify
The ``max_value`` and ``min_value`` error messages may contain The ``max_value`` and ``min_value`` error messages may contain
``%(limit_value)s``, which will be substituted by the appropriate limit. ``%(limit_value)s``, which will be substituted by the appropriate limit.
.. versionchanged:: 1.6
Similarly, the ``max_digits``, ``max_decimal_places`` and
``max_whole_digits`` error messages may contain ``%(max)s``.
Takes four optional arguments: Takes four optional arguments:
.. attribute:: max_value .. attribute:: max_value
@ -1010,9 +1015,16 @@ objects (in the case of ``ModelMultipleChoiceField``) into the
``invalid_pk_value`` ``invalid_pk_value``
.. versionchanged:: 1.5 .. versionchanged:: 1.5
The empty and normalized values were changed to be consistently The empty and normalized values were changed to be consistently
``QuerySets`` instead of ``[]`` and ``QuerySet`` respectively. ``QuerySets`` instead of ``[]`` and ``QuerySet`` respectively.
.. versionchanged:: 1.6
The ``invalid_choice`` message may contain ``%(value)s`` and the
``invalid_pk_value`` message may contain ``%(pk)s``, which will be
substituted by the appropriate values.
Allows the selection of one or more model objects, suitable for Allows the selection of one or more model objects, suitable for
representing a many-to-many relation. As with :class:`ModelChoiceField`, representing a many-to-many relation. As with :class:`ModelChoiceField`,
you can use ``label_from_instance`` to customize the object you can use ``label_from_instance`` to customize the object

View File

@ -25,6 +25,14 @@ Model Form Functions
See :ref:`modelforms-factory` for example usage. See :ref:`modelforms-factory` for example usage.
.. versionchanged:: 1.6
You must provide the list of fields explicitly, either via keyword arguments
``fields`` or ``exclude``, or the corresponding attributes on the form's
inner ``Meta`` class. See :ref:`modelforms-selecting-fields` for more
information. Omitting any definition of the fields to use will result in all
fields being used, but this behaviour is deprecated.
.. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False) .. function:: modelformset_factory(model, form=ModelForm, formfield_callback=None, formset=BaseModelFormSet, extra=1, can_delete=False, can_order=False, max_num=None, fields=None, exclude=None, widgets=None, validate_max=False)
Returns a ``FormSet`` class for the given ``model`` class. Returns a ``FormSet`` class for the given ``model`` class.

View File

@ -522,6 +522,7 @@ Selector and checkbox widgets
``True`` if the checkbox should be checked for that value. ``True`` if the checkbox should be checked for that value.
.. versionchanged:: 1.5 .. versionchanged:: 1.5
Exceptions from ``check_test`` used to be silenced by its caller, Exceptions from ``check_test`` used to be silenced by its caller,
this is no longer the case, they will propagate upwards. this is no longer the case, they will propagate upwards.

Some files were not shown because too many files have changed in this diff Show More