mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
unicode: Merged from trunk up to [5308].
git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5310 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
f1091ec619
commit
6f23be4ee9
5
AUTHORS
5
AUTHORS
@ -41,7 +41,6 @@ And here is an inevitably incomplete list of MUCH-APPRECIATED CONTRIBUTORS --
|
|||||||
people who have submitted patches, reported bugs, added translations, helped
|
people who have submitted patches, reported bugs, added translations, helped
|
||||||
answer newbie questions, and generally made Django that much better:
|
answer newbie questions, and generally made Django that much better:
|
||||||
|
|
||||||
adurdin@gmail.com
|
|
||||||
alang@bright-green.com
|
alang@bright-green.com
|
||||||
Marty Alchin <gulopine@gamemusic.org>
|
Marty Alchin <gulopine@gamemusic.org>
|
||||||
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
|
Daniel Alves Barbosa de Oliveira Vaz <danielvaz@gmail.com>
|
||||||
@ -90,6 +89,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
dne@mayonnaise.net
|
dne@mayonnaise.net
|
||||||
Maximillian Dornseif <md@hudora.de>
|
Maximillian Dornseif <md@hudora.de>
|
||||||
Jeremy Dunck <http://dunck.us/>
|
Jeremy Dunck <http://dunck.us/>
|
||||||
|
Andrew Durdin <adurdin@gmail.com>
|
||||||
Andy Dustman <farcepest@gmail.com>
|
Andy Dustman <farcepest@gmail.com>
|
||||||
Clint Ecker
|
Clint Ecker
|
||||||
enlight
|
enlight
|
||||||
@ -192,7 +192,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
polpak@yahoo.com
|
polpak@yahoo.com
|
||||||
J. Rademaker
|
J. Rademaker
|
||||||
Michael Radziej <mir@noris.de>
|
Michael Radziej <mir@noris.de>
|
||||||
ramiro
|
Ramiro Morales <rm0@gmx.net>
|
||||||
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
|
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
|
||||||
Brian Ray <http://brianray.chipy.org/>
|
Brian Ray <http://brianray.chipy.org/>
|
||||||
remco@diji.biz
|
remco@diji.biz
|
||||||
@ -211,6 +211,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
sopel
|
sopel
|
||||||
Wiliam Alves de Souza <wiliamsouza83@gmail.com>
|
Wiliam Alves de Souza <wiliamsouza83@gmail.com>
|
||||||
Georgi Stanojevski <glisha@gmail.com>
|
Georgi Stanojevski <glisha@gmail.com>
|
||||||
|
Vasiliy Stavenko <stavenko@gmail.com>
|
||||||
Thomas Steinacher <http://www.eggdrop.ch/>
|
Thomas Steinacher <http://www.eggdrop.ch/>
|
||||||
nowell strite
|
nowell strite
|
||||||
Radek Švarz <http://www.svarz.cz/translate/>
|
Radek Švarz <http://www.svarz.cz/translate/>
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -3,20 +3,19 @@
|
|||||||
# Copyright (C)
|
# Copyright (C)
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
#
|
#
|
||||||
# Jorge Gajon <gajon@gajon.org>, 2005.
|
|
||||||
# Marc Fargas <marc@fargas.com>, 2007.
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: djangojs\n"
|
"Project-Id-Version: djangojs\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2007-02-15 11:05+1100\n"
|
"POT-Creation-Date: 2007-05-20 18:25+0200\n"
|
||||||
"PO-Revision-Date: 2007-01-19 10:30+0100\n"
|
"PO-Revision-Date: 2007-05-20 18:24+0200\n"
|
||||||
"Last-Translator: Marc Fargas <marc@fargas.com>\n"
|
"Last-Translator: Marc Fargas <marc@fargas.com>\n"
|
||||||
"Language-Team: <es@li.org>\n"
|
"Language-Team: <es@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=ISO-8859-1\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: KBabel 1.11.4\n"
|
"X-Generator: VIM 7.0\n"
|
||||||
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:33
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
#, perl-format
|
#, perl-format
|
||||||
@ -54,7 +53,7 @@ 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 ""
|
||||||
"Febrer Març Abril Maig Juny Juliol Agost Setembre Octubre Novembre Desembre"
|
"Febrer Març Abril Maig Juny Juliol Agost Setembre Octubre Novembre Desembre"
|
||||||
|
|
||||||
#: contrib/admin/media/js/dateparse.js:33
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
@ -92,7 +91,7 @@ msgstr "Migdia"
|
|||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Cancel·lar"
|
msgstr "Cancel·lar"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
@ -109,7 +108,7 @@ msgstr "Ahir"
|
|||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
msgid "Tomorrow"
|
msgid "Tomorrow"
|
||||||
msgstr "Demà"
|
msgstr "Demà"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -2,19 +2,19 @@
|
|||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
#
|
#
|
||||||
# pavithran <pavithran.s@gmail.com>, 2007.
|
|
||||||
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: 2006-09-25 15:43+0200\n"
|
"POT-Creation-Date: 2006-09-25 15:43+0200\n"
|
||||||
"PO-Revision-Date: 2007-02-28 18:35+0530\n"
|
"PO-Revision-Date: 2007-05-19 12:44+0530\n"
|
||||||
"Last-Translator: pavithran <pavithran.s@gmail.com>\n"
|
"Last-Translator: pavithran <pavithran.s@gmail.com>\n"
|
||||||
"Language-Team: Telugu <indlinux-telugu@lists.sourceforge.net>\n"
|
"Language-Team: Telugu <indlinux-telugu@lists.sourceforge.net>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: KBabel 1.11.4\n"
|
"X-Generator: KBabel 1.11.4\n"
|
||||||
|
"Plural-Forms: nplurals=2; nplurals=n>1;"
|
||||||
|
|
||||||
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
||||||
msgid "object ID"
|
msgid "object ID"
|
||||||
@ -144,7 +144,7 @@ msgstr "కర్మ స్కొరులు"
|
|||||||
#: contrib/comments/models.py:242
|
#: contrib/comments/models.py:242
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(score)d rating by %(user)s"
|
msgid "%(score)d rating by %(user)s"
|
||||||
msgstr "%(user) రేటింగ్"
|
msgstr "%(score)d కి %(user)s రేటింగ్"
|
||||||
|
|
||||||
#: contrib/comments/models.py:258
|
#: contrib/comments/models.py:258
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -153,9 +153,9 @@ msgid ""
|
|||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"%(user)s చేత చేయబడ్డ వ్యాఖ్యానములు"
|
"%(user)s చేత చేయబడ్డ వ్యాఖ్యానములు:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)లు"
|
"%(text)s"
|
||||||
|
|
||||||
#: contrib/comments/models.py:265
|
#: contrib/comments/models.py:265
|
||||||
msgid "flag date"
|
msgid "flag date"
|
||||||
@ -220,12 +220,12 @@ msgid_plural ""
|
|||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
"ఈ వ్యాఖ్యానము చేసిన యూజర్ %(count)లు కన్న తక్కువ సమర్పించాడు "
|
"ఈ వ్యాఖ్యానము చేసిన యూజర్ %(count)s లు కన్న తక్కువ సమర్పించాడు "
|
||||||
"వ్యాఖ్యానము:\n"
|
"వ్యాఖ్యానము:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
"ఈ వ్యాఖ్యానము చేసిన యూజర్ %(count)లు కన్న తక్కువ సమర్పించాడు"
|
"ఈ వ్యాఖ్యానము చేసిన యూజర్ %(count)s లు కన్న తక్కువ సమర్పించాడు"
|
||||||
"వ్యాఖ్యానములు:\n"
|
"వ్యాఖ్యానములు:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
@ -343,7 +343,8 @@ msgstr "మీ పేరు"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"<h3>By %s:</h3>\n"
|
"<h3>By %s:</h3>\n"
|
||||||
"<ul>\n"
|
"<ul>\n"
|
||||||
msgstr "<h3> %s తో:</h3>\n"
|
msgstr ""
|
||||||
|
"<h3> %s తో:</h3>\n"
|
||||||
"<ul>\n"
|
"<ul>\n"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
|
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
|
||||||
@ -513,17 +514,17 @@ msgstr "%s ని మార్చంది"
|
|||||||
#: contrib/admin/views/main.py:473
|
#: contrib/admin/views/main.py:473
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
|
msgid "One or more %(fieldname)s in %(name)s: %(obj)s"
|
||||||
msgstr "ఒకటి కాని ,అంత కన్నఎక్కువ %(name)లు లో %(fieldname)లు : %(obj)లు "
|
msgstr "ఒకటి కాని ,అంత కన్నఎక్కువ %(name)s లో %(fieldname)s : %(obj)s "
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:478
|
#: contrib/admin/views/main.py:478
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "One or more %(fieldname)s in %(name)s:"
|
msgid "One or more %(fieldname)s in %(name)s:"
|
||||||
msgstr "ఒకటి కాని ,అంత కన్నఎక్కువ %(name)లు లో %(fieldname)లు"
|
msgstr "ఒకటి కాని ,అంత కన్నఎక్కువ %(name)s లో %(fieldname)s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:511
|
#: contrib/admin/views/main.py:511
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
||||||
msgstr "%(name)లు \"%(obj)s\"జయప్రదంగా తీసివేయబడ్డడి"
|
msgstr "%(name)s \"%(obj)s\"జయప్రదంగా తీసివేయబడ్డడి"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:514
|
#: contrib/admin/views/main.py:514
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
@ -532,7 +533,7 @@ msgstr "మీరు కచ్చితంగా ఉన్నారా?"
|
|||||||
#: contrib/admin/views/main.py:536
|
#: contrib/admin/views/main.py:536
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change history: %s"
|
msgid "Change history: %s"
|
||||||
msgstr "మార్చబడిన పురాణము"
|
msgstr "మార్చబడిన పురాణము: %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:570
|
#: contrib/admin/views/main.py:570
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -796,12 +797,12 @@ msgstr "క్షమించండి మీరు కోరిన పేజి
|
|||||||
#: contrib/admin/templates/admin/index.html:17
|
#: contrib/admin/templates/admin/index.html:17
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Models available in the %(name)s application."
|
msgid "Models available in the %(name)s application."
|
||||||
msgstr "మొడల్ లు %(name)లో దొరికే అప్ప్లికేషన్"
|
msgstr "మొడల్ లు %(name)s లో దొరికే అప్ప్లికేషన్"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:18
|
#: contrib/admin/templates/admin/index.html:18
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(name)s"
|
msgid "%(name)s"
|
||||||
msgstr "%(name)లు"
|
msgstr "%(name)s"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:28
|
#: contrib/admin/templates/admin/index.html:28
|
||||||
#: contrib/admin/templates/admin/change_form.html:15
|
#: contrib/admin/templates/admin/change_form.html:15
|
||||||
@ -831,7 +832,7 @@ msgstr "ఏమి దొరకలేదు"
|
|||||||
#: contrib/admin/templates/admin/change_list.html:11
|
#: contrib/admin/templates/admin/change_list.html:11
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Add %(name)s"
|
msgid "Add %(name)s"
|
||||||
msgstr "%(name)లు జత చేయు"
|
msgstr "%(name)s జత చేయు"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/login.html:22
|
#: contrib/admin/templates/admin/login.html:22
|
||||||
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
|
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
|
||||||
@ -1794,7 +1795,7 @@ msgstr "సంవత్సరము 1900 లేక దాని తరువా
|
|||||||
#: core/validators.py:142
|
#: core/validators.py:142
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Invalid date: %s."
|
msgid "Invalid date: %s."
|
||||||
msgstr "సరికాని తారీఖు"
|
msgstr "సరికాని తారీఖు : %s."
|
||||||
|
|
||||||
#: core/validators.py:146 db/models/fields/__init__.py:415
|
#: core/validators.py:146 db/models/fields/__init__.py:415
|
||||||
msgid "Enter a valid date in YYYY-MM-DD format."
|
msgid "Enter a valid date in YYYY-MM-DD format."
|
||||||
@ -1846,8 +1847,10 @@ msgstr "సరైన URL కావాలి"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Valid HTML is required. Specific errors are:\n"
|
"Valid HTML is required. Specific errors are:\n"
|
||||||
"%s"
|
"%s"
|
||||||
msgstr "సరైన HTML ఇవ్వండి .ప్రత్యేకమైన తప్పులు :\n"
|
msgstr ""
|
||||||
|
"సరైన HTML ఇవ్వండి .ప్రత్యేకమైన తప్పులు :\n"
|
||||||
"%s"
|
"%s"
|
||||||
|
|
||||||
#: core/validators.py:220
|
#: core/validators.py:220
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Badly formed XML: %s"
|
msgid "Badly formed XML: %s"
|
||||||
@ -1856,7 +1859,7 @@ msgstr ""
|
|||||||
#: core/validators.py:230
|
#: core/validators.py:230
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Invalid URL: %s"
|
msgid "Invalid URL: %s"
|
||||||
msgstr ""
|
msgstr "సరికాని URL: %s"
|
||||||
|
|
||||||
#: core/validators.py:234 core/validators.py:236
|
#: core/validators.py:234 core/validators.py:236
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -2004,27 +2007,27 @@ msgstr ""
|
|||||||
#: views/generic/create_update.py:43
|
#: views/generic/create_update.py:43
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(verbose_name)s was created successfully."
|
msgid "The %(verbose_name)s was created successfully."
|
||||||
msgstr "%(verbose_name)లు జయప్రదంగా తయారయింది"
|
msgstr "%(verbose_name)s జయప్రదంగా తయారయింది"
|
||||||
|
|
||||||
#: views/generic/create_update.py:117
|
#: views/generic/create_update.py:117
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(verbose_name)s was updated successfully."
|
msgid "The %(verbose_name)s was updated successfully."
|
||||||
msgstr "%(verbose_name)లు జయప్రదంగా @@"
|
msgstr "%(verbose_name)s జయప్రదంగా @@"
|
||||||
|
|
||||||
#: views/generic/create_update.py:184
|
#: views/generic/create_update.py:184
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(verbose_name)s was deleted."
|
msgid "The %(verbose_name)s was deleted."
|
||||||
msgstr "%(verbose_name)లు తీసివేయబడినది"
|
msgstr "%(verbose_name)s తీసివేయబడినది"
|
||||||
|
|
||||||
#: db/models/manipulators.py:302
|
#: db/models/manipulators.py:302
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
|
msgid "%(object)s with this %(type)s already exists for the given %(field)s."
|
||||||
msgstr "%(field)ల లో %(object)తో %(type) ఉన్నాయి"
|
msgstr "%(field)s లో %(object)s తో %(type)s ఉన్నాయి"
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:40
|
#: db/models/fields/__init__.py:40
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(optname)s with this %(fieldname)s already exists."
|
msgid "%(optname)s with this %(fieldname)s already exists."
|
||||||
msgstr "%(optname)లు తో %(fieldname) ముందే ఉన్నాయి ."
|
msgstr "%(optname)s తో %(fieldname)s ముందే ఉన్నాయి ."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
|
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
|
||||||
#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562
|
#: db/models/fields/__init__.py:551 db/models/fields/__init__.py:562
|
||||||
@ -2082,7 +2085,7 @@ msgstr "లైన్ బ్రేక్స్ కి ఇక్కడ ఆన
|
|||||||
#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599
|
#: forms/__init__.py:487 forms/__init__.py:560 forms/__init__.py:599
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
|
msgid "Select a valid choice; '%(data)s' is not in %(choices)s."
|
||||||
msgstr "సరైనది ఎంచుకోండి; %(choices) ల లో '%(data)s' లేవు "
|
msgstr "సరైనది ఎంచుకోండి; %(choices)s లో '%(data)s' లేవు "
|
||||||
|
|
||||||
#: forms/__init__.py:663
|
#: forms/__init__.py:663
|
||||||
msgid "The submitted file is empty."
|
msgid "The submitted file is empty."
|
||||||
|
@ -169,8 +169,8 @@ def items_for_result(cl, result):
|
|||||||
# Booleans are special: We use images.
|
# Booleans are special: We use images.
|
||||||
elif isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField):
|
elif isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField):
|
||||||
result_repr = _boolean_icon(field_val)
|
result_repr = _boolean_icon(field_val)
|
||||||
# FloatFields are special: Zero-pad the decimals.
|
# DecimalFields are special: Zero-pad the decimals.
|
||||||
elif isinstance(f, models.FloatField):
|
elif isinstance(f, models.DecimalField):
|
||||||
if field_val is not None:
|
if field_val is not None:
|
||||||
result_repr = ('%%.%sf' % f.decimal_places) % field_val
|
result_repr = ('%%.%sf' % f.decimal_places) % field_val
|
||||||
else:
|
else:
|
||||||
|
@ -295,10 +295,11 @@ DATA_TYPE_MAPPING = {
|
|||||||
'CommaSeparatedIntegerField': _('Comma-separated integers'),
|
'CommaSeparatedIntegerField': _('Comma-separated integers'),
|
||||||
'DateField' : _('Date (without time)'),
|
'DateField' : _('Date (without time)'),
|
||||||
'DateTimeField' : _('Date (with time)'),
|
'DateTimeField' : _('Date (with time)'),
|
||||||
|
'DecimalField' : _('Decimal number'),
|
||||||
'EmailField' : _('E-mail address'),
|
'EmailField' : _('E-mail address'),
|
||||||
'FileField' : _('File path'),
|
'FileField' : _('File path'),
|
||||||
'FilePathField' : _('File path'),
|
'FilePathField' : _('File path'),
|
||||||
'FloatField' : _('Decimal number'),
|
'FloatField' : _('Floating point number'),
|
||||||
'ForeignKey' : _('Integer'),
|
'ForeignKey' : _('Integer'),
|
||||||
'ImageField' : _('File path'),
|
'ImageField' : _('File path'),
|
||||||
'IntegerField' : _('Integer'),
|
'IntegerField' : _('Integer'),
|
||||||
|
@ -83,7 +83,7 @@ class FormPreview(object):
|
|||||||
"""
|
"""
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
try:
|
||||||
f = self.form.fields[name]
|
f = self.form.base_fields[name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
break # This field name isn't being used by the form.
|
break # This field name isn't being used by the form.
|
||||||
name += '_'
|
name += '_'
|
||||||
|
@ -36,6 +36,9 @@ class SessionWrapper(object):
|
|||||||
def get(self, key, default=None):
|
def get(self, key, default=None):
|
||||||
return self._session.get(key, default)
|
return self._session.get(key, default)
|
||||||
|
|
||||||
|
def pop(self, key, *args):
|
||||||
|
return self._session.pop(key, *args)
|
||||||
|
|
||||||
def set_test_cookie(self):
|
def set_test_cookie(self):
|
||||||
self[TEST_COOKIE_NAME] = TEST_COOKIE_VALUE
|
self[TEST_COOKIE_NAME] = TEST_COOKIE_VALUE
|
||||||
|
|
||||||
|
19
django/contrib/sessions/tests.py
Normal file
19
django/contrib/sessions/tests.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
r"""
|
||||||
|
>>> s = SessionWrapper(None)
|
||||||
|
|
||||||
|
Inject data into the session cache.
|
||||||
|
>>> s._session_cache = {}
|
||||||
|
>>> s._session_cache['some key'] = 'exists'
|
||||||
|
|
||||||
|
>>> s.pop('some key')
|
||||||
|
'exists'
|
||||||
|
|
||||||
|
>>> s.pop('some key', 'does not exist')
|
||||||
|
'does not exist'
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.contrib.sessions.middleware import SessionWrapper
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import doctest
|
||||||
|
doctest.testmod()
|
@ -1,7 +1,7 @@
|
|||||||
from django.core import urlresolvers
|
from django.core import urlresolvers
|
||||||
import urllib
|
import urllib
|
||||||
|
|
||||||
PING_URL = "http://www.google.com/webmasters/sitemaps/ping"
|
PING_URL = "http://www.google.com/webmasters/tools/ping"
|
||||||
|
|
||||||
class SitemapNotFound(Exception):
|
class SitemapNotFound(Exception):
|
||||||
pass
|
pass
|
||||||
@ -29,7 +29,7 @@ def ping_google(sitemap_url=None, ping_url=PING_URL):
|
|||||||
|
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
current_site = Site.objects.get_current()
|
current_site = Site.objects.get_current()
|
||||||
url = "%s%s" % (current_site.domain, sitemap_url)
|
url = "http://%s%s" % (current_site.domain, sitemap_url)
|
||||||
params = urllib.urlencode({'sitemap':url})
|
params = urllib.urlencode({'sitemap':url})
|
||||||
urllib.urlopen("%s?%s" % (ping_url, params))
|
urllib.urlopen("%s?%s" % (ping_url, params))
|
||||||
|
|
||||||
|
17
django/contrib/webdesign/tests.py
Normal file
17
django/contrib/webdesign/tests.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
r"""
|
||||||
|
>>> words(7)
|
||||||
|
u'lorem ipsum dolor sit amet consectetur adipisicing'
|
||||||
|
|
||||||
|
>>> paragraphs(1)
|
||||||
|
['Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.']
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.contrib.webdesign.lorem_ipsum import *
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
import doctest
|
||||||
|
doctest.testmod()
|
@ -870,7 +870,7 @@ def inspectdb():
|
|||||||
if field_type == 'CharField' and row[3]:
|
if field_type == 'CharField' and row[3]:
|
||||||
extra_params['maxlength'] = row[3]
|
extra_params['maxlength'] = row[3]
|
||||||
|
|
||||||
if field_type == 'FloatField':
|
if field_type == 'DecimalField':
|
||||||
extra_params['max_digits'] = row[4]
|
extra_params['max_digits'] = row[4]
|
||||||
extra_params['decimal_places'] = row[5]
|
extra_params['decimal_places'] = row[5]
|
||||||
|
|
||||||
@ -945,11 +945,11 @@ def get_validation_errors(outfile, app=None):
|
|||||||
e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name)
|
e.add(opts, '"%s": You can\'t use "id" as a field name, because each model automatically gets an "id" field if none of the fields have primary_key=True. You need to either remove/rename your "id" field or add primary_key=True to a field.' % f.name)
|
||||||
if isinstance(f, models.CharField) and f.maxlength in (None, 0):
|
if isinstance(f, models.CharField) and f.maxlength in (None, 0):
|
||||||
e.add(opts, '"%s": CharFields require a "maxlength" attribute.' % f.name)
|
e.add(opts, '"%s": CharFields require a "maxlength" attribute.' % f.name)
|
||||||
if isinstance(f, models.FloatField):
|
if isinstance(f, models.DecimalField):
|
||||||
if f.decimal_places is None:
|
if f.decimal_places is None:
|
||||||
e.add(opts, '"%s": FloatFields require a "decimal_places" attribute.' % f.name)
|
e.add(opts, '"%s": DecimalFields require a "decimal_places" attribute.' % f.name)
|
||||||
if f.max_digits is None:
|
if f.max_digits is None:
|
||||||
e.add(opts, '"%s": FloatFields require a "max_digits" attribute.' % f.name)
|
e.add(opts, '"%s": DecimalFields require a "max_digits" attribute.' % f.name)
|
||||||
if isinstance(f, models.FileField) and not f.upload_to:
|
if isinstance(f, models.FileField) and not f.upload_to:
|
||||||
e.add(opts, '"%s": FileFields require an "upload_to" attribute.' % f.name)
|
e.add(opts, '"%s": FileFields require an "upload_to" attribute.' % f.name)
|
||||||
if isinstance(f, models.ImageField):
|
if isinstance(f, models.ImageField):
|
||||||
|
@ -4,19 +4,24 @@ Serialize data to/from JSON
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
from django.utils import simplejson
|
from django.utils import simplejson
|
||||||
|
from django.utils.simplejson import decoder
|
||||||
from django.core.serializers.python import Serializer as PythonSerializer
|
from django.core.serializers.python import Serializer as PythonSerializer
|
||||||
from django.core.serializers.python import Deserializer as PythonDeserializer
|
from django.core.serializers.python import Deserializer as PythonDeserializer
|
||||||
try:
|
try:
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from StringIO import StringIO
|
from StringIO import StringIO
|
||||||
|
try:
|
||||||
|
import decimal
|
||||||
|
except ImportError:
|
||||||
|
from django.utils import _decimal as decimal # Python 2.3 fallback
|
||||||
|
|
||||||
class Serializer(PythonSerializer):
|
class Serializer(PythonSerializer):
|
||||||
"""
|
"""
|
||||||
Convert a queryset to JSON.
|
Convert a queryset to JSON.
|
||||||
"""
|
"""
|
||||||
def end_serialization(self):
|
def end_serialization(self):
|
||||||
simplejson.dump(self.objects, self.stream, cls=DateTimeAwareJSONEncoder, **self.options)
|
simplejson.dump(self.objects, self.stream, cls=DjangoJSONEncoder, **self.options)
|
||||||
|
|
||||||
def getvalue(self):
|
def getvalue(self):
|
||||||
if callable(getattr(self.stream, 'getvalue', None)):
|
if callable(getattr(self.stream, 'getvalue', None)):
|
||||||
@ -30,12 +35,13 @@ def Deserializer(stream_or_string, **options):
|
|||||||
stream = StringIO(stream_or_string)
|
stream = StringIO(stream_or_string)
|
||||||
else:
|
else:
|
||||||
stream = stream_or_string
|
stream = stream_or_string
|
||||||
|
#for obj in PythonDeserializer(simplejson.load(stream, cls=DjangoJSONDecoder)):
|
||||||
for obj in PythonDeserializer(simplejson.load(stream)):
|
for obj in PythonDeserializer(simplejson.load(stream)):
|
||||||
yield obj
|
yield obj
|
||||||
|
|
||||||
class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
|
class DjangoJSONEncoder(simplejson.JSONEncoder):
|
||||||
"""
|
"""
|
||||||
JSONEncoder subclass that knows how to encode date/time types
|
JSONEncoder subclass that knows how to encode date/time and decimal types.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DATE_FORMAT = "%Y-%m-%d"
|
DATE_FORMAT = "%Y-%m-%d"
|
||||||
@ -48,5 +54,33 @@ class DateTimeAwareJSONEncoder(simplejson.JSONEncoder):
|
|||||||
return o.strftime(self.DATE_FORMAT)
|
return o.strftime(self.DATE_FORMAT)
|
||||||
elif isinstance(o, datetime.time):
|
elif isinstance(o, datetime.time):
|
||||||
return o.strftime(self.TIME_FORMAT)
|
return o.strftime(self.TIME_FORMAT)
|
||||||
|
elif isinstance(o, decimal.Decimal):
|
||||||
|
return str(o)
|
||||||
else:
|
else:
|
||||||
return super(DateTimeAwareJSONEncoder, self).default(o)
|
return super(DjangoJSONEncoder, self).default(o)
|
||||||
|
|
||||||
|
# Older, deprecated class name (for backwards compatibility purposes).
|
||||||
|
DateTimeAwareJSONEncoder = DjangoJSONEncoder
|
||||||
|
|
||||||
|
## Our override for simplejson.JSONNumber, because we want to use decimals in
|
||||||
|
## preference to floats (we can convert decimal -> float when they stored, if
|
||||||
|
## needed, but cannot go the other way).
|
||||||
|
#def DjangoNumber(match, context):
|
||||||
|
# match = DjangoNumber.regex.match(match.string, *match.span())
|
||||||
|
# integer, frac, exp = match.groups()
|
||||||
|
# if exp:
|
||||||
|
# res = float(integer + (frac or '') + (exp or ''))
|
||||||
|
# elif frac:
|
||||||
|
# res = decimal.Decimal(integer + frac)
|
||||||
|
# else:
|
||||||
|
# res = int(integer)
|
||||||
|
# return res, None
|
||||||
|
#decoder.pattern(r'(-?(?:0|[1-9]\d*))(\.\d+)?([eE][-+]?\d+)?')(DjangoNumber)
|
||||||
|
#
|
||||||
|
#converters = decoder.ANYTHING[:]
|
||||||
|
#converters[-1] = DjangoNumber
|
||||||
|
#decoder.JSONScanner = decoder.Scanner(converters)
|
||||||
|
#
|
||||||
|
#class DjangoJSONDecoder(simplejson.JSONDecoder):
|
||||||
|
# _scanner = decoder.Scanner(converters)
|
||||||
|
#
|
||||||
|
@ -25,6 +25,7 @@ email_re = re.compile(
|
|||||||
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
|
r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
|
||||||
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
|
r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
|
||||||
r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain
|
r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE) # domain
|
||||||
|
decimal_re = re.compile(r'^-?(?P<digits>\d+)(\.(?P<decimals>\d+))?$')
|
||||||
integer_re = re.compile(r'^-?\d+$')
|
integer_re = re.compile(r'^-?\d+$')
|
||||||
ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
|
ip4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
|
||||||
phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)
|
phone_re = re.compile(r'^[A-PR-Y0-9]{3}-[A-PR-Y0-9]{3}-[A-PR-Y0-9]{4}$', re.IGNORECASE)
|
||||||
@ -406,28 +407,35 @@ class IsAPowerOf(object):
|
|||||||
if val != int(val):
|
if val != int(val):
|
||||||
raise ValidationError, _("This value must be a power of %s.") % self.power_of
|
raise ValidationError, _("This value must be a power of %s.") % self.power_of
|
||||||
|
|
||||||
class IsValidFloat(object):
|
class IsValidDecimal(object):
|
||||||
def __init__(self, max_digits, decimal_places):
|
def __init__(self, max_digits, decimal_places):
|
||||||
self.max_digits, self.decimal_places = max_digits, decimal_places
|
self.max_digits, self.decimal_places = max_digits, decimal_places
|
||||||
|
|
||||||
def __call__(self, field_data, all_data):
|
def __call__(self, field_data, all_data):
|
||||||
data = str(field_data)
|
match = decimal_re.search(str(field_data))
|
||||||
try:
|
if not match:
|
||||||
float(data)
|
|
||||||
except ValueError:
|
|
||||||
raise ValidationError, _("Please enter a valid decimal number.")
|
raise ValidationError, _("Please enter a valid decimal number.")
|
||||||
# Negative floats require more space to input.
|
|
||||||
max_allowed_length = data.startswith('-') and (self.max_digits + 2) or (self.max_digits + 1)
|
digits = len(match.group('digits') or '')
|
||||||
if len(data) > max_allowed_length:
|
decimals = len(match.group('decimals') or '')
|
||||||
|
|
||||||
|
if digits + decimals > self.max_digits:
|
||||||
raise ValidationError, ungettext("Please enter a valid decimal number with at most %s total digit.",
|
raise ValidationError, ungettext("Please enter a valid decimal number with at most %s total digit.",
|
||||||
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
|
"Please enter a valid decimal number with at most %s total digits.", self.max_digits) % self.max_digits
|
||||||
if (not '.' in data and len(data) > (max_allowed_length - self.decimal_places - 1)) or ('.' in data and len(data) > (max_allowed_length - (self.decimal_places - len(data.split('.')[1])))):
|
if digits > (self.max_digits - self.decimal_places):
|
||||||
raise ValidationError, ungettext( "Please enter a valid decimal number with a whole part of at most %s digit.",
|
raise ValidationError, ungettext( "Please enter a valid decimal number with a whole part of at most %s digit.",
|
||||||
"Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places)
|
"Please enter a valid decimal number with a whole part of at most %s digits.", str(self.max_digits-self.decimal_places)) % str(self.max_digits-self.decimal_places)
|
||||||
if '.' in data and len(data.split('.')[1]) > self.decimal_places:
|
if decimals > self.decimal_places:
|
||||||
raise ValidationError, ungettext("Please enter a valid decimal number with at most %s decimal place.",
|
raise ValidationError, ungettext("Please enter a valid decimal number with at most %s decimal place.",
|
||||||
"Please enter a valid decimal number with at most %s decimal places.", self.decimal_places) % self.decimal_places
|
"Please enter a valid decimal number with at most %s decimal places.", self.decimal_places) % self.decimal_places
|
||||||
|
|
||||||
|
def isValidFloat(field_data, all_data):
|
||||||
|
data = str(field_data)
|
||||||
|
try:
|
||||||
|
float(data)
|
||||||
|
except ValueError:
|
||||||
|
raise ValidationError, gettext("Please enter a valid floating point number.")
|
||||||
|
|
||||||
class HasAllowableSize(object):
|
class HasAllowableSize(object):
|
||||||
"""
|
"""
|
||||||
Checks that the file-upload field data is a certain size. min_size and
|
Checks that the file-upload field data is a certain size. min_size and
|
||||||
|
@ -5,9 +5,10 @@ DATA_TYPES = {
|
|||||||
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
||||||
'DateField': 'smalldatetime',
|
'DateField': 'smalldatetime',
|
||||||
'DateTimeField': 'smalldatetime',
|
'DateTimeField': 'smalldatetime',
|
||||||
|
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
||||||
'FileField': 'varchar(100)',
|
'FileField': 'varchar(100)',
|
||||||
'FilePathField': 'varchar(100)',
|
'FilePathField': 'varchar(100)',
|
||||||
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
'FloatField': 'double precision',
|
||||||
'ImageField': 'varchar(100)',
|
'ImageField': 'varchar(100)',
|
||||||
'IntegerField': 'int',
|
'IntegerField': 'int',
|
||||||
'IPAddressField': 'char(15)',
|
'IPAddressField': 'char(15)',
|
||||||
|
@ -15,7 +15,7 @@ except ImportError, e:
|
|||||||
# lexicographic ordering in this check because then (1, 2, 1, 'gamma')
|
# lexicographic ordering in this check because then (1, 2, 1, 'gamma')
|
||||||
# inadvertently passes the version test.
|
# inadvertently passes the version test.
|
||||||
version = Database.version_info
|
version = Database.version_info
|
||||||
if (version < (1,2,1) or (version[:3] == (1, 2, 1) and
|
if (version < (1,2,1) or (version[:3] == (1, 2, 1) and
|
||||||
(len(version) < 5 or version[3] != 'final' or version[4] < 2))):
|
(len(version) < 5 or version[3] != 'final' or version[4] < 2))):
|
||||||
raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__
|
raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__
|
||||||
|
|
||||||
@ -36,6 +36,8 @@ IntegrityError = Database.IntegrityError
|
|||||||
django_conversions = conversions.copy()
|
django_conversions = conversions.copy()
|
||||||
django_conversions.update({
|
django_conversions.update({
|
||||||
FIELD_TYPE.TIME: util.typecast_time,
|
FIELD_TYPE.TIME: util.typecast_time,
|
||||||
|
FIELD_TYPE.DECIMAL: util.typecast_decimal,
|
||||||
|
FIELD_TYPE.NEWDECIMAL: util.typecast_decimal,
|
||||||
})
|
})
|
||||||
|
|
||||||
# This should match the numerical portion of the version numbers (we can treat
|
# This should match the numerical portion of the version numbers (we can treat
|
||||||
|
@ -9,9 +9,10 @@ DATA_TYPES = {
|
|||||||
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
||||||
'DateField': 'date',
|
'DateField': 'date',
|
||||||
'DateTimeField': 'datetime',
|
'DateTimeField': 'datetime',
|
||||||
|
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
||||||
'FileField': 'varchar(100)',
|
'FileField': 'varchar(100)',
|
||||||
'FilePathField': 'varchar(100)',
|
'FilePathField': 'varchar(100)',
|
||||||
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
'FloatField': 'double precision',
|
||||||
'ImageField': 'varchar(100)',
|
'ImageField': 'varchar(100)',
|
||||||
'IntegerField': 'integer',
|
'IntegerField': 'integer',
|
||||||
'IPAddressField': 'char(15)',
|
'IPAddressField': 'char(15)',
|
||||||
|
@ -76,7 +76,7 @@ def get_indexes(cursor, table_name):
|
|||||||
DATA_TYPES_REVERSE = {
|
DATA_TYPES_REVERSE = {
|
||||||
FIELD_TYPE.BLOB: 'TextField',
|
FIELD_TYPE.BLOB: 'TextField',
|
||||||
FIELD_TYPE.CHAR: 'CharField',
|
FIELD_TYPE.CHAR: 'CharField',
|
||||||
FIELD_TYPE.DECIMAL: 'FloatField',
|
FIELD_TYPE.DECIMAL: 'DecimalField',
|
||||||
FIELD_TYPE.DATE: 'DateField',
|
FIELD_TYPE.DATE: 'DateField',
|
||||||
FIELD_TYPE.DATETIME: 'DateTimeField',
|
FIELD_TYPE.DATETIME: 'DateTimeField',
|
||||||
FIELD_TYPE.DOUBLE: 'FloatField',
|
FIELD_TYPE.DOUBLE: 'FloatField',
|
||||||
|
@ -24,6 +24,8 @@ django_conversions.update({
|
|||||||
FIELD_TYPE.DATETIME: util.typecast_timestamp,
|
FIELD_TYPE.DATETIME: util.typecast_timestamp,
|
||||||
FIELD_TYPE.DATE: util.typecast_date,
|
FIELD_TYPE.DATE: util.typecast_date,
|
||||||
FIELD_TYPE.TIME: util.typecast_time,
|
FIELD_TYPE.TIME: util.typecast_time,
|
||||||
|
FIELD_TYPE.DECIMAL: util.typecast_decimal,
|
||||||
|
FIELD_TYPE.NEWDECIMAL: util.typecast_decimal,
|
||||||
})
|
})
|
||||||
|
|
||||||
# This should match the numerical portion of the version numbers (we can treat
|
# This should match the numerical portion of the version numbers (we can treat
|
||||||
|
@ -9,9 +9,10 @@ DATA_TYPES = {
|
|||||||
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
||||||
'DateField': 'date',
|
'DateField': 'date',
|
||||||
'DateTimeField': 'datetime',
|
'DateTimeField': 'datetime',
|
||||||
|
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
||||||
'FileField': 'varchar(100)',
|
'FileField': 'varchar(100)',
|
||||||
'FilePathField': 'varchar(100)',
|
'FilePathField': 'varchar(100)',
|
||||||
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
'FloatField': 'double precision',
|
||||||
'ImageField': 'varchar(100)',
|
'ImageField': 'varchar(100)',
|
||||||
'IntegerField': 'integer',
|
'IntegerField': 'integer',
|
||||||
'IPAddressField': 'char(15)',
|
'IPAddressField': 'char(15)',
|
||||||
|
@ -76,7 +76,7 @@ def get_indexes(cursor, table_name):
|
|||||||
DATA_TYPES_REVERSE = {
|
DATA_TYPES_REVERSE = {
|
||||||
FIELD_TYPE.BLOB: 'TextField',
|
FIELD_TYPE.BLOB: 'TextField',
|
||||||
FIELD_TYPE.CHAR: 'CharField',
|
FIELD_TYPE.CHAR: 'CharField',
|
||||||
FIELD_TYPE.DECIMAL: 'FloatField',
|
FIELD_TYPE.DECIMAL: 'DecimalField',
|
||||||
FIELD_TYPE.DATE: 'DateField',
|
FIELD_TYPE.DATE: 'DateField',
|
||||||
FIELD_TYPE.DATETIME: 'DateTimeField',
|
FIELD_TYPE.DATETIME: 'DateTimeField',
|
||||||
FIELD_TYPE.DOUBLE: 'FloatField',
|
FIELD_TYPE.DOUBLE: 'FloatField',
|
||||||
|
@ -5,9 +5,10 @@ DATA_TYPES = {
|
|||||||
'CommaSeparatedIntegerField': 'varchar2(%(maxlength)s)',
|
'CommaSeparatedIntegerField': 'varchar2(%(maxlength)s)',
|
||||||
'DateField': 'date',
|
'DateField': 'date',
|
||||||
'DateTimeField': 'date',
|
'DateTimeField': 'date',
|
||||||
|
'DecimalField': 'number(%(max_digits)s, %(decimal_places)s)',
|
||||||
'FileField': 'varchar2(100)',
|
'FileField': 'varchar2(100)',
|
||||||
'FilePathField': 'varchar2(100)',
|
'FilePathField': 'varchar2(100)',
|
||||||
'FloatField': 'number(%(max_digits)s, %(decimal_places)s)',
|
'FloatField': 'double precision',
|
||||||
'ImageField': 'varchar2(100)',
|
'ImageField': 'varchar2(100)',
|
||||||
'IntegerField': 'integer',
|
'IntegerField': 'integer',
|
||||||
'IPAddressField': 'char(15)',
|
'IPAddressField': 'char(15)',
|
||||||
|
@ -46,5 +46,5 @@ DATA_TYPES_REVERSE = {
|
|||||||
1114: 'DateTimeField',
|
1114: 'DateTimeField',
|
||||||
1184: 'DateTimeField',
|
1184: 'DateTimeField',
|
||||||
1266: 'TimeField',
|
1266: 'TimeField',
|
||||||
1700: 'FloatField',
|
1700: 'DecimalField',
|
||||||
}
|
}
|
||||||
|
@ -277,6 +277,7 @@ except AttributeError:
|
|||||||
Database.register_type(Database.new_type((1083,1266), "TIME", util.typecast_time))
|
Database.register_type(Database.new_type((1083,1266), "TIME", util.typecast_time))
|
||||||
Database.register_type(Database.new_type((1114,1184), "TIMESTAMP", util.typecast_timestamp))
|
Database.register_type(Database.new_type((1114,1184), "TIMESTAMP", util.typecast_timestamp))
|
||||||
Database.register_type(Database.new_type((16,), "BOOLEAN", util.typecast_boolean))
|
Database.register_type(Database.new_type((16,), "BOOLEAN", util.typecast_boolean))
|
||||||
|
Database.register_type(Database.new_type((1700,), "NUMERIC", util.typecast_decimal))
|
||||||
|
|
||||||
OPERATOR_MAPPING = {
|
OPERATOR_MAPPING = {
|
||||||
'exact': '= %s',
|
'exact': '= %s',
|
||||||
|
@ -9,9 +9,10 @@ DATA_TYPES = {
|
|||||||
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
||||||
'DateField': 'date',
|
'DateField': 'date',
|
||||||
'DateTimeField': 'timestamp with time zone',
|
'DateTimeField': 'timestamp with time zone',
|
||||||
|
'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
||||||
'FileField': 'varchar(100)',
|
'FileField': 'varchar(100)',
|
||||||
'FilePathField': 'varchar(100)',
|
'FilePathField': 'varchar(100)',
|
||||||
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
'FloatField': 'double precision',
|
||||||
'ImageField': 'varchar(100)',
|
'ImageField': 'varchar(100)',
|
||||||
'IntegerField': 'integer',
|
'IntegerField': 'integer',
|
||||||
'IPAddressField': 'inet',
|
'IPAddressField': 'inet',
|
||||||
|
@ -72,6 +72,7 @@ DATA_TYPES_REVERSE = {
|
|||||||
21: 'SmallIntegerField',
|
21: 'SmallIntegerField',
|
||||||
23: 'IntegerField',
|
23: 'IntegerField',
|
||||||
25: 'TextField',
|
25: 'TextField',
|
||||||
|
701: 'FloatField',
|
||||||
869: 'IPAddressField',
|
869: 'IPAddressField',
|
||||||
1043: 'CharField',
|
1043: 'CharField',
|
||||||
1082: 'DateField',
|
1082: 'DateField',
|
||||||
@ -79,5 +80,5 @@ DATA_TYPES_REVERSE = {
|
|||||||
1114: 'DateTimeField',
|
1114: 'DateTimeField',
|
||||||
1184: 'DateTimeField',
|
1184: 'DateTimeField',
|
||||||
1266: 'TimeField',
|
1266: 'TimeField',
|
||||||
1700: 'FloatField',
|
1700: 'DecimalField',
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,7 @@ DATA_TYPES_REVERSE = {
|
|||||||
21: 'SmallIntegerField',
|
21: 'SmallIntegerField',
|
||||||
23: 'IntegerField',
|
23: 'IntegerField',
|
||||||
25: 'TextField',
|
25: 'TextField',
|
||||||
|
701: 'FloatField',
|
||||||
869: 'IPAddressField',
|
869: 'IPAddressField',
|
||||||
1043: 'CharField',
|
1043: 'CharField',
|
||||||
1082: 'DateField',
|
1082: 'DateField',
|
||||||
@ -79,5 +80,5 @@ DATA_TYPES_REVERSE = {
|
|||||||
1114: 'DateTimeField',
|
1114: 'DateTimeField',
|
||||||
1184: 'DateTimeField',
|
1184: 'DateTimeField',
|
||||||
1266: 'TimeField',
|
1266: 'TimeField',
|
||||||
1700: 'FloatField',
|
1700: 'DecimalField',
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,11 @@ except ImportError, e:
|
|||||||
module = 'sqlite3'
|
module = 'sqlite3'
|
||||||
raise ImproperlyConfigured, "Error loading %s module: %s" % (module, e)
|
raise ImproperlyConfigured, "Error loading %s module: %s" % (module, e)
|
||||||
|
|
||||||
|
try:
|
||||||
|
import decimal
|
||||||
|
except ImportError:
|
||||||
|
from django.utils import _decimal as decimal # for Python 2.3
|
||||||
|
|
||||||
DatabaseError = Database.DatabaseError
|
DatabaseError = Database.DatabaseError
|
||||||
IntegrityError = Database.IntegrityError
|
IntegrityError = Database.IntegrityError
|
||||||
|
|
||||||
@ -26,6 +31,8 @@ Database.register_converter("date", util.typecast_date)
|
|||||||
Database.register_converter("datetime", util.typecast_timestamp)
|
Database.register_converter("datetime", util.typecast_timestamp)
|
||||||
Database.register_converter("timestamp", util.typecast_timestamp)
|
Database.register_converter("timestamp", util.typecast_timestamp)
|
||||||
Database.register_converter("TIMESTAMP", util.typecast_timestamp)
|
Database.register_converter("TIMESTAMP", util.typecast_timestamp)
|
||||||
|
Database.register_converter("decimal", util.typecast_decimal)
|
||||||
|
Database.register_adapter(decimal.Decimal, util.rev_typecast_decimal)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Only exists in Python 2.4+
|
# Only exists in Python 2.4+
|
||||||
|
@ -8,9 +8,10 @@ DATA_TYPES = {
|
|||||||
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
||||||
'DateField': 'date',
|
'DateField': 'date',
|
||||||
'DateTimeField': 'datetime',
|
'DateTimeField': 'datetime',
|
||||||
|
'DecimalField': 'decimal',
|
||||||
'FileField': 'varchar(100)',
|
'FileField': 'varchar(100)',
|
||||||
'FilePathField': 'varchar(100)',
|
'FilePathField': 'varchar(100)',
|
||||||
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
'FloatField': 'real',
|
||||||
'ImageField': 'varchar(100)',
|
'ImageField': 'varchar(100)',
|
||||||
'IntegerField': 'integer',
|
'IntegerField': 'integer',
|
||||||
'IPAddressField': 'char(15)',
|
'IPAddressField': 'char(15)',
|
||||||
|
@ -2,6 +2,11 @@ import datetime
|
|||||||
from time import time
|
from time import time
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
|
|
||||||
|
try:
|
||||||
|
import decimal
|
||||||
|
except ImportError:
|
||||||
|
from django.utils import _decimal as decimal # for Python 2.3
|
||||||
|
|
||||||
class CursorDebugWrapper(object):
|
class CursorDebugWrapper(object):
|
||||||
def __init__(self, cursor, db):
|
def __init__(self, cursor, db):
|
||||||
self.cursor = cursor
|
self.cursor = cursor
|
||||||
@ -91,6 +96,11 @@ def typecast_boolean(s):
|
|||||||
if not s: return False
|
if not s: return False
|
||||||
return str(s)[0].lower() == 't'
|
return str(s)[0].lower() == 't'
|
||||||
|
|
||||||
|
def typecast_decimal(s):
|
||||||
|
if s is None:
|
||||||
|
return None
|
||||||
|
return decimal.Decimal(s)
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
# Converters from Python to database (string) #
|
# Converters from Python to database (string) #
|
||||||
###############################################
|
###############################################
|
||||||
@ -98,6 +108,11 @@ def typecast_boolean(s):
|
|||||||
def rev_typecast_boolean(obj, d):
|
def rev_typecast_boolean(obj, d):
|
||||||
return obj and '1' or '0'
|
return obj and '1' or '0'
|
||||||
|
|
||||||
|
def rev_typecast_decimal(d):
|
||||||
|
if d is None:
|
||||||
|
return None
|
||||||
|
return str(d)
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
# Helper functions for dictfetch* for databases that don't natively support them #
|
# Helper functions for dictfetch* for databases that don't natively support them #
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
@ -11,6 +11,10 @@ from django.utils.text import capfirst
|
|||||||
from django.utils.translation import ugettext_lazy, ugettext as _
|
from django.utils.translation import ugettext_lazy, ugettext as _
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
import datetime, os, time
|
import datetime, os, time
|
||||||
|
try:
|
||||||
|
import decimal
|
||||||
|
except ImportError:
|
||||||
|
from django.utils import _decimal as decimal # for Python 2.3
|
||||||
|
|
||||||
class NOT_PROVIDED:
|
class NOT_PROVIDED:
|
||||||
pass
|
pass
|
||||||
@ -574,6 +578,65 @@ class DateTimeField(DateField):
|
|||||||
defaults.update(kwargs)
|
defaults.update(kwargs)
|
||||||
return super(DateTimeField, self).formfield(**defaults)
|
return super(DateTimeField, self).formfield(**defaults)
|
||||||
|
|
||||||
|
class DecimalField(Field):
|
||||||
|
empty_strings_allowed = False
|
||||||
|
def __init__(self, verbose_name=None, name=None, max_digits=None, decimal_places=None, **kwargs):
|
||||||
|
self.max_digits, self.decimal_places = max_digits, decimal_places
|
||||||
|
Field.__init__(self, verbose_name, name, **kwargs)
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
if value is None:
|
||||||
|
return value
|
||||||
|
try:
|
||||||
|
return decimal.Decimal(value)
|
||||||
|
except decimal.InvalidOperation:
|
||||||
|
raise validators.ValidationError, ugettext("This value must be a decimal number.")
|
||||||
|
|
||||||
|
def _format(self, value):
|
||||||
|
if isinstance(value, basestring):
|
||||||
|
return value
|
||||||
|
else:
|
||||||
|
return self.format_number(value)
|
||||||
|
|
||||||
|
def format_number(self, value):
|
||||||
|
"""
|
||||||
|
Formats a number into a string with the requisite number of digits and
|
||||||
|
decimal places.
|
||||||
|
"""
|
||||||
|
num_chars = self.max_digits
|
||||||
|
# Allow for a decimal point
|
||||||
|
if self.decimal_places > 0:
|
||||||
|
num_chars += 1
|
||||||
|
# Allow for a minus sign
|
||||||
|
if value < 0:
|
||||||
|
num_chars += 1
|
||||||
|
|
||||||
|
return u"%.*f" % (self.decimal_places, value)
|
||||||
|
|
||||||
|
def get_db_prep_save(self, value):
|
||||||
|
if value is not None:
|
||||||
|
value = self._format(value)
|
||||||
|
return super(DecimalField, self).get_db_prep_save(value)
|
||||||
|
|
||||||
|
def get_db_prep_lookup(self, lookup_type, value):
|
||||||
|
if lookup_type == 'range':
|
||||||
|
value = [self._format(v) for v in value]
|
||||||
|
else:
|
||||||
|
value = self._format(value)
|
||||||
|
return super(DecimalField, self).get_db_prep_lookup(lookup_type, value)
|
||||||
|
|
||||||
|
def get_manipulator_field_objs(self):
|
||||||
|
return [curry(oldforms.DecimalField, max_digits=self.max_digits, decimal_places=self.decimal_places)]
|
||||||
|
|
||||||
|
def formfield(self, **kwargs):
|
||||||
|
defaults = {
|
||||||
|
'max_digits': self.max_digits,
|
||||||
|
'decimal_places': self.decimal_places,
|
||||||
|
'form_class': forms.DecimalField,
|
||||||
|
}
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return super(DecimalField, self).formfield(**defaults)
|
||||||
|
|
||||||
class EmailField(CharField):
|
class EmailField(CharField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs['maxlength'] = 75
|
kwargs['maxlength'] = 75
|
||||||
@ -684,12 +747,14 @@ class FilePathField(Field):
|
|||||||
|
|
||||||
class FloatField(Field):
|
class FloatField(Field):
|
||||||
empty_strings_allowed = False
|
empty_strings_allowed = False
|
||||||
def __init__(self, verbose_name=None, name=None, max_digits=None, decimal_places=None, **kwargs):
|
|
||||||
self.max_digits, self.decimal_places = max_digits, decimal_places
|
|
||||||
Field.__init__(self, verbose_name, name, **kwargs)
|
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [curry(oldforms.FloatField, max_digits=self.max_digits, decimal_places=self.decimal_places)]
|
return [oldforms.FloatField]
|
||||||
|
|
||||||
|
def formfield(self, **kwargs):
|
||||||
|
defaults = {'form_class': forms.FloatField}
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return super(FloatField, self).formfield(**defaults)
|
||||||
|
|
||||||
class ImageField(FileField):
|
class ImageField(FileField):
|
||||||
def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):
|
def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):
|
||||||
|
@ -155,9 +155,12 @@ class QueryDict(MultiValueDict):
|
|||||||
self._assert_mutable()
|
self._assert_mutable()
|
||||||
MultiValueDict.update(self, other_dict)
|
MultiValueDict.update(self, other_dict)
|
||||||
|
|
||||||
def pop(self, key):
|
def pop(self, key, *args):
|
||||||
self._assert_mutable()
|
self._assert_mutable()
|
||||||
return [str_to_unicode(v, self.encoding) for v in MultiValueDict.pop(self, key)]
|
val = MultiValueDict.pop(self, key, *args)
|
||||||
|
if isinstance(val, list):
|
||||||
|
return [str_to_unicode(v, self.encoding) for v in val]
|
||||||
|
return str_to_unicode(val, self.encoding)
|
||||||
|
|
||||||
def popitem(self):
|
def popitem(self):
|
||||||
self._assert_mutable()
|
self._assert_mutable()
|
||||||
|
@ -19,7 +19,7 @@ __all__ = (
|
|||||||
'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
|
'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
|
||||||
'RegexField', 'EmailField', 'URLField', 'BooleanField',
|
'RegexField', 'EmailField', 'URLField', 'BooleanField',
|
||||||
'ChoiceField', 'NullBooleanField', 'MultipleChoiceField',
|
'ChoiceField', 'NullBooleanField', 'MultipleChoiceField',
|
||||||
'ComboField', 'MultiValueField',
|
'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
|
||||||
'SplitDateTimeField',
|
'SplitDateTimeField',
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,6 +31,11 @@ try:
|
|||||||
except NameError:
|
except NameError:
|
||||||
from sets import Set as set # Python 2.3 fallback
|
from sets import Set as set # Python 2.3 fallback
|
||||||
|
|
||||||
|
try:
|
||||||
|
from decimal import Decimal
|
||||||
|
except ImportError:
|
||||||
|
from django.utils._decimal import Decimal # Python 2.3 fallback
|
||||||
|
|
||||||
class Field(object):
|
class Field(object):
|
||||||
widget = TextInput # Default widget to use when rendering this type of Field.
|
widget = TextInput # Default widget to use when rendering this type of Field.
|
||||||
hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
|
hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
|
||||||
@ -134,6 +139,67 @@ class IntegerField(Field):
|
|||||||
raise ValidationError(ugettext(u'Ensure this value is greater than or equal to %s.') % self.min_value)
|
raise ValidationError(ugettext(u'Ensure this value is greater than or equal to %s.') % self.min_value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
class FloatField(Field):
|
||||||
|
def __init__(self, max_value=None, min_value=None, *args, **kwargs):
|
||||||
|
self.max_value, self.min_value = max_value, min_value
|
||||||
|
Field.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
"""
|
||||||
|
Validates that float() can be called on the input. Returns a float.
|
||||||
|
Returns None for empty values.
|
||||||
|
"""
|
||||||
|
super(FloatField, self).clean(value)
|
||||||
|
if not self.required and value in EMPTY_VALUES:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
value = float(value)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
raise ValidationError(ugettext('Enter a number.'))
|
||||||
|
if self.max_value is not None and value > self.max_value:
|
||||||
|
raise ValidationError(ugettext('Ensure this value is less than or equal to %s.') % self.max_value)
|
||||||
|
if self.min_value is not None and value < self.min_value:
|
||||||
|
raise ValidationError(ugettext('Ensure this value is greater than or equal to %s.') % self.min_value)
|
||||||
|
return value
|
||||||
|
|
||||||
|
decimal_re = re.compile(r'^-?(?P<digits>\d+)(\.(?P<decimals>\d+))?$')
|
||||||
|
|
||||||
|
class DecimalField(Field):
|
||||||
|
def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs):
|
||||||
|
self.max_value, self.min_value = max_value, min_value
|
||||||
|
self.max_digits, self.decimal_places = max_digits, decimal_places
|
||||||
|
Field.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
def clean(self, value):
|
||||||
|
"""
|
||||||
|
Validates that the input is a decimal number. Returns a Decimal
|
||||||
|
instance. Returns None for empty values. Ensures that there are no more
|
||||||
|
than max_digits in the number, and no more than decimal_places digits
|
||||||
|
after the decimal point.
|
||||||
|
"""
|
||||||
|
super(DecimalField, self).clean(value)
|
||||||
|
if not self.required and value in EMPTY_VALUES:
|
||||||
|
return None
|
||||||
|
value = value.strip()
|
||||||
|
match = decimal_re.search(value)
|
||||||
|
if not match:
|
||||||
|
raise ValidationError(ugettext('Enter a number.'))
|
||||||
|
else:
|
||||||
|
value = Decimal(value)
|
||||||
|
digits = len(match.group('digits') or '')
|
||||||
|
decimals = len(match.group('decimals') or '')
|
||||||
|
if self.max_value is not None and value > self.max_value:
|
||||||
|
raise ValidationError(ugettext('Ensure this value is less than or equal to %s.') % self.max_value)
|
||||||
|
if self.min_value is not None and value < self.min_value:
|
||||||
|
raise ValidationError(ugettext('Ensure this value is greater than or equal to %s.') % self.min_value)
|
||||||
|
if self.max_digits is not None and (digits + decimals) > self.max_digits:
|
||||||
|
raise ValidationError(ugettext('Ensure that there are no more than %s digits in total.') % self.max_digits)
|
||||||
|
if self.decimal_places is not None and decimals > self.decimal_places:
|
||||||
|
raise ValidationError(ugettext('Ensure that there are no more than %s decimal places.') % self.decimal_places)
|
||||||
|
if self.max_digits is not None and self.decimal_places is not None and digits > (self.max_digits - self.decimal_places):
|
||||||
|
raise ValidationError(ugettext('Ensure that there are no more than %s digits before the decimal point.') % (self.max_digits - self.decimal_places))
|
||||||
|
return value
|
||||||
|
|
||||||
DEFAULT_DATE_INPUT_FORMATS = (
|
DEFAULT_DATE_INPUT_FORMATS = (
|
||||||
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
|
'%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
|
||||||
'%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
|
'%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
|
|
||||||
# Converts a dictionary to a single string with key="value", XML-style with
|
def flatatt(attrs):
|
||||||
# a leading space. Assumes keys do not need to be XML-escaped.
|
"""
|
||||||
flatatt = lambda attrs: u''.join([u' %s="%s"' % (k, escape(v)) for k, v in attrs.items()])
|
Convert a dictionary of attributes to a single string.
|
||||||
|
The returned string will contain a leading space followed by key="value",
|
||||||
|
XML-style pairs. It is assumed that the keys do not need to be XML-escaped.
|
||||||
|
If the passed dictionary is empty, then return an empty string.
|
||||||
|
"""
|
||||||
|
return u''.join([u' %s="%s"' % (k, escape(v)) for k, v in attrs.items()])
|
||||||
|
|
||||||
class ErrorDict(dict):
|
class ErrorDict(dict):
|
||||||
"""
|
"""
|
||||||
|
@ -760,14 +760,27 @@ class PositiveSmallIntegerField(IntegerField):
|
|||||||
raise validators.CriticalValidationError, ugettext("Enter a whole number between 0 and 32,767.")
|
raise validators.CriticalValidationError, ugettext("Enter a whole number between 0 and 32,767.")
|
||||||
|
|
||||||
class FloatField(TextField):
|
class FloatField(TextField):
|
||||||
|
def __init__(self, field_name, is_required=False, validator_list=None):
|
||||||
|
if validator_list is None: validator_list = []
|
||||||
|
validator_list = [validators.isValidFloat] + validator_list
|
||||||
|
TextField.__init__(self, field_name, is_required=is_required, validator_list=validator_list)
|
||||||
|
|
||||||
|
def html2python(data):
|
||||||
|
if data == '' or data is None:
|
||||||
|
return None
|
||||||
|
return float(data)
|
||||||
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
|
class DecimalField(TextField):
|
||||||
def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None):
|
def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None):
|
||||||
if validator_list is None: validator_list = []
|
if validator_list is None: validator_list = []
|
||||||
self.max_digits, self.decimal_places = max_digits, decimal_places
|
self.max_digits, self.decimal_places = max_digits, decimal_places
|
||||||
validator_list = [self.isValidFloat] + validator_list
|
validator_list = [self.isValidDecimal] + validator_list
|
||||||
TextField.__init__(self, field_name, max_digits+2, max_digits+2, is_required, validator_list)
|
# Initialise the TextField, making sure it's large enough to fit the number with a - sign and a decimal point.
|
||||||
|
super(DecimalField, self).__init__(field_name, max_digits+2, max_digits+2, is_required, validator_list)
|
||||||
|
|
||||||
def isValidFloat(self, field_data, all_data):
|
def isValidDecimal(self, field_data, all_data):
|
||||||
v = validators.IsValidFloat(self.max_digits, self.decimal_places)
|
v = validators.IsValidDecimal(self.max_digits, self.decimal_places)
|
||||||
try:
|
try:
|
||||||
v(field_data, all_data)
|
v(field_data, all_data)
|
||||||
except validators.ValidationError, e:
|
except validators.ValidationError, e:
|
||||||
@ -776,7 +789,14 @@ class FloatField(TextField):
|
|||||||
def html2python(data):
|
def html2python(data):
|
||||||
if data == '' or data is None:
|
if data == '' or data is None:
|
||||||
return None
|
return None
|
||||||
return float(data)
|
try:
|
||||||
|
import decimal
|
||||||
|
except ImportError:
|
||||||
|
from django.utils import decimal
|
||||||
|
try:
|
||||||
|
return decimal.Decimal(data)
|
||||||
|
except decimal.InvalidOperation, e:
|
||||||
|
raise ValueError, e
|
||||||
html2python = staticmethod(html2python)
|
html2python = staticmethod(html2python)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
|
3079
django/utils/_decimal.py
Normal file
3079
django/utils/_decimal.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -567,6 +567,7 @@ check for the given property:
|
|||||||
* isValidANSIDate
|
* isValidANSIDate
|
||||||
* isValidANSITime
|
* isValidANSITime
|
||||||
* isValidEmail
|
* isValidEmail
|
||||||
|
* isValidFloat
|
||||||
* isValidImage
|
* isValidImage
|
||||||
* isValidImageURL
|
* isValidImageURL
|
||||||
* isValidPhone
|
* isValidPhone
|
||||||
@ -664,10 +665,10 @@ fails. If no message is passed in, a default message is used.
|
|||||||
Takes an integer argument and when called as a validator, checks that the
|
Takes an integer argument and when called as a validator, checks that the
|
||||||
field being validated is a power of the integer.
|
field being validated is a power of the integer.
|
||||||
|
|
||||||
``IsValidFloat``
|
``IsValidDecimal``
|
||||||
Takes a maximum number of digits and number of decimal places (in that
|
Takes a maximum number of digits and number of decimal places (in that
|
||||||
order) and validates whether the field is a float with less than the
|
order) and validates whether the field is a decimal with no more than the
|
||||||
maximum number of digits and decimal place.
|
maximum number of digits and decimal places.
|
||||||
|
|
||||||
``MatchesRegularExpression``
|
``MatchesRegularExpression``
|
||||||
Takes a regular expression (a string) as a parameter and validates the
|
Takes a regular expression (a string) as a parameter and validates the
|
||||||
|
@ -11,8 +11,8 @@ Being a Python Web framework, Django requires Python.
|
|||||||
|
|
||||||
It works with any Python version 2.3 and higher.
|
It works with any Python version 2.3 and higher.
|
||||||
|
|
||||||
Get Python at www.python.org. If you're running Linux or Mac OS X, you probably
|
Get Python at http://www.python.org. If you're running Linux or Mac OS X, you
|
||||||
already have it installed.
|
probably already have it installed.
|
||||||
|
|
||||||
Install Apache and mod_python
|
Install Apache and mod_python
|
||||||
=============================
|
=============================
|
||||||
|
@ -184,6 +184,35 @@ A date and time field. Takes the same extra options as ``DateField``.
|
|||||||
The admin represents this as two ``<input type="text">`` fields, with
|
The admin represents this as two ``<input type="text">`` fields, with
|
||||||
JavaScript shortcuts.
|
JavaScript shortcuts.
|
||||||
|
|
||||||
|
``DecimalField``
|
||||||
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
A fixed-precision decimal number, represented in Python by a ``Decimal`` instance.
|
||||||
|
Has two **required** arguments:
|
||||||
|
|
||||||
|
====================== ===================================================
|
||||||
|
Argument Description
|
||||||
|
====================== ===================================================
|
||||||
|
``max_digits`` The maximum number of digits allowed in the number.
|
||||||
|
|
||||||
|
``decimal_places`` The number of decimal places to store with the
|
||||||
|
number.
|
||||||
|
====================== ===================================================
|
||||||
|
|
||||||
|
For example, to store numbers up to 999 with a resolution of 2 decimal places,
|
||||||
|
you'd use::
|
||||||
|
|
||||||
|
models.DecimalField(..., max_digits=5, decimal_places=2)
|
||||||
|
|
||||||
|
And to store numbers up to approximately one billion with a resolution of 10
|
||||||
|
decimal places::
|
||||||
|
|
||||||
|
models.DecimalField(..., max_digits=19, decimal_places=10)
|
||||||
|
|
||||||
|
The admin represents this as an ``<input type="text">`` (a single-line input).
|
||||||
|
|
||||||
``EmailField``
|
``EmailField``
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -290,29 +319,17 @@ because the ``match`` applies to the base filename (``foo.gif`` and
|
|||||||
``FloatField``
|
``FloatField``
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
A floating-point number. Has two **required** arguments:
|
**Changed in Django development version**
|
||||||
|
|
||||||
====================== ===================================================
|
A floating-point number represented in Python by a ``float`` instance.
|
||||||
Argument Description
|
|
||||||
====================== ===================================================
|
|
||||||
``max_digits`` The maximum number of digits allowed in the number.
|
|
||||||
|
|
||||||
``decimal_places`` The number of decimal places to store with the
|
|
||||||
number.
|
|
||||||
====================== ===================================================
|
|
||||||
|
|
||||||
For example, to store numbers up to 999 with a resolution of 2 decimal places,
|
|
||||||
you'd use::
|
|
||||||
|
|
||||||
models.FloatField(..., max_digits=5, decimal_places=2)
|
|
||||||
|
|
||||||
And to store numbers up to approximately one billion with a resolution of 10
|
|
||||||
decimal places::
|
|
||||||
|
|
||||||
models.FloatField(..., max_digits=19, decimal_places=10)
|
|
||||||
|
|
||||||
The admin represents this as an ``<input type="text">`` (a single-line input).
|
The admin represents this as an ``<input type="text">`` (a single-line input).
|
||||||
|
|
||||||
|
**NOTE:** The semantics of ``FloatField`` have changed in the Django
|
||||||
|
development version. See the `Django 0.96 documentation`_ for the old behavior.
|
||||||
|
|
||||||
|
.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield
|
||||||
|
|
||||||
``ImageField``
|
``ImageField``
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -743,7 +760,7 @@ relationship should work. All are optional:
|
|||||||
``limit_choices_to`` A dictionary of lookup arguments and values (see
|
``limit_choices_to`` A dictionary of lookup arguments and values (see
|
||||||
the `Database API reference`_) that limit the
|
the `Database API reference`_) that limit the
|
||||||
available admin choices for this object. Use this
|
available admin choices for this object. Use this
|
||||||
with functions from the Python ``datetime`` module
|
with functions from the Python ``datetime`` module
|
||||||
to limit choices of objects by date. For example::
|
to limit choices of objects by date. For example::
|
||||||
|
|
||||||
limit_choices_to = {'pub_date__lte': datetime.now}
|
limit_choices_to = {'pub_date__lte': datetime.now}
|
||||||
@ -1760,8 +1777,8 @@ But this template code is good::
|
|||||||
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
|
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The string you return from ``get_absolute_url()`` must be use only ASCII
|
The string you return from ``get_absolute_url()`` must contain only ASCII
|
||||||
characters (required by the URI spec, `RFC 2396`_) that has been
|
characters (required by the URI spec, `RFC 2396`_) that have been
|
||||||
URL-encoded, if necessary. Code and templates using ``get_absolute_url()``
|
URL-encoded, if necessary. Code and templates using ``get_absolute_url()``
|
||||||
should be able to use the result directly without needing to do any
|
should be able to use the result directly without needing to do any
|
||||||
further processing. You may wish to use the
|
further processing. You may wish to use the
|
||||||
|
@ -602,6 +602,102 @@ when printed::
|
|||||||
>>> str(f['subject'].errors)
|
>>> str(f['subject'].errors)
|
||||||
''
|
''
|
||||||
|
|
||||||
|
Using forms in views and templates
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Let's put this all together and use the ``ContactForm`` example in a Django
|
||||||
|
view and template. This example view displays the contact form by default and
|
||||||
|
validates/processes it if accessed via a POST request::
|
||||||
|
|
||||||
|
def contact(request):
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = ContactForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
# Do form processing here...
|
||||||
|
return HttpResponseRedirect('/url/on_success/')
|
||||||
|
else:
|
||||||
|
form = ContactForm()
|
||||||
|
return render_to_response('contact.html', {'form': form})
|
||||||
|
|
||||||
|
Simple template output
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
The template, ``contact.html``, is responsible for displaying the form as HTML.
|
||||||
|
To do this, we can use the techniques outlined in the "Outputting forms as HTML"
|
||||||
|
section above.
|
||||||
|
|
||||||
|
The simplest way to display a form's HTML is to use the variable on its own,
|
||||||
|
like this::
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<table>{{ form }}</table>
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
The above template code will display the form as an HTML table, using the
|
||||||
|
``form.as_table()`` method explained previously. This works because Django's
|
||||||
|
template system displays an object's ``__str__()`` value, and the ``Form``
|
||||||
|
class' ``__str__()`` method calls its ``as_table()`` method.
|
||||||
|
|
||||||
|
The following is equivalent but a bit more explicit::
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<table>{{ form.as_table }}</table>
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
``form.as_ul`` and ``form.as_p`` are also available, as you may expect.
|
||||||
|
|
||||||
|
Note that in the above two examples, we included the ``<form>``, ``<table>``
|
||||||
|
``<input type="submit" />``, ``</table>`` and ``</form>`` tags. The form
|
||||||
|
convenience methods (``as_table()``, ``as_ul()`` and ``as_p()``) do not include
|
||||||
|
that HTML.
|
||||||
|
|
||||||
|
Complex template output
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
As we've stressed several times, the ``as_table()``, ``as_ul()`` and ``as_p()``
|
||||||
|
methods are just shortcuts for the common case. You can also work with the
|
||||||
|
individual fields for complete template control over the form's design.
|
||||||
|
|
||||||
|
The easiest way is to iterate over the form's fields, with
|
||||||
|
``{% for field in form %}``. For example::
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<dl>
|
||||||
|
{% for field in form %}
|
||||||
|
<dt>{{ field.label }}</dt>
|
||||||
|
<dd>{{ field }}</dd>
|
||||||
|
{% if field.help_text %}<dd>{{ field.help_text }}</dd>{% endif %}
|
||||||
|
{% if field.errors %}<dd class="myerrors">{{ field.errors }}</dd>{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</dl>
|
||||||
|
<input type="submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
This iteration technique is useful if you want to apply the same HTML
|
||||||
|
formatting to each field, or if you don't know the names of the form fields
|
||||||
|
ahead of time. Note that the fields will be listed in the order in which
|
||||||
|
they're defined in the ``Form`` class.
|
||||||
|
|
||||||
|
Alternatively, you can arrange the form's fields explicitly, by name. Do that
|
||||||
|
by accessing ``{{ form.fieldname }}``, where ``fieldname`` is the field's name.
|
||||||
|
For example::
|
||||||
|
|
||||||
|
<form method="post">
|
||||||
|
<ul class="myformclass">
|
||||||
|
<li>{{ form.sender.label }} {{ form.sender.label }}</li>
|
||||||
|
<li class="helptext">{{ form.sender.help_text }}</li>
|
||||||
|
{% if form.sender.errors %}<ul class="errorlist">{{ form.sender.errors }}</dd>{% endif %}
|
||||||
|
|
||||||
|
<li>{{ form.subject.label }} {{ form.subject.label }}</li>
|
||||||
|
<li class="helptext">{{ form.subject.help_text }}</li>
|
||||||
|
{% if form.subject.errors %}<ul class="errorlist">{{ form.subject.errors }}</dd>{% endif %}
|
||||||
|
|
||||||
|
...
|
||||||
|
</ul>
|
||||||
|
</form>
|
||||||
|
|
||||||
Subclassing forms
|
Subclassing forms
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -1157,10 +1253,11 @@ the full list of conversions:
|
|||||||
``CommaSeparatedIntegerField`` ``CharField``
|
``CommaSeparatedIntegerField`` ``CharField``
|
||||||
``DateField`` ``DateField``
|
``DateField`` ``DateField``
|
||||||
``DateTimeField`` ``DateTimeField``
|
``DateTimeField`` ``DateTimeField``
|
||||||
|
``DecimalField`` ``DecimalField``
|
||||||
``EmailField`` ``EmailField``
|
``EmailField`` ``EmailField``
|
||||||
``FileField`` ``CharField``
|
``FileField`` ``CharField``
|
||||||
``FilePathField`` ``CharField``
|
``FilePathField`` ``CharField``
|
||||||
``FloatField`` ``CharField``
|
``FloatField`` ``FloatField``
|
||||||
``ForeignKey`` ``ModelChoiceField`` (see below)
|
``ForeignKey`` ``ModelChoiceField`` (see below)
|
||||||
``ImageField`` ``CharField``
|
``ImageField`` ``CharField``
|
||||||
``IntegerField`` ``IntegerField``
|
``IntegerField`` ``IntegerField``
|
||||||
@ -1185,6 +1282,11 @@ the full list of conversions:
|
|||||||
``XMLField`` ``CharField`` with ``widget=Textarea``
|
``XMLField`` ``CharField`` with ``widget=Textarea``
|
||||||
=============================== ========================================
|
=============================== ========================================
|
||||||
|
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
The ``FloatField`` form field and ``DecimalField`` model and form fields
|
||||||
|
are new in the development version.
|
||||||
|
|
||||||
As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
|
As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
|
||||||
types are special cases:
|
types are special cases:
|
||||||
|
|
||||||
|
@ -1063,7 +1063,7 @@ You can tell Django to stop reporting particular 404s by tweaking the
|
|||||||
tuple of strings. For example::
|
tuple of strings. For example::
|
||||||
|
|
||||||
IGNORABLE_404_ENDS = ('.php', '.cgi')
|
IGNORABLE_404_ENDS = ('.php', '.cgi')
|
||||||
IGNORABLE_404_STARTS = ('/phpmyadmin/')
|
IGNORABLE_404_STARTS = ('/phpmyadmin/',)
|
||||||
|
|
||||||
In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not*
|
In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not*
|
||||||
be reported. Neither will any URL starting with ``/phpmyadmin/``.
|
be reported. Neither will any URL starting with ``/phpmyadmin/``.
|
||||||
|
@ -320,7 +320,7 @@ method a ``short_description`` attribute::
|
|||||||
|
|
||||||
|
|
||||||
Let's add another improvement to the Poll change list page: Filters. Add the
|
Let's add another improvement to the Poll change list page: Filters. Add the
|
||||||
following line to ``Poll.admin``::
|
following line to ``Poll.Admin``::
|
||||||
|
|
||||||
list_filter = ['pub_date']
|
list_filter = ['pub_date']
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ from django.db import models
|
|||||||
|
|
||||||
class FieldErrors(models.Model):
|
class FieldErrors(models.Model):
|
||||||
charfield = models.CharField()
|
charfield = models.CharField()
|
||||||
floatfield = models.FloatField()
|
decimalfield = models.DecimalField()
|
||||||
filefield = models.FileField()
|
filefield = models.FileField()
|
||||||
prepopulate = models.CharField(maxlength=10, prepopulate_from='bad')
|
prepopulate = models.CharField(maxlength=10, prepopulate_from='bad')
|
||||||
choices = models.CharField(maxlength=10, choices='bad')
|
choices = models.CharField(maxlength=10, choices='bad')
|
||||||
@ -87,10 +87,10 @@ class SelfClashM2M(models.Model):
|
|||||||
src_safe = models.CharField(maxlength=10)
|
src_safe = models.CharField(maxlength=10)
|
||||||
selfclashm2m = models.CharField(maxlength=10)
|
selfclashm2m = models.CharField(maxlength=10)
|
||||||
|
|
||||||
# Non-symmetrical M2M fields _do_ have related accessors, so
|
# Non-symmetrical M2M fields _do_ have related accessors, so
|
||||||
# there is potential for clashes.
|
# there is potential for clashes.
|
||||||
selfclashm2m_set = models.ManyToManyField("SelfClashM2M", symmetrical=False)
|
selfclashm2m_set = models.ManyToManyField("SelfClashM2M", symmetrical=False)
|
||||||
|
|
||||||
m2m_1 = models.ManyToManyField("SelfClashM2M", related_name='id', symmetrical=False)
|
m2m_1 = models.ManyToManyField("SelfClashM2M", related_name='id', symmetrical=False)
|
||||||
m2m_2 = models.ManyToManyField("SelfClashM2M", related_name='src_safe', symmetrical=False)
|
m2m_2 = models.ManyToManyField("SelfClashM2M", related_name='src_safe', symmetrical=False)
|
||||||
|
|
||||||
@ -108,8 +108,8 @@ class Car(models.Model):
|
|||||||
model = models.ForeignKey(Model)
|
model = models.ForeignKey(Model)
|
||||||
|
|
||||||
model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "maxlength" attribute.
|
model_errors = """invalid_models.fielderrors: "charfield": CharFields require a "maxlength" attribute.
|
||||||
invalid_models.fielderrors: "floatfield": FloatFields require a "decimal_places" attribute.
|
invalid_models.fielderrors: "decimalfield": DecimalFields require a "decimal_places" attribute.
|
||||||
invalid_models.fielderrors: "floatfield": FloatFields require a "max_digits" attribute.
|
invalid_models.fielderrors: "decimalfield": DecimalFields require a "max_digits" attribute.
|
||||||
invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute.
|
invalid_models.fielderrors: "filefield": FileFields require an "upload_to" attribute.
|
||||||
invalid_models.fielderrors: "prepopulate": prepopulate_from should be a list or tuple.
|
invalid_models.fielderrors: "prepopulate": prepopulate_from should be a list or tuple.
|
||||||
invalid_models.fielderrors: "choices": "choices" should be iterable (e.g., a tuple or list).
|
invalid_models.fielderrors: "choices": "choices" should be iterable (e.g., a tuple or list).
|
||||||
|
@ -7,6 +7,10 @@ form_tests = r"""
|
|||||||
>>> import datetime
|
>>> import datetime
|
||||||
>>> import time
|
>>> import time
|
||||||
>>> import re
|
>>> import re
|
||||||
|
>>> try:
|
||||||
|
... from decimal import Decimal
|
||||||
|
... except ImportError:
|
||||||
|
... from django.utils._decimal import Decimal
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# Widgets #
|
# Widgets #
|
||||||
@ -1046,6 +1050,133 @@ Traceback (most recent call last):
|
|||||||
...
|
...
|
||||||
ValidationError: [u'Ensure this value is less than or equal to 20.']
|
ValidationError: [u'Ensure this value is less than or equal to 20.']
|
||||||
|
|
||||||
|
# FloatField ##################################################################
|
||||||
|
|
||||||
|
>>> f = FloatField()
|
||||||
|
>>> f.clean('')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'This field is required.']
|
||||||
|
>>> f.clean(None)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'This field is required.']
|
||||||
|
>>> f.clean('1')
|
||||||
|
1.0
|
||||||
|
>>> isinstance(f.clean('1'), float)
|
||||||
|
True
|
||||||
|
>>> f.clean('23')
|
||||||
|
23.0
|
||||||
|
>>> f.clean('3.14')
|
||||||
|
3.1400000000000001
|
||||||
|
>>> f.clean('a')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a number.']
|
||||||
|
>>> f.clean('1.0 ')
|
||||||
|
1.0
|
||||||
|
>>> f.clean(' 1.0')
|
||||||
|
1.0
|
||||||
|
>>> f.clean(' 1.0 ')
|
||||||
|
1.0
|
||||||
|
>>> f.clean('1.0a')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a number.']
|
||||||
|
|
||||||
|
>>> f = FloatField(required=False)
|
||||||
|
>>> f.clean('')
|
||||||
|
|
||||||
|
>>> f.clean(None)
|
||||||
|
|
||||||
|
>>> f.clean('1')
|
||||||
|
1.0
|
||||||
|
|
||||||
|
FloatField accepts min_value and max_value just like IntegerField:
|
||||||
|
>>> f = FloatField(max_value=1.5, min_value=0.5)
|
||||||
|
|
||||||
|
>>> f.clean('1.6')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Ensure this value is less than or equal to 1.5.']
|
||||||
|
>>> f.clean('0.4')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Ensure this value is greater than or equal to 0.5.']
|
||||||
|
>>> f.clean('1.5')
|
||||||
|
1.5
|
||||||
|
>>> f.clean('0.5')
|
||||||
|
0.5
|
||||||
|
|
||||||
|
# DecimalField ################################################################
|
||||||
|
|
||||||
|
>>> f = DecimalField(max_digits=4, decimal_places=2)
|
||||||
|
>>> f.clean('')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'This field is required.']
|
||||||
|
>>> f.clean(None)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'This field is required.']
|
||||||
|
>>> f.clean('1')
|
||||||
|
Decimal("1")
|
||||||
|
>>> isinstance(f.clean('1'), Decimal)
|
||||||
|
True
|
||||||
|
>>> f.clean('23')
|
||||||
|
Decimal("23")
|
||||||
|
>>> f.clean('3.14')
|
||||||
|
Decimal("3.14")
|
||||||
|
>>> f.clean('a')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a number.']
|
||||||
|
>>> f.clean('1.0 ')
|
||||||
|
Decimal("1.0")
|
||||||
|
>>> f.clean(' 1.0')
|
||||||
|
Decimal("1.0")
|
||||||
|
>>> f.clean(' 1.0 ')
|
||||||
|
Decimal("1.0")
|
||||||
|
>>> f.clean('1.0a')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Enter a number.']
|
||||||
|
>>> f.clean('123.45')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Ensure that there are no more than 4 digits in total.']
|
||||||
|
>>> f.clean('1.234')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Ensure that there are no more than 2 decimal places.']
|
||||||
|
>>> f.clean('123.4')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Ensure that there are no more than 2 digits before the decimal point.']
|
||||||
|
>>> f = DecimalField(max_digits=4, decimal_places=2, required=False)
|
||||||
|
>>> f.clean('')
|
||||||
|
|
||||||
|
>>> f.clean(None)
|
||||||
|
|
||||||
|
>>> f.clean('1')
|
||||||
|
Decimal("1")
|
||||||
|
|
||||||
|
DecimalField accepts min_value and max_value just like IntegerField:
|
||||||
|
>>> f = DecimalField(max_digits=4, decimal_places=2, max_value=Decimal('1.5'), min_value=Decimal('0.5'))
|
||||||
|
|
||||||
|
>>> f.clean('1.6')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Ensure this value is less than or equal to 1.5.']
|
||||||
|
>>> f.clean('0.4')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValidationError: [u'Ensure this value is greater than or equal to 0.5.']
|
||||||
|
>>> f.clean('1.5')
|
||||||
|
Decimal("1.5")
|
||||||
|
>>> f.clean('0.5')
|
||||||
|
Decimal("0.5")
|
||||||
|
|
||||||
# DateField ###################################################################
|
# DateField ###################################################################
|
||||||
|
|
||||||
>>> import datetime
|
>>> import datetime
|
||||||
@ -3515,6 +3646,15 @@ u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
|
|||||||
u'1'
|
u'1'
|
||||||
>>> smart_unicode('foo')
|
>>> smart_unicode('foo')
|
||||||
u'foo'
|
u'foo'
|
||||||
|
|
||||||
|
# flatatt tests
|
||||||
|
>>> from django.newforms.util import flatatt
|
||||||
|
>>> flatatt({'id': "header"})
|
||||||
|
u' id="header"'
|
||||||
|
>>> flatatt({'class': "news", 'title': "Read this"})
|
||||||
|
u' class="news" title="Read this"'
|
||||||
|
>>> flatatt({})
|
||||||
|
u''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__test__ = {
|
__test__ = {
|
||||||
|
@ -166,6 +166,9 @@ u'hello'
|
|||||||
>>> q.pop('foo')
|
>>> q.pop('foo')
|
||||||
[u'bar', u'baz', u'another', u'hello']
|
[u'bar', u'baz', u'another', u'hello']
|
||||||
|
|
||||||
|
>>> q.pop('foo', 'not there')
|
||||||
|
u'not there'
|
||||||
|
|
||||||
>>> q.get('foo', 'not there')
|
>>> q.get('foo', 'not there')
|
||||||
u'not there'
|
u'not there'
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
A test spanning all the capabilities of all the serializers.
|
A test spanning all the capabilities of all the serializers.
|
||||||
|
|
||||||
This class sets up a model for each model field type
|
This class sets up a model for each model field type
|
||||||
(except for image types, because of the PIL dependency).
|
(except for image types, because of the PIL dependency).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -9,12 +9,12 @@ from django.db import models
|
|||||||
from django.contrib.contenttypes import generic
|
from django.contrib.contenttypes import generic
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
# The following classes are for testing basic data
|
# The following classes are for testing basic data
|
||||||
# marshalling, including NULL values.
|
# marshalling, including NULL values.
|
||||||
|
|
||||||
class BooleanData(models.Model):
|
class BooleanData(models.Model):
|
||||||
data = models.BooleanField(null=True)
|
data = models.BooleanField(null=True)
|
||||||
|
|
||||||
class CharData(models.Model):
|
class CharData(models.Model):
|
||||||
data = models.CharField(maxlength=30, null=True)
|
data = models.CharField(maxlength=30, null=True)
|
||||||
|
|
||||||
@ -24,6 +24,9 @@ class DateData(models.Model):
|
|||||||
class DateTimeData(models.Model):
|
class DateTimeData(models.Model):
|
||||||
data = models.DateTimeField(null=True)
|
data = models.DateTimeField(null=True)
|
||||||
|
|
||||||
|
class DecimalData(models.Model):
|
||||||
|
data = models.DecimalField(null=True, decimal_places=3, max_digits=5)
|
||||||
|
|
||||||
class EmailData(models.Model):
|
class EmailData(models.Model):
|
||||||
data = models.EmailField(null=True)
|
data = models.EmailField(null=True)
|
||||||
|
|
||||||
@ -34,7 +37,7 @@ class FilePathData(models.Model):
|
|||||||
data = models.FilePathField(null=True)
|
data = models.FilePathField(null=True)
|
||||||
|
|
||||||
class FloatData(models.Model):
|
class FloatData(models.Model):
|
||||||
data = models.FloatField(null=True, decimal_places=3, max_digits=5)
|
data = models.FloatField(null=True)
|
||||||
|
|
||||||
class IntegerData(models.Model):
|
class IntegerData(models.Model):
|
||||||
data = models.IntegerField(null=True)
|
data = models.IntegerField(null=True)
|
||||||
@ -145,6 +148,9 @@ class CharPKData(models.Model):
|
|||||||
# class DateTimePKData(models.Model):
|
# class DateTimePKData(models.Model):
|
||||||
# data = models.DateTimeField(primary_key=True)
|
# data = models.DateTimeField(primary_key=True)
|
||||||
|
|
||||||
|
class DecimalPKData(models.Model):
|
||||||
|
data = models.DecimalField(primary_key=True, decimal_places=3, max_digits=5)
|
||||||
|
|
||||||
class EmailPKData(models.Model):
|
class EmailPKData(models.Model):
|
||||||
data = models.EmailField(primary_key=True)
|
data = models.EmailField(primary_key=True)
|
||||||
|
|
||||||
@ -155,7 +161,7 @@ class FilePathPKData(models.Model):
|
|||||||
data = models.FilePathField(primary_key=True)
|
data = models.FilePathField(primary_key=True)
|
||||||
|
|
||||||
class FloatPKData(models.Model):
|
class FloatPKData(models.Model):
|
||||||
data = models.FloatField(primary_key=True, decimal_places=3, max_digits=5)
|
data = models.FloatField(primary_key=True)
|
||||||
|
|
||||||
class IntegerPKData(models.Model):
|
class IntegerPKData(models.Model):
|
||||||
data = models.IntegerField(primary_key=True)
|
data = models.IntegerField(primary_key=True)
|
||||||
|
@ -16,6 +16,10 @@ from django.db import transaction
|
|||||||
from django.core import management
|
from django.core import management
|
||||||
|
|
||||||
from models import *
|
from models import *
|
||||||
|
try:
|
||||||
|
import decimal
|
||||||
|
except ImportError:
|
||||||
|
from django.utils import _decimal as decimal
|
||||||
|
|
||||||
# A set of functions that can be used to recreate
|
# A set of functions that can be used to recreate
|
||||||
# test data objects of various kinds
|
# test data objects of various kinds
|
||||||
@ -118,10 +122,14 @@ test_data = [
|
|||||||
(data_obj, 51, FileData, None),
|
(data_obj, 51, FileData, None),
|
||||||
(data_obj, 60, FilePathData, "/foo/bar/whiz.txt"),
|
(data_obj, 60, FilePathData, "/foo/bar/whiz.txt"),
|
||||||
(data_obj, 61, FilePathData, None),
|
(data_obj, 61, FilePathData, None),
|
||||||
(data_obj, 70, FloatData, 12.345),
|
(data_obj, 70, DecimalData, decimal.Decimal('12.345')),
|
||||||
(data_obj, 71, FloatData, -12.345),
|
(data_obj, 71, DecimalData, decimal.Decimal('-12.345')),
|
||||||
(data_obj, 72, FloatData, 0.0),
|
(data_obj, 72, DecimalData, decimal.Decimal('0.0')),
|
||||||
(data_obj, 73, FloatData, None),
|
(data_obj, 73, DecimalData, None),
|
||||||
|
(data_obj, 74, FloatData, 12.345),
|
||||||
|
(data_obj, 75, FloatData, -12.345),
|
||||||
|
(data_obj, 76, FloatData, 0.0),
|
||||||
|
(data_obj, 77, FloatData, None),
|
||||||
(data_obj, 80, IntegerData, 123456789),
|
(data_obj, 80, IntegerData, 123456789),
|
||||||
(data_obj, 81, IntegerData, -123456789),
|
(data_obj, 81, IntegerData, -123456789),
|
||||||
(data_obj, 82, IntegerData, 0),
|
(data_obj, 82, IntegerData, 0),
|
||||||
@ -204,9 +212,12 @@ The end."""),
|
|||||||
(pk_obj, 640, EmailPKData, "hovercraft@example.com"),
|
(pk_obj, 640, EmailPKData, "hovercraft@example.com"),
|
||||||
(pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'),
|
(pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'),
|
||||||
(pk_obj, 660, FilePathPKData, "/foo/bar/whiz.txt"),
|
(pk_obj, 660, FilePathPKData, "/foo/bar/whiz.txt"),
|
||||||
(pk_obj, 670, FloatPKData, 12.345),
|
(pk_obj, 670, DecimalPKData, decimal.Decimal('12.345')),
|
||||||
(pk_obj, 671, FloatPKData, -12.345),
|
(pk_obj, 671, DecimalPKData, decimal.Decimal('-12.345')),
|
||||||
(pk_obj, 672, FloatPKData, 0.0),
|
(pk_obj, 672, DecimalPKData, decimal.Decimal('0.0')),
|
||||||
|
(pk_obj, 673, FloatPKData, 12.345),
|
||||||
|
(pk_obj, 674, FloatPKData, -12.345),
|
||||||
|
(pk_obj, 675, FloatPKData, 0.0),
|
||||||
(pk_obj, 680, IntegerPKData, 123456789),
|
(pk_obj, 680, IntegerPKData, 123456789),
|
||||||
(pk_obj, 681, IntegerPKData, -123456789),
|
(pk_obj, 681, IntegerPKData, -123456789),
|
||||||
(pk_obj, 682, IntegerPKData, 0),
|
(pk_obj, 682, IntegerPKData, 0),
|
||||||
|
@ -3,11 +3,15 @@
|
|||||||
import os, sys, traceback
|
import os, sys, traceback
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
import django.contrib as contrib
|
||||||
|
CONTRIB_DIR_NAME = 'django.contrib'
|
||||||
MODEL_TESTS_DIR_NAME = 'modeltests'
|
MODEL_TESTS_DIR_NAME = 'modeltests'
|
||||||
REGRESSION_TESTS_DIR_NAME = 'regressiontests'
|
REGRESSION_TESTS_DIR_NAME = 'regressiontests'
|
||||||
|
|
||||||
TEST_DATABASE_NAME = 'django_test_db'
|
TEST_DATABASE_NAME = 'django_test_db'
|
||||||
TEST_TEMPLATE_DIR = 'templates'
|
TEST_TEMPLATE_DIR = 'templates'
|
||||||
|
|
||||||
|
CONTRIB_DIR = os.path.dirname(contrib.__file__)
|
||||||
MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME)
|
MODEL_TEST_DIR = os.path.join(os.path.dirname(__file__), MODEL_TESTS_DIR_NAME)
|
||||||
REGRESSION_TEST_DIR = os.path.join(os.path.dirname(__file__), REGRESSION_TESTS_DIR_NAME)
|
REGRESSION_TEST_DIR = os.path.join(os.path.dirname(__file__), REGRESSION_TESTS_DIR_NAME)
|
||||||
|
|
||||||
@ -24,7 +28,7 @@ ALWAYS_INSTALLED_APPS = [
|
|||||||
|
|
||||||
def get_test_models():
|
def get_test_models():
|
||||||
models = []
|
models = []
|
||||||
for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR):
|
for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR), (CONTRIB_DIR_NAME, CONTRIB_DIR):
|
||||||
for f in os.listdir(dirpath):
|
for f in os.listdir(dirpath):
|
||||||
if f.startswith('__init__') or f.startswith('.') or f.startswith('sql') or f.startswith('invalid'):
|
if f.startswith('__init__') or f.startswith('.') or f.startswith('sql') or f.startswith('invalid'):
|
||||||
continue
|
continue
|
||||||
@ -33,7 +37,7 @@ def get_test_models():
|
|||||||
|
|
||||||
def get_invalid_models():
|
def get_invalid_models():
|
||||||
models = []
|
models = []
|
||||||
for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR):
|
for loc, dirpath in (MODEL_TESTS_DIR_NAME, MODEL_TEST_DIR), (REGRESSION_TESTS_DIR_NAME, REGRESSION_TEST_DIR), (CONTRIB_DIR_NAME, CONTRIB_DIR):
|
||||||
for f in os.listdir(dirpath):
|
for f in os.listdir(dirpath):
|
||||||
if f.startswith('__init__') or f.startswith('.') or f.startswith('sql'):
|
if f.startswith('__init__') or f.startswith('.') or f.startswith('sql'):
|
||||||
continue
|
continue
|
||||||
@ -109,8 +113,10 @@ def django_tests(verbosity, tests_to_run):
|
|||||||
if verbosity >= 1:
|
if verbosity >= 1:
|
||||||
print "Importing model %s" % model_name
|
print "Importing model %s" % model_name
|
||||||
mod = load_app(model_label)
|
mod = load_app(model_label)
|
||||||
settings.INSTALLED_APPS.append(model_label)
|
if mod:
|
||||||
test_models.append(mod)
|
if model_label not in settings.INSTALLED_APPS:
|
||||||
|
settings.INSTALLED_APPS.append(model_label)
|
||||||
|
test_models.append(mod)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
sys.stderr.write("Error while importing %s:" % model_name + ''.join(traceback.format_exception(*sys.exc_info())[1:]))
|
sys.stderr.write("Error while importing %s:" % model_name + ''.join(traceback.format_exception(*sys.exc_info())[1:]))
|
||||||
continue
|
continue
|
||||||
|
Loading…
x
Reference in New Issue
Block a user