mirror of
https://github.com/django/django.git
synced 2025-07-04 17:59:13 +00:00
newforms-admin: Merged to [5571]
git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@5572 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
7a981380de
commit
6f4e933fcc
9
AUTHORS
9
AUTHORS
@ -100,11 +100,14 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Marc Fargas <telenieko@telenieko.com>
|
Marc Fargas <telenieko@telenieko.com>
|
||||||
favo@exoweb.net
|
favo@exoweb.net
|
||||||
Bill Fenner <fenner@gmail.com>
|
Bill Fenner <fenner@gmail.com>
|
||||||
|
Stefane Fermgier <sf@fermigier.com>
|
||||||
|
Afonso Fernández Nogueira <fonzzo.django@gmail.com>
|
||||||
Matthew Flanagan <http://wadofstuff.blogspot.com>
|
Matthew Flanagan <http://wadofstuff.blogspot.com>
|
||||||
Eric Floehr <eric@intellovations.com>
|
Eric Floehr <eric@intellovations.com>
|
||||||
Jorge Gajon <gajon@gajon.org>
|
Jorge Gajon <gajon@gajon.org>
|
||||||
gandalf@owca.info
|
gandalf@owca.info
|
||||||
Baishampayan Ghose
|
Baishampayan Ghose
|
||||||
|
glin@seznam.cz
|
||||||
martin.glueck@gmail.com
|
martin.glueck@gmail.com
|
||||||
GomoX <gomo@datafull.com>
|
GomoX <gomo@datafull.com>
|
||||||
Simon Greenhill <dev@simon.net.nz>
|
Simon Greenhill <dev@simon.net.nz>
|
||||||
@ -119,6 +122,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Ian Holsman <http://feh.holsman.net/>
|
Ian Holsman <http://feh.holsman.net/>
|
||||||
Kieran Holland <http://www.kieranholland.com>
|
Kieran Holland <http://www.kieranholland.com>
|
||||||
Sung-Jin Hong <serialx.net@gmail.com>
|
Sung-Jin Hong <serialx.net@gmail.com>
|
||||||
|
Richard House <Richard.House@i-logue.com>
|
||||||
Robert Rock Howard <http://djangomojo.com/>
|
Robert Rock Howard <http://djangomojo.com/>
|
||||||
Jason Huggins <http://www.jrandolph.com/blog/>
|
Jason Huggins <http://www.jrandolph.com/blog/>
|
||||||
Hyun Mi Ae
|
Hyun Mi Ae
|
||||||
@ -170,6 +174,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
mikko@sorl.net
|
mikko@sorl.net
|
||||||
mitakummaa@gmail.com
|
mitakummaa@gmail.com
|
||||||
mmarshall
|
mmarshall
|
||||||
|
Reza Mohammadi <reza@zeerak.ir>
|
||||||
Eric Moritz <http://eric.themoritzfamily.com/>
|
Eric Moritz <http://eric.themoritzfamily.com/>
|
||||||
mrmachine <real.human@mrmachine.net>
|
mrmachine <real.human@mrmachine.net>
|
||||||
Robin Munn <http://www.geekforgod.com/>
|
Robin Munn <http://www.geekforgod.com/>
|
||||||
@ -183,6 +188,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Jay Parlar <parlar@gmail.com>
|
Jay Parlar <parlar@gmail.com>
|
||||||
pavithran s <pavithran.s@gmail.com>
|
pavithran s <pavithran.s@gmail.com>
|
||||||
Barry Pederson <bp@barryp.org>
|
Barry Pederson <bp@barryp.org>
|
||||||
|
petr.marhoun@gmail.com
|
||||||
pgross@thoughtworks.com
|
pgross@thoughtworks.com
|
||||||
phaedo <http://phaedo.cx/>
|
phaedo <http://phaedo.cx/>
|
||||||
phil@produxion.net
|
phil@produxion.net
|
||||||
@ -224,6 +230,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Frank Tegtmeyer <fte@fte.to>
|
Frank Tegtmeyer <fte@fte.to>
|
||||||
thebjorn <bp@datakortet.no>
|
thebjorn <bp@datakortet.no>
|
||||||
Zach Thompson <zthompson47@gmail.com>
|
Zach Thompson <zthompson47@gmail.com>
|
||||||
|
tibimicu@gmax.net
|
||||||
Tom Tobin
|
Tom Tobin
|
||||||
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
Joe Topjian <http://joe.terrarum.net/geek/code/python/django/>
|
||||||
torne-django@wolfpuppy.org.uk
|
torne-django@wolfpuppy.org.uk
|
||||||
@ -233,6 +240,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Amit Upadhyay
|
Amit Upadhyay
|
||||||
Geert Vanderkelen
|
Geert Vanderkelen
|
||||||
viestards.lists@gmail.com
|
viestards.lists@gmail.com
|
||||||
|
Vlado <vlado@labath.org>
|
||||||
Milton Waddams
|
Milton Waddams
|
||||||
wam-djangobug@wamber.net
|
wam-djangobug@wamber.net
|
||||||
wangchun <yaohua2000@gmail.com>
|
wangchun <yaohua2000@gmail.com>
|
||||||
@ -245,6 +253,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
wojtek
|
wojtek
|
||||||
ye7cakf02@sneakemail.com
|
ye7cakf02@sneakemail.com
|
||||||
ymasuda@ethercube.com
|
ymasuda@ethercube.com
|
||||||
|
Jarek Zgoda <jarek.zgoda@gmail.com>
|
||||||
Cheng Zhang
|
Cheng Zhang
|
||||||
|
|
||||||
A big THANK YOU goes to:
|
A big THANK YOU goes to:
|
||||||
|
@ -48,6 +48,7 @@ LANGUAGES = (
|
|||||||
('en', gettext_noop('English')),
|
('en', gettext_noop('English')),
|
||||||
('es', gettext_noop('Spanish')),
|
('es', gettext_noop('Spanish')),
|
||||||
('es_AR', gettext_noop('Argentinean Spanish')),
|
('es_AR', gettext_noop('Argentinean Spanish')),
|
||||||
|
('fa', gettext_noop('Persian')),
|
||||||
('fi', gettext_noop('Finnish')),
|
('fi', gettext_noop('Finnish')),
|
||||||
('fr', gettext_noop('French')),
|
('fr', gettext_noop('French')),
|
||||||
('gl', gettext_noop('Galician')),
|
('gl', gettext_noop('Galician')),
|
||||||
|
BIN
django/conf/locale/bn/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/bn/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
118
django/conf/locale/bn/LC_MESSAGES/djangojs.po
Normal file
118
django/conf/locale/bn/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-06-28 17:36+1000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Now"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr ""
|
Binary file not shown.
@ -1,20 +1,18 @@
|
|||||||
# translation of django.po to
|
# translation of django.po to
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the Django package.
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
|
|
||||||
#
|
#
|
||||||
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: 2007-05-25 13:04+0200\n"
|
"POT-Creation-Date: 2007-06-25 17:31+0200\n"
|
||||||
"PO-Revision-Date: 2007-05-25 13:04+0200\n"
|
"PO-Revision-Date: 2007-06-25 17:47+0200\n"
|
||||||
"Last-Translator: Marc Fargas <marc@fargas.com>\n"
|
"Last-Translator: Marc Fargas <telenieko@telenieko.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=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: VIM 7.0\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
#: template/defaultfilters.py:491
|
#: template/defaultfilters.py:491
|
||||||
msgid "yes,no,maybe"
|
msgid "yes,no,maybe"
|
||||||
@ -42,38 +40,38 @@ msgstr "%.1f MB"
|
|||||||
msgid "%.1f GB"
|
msgid "%.1f GB"
|
||||||
msgstr "%.1f GB"
|
msgstr "%.1f GB"
|
||||||
|
|
||||||
#: newforms/models.py:173 newforms/fields.py:432
|
#: newforms/models.py:172 newforms/fields.py:432
|
||||||
msgid "Select a valid choice. That choice is not one of the available choices."
|
msgid "Select a valid choice. That choice is not one of the available choices."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Esculli una opció vàlida; Aquesta opció no és una de les opcions disponibles."
|
"Esculli una opció vàlida; Aquesta opció no és una de les opcions disponibles."
|
||||||
|
|
||||||
#: newforms/models.py:186 newforms/fields.py:87 newforms/fields.py:444
|
#: newforms/models.py:185 newforms/fields.py:87 newforms/fields.py:444
|
||||||
#: newforms/fields.py:520 newforms/fields.py:531 oldforms/__init__.py:357
|
#: newforms/fields.py:522 newforms/fields.py:533 oldforms/__init__.py:357
|
||||||
#: db/models/fields/__init__.py:121 db/models/fields/__init__.py:278
|
#: db/models/fields/__init__.py:126 db/models/fields/__init__.py:283
|
||||||
#: db/models/fields/__init__.py:675 db/models/fields/__init__.py:686
|
#: db/models/fields/__init__.py:680 db/models/fields/__init__.py:691
|
||||||
msgid "This field is required."
|
msgid "This field is required."
|
||||||
msgstr "Aquest camp és obligatori."
|
msgstr "Aquest camp és obligatori."
|
||||||
|
|
||||||
#: newforms/models.py:190 newforms/fields.py:448 newforms/fields.py:524
|
#: newforms/models.py:189 newforms/fields.py:448 newforms/fields.py:526
|
||||||
msgid "Enter a list of values."
|
msgid "Enter a list of values."
|
||||||
msgstr "Introdueixi una llista de valors."
|
msgstr "Introdueixi una llista de valors."
|
||||||
|
|
||||||
#: newforms/models.py:196 newforms/fields.py:457
|
#: newforms/models.py:195 newforms/fields.py:457
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Select a valid choice. %s is not one of the available choices."
|
msgid "Select a valid choice. %s is not one of the available choices."
|
||||||
msgstr "Esculli una opció vàlida; %s' no és una de les opcions vàlides."
|
msgstr "Esculli una opció vàlida; %s' no és una de les opcions vàlides."
|
||||||
|
|
||||||
#: newforms/widgets.py:182 contrib/admin/filterspecs.py:150
|
#: newforms/widgets.py:181 contrib/admin/filterspecs.py:150
|
||||||
#: oldforms/__init__.py:577
|
#: oldforms/__init__.py:577
|
||||||
msgid "Unknown"
|
msgid "Unknown"
|
||||||
msgstr "Desconegut"
|
msgstr "Desconegut"
|
||||||
|
|
||||||
#: newforms/widgets.py:182 contrib/admin/filterspecs.py:143
|
#: newforms/widgets.py:181 contrib/admin/filterspecs.py:143
|
||||||
#: oldforms/__init__.py:577
|
#: oldforms/__init__.py:577
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr "Si"
|
msgstr "Si"
|
||||||
|
|
||||||
#: newforms/widgets.py:182 contrib/admin/filterspecs.py:143
|
#: newforms/widgets.py:181 contrib/admin/filterspecs.py:143
|
||||||
#: oldforms/__init__.py:577
|
#: oldforms/__init__.py:577
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "No"
|
msgstr "No"
|
||||||
@ -121,11 +119,11 @@ msgstr "Asseguris de que no hi ha més de %s decimals."
|
|||||||
msgid "Ensure that there are no more than %s digits before the decimal point."
|
msgid "Ensure that there are no more than %s digits before the decimal point."
|
||||||
msgstr "Asseguris de que no hia ha més de %s dígits decimals."
|
msgstr "Asseguris de que no hia ha més de %s dígits decimals."
|
||||||
|
|
||||||
#: newforms/fields.py:233
|
#: newforms/fields.py:233 newforms/fields.py:566
|
||||||
msgid "Enter a valid date."
|
msgid "Enter a valid date."
|
||||||
msgstr "Introdueixi una data vàlida."
|
msgstr "Introdueixi una data vàlida."
|
||||||
|
|
||||||
#: newforms/fields.py:260
|
#: newforms/fields.py:260 newforms/fields.py:568
|
||||||
msgid "Enter a valid time."
|
msgid "Enter a valid time."
|
||||||
msgstr "Introdueixi una hora vàlida."
|
msgstr "Introdueixi una hora vàlida."
|
||||||
|
|
||||||
@ -198,118 +196,122 @@ msgid "Argentinean Spanish"
|
|||||||
msgstr "Castellà Argentí"
|
msgstr "Castellà Argentí"
|
||||||
|
|
||||||
#: conf/global_settings.py:51
|
#: conf/global_settings.py:51
|
||||||
|
msgid "Persian"
|
||||||
|
msgstr "Persa"
|
||||||
|
|
||||||
|
#: conf/global_settings.py:52
|
||||||
msgid "Finnish"
|
msgid "Finnish"
|
||||||
msgstr "Finlandès"
|
msgstr "Finlandès"
|
||||||
|
|
||||||
#: conf/global_settings.py:52
|
#: conf/global_settings.py:53
|
||||||
msgid "French"
|
msgid "French"
|
||||||
msgstr "Francès"
|
msgstr "Francès"
|
||||||
|
|
||||||
#: conf/global_settings.py:53
|
#: conf/global_settings.py:54
|
||||||
msgid "Galician"
|
msgid "Galician"
|
||||||
msgstr "Galleg"
|
msgstr "Galleg"
|
||||||
|
|
||||||
#: conf/global_settings.py:54
|
#: conf/global_settings.py:55
|
||||||
msgid "Hungarian"
|
msgid "Hungarian"
|
||||||
msgstr "Húngar"
|
msgstr "Húngar"
|
||||||
|
|
||||||
#: conf/global_settings.py:55
|
#: conf/global_settings.py:56
|
||||||
msgid "Hebrew"
|
msgid "Hebrew"
|
||||||
msgstr "Hebreu"
|
msgstr "Hebreu"
|
||||||
|
|
||||||
#: conf/global_settings.py:56
|
#: conf/global_settings.py:57
|
||||||
msgid "Icelandic"
|
msgid "Icelandic"
|
||||||
msgstr "Islandès"
|
msgstr "Islandès"
|
||||||
|
|
||||||
#: conf/global_settings.py:57
|
#: conf/global_settings.py:58
|
||||||
msgid "Italian"
|
msgid "Italian"
|
||||||
msgstr "Italià"
|
msgstr "Italià"
|
||||||
|
|
||||||
#: conf/global_settings.py:58
|
#: conf/global_settings.py:59
|
||||||
msgid "Japanese"
|
msgid "Japanese"
|
||||||
msgstr "Japonès"
|
msgstr "Japonès"
|
||||||
|
|
||||||
#: conf/global_settings.py:59
|
#: conf/global_settings.py:60
|
||||||
msgid "Korean"
|
msgid "Korean"
|
||||||
msgstr "Coreà"
|
msgstr "Coreà"
|
||||||
|
|
||||||
#: conf/global_settings.py:60
|
#: conf/global_settings.py:61
|
||||||
msgid "Kannada"
|
msgid "Kannada"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: conf/global_settings.py:61
|
|
||||||
msgid "Latvian"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: conf/global_settings.py:62
|
#: conf/global_settings.py:62
|
||||||
|
msgid "Latvian"
|
||||||
|
msgstr "Letó"
|
||||||
|
|
||||||
|
#: conf/global_settings.py:63
|
||||||
msgid "Macedonian"
|
msgid "Macedonian"
|
||||||
msgstr "Macedoni"
|
msgstr "Macedoni"
|
||||||
|
|
||||||
#: conf/global_settings.py:63
|
#: conf/global_settings.py:64
|
||||||
msgid "Dutch"
|
msgid "Dutch"
|
||||||
msgstr "Holandès"
|
msgstr "Holandès"
|
||||||
|
|
||||||
#: conf/global_settings.py:64
|
#: conf/global_settings.py:65
|
||||||
msgid "Norwegian"
|
msgid "Norwegian"
|
||||||
msgstr "Norueg"
|
msgstr "Norueg"
|
||||||
|
|
||||||
#: conf/global_settings.py:65
|
#: conf/global_settings.py:66
|
||||||
msgid "Polish"
|
msgid "Polish"
|
||||||
msgstr "Polac"
|
msgstr "Polac"
|
||||||
|
|
||||||
#: conf/global_settings.py:66
|
#: conf/global_settings.py:67
|
||||||
msgid "Portugese"
|
msgid "Portugese"
|
||||||
msgstr "Portuguès"
|
msgstr "Portuguès"
|
||||||
|
|
||||||
#: conf/global_settings.py:67
|
#: conf/global_settings.py:68
|
||||||
msgid "Brazilian"
|
msgid "Brazilian"
|
||||||
msgstr "Brasileny"
|
msgstr "Brasileny"
|
||||||
|
|
||||||
#: conf/global_settings.py:68
|
#: conf/global_settings.py:69
|
||||||
msgid "Romanian"
|
msgid "Romanian"
|
||||||
msgstr "Rumanès"
|
msgstr "Rumanès"
|
||||||
|
|
||||||
#: conf/global_settings.py:69
|
#: conf/global_settings.py:70
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
msgstr "Rús"
|
msgstr "Rús"
|
||||||
|
|
||||||
#: conf/global_settings.py:70
|
#: conf/global_settings.py:71
|
||||||
msgid "Slovak"
|
msgid "Slovak"
|
||||||
msgstr "Eslovac"
|
msgstr "Eslovac"
|
||||||
|
|
||||||
#: conf/global_settings.py:71
|
#: conf/global_settings.py:72
|
||||||
msgid "Slovenian"
|
msgid "Slovenian"
|
||||||
msgstr "Esloveni"
|
msgstr "Esloveni"
|
||||||
|
|
||||||
#: conf/global_settings.py:72
|
#: conf/global_settings.py:73
|
||||||
msgid "Serbian"
|
msgid "Serbian"
|
||||||
msgstr "Serbi"
|
msgstr "Serbi"
|
||||||
|
|
||||||
#: conf/global_settings.py:73
|
#: conf/global_settings.py:74
|
||||||
msgid "Swedish"
|
msgid "Swedish"
|
||||||
msgstr "Suec"
|
msgstr "Suec"
|
||||||
|
|
||||||
#: conf/global_settings.py:74
|
|
||||||
msgid "Tamil"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: conf/global_settings.py:75
|
#: conf/global_settings.py:75
|
||||||
msgid "Telugu"
|
msgid "Tamil"
|
||||||
msgstr ""
|
msgstr "Tàmil"
|
||||||
|
|
||||||
#: conf/global_settings.py:76
|
#: conf/global_settings.py:76
|
||||||
|
msgid "Telugu"
|
||||||
|
msgstr "Telugu"
|
||||||
|
|
||||||
|
#: conf/global_settings.py:77
|
||||||
msgid "Turkish"
|
msgid "Turkish"
|
||||||
msgstr "Turc"
|
msgstr "Turc"
|
||||||
|
|
||||||
#: conf/global_settings.py:77
|
#: conf/global_settings.py:78
|
||||||
msgid "Ukrainian"
|
msgid "Ukrainian"
|
||||||
msgstr "Ucranià"
|
msgstr "Ucranià"
|
||||||
|
|
||||||
#: conf/global_settings.py:78
|
#: conf/global_settings.py:79
|
||||||
msgid "Simplified Chinese"
|
msgid "Simplified Chinese"
|
||||||
msgstr "Xinés simplificat"
|
msgstr "Xinés simplificat"
|
||||||
|
|
||||||
#: conf/global_settings.py:79
|
#: conf/global_settings.py:80
|
||||||
msgid "Traditional Chinese"
|
msgid "Traditional Chinese"
|
||||||
msgstr "Xinés tradicional"
|
msgstr "Xinés tradicional"
|
||||||
|
|
||||||
@ -576,17 +578,15 @@ msgid ""
|
|||||||
"comment:\n"
|
"comment:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgid_plural ""
|
|
||||||
"This comment was posted by a user who has posted fewer than %(count)s "
|
"This comment was posted by a user who has posted fewer than %(count)s "
|
||||||
"comments:\n"
|
"comments:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr[0] ""
|
msgstr ""
|
||||||
"Aquest comentari el va enviar un usuari que ha enviat menys de %(count)s "
|
"Aquest comentari el va enviar un usuari que ha enviat menys de %(count)s "
|
||||||
"comentari:\n"
|
"comentari:\n"
|
||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr[1] ""
|
|
||||||
"Aquest comentari el va enviar un usuari que ha enviat menys de %(count)s "
|
"Aquest comentari el va enviar un usuari que ha enviat menys de %(count)s "
|
||||||
"comentaris:\n"
|
"comentaris:\n"
|
||||||
"\n"
|
"\n"
|
||||||
@ -1218,13 +1218,13 @@ msgstr "Editar aquest objecte (nova finestra)"
|
|||||||
msgid "As above, but opens the admin page in a new window."
|
msgid "As above, but opens the admin page in a new window."
|
||||||
msgstr "Com abans, però obre la pàgina d'administració en una nova finestra."
|
msgstr "Com abans, però obre la pàgina d'administració en una nova finestra."
|
||||||
|
|
||||||
#: contrib/admin/views/auth.py:19 contrib/admin/views/main.py:257
|
#: contrib/admin/views/auth.py:19 contrib/admin/views/main.py:262
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
||||||
msgstr "El/la %(name)s \"%(obj)s\".ha estat agregat/da amb èxit."
|
msgstr "El/la %(name)s \"%(obj)s\".ha estat agregat/da amb èxit."
|
||||||
|
|
||||||
#: contrib/admin/views/auth.py:24 contrib/admin/views/main.py:261
|
#: contrib/admin/views/auth.py:24 contrib/admin/views/main.py:266
|
||||||
#: contrib/admin/views/main.py:347
|
#: contrib/admin/views/main.py:352
|
||||||
msgid "You may edit it again below."
|
msgid "You may edit it again below."
|
||||||
msgstr "Pot editar-lo de nou abaix."
|
msgstr "Pot editar-lo de nou abaix."
|
||||||
|
|
||||||
@ -1241,96 +1241,96 @@ msgstr "Canvi de clau exitós"
|
|||||||
msgid "Change password: %s"
|
msgid "Change password: %s"
|
||||||
msgstr "Canviar clau: %s"
|
msgstr "Canviar clau: %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:223
|
#: contrib/admin/views/main.py:228
|
||||||
msgid "Site administration"
|
msgid "Site administration"
|
||||||
msgstr "Lloc administratiu"
|
msgstr "Lloc administratiu"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:271 contrib/admin/views/main.py:356
|
#: contrib/admin/views/main.py:276 contrib/admin/views/main.py:361
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You may add another %s below."
|
msgid "You may add another %s below."
|
||||||
msgstr "Pot agregar un altre %s abaix."
|
msgstr "Pot agregar un altre %s abaix."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:289
|
#: contrib/admin/views/main.py:294
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Add %s"
|
msgid "Add %s"
|
||||||
msgstr "Agregar %s"
|
msgstr "Agregar %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:335
|
#: contrib/admin/views/main.py:340
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Added %s."
|
msgid "Added %s."
|
||||||
msgstr "Agregat %s."
|
msgstr "Agregat %s."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:335 contrib/admin/views/main.py:337
|
#: contrib/admin/views/main.py:340 contrib/admin/views/main.py:342
|
||||||
#: contrib/admin/views/main.py:339 db/models/manipulators.py:308
|
#: contrib/admin/views/main.py:344 db/models/manipulators.py:308
|
||||||
msgid "and"
|
msgid "and"
|
||||||
msgstr "i"
|
msgstr "i"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:337
|
#: contrib/admin/views/main.py:342
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Changed %s."
|
msgid "Changed %s."
|
||||||
msgstr "Modificat %s."
|
msgstr "Modificat %s."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:339
|
#: contrib/admin/views/main.py:344
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Deleted %s."
|
msgid "Deleted %s."
|
||||||
msgstr "Eliminat %s."
|
msgstr "Eliminat %s."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:342
|
#: contrib/admin/views/main.py:347
|
||||||
msgid "No fields changed."
|
msgid "No fields changed."
|
||||||
msgstr "Cap camp canviat."
|
msgstr "Cap camp canviat."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:345
|
#: contrib/admin/views/main.py:350
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
||||||
msgstr "S'ha modificat amb èxist el/la %(name)s \"%(obj)s."
|
msgstr "S'ha modificat amb èxist el/la %(name)s \"%(obj)s."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:353
|
#: contrib/admin/views/main.py:358
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"S'ha agregat amb èxit el/la %(name)s \"%(obj)s\". Pot editar-lo de nou abaix."
|
"S'ha agregat amb èxit el/la %(name)s \"%(obj)s\". Pot editar-lo de nou abaix."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:391
|
#: contrib/admin/views/main.py:396
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change %s"
|
msgid "Change %s"
|
||||||
msgstr "Modificar %s"
|
msgstr "Modificar %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:476
|
#: contrib/admin/views/main.py:481
|
||||||
#, 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 "Un o més %(fieldname)s en %(name)s: %(obj)s"
|
msgstr "Un o més %(fieldname)s en %(name)s: %(obj)s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:481
|
#: contrib/admin/views/main.py:486
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "One or more %(fieldname)s in %(name)s:"
|
msgid "One or more %(fieldname)s in %(name)s:"
|
||||||
msgstr "Un o més %(fieldname)s en %(name)s:"
|
msgstr "Un o més %(fieldname)s en %(name)s:"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:514
|
#: contrib/admin/views/main.py:518
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
||||||
msgstr "El/la %(name)s \"%(obj)s\".ha estat eliminat amb èxit."
|
msgstr "El/la %(name)s \"%(obj)s\".ha estat eliminat amb èxit."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:517
|
#: contrib/admin/views/main.py:521
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
msgstr "Està segur?"
|
msgstr "Està segur?"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:539
|
#: contrib/admin/views/main.py:543
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change history: %s"
|
msgid "Change history: %s"
|
||||||
msgstr "Modificar històric: %s"
|
msgstr "Modificar històric: %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:573
|
#: contrib/admin/views/main.py:577
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Select %s"
|
msgid "Select %s"
|
||||||
msgstr "Seleccioni %s"
|
msgstr "Seleccioni %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:573
|
#: contrib/admin/views/main.py:577
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Select %s to change"
|
msgid "Select %s to change"
|
||||||
msgstr "Seleccioni %s per modificar"
|
msgstr "Seleccioni %s per modificar"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:768
|
#: contrib/admin/views/main.py:772
|
||||||
msgid "Database error"
|
msgid "Database error"
|
||||||
msgstr "Error de/en la base de dades"
|
msgstr "Error de/en la base de dades"
|
||||||
|
|
||||||
@ -1697,35 +1697,35 @@ msgstr "llocs"
|
|||||||
msgid "Logged out"
|
msgid "Logged out"
|
||||||
msgstr "Sessió finalitzada"
|
msgstr "Sessió finalitzada"
|
||||||
|
|
||||||
#: contrib/auth/models.py:44 contrib/auth/models.py:64
|
#: contrib/auth/models.py:49 contrib/auth/models.py:69
|
||||||
msgid "name"
|
msgid "name"
|
||||||
msgstr "nom"
|
msgstr "nom"
|
||||||
|
|
||||||
#: contrib/auth/models.py:46
|
#: contrib/auth/models.py:51
|
||||||
msgid "codename"
|
msgid "codename"
|
||||||
msgstr "nom en clau"
|
msgstr "nom en clau"
|
||||||
|
|
||||||
#: contrib/auth/models.py:49
|
#: contrib/auth/models.py:54
|
||||||
msgid "permission"
|
msgid "permission"
|
||||||
msgstr "permís"
|
msgstr "permís"
|
||||||
|
|
||||||
#: contrib/auth/models.py:50 contrib/auth/models.py:65
|
#: contrib/auth/models.py:55 contrib/auth/models.py:70
|
||||||
msgid "permissions"
|
msgid "permissions"
|
||||||
msgstr "permissos"
|
msgstr "permissos"
|
||||||
|
|
||||||
#: contrib/auth/models.py:68
|
#: contrib/auth/models.py:73
|
||||||
msgid "group"
|
msgid "group"
|
||||||
msgstr "grup"
|
msgstr "grup"
|
||||||
|
|
||||||
#: contrib/auth/models.py:69 contrib/auth/models.py:109
|
#: contrib/auth/models.py:74 contrib/auth/models.py:114
|
||||||
msgid "groups"
|
msgid "groups"
|
||||||
msgstr "grups"
|
msgstr "grups"
|
||||||
|
|
||||||
#: contrib/auth/models.py:99
|
#: contrib/auth/models.py:104
|
||||||
msgid "username"
|
msgid "username"
|
||||||
msgstr "nom d'usuari"
|
msgstr "nom d'usuari"
|
||||||
|
|
||||||
#: contrib/auth/models.py:99
|
#: contrib/auth/models.py:104
|
||||||
msgid ""
|
msgid ""
|
||||||
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
"Required. 30 characters or fewer. Alphanumeric characters only (letters, "
|
||||||
"digits and underscores)."
|
"digits and underscores)."
|
||||||
@ -1733,23 +1733,23 @@ msgstr ""
|
|||||||
"Requerit. 30 o menys caracters. Només caracters alfanumèrics (lletres, "
|
"Requerit. 30 o menys caracters. Només caracters alfanumèrics (lletres, "
|
||||||
"dígits i guions baixos)."
|
"dígits i guions baixos)."
|
||||||
|
|
||||||
#: contrib/auth/models.py:100
|
#: contrib/auth/models.py:105
|
||||||
msgid "first name"
|
msgid "first name"
|
||||||
msgstr "nom propi"
|
msgstr "nom propi"
|
||||||
|
|
||||||
#: contrib/auth/models.py:101
|
#: contrib/auth/models.py:106
|
||||||
msgid "last name"
|
msgid "last name"
|
||||||
msgstr "cognoms"
|
msgstr "cognoms"
|
||||||
|
|
||||||
#: contrib/auth/models.py:102
|
#: contrib/auth/models.py:107
|
||||||
msgid "e-mail address"
|
msgid "e-mail address"
|
||||||
msgstr "adreça de correu electrònic"
|
msgstr "adreça de correu electrònic"
|
||||||
|
|
||||||
#: contrib/auth/models.py:103
|
#: contrib/auth/models.py:108
|
||||||
msgid "password"
|
msgid "password"
|
||||||
msgstr "contrasenya"
|
msgstr "contrasenya"
|
||||||
|
|
||||||
#: contrib/auth/models.py:103
|
#: contrib/auth/models.py:108
|
||||||
msgid ""
|
msgid ""
|
||||||
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
|
"Use '[algo]$[salt]$[hexdigest]' or use the <a href=\"password/\">change "
|
||||||
"password form</a>."
|
"password form</a>."
|
||||||
@ -1757,19 +1757,19 @@ msgstr ""
|
|||||||
"Utilitzi '[algo]$[salt]$[hexdigest]' o el <a href=\"password/\">formulari de "
|
"Utilitzi '[algo]$[salt]$[hexdigest]' o el <a href=\"password/\">formulari de "
|
||||||
"canvi de contrasenya</a>."
|
"canvi de contrasenya</a>."
|
||||||
|
|
||||||
#: contrib/auth/models.py:104
|
#: contrib/auth/models.py:109
|
||||||
msgid "staff status"
|
msgid "staff status"
|
||||||
msgstr "és membre del personal"
|
msgstr "és membre del personal"
|
||||||
|
|
||||||
#: contrib/auth/models.py:104
|
#: contrib/auth/models.py:109
|
||||||
msgid "Designates whether the user can log into this admin site."
|
msgid "Designates whether the user can log into this admin site."
|
||||||
msgstr "Indica si l'usuari pot entrar en el lloc administratiu."
|
msgstr "Indica si l'usuari pot entrar en el lloc administratiu."
|
||||||
|
|
||||||
#: contrib/auth/models.py:105
|
#: contrib/auth/models.py:110
|
||||||
msgid "active"
|
msgid "active"
|
||||||
msgstr "actiu"
|
msgstr "actiu"
|
||||||
|
|
||||||
#: contrib/auth/models.py:105
|
#: contrib/auth/models.py:110
|
||||||
msgid ""
|
msgid ""
|
||||||
"Designates whether this user can log into the Django admin. Unselect this "
|
"Designates whether this user can log into the Django admin. Unselect this "
|
||||||
"instead of deleting accounts."
|
"instead of deleting accounts."
|
||||||
@ -1777,11 +1777,11 @@ msgstr ""
|
|||||||
"Designa si aquest usuari pot iniciar sessió a la interfície administrativa "
|
"Designa si aquest usuari pot iniciar sessió a la interfície administrativa "
|
||||||
"Djano. Deselecciona-ho enlloc de esborrar comptes d'usuari."
|
"Djano. Deselecciona-ho enlloc de esborrar comptes d'usuari."
|
||||||
|
|
||||||
#: contrib/auth/models.py:106
|
#: contrib/auth/models.py:111
|
||||||
msgid "superuser status"
|
msgid "superuser status"
|
||||||
msgstr "estat de superusuari"
|
msgstr "estat de superusuari"
|
||||||
|
|
||||||
#: contrib/auth/models.py:106
|
#: contrib/auth/models.py:111
|
||||||
msgid ""
|
msgid ""
|
||||||
"Designates that this user has all permissions without explicitly assigning "
|
"Designates that this user has all permissions without explicitly assigning "
|
||||||
"them."
|
"them."
|
||||||
@ -1789,15 +1789,15 @@ msgstr ""
|
|||||||
"Designa que aquest usuari té tots els permisos sense assignar-los "
|
"Designa que aquest usuari té tots els permisos sense assignar-los "
|
||||||
"explícitament."
|
"explícitament."
|
||||||
|
|
||||||
#: contrib/auth/models.py:107
|
#: contrib/auth/models.py:112
|
||||||
msgid "last login"
|
msgid "last login"
|
||||||
msgstr "últim inici de sessió"
|
msgstr "últim inici de sessió"
|
||||||
|
|
||||||
#: contrib/auth/models.py:108
|
#: contrib/auth/models.py:113
|
||||||
msgid "date joined"
|
msgid "date joined"
|
||||||
msgstr "data de creació"
|
msgstr "data de creació"
|
||||||
|
|
||||||
#: contrib/auth/models.py:110
|
#: contrib/auth/models.py:115
|
||||||
msgid ""
|
msgid ""
|
||||||
"In addition to the permissions manually assigned, this user will also get "
|
"In addition to the permissions manually assigned, this user will also get "
|
||||||
"all permissions granted to each group he/she is in."
|
"all permissions granted to each group he/she is in."
|
||||||
@ -1805,39 +1805,39 @@ msgstr ""
|
|||||||
"Junt amb els permissos asignats manualment, aquest usuari tindrà, també, els "
|
"Junt amb els permissos asignats manualment, aquest usuari tindrà, també, els "
|
||||||
"permissos dels grups dels que sigui membre."
|
"permissos dels grups dels que sigui membre."
|
||||||
|
|
||||||
#: contrib/auth/models.py:111
|
#: contrib/auth/models.py:116
|
||||||
msgid "user permissions"
|
msgid "user permissions"
|
||||||
msgstr "permissos de l'usuari"
|
msgstr "permissos de l'usuari"
|
||||||
|
|
||||||
#: contrib/auth/models.py:115
|
#: contrib/auth/models.py:120
|
||||||
msgid "user"
|
msgid "user"
|
||||||
msgstr "usuari"
|
msgstr "usuari"
|
||||||
|
|
||||||
#: contrib/auth/models.py:116
|
#: contrib/auth/models.py:121
|
||||||
msgid "users"
|
msgid "users"
|
||||||
msgstr "usuaris"
|
msgstr "usuaris"
|
||||||
|
|
||||||
#: contrib/auth/models.py:122
|
#: contrib/auth/models.py:127
|
||||||
msgid "Personal info"
|
msgid "Personal info"
|
||||||
msgstr "Informaciò personal"
|
msgstr "Informaciò personal"
|
||||||
|
|
||||||
#: contrib/auth/models.py:123
|
#: contrib/auth/models.py:128
|
||||||
msgid "Permissions"
|
msgid "Permissions"
|
||||||
msgstr "permissos"
|
msgstr "permissos"
|
||||||
|
|
||||||
#: contrib/auth/models.py:124
|
#: contrib/auth/models.py:129
|
||||||
msgid "Important dates"
|
msgid "Important dates"
|
||||||
msgstr "Dates importants"
|
msgstr "Dates importants"
|
||||||
|
|
||||||
#: contrib/auth/models.py:125
|
#: contrib/auth/models.py:130
|
||||||
msgid "Groups"
|
msgid "Groups"
|
||||||
msgstr "Grups"
|
msgstr "Grups"
|
||||||
|
|
||||||
#: contrib/auth/models.py:269
|
#: contrib/auth/models.py:273
|
||||||
msgid "message"
|
msgid "message"
|
||||||
msgstr "missatge"
|
msgstr "missatge"
|
||||||
|
|
||||||
#: contrib/auth/models.py:282
|
#: contrib/auth/models.py:286
|
||||||
msgid "AnonymousUser"
|
msgid "AnonymousUser"
|
||||||
msgstr "AnonymousUser"
|
msgstr "AnonymousUser"
|
||||||
|
|
||||||
@ -1861,7 +1861,7 @@ msgstr ""
|
|||||||
msgid "This account is inactive."
|
msgid "This account is inactive."
|
||||||
msgstr "Aquest compte està inactiu"
|
msgstr "Aquest compte està inactiu"
|
||||||
|
|
||||||
#: contrib/auth/forms.py:85
|
#: contrib/auth/forms.py:84
|
||||||
msgid ""
|
msgid ""
|
||||||
"That e-mail address doesn't have an associated user account. Are you sure "
|
"That e-mail address doesn't have an associated user account. Are you sure "
|
||||||
"you've registered?"
|
"you've registered?"
|
||||||
@ -2423,7 +2423,7 @@ msgstr "L'any ha de ser posterior al 1900"
|
|||||||
msgid "Invalid date: %s"
|
msgid "Invalid date: %s"
|
||||||
msgstr "Data invàlida: %s"
|
msgstr "Data invàlida: %s"
|
||||||
|
|
||||||
#: core/validators.py:149 db/models/fields/__init__.py:463
|
#: core/validators.py:149 db/models/fields/__init__.py:468
|
||||||
msgid "Enter a valid date in YYYY-MM-DD format."
|
msgid "Enter a valid date in YYYY-MM-DD format."
|
||||||
msgstr "Introdueixi una data vàlida en el forma AAAA-MM-DD."
|
msgstr "Introdueixi una data vàlida en el forma AAAA-MM-DD."
|
||||||
|
|
||||||
@ -2431,7 +2431,7 @@ msgstr "Introdueixi una data vàlida en el forma AAAA-MM-DD."
|
|||||||
msgid "Enter a valid time in HH:MM format."
|
msgid "Enter a valid time in HH:MM format."
|
||||||
msgstr "Introdueixi una hora vàlida en el format HH:MM."
|
msgstr "Introdueixi una hora vàlida en el format HH:MM."
|
||||||
|
|
||||||
#: core/validators.py:158 db/models/fields/__init__.py:532
|
#: core/validators.py:158 db/models/fields/__init__.py:537
|
||||||
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
msgid "Enter a valid date/time in YYYY-MM-DD HH:MM format."
|
||||||
msgstr "Introdueixi un data/hora vàlida en format YYYY-MM-DD HH:MM."
|
msgstr "Introdueixi un data/hora vàlida en format YYYY-MM-DD HH:MM."
|
||||||
|
|
||||||
@ -2558,35 +2558,29 @@ msgstr "Si us plau, introdueixi un número decimal vàlid."
|
|||||||
#: core/validators.py:423
|
#: core/validators.py:423
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid decimal number with at most %s total digit."
|
msgid "Please enter a valid decimal number with at most %s total digit."
|
||||||
msgid_plural ""
|
|
||||||
"Please enter a valid decimal number with at most %s total digits."
|
"Please enter a valid decimal number with at most %s total digits."
|
||||||
msgstr[0] ""
|
msgstr ""
|
||||||
"Si us plau, introdueixi un número decimal vàlid amb no més de %s digit."
|
"Si us plau, introdueixi un número decimal vàlid amb no més de %s digit."
|
||||||
msgstr[1] ""
|
|
||||||
"Si us plau, introdueixi un número decimal vàlid amb no més de %s digits."
|
"Si us plau, introdueixi un número decimal vàlid amb no més de %s digits."
|
||||||
|
|
||||||
#: core/validators.py:426
|
#: core/validators.py:426
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"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 digit."
|
||||||
msgid_plural ""
|
|
||||||
"Please enter a valid decimal number with a whole part of at most %s digits."
|
"Please enter a valid decimal number with a whole part of at most %s digits."
|
||||||
msgstr[0] ""
|
msgstr ""
|
||||||
"Si us plau, introdueixi un número decimal vàlid amb la part entera amb com a "
|
"Si us plau, introdueixi un número decimal vàlid amb la part entera amb com a "
|
||||||
"màxim %s dígit."
|
"màxim %s dígit."
|
||||||
msgstr[1] ""
|
|
||||||
"Si us plau, introdueixi un número decimal vàlid amb la part entera amb com a "
|
"Si us plau, introdueixi un número decimal vàlid amb la part entera amb com a "
|
||||||
"màxim %s dígits."
|
"màxim %s dígits."
|
||||||
|
|
||||||
#: core/validators.py:429
|
#: core/validators.py:429
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid decimal number with at most %s decimal place."
|
msgid "Please enter a valid decimal number with at most %s decimal place."
|
||||||
msgid_plural ""
|
|
||||||
"Please enter a valid decimal number with at most %s decimal places."
|
"Please enter a valid decimal number with at most %s decimal places."
|
||||||
msgstr[0] ""
|
msgstr ""
|
||||||
"Si us plau, introdueixi un número decimal vàlid amb no més de %s dígit en la "
|
"Si us plau, introdueixi un número decimal vàlid amb no més de %s dígit en la "
|
||||||
"part decimal."
|
"part decimal."
|
||||||
msgstr[1] ""
|
|
||||||
"Si us plau, introdueixi un número decimal vàlid amb no més de %s dígits en "
|
"Si us plau, introdueixi un número decimal vàlid amb no més de %s dígits en "
|
||||||
"la part decimal."
|
"la part decimal."
|
||||||
|
|
||||||
@ -2983,52 +2977,51 @@ msgstr "Ja existeix un %(object)s del tipus %(type)s amb aquest %(field)s."
|
|||||||
msgid "%(optname)s with this %(fieldname)s already exists."
|
msgid "%(optname)s with this %(fieldname)s already exists."
|
||||||
msgstr "Ja existeix %(optname)s amb auqest %(fieldname)s."
|
msgstr "Ja existeix %(optname)s amb auqest %(fieldname)s."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:373
|
#: db/models/fields/__init__.py:378
|
||||||
msgid "This value must be an integer."
|
msgid "This value must be an integer."
|
||||||
msgstr "Aquest valor ha de ser un enter."
|
msgstr "Aquest valor ha de ser un enter."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:408
|
#: db/models/fields/__init__.py:413
|
||||||
msgid "This value must be either True or False."
|
msgid "This value must be either True or False."
|
||||||
msgstr "Aquest valor ha de ser True (Veritat) o False (Fals)"
|
msgstr "Aquest valor ha de ser True (Veritat) o False (Fals)"
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:429
|
#: db/models/fields/__init__.py:434
|
||||||
msgid "This field cannot be null."
|
msgid "This field cannot be null."
|
||||||
msgstr "Aquest camp no pot ser null (estar buit)."
|
msgstr "Aquest camp no pot ser null (estar buit)."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:592
|
#: db/models/fields/__init__.py:597
|
||||||
msgid "This value must be a decimal number."
|
msgid "This value must be a decimal number."
|
||||||
msgstr "Aquest valor ha de ser un número decimal."
|
msgstr "Aquest valor ha de ser un número decimal."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:695
|
#: db/models/fields/__init__.py:700
|
||||||
msgid "Enter a valid filename."
|
msgid "Enter a valid filename."
|
||||||
msgstr "Introdueixi un nom de fitxer vàlid."
|
msgstr "Introdueixi un nom de fitxer vàlid."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:818
|
#: db/models/fields/__init__.py:824
|
||||||
msgid "This value must be either None, True or False."
|
msgid "This value must be either None, True or False."
|
||||||
msgstr "Aquest valor ha de ser None (Cap), True (Veritat) o False (Fals)"
|
msgstr "Aquest valor ha de ser None (Cap), True (Veritat) o False (Fals)"
|
||||||
|
|
||||||
#: db/models/fields/related.py:53
|
#: db/models/fields/related.py:54
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid %s."
|
msgid "Please enter a valid %s."
|
||||||
msgstr "Si us plau, introdueixi un %s vàlid."
|
msgstr "Si us plau, introdueixi un %s vàlid."
|
||||||
|
|
||||||
#: db/models/fields/related.py:642
|
#: db/models/fields/related.py:640
|
||||||
msgid "Separate multiple IDs with commas."
|
msgid "Separate multiple IDs with commas."
|
||||||
msgstr "Separi múltiples IDs amb comes."
|
msgstr "Separi múltiples IDs amb comes."
|
||||||
|
|
||||||
#: db/models/fields/related.py:644
|
#: db/models/fields/related.py:642
|
||||||
msgid ""
|
msgid ""
|
||||||
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
"Hold down \"Control\", or \"Command\" on a Mac, to select more than one."
|
||||||
msgstr "Premi \"Control\" o \"Command\" en un Mac per escollir més d'un."
|
msgstr "Premi \"Control\" o \"Command\" en un Mac per escollir més d'un."
|
||||||
|
|
||||||
#: db/models/fields/related.py:691
|
#: db/models/fields/related.py:689
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
msgid "Please enter valid %(self)s IDs. The value %(value)r is invalid."
|
||||||
msgid_plural ""
|
|
||||||
"Please enter valid %(self)s IDs. The values %(value)r are invalid."
|
"Please enter valid %(self)s IDs. The values %(value)r are invalid."
|
||||||
msgstr[0] ""
|
msgstr ""
|
||||||
"Si us plau, introdueixi IDs de %(self)s vàlids. El valor %(value)r és "
|
"Si us plau, introdueixi IDs de %(self)s vàlids. El valor %(value)r és "
|
||||||
"invàlid."
|
"invàlid."
|
||||||
msgstr[1] ""
|
|
||||||
"Si us plau, introdueixi IDs de %(self)s vàlids. Els valors %(value)r són "
|
"Si us plau, introdueixi IDs de %(self)s vàlids. Els valors %(value)r són "
|
||||||
"invàlids."
|
"invàlids."
|
||||||
|
|
||||||
|
Binary file not shown.
@ -1,15 +1,14 @@
|
|||||||
# translation of djangojs.po to
|
# translation of djangojs.po to
|
||||||
# Spanish translation for the django-admin JS files.
|
# Catalan translation for the django-admin JS files.
|
||||||
# Copyright (C)
|
# This file is distributed under the same license as the Django package.
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
|
||||||
#
|
#
|
||||||
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-05-20 18:25+0200\n"
|
"POT-Creation-Date: 2007-05-20 18:25+0200\n"
|
||||||
"PO-Revision-Date: 2007-05-20 18:24+0200\n"
|
"PO-Revision-Date: 2007-06-25 17:47+0200\n"
|
||||||
"Last-Translator: Marc Fargas <marc@fargas.com>\n"
|
"Last-Translator: Marc Fargas <telenieko@telenieko.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=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -7,25 +7,34 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Django JavaScript Czech translation\n"
|
"Project-Id-Version: Django JavaScript Czech translation\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2005-12-17 22:26+0100\n"
|
"POT-Creation-Date: 2007-06-18 11:26+0200\n"
|
||||||
"PO-Revision-Date: 2006-05-03 12:04+0100\n"
|
|
||||||
"Last-Translator: \n"
|
|
||||||
"Language-Team: Czech\n"
|
"Language-Team: Czech\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n>1 && n<5 ? 1 : 2;\n"
|
||||||
"X-Poedit-Language: Czech\n"
|
|
||||||
"X-Poedit-Country: CZECH REPUBLIC\n"
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr ""
|
||||||
|
"Leden Únor Březen Duben Květen Červen Červenec Srpen Září Říjen Listopad "
|
||||||
|
"Prosinec"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr "Neděle Pondělí Úterý Středa Čtvrtek Pátek Sobota"
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:33
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
#, perl-format
|
#, perl-format
|
||||||
msgid "Available %s"
|
msgid "Available %s"
|
||||||
msgstr "K dispozici %s"
|
msgstr "Dostupná %s"
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:41
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
msgid "Choose all"
|
msgid "Choose all"
|
||||||
msgstr "Vybrat vše"
|
msgstr "Vybrat vše"
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:46
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
@ -38,75 +47,72 @@ msgstr "Odebrat"
|
|||||||
#: contrib/admin/media/js/SelectFilter2.js:53
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
#, perl-format
|
#, perl-format
|
||||||
msgid "Chosen %s"
|
msgid "Chosen %s"
|
||||||
msgstr "Vybraný %s"
|
msgstr "Vybraná %s"
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:54
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
msgid "Select your choice(s) and click "
|
msgid "Select your choice(s) and click "
|
||||||
msgstr "Vyberte si a klikněte"
|
msgstr "Vyberte si a klikněte "
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:59
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
msgid "Clear all"
|
msgid "Clear all"
|
||||||
msgstr "Vše vymazat"
|
msgstr "Vymazat vše"
|
||||||
|
|
||||||
#: contrib/admin/media/js/dateparse.js:26
|
|
||||||
#: contrib/admin/media/js/calendar.js:24
|
|
||||||
msgid "January February March April May June July August September October November December"
|
|
||||||
msgstr "Leden Únor Březen Duben Květen Červen Červenec Srpen Září Říjen Listopad Prosinec"
|
|
||||||
|
|
||||||
#: contrib/admin/media/js/dateparse.js:27
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
|
||||||
msgstr "Neděle Pondělí Úterý Středa Čtvrtek Pátek Sobota"
|
|
||||||
|
|
||||||
#: contrib/admin/media/js/calendar.js:25
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
#, fuzzy
|
|
||||||
msgid "S M T W T F S"
|
msgid "S M T W T F S"
|
||||||
msgstr "N P U S C P S"
|
msgstr "N P U S C P S"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr "Ukázat"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr "Skrýt"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
msgid "Now"
|
msgid "Now"
|
||||||
msgstr "Nyní"
|
msgstr "Nyní"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
msgid "Clock"
|
msgid "Clock"
|
||||||
msgstr "Hodiny"
|
msgstr "Hodiny"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
msgid "Choose a time"
|
msgid "Choose a time"
|
||||||
msgstr "Vyberte čas"
|
msgstr "Vyberte čas"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
msgid "Midnight"
|
msgid "Midnight"
|
||||||
msgstr "Půlnoc"
|
msgstr "Půlnoc"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
msgid "6 a.m."
|
msgid "6 a.m."
|
||||||
msgstr "6 ráno"
|
msgstr "6 ráno"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
msgid "Noon"
|
msgid "Noon"
|
||||||
msgstr "Poledne"
|
msgstr "Poledne"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Storno"
|
msgstr "Storno"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "Dnes"
|
msgstr "Dnes"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
msgid "Calendar"
|
msgid "Calendar"
|
||||||
msgstr "Kalendář"
|
msgstr "Kalendář"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
msgid "Yesterday"
|
msgid "Yesterday"
|
||||||
msgstr "Včera"
|
msgstr "Včera"
|
||||||
|
|
||||||
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
msgid "Tomorrow"
|
msgid "Tomorrow"
|
||||||
msgstr "Zítra"
|
msgstr "Zítra"
|
||||||
|
|
||||||
|
BIN
django/conf/locale/da/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/da/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
118
django/conf/locale/da/LC_MESSAGES/djangojs.po
Normal file
118
django/conf/locale/da/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-06-28 17:36+1000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Now"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr ""
|
BIN
django/conf/locale/fa/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/fa/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2854
django/conf/locale/fa/LC_MESSAGES/django.po
Normal file
2854
django/conf/locale/fa/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/fa/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/fa/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
118
django/conf/locale/fa/LC_MESSAGES/djangojs.po
Normal file
118
django/conf/locale/fa/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-06-24 22:09+1000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Now"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr ""
|
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.
@ -28,7 +28,8 @@ msgstr "To pole jest wymagane."
|
|||||||
msgid "Ensure your text is less than %s character."
|
msgid "Ensure your text is less than %s character."
|
||||||
msgid_plural "Ensure your text is less than %s characters."
|
msgid_plural "Ensure your text is less than %s characters."
|
||||||
msgstr[0] "Upewnij się, że tekst ma mniej niż %s znak."
|
msgstr[0] "Upewnij się, że tekst ma mniej niż %s znak."
|
||||||
msgstr[1] "Upewnij się, że tekst ma mniej niż %s znaków."
|
msgstr[1] "Upewnij się, że tekst ma mniej niż %s znaki."
|
||||||
|
msgstr[2] "Upewnij się, że tekst ma mniej niż %s znaków."
|
||||||
|
|
||||||
#: oldforms/__init__.py:397
|
#: oldforms/__init__.py:397
|
||||||
msgid "Line breaks are not allowed here."
|
msgid "Line breaks are not allowed here."
|
||||||
@ -75,7 +76,7 @@ msgid "Enter a whole number between 0 and 32,767."
|
|||||||
msgstr "Proszę wpisać liczbę całkowitą z zakresu od 0 do 32 767"
|
msgstr "Proszę wpisać liczbę całkowitą z zakresu od 0 do 32 767"
|
||||||
|
|
||||||
#: db/models/manipulators.py:307
|
#: db/models/manipulators.py:307
|
||||||
#, fuzzy, 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 "%(object)s z %(type)s już istnieje dla %(field)s."
|
msgstr "%(object)s z %(type)s już istnieje dla %(field)s."
|
||||||
|
|
||||||
@ -85,7 +86,7 @@ msgid "and"
|
|||||||
msgstr "i"
|
msgstr "i"
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:42
|
#: db/models/fields/__init__.py:42
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "%(optname)s with this %(fieldname)s already exists."
|
msgid "%(optname)s with this %(fieldname)s already exists."
|
||||||
msgstr "Już istnieje %(optname)s z %(fieldname)s."
|
msgstr "Już istnieje %(optname)s z %(fieldname)s."
|
||||||
|
|
||||||
@ -142,6 +143,9 @@ msgstr[0] ""
|
|||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
"Proszę podać poprawne identyfikatory %(self)s. Wartości %(value)r są "
|
"Proszę podać poprawne identyfikatory %(self)s. Wartości %(value)r są "
|
||||||
"niepoprawne."
|
"niepoprawne."
|
||||||
|
msgstr[2] ""
|
||||||
|
"Proszę podać poprawne identyfikatory %(self)s. Wartości %(value)r są "
|
||||||
|
"niepoprawne."
|
||||||
|
|
||||||
#: conf/global_settings.py:39
|
#: conf/global_settings.py:39
|
||||||
msgid "Arabic"
|
msgid "Arabic"
|
||||||
@ -370,7 +374,7 @@ msgstr "Niepoprawna data: %s"
|
|||||||
|
|
||||||
#: core/validators.py:153
|
#: core/validators.py:153
|
||||||
msgid "Enter a valid time in HH:MM format."
|
msgid "Enter a valid time in HH:MM format."
|
||||||
msgstr "Proszę wpisać poprawną godzinę w formacie GG:MM."
|
msgstr "Proszę wpisać poprawną godzinę w formacie HH:MM."
|
||||||
|
|
||||||
#: core/validators.py:162 newforms/fields.py:271
|
#: core/validators.py:162 newforms/fields.py:271
|
||||||
msgid "Enter a valid e-mail address."
|
msgid "Enter a valid e-mail address."
|
||||||
@ -439,6 +443,7 @@ msgid "Watch your mouth! The word %s is not allowed here."
|
|||||||
msgid_plural "Watch your mouth! The words %s are not allowed here."
|
msgid_plural "Watch your mouth! The words %s are not allowed here."
|
||||||
msgstr[0] "Nie wolno przeklinać! Słowo %s nie jest dozwolone."
|
msgstr[0] "Nie wolno przeklinać! Słowo %s nie jest dozwolone."
|
||||||
msgstr[1] "Nie wolno przeklinać! Słowa %s nie są dozwolone."
|
msgstr[1] "Nie wolno przeklinać! Słowa %s nie są dozwolone."
|
||||||
|
msgstr[2] "Nie wolno przeklinać! Słowa %s nie są dozwolone."
|
||||||
|
|
||||||
#: core/validators.py:273
|
#: core/validators.py:273
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -497,13 +502,15 @@ msgid "Please enter a valid decimal number with at most %s total digit."
|
|||||||
msgid_plural "Please enter a valid decimal number with at most %s total digits."
|
msgid_plural "Please enter a valid decimal number with at most %s total digits."
|
||||||
msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną o nie więcej niż %s cyfrze."
|
msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną o nie więcej niż %s cyfrze."
|
||||||
msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną o nie więcej niż %s cyfrach."
|
msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną o nie więcej niż %s cyfrach."
|
||||||
|
msgstr[2] "Proszę wpisać poprawną liczbę dziesiętną o nie więcej niż %s cyfrach."
|
||||||
|
|
||||||
#: core/validators.py:425
|
#: core/validators.py:425
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid decimal number with a whole part of at most %s digit."
|
msgid "Please enter a valid decimal number with a whole part of at most %s digit."
|
||||||
msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits."
|
msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits."
|
||||||
msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfry."
|
msgstr[0] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfrę."
|
||||||
msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfr."
|
msgstr[1] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfry."
|
||||||
|
msgstr[2] "Proszę wpisać poprawną liczbę dziesiętną zawierającą nie więcej niż %s cyfr."
|
||||||
|
|
||||||
#: core/validators.py:428
|
#: core/validators.py:428
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -515,6 +522,9 @@ msgstr[0] ""
|
|||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
"Proszę wpisać poprawną liczbę dziesiętną z dokładnością do %s miejsc po "
|
"Proszę wpisać poprawną liczbę dziesiętną z dokładnością do %s miejsc po "
|
||||||
"przecinku."
|
"przecinku."
|
||||||
|
msgstr[2] ""
|
||||||
|
"Proszę wpisać poprawną liczbę dziesiętną z dokładnością do %s miejsc po "
|
||||||
|
"przecinku."
|
||||||
|
|
||||||
#: core/validators.py:438
|
#: core/validators.py:438
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -668,7 +678,7 @@ msgstr "Wpisz poprawny URL."
|
|||||||
|
|
||||||
#: newforms/fields.py:313
|
#: newforms/fields.py:313
|
||||||
msgid "This URL appears to be a broken link."
|
msgid "This URL appears to be a broken link."
|
||||||
msgstr "Odnośnik %s jest nieprawidłowy."
|
msgstr "Ten odnośnik jest nieprawidłowy."
|
||||||
|
|
||||||
#: contrib/humanize/templatetags/humanize.py:17
|
#: contrib/humanize/templatetags/humanize.py:17
|
||||||
msgid "th"
|
msgid "th"
|
||||||
@ -691,21 +701,24 @@ msgstr "-ci"
|
|||||||
msgid "%(value).1f million"
|
msgid "%(value).1f million"
|
||||||
msgid_plural "%(value).1f million"
|
msgid_plural "%(value).1f million"
|
||||||
msgstr[0] "%(value).1f milion"
|
msgstr[0] "%(value).1f milion"
|
||||||
msgstr[1] "%(value).1f milionów"
|
msgstr[1] "%(value).1f miliony"
|
||||||
|
msgstr[2] "%(value).1f milionów"
|
||||||
|
|
||||||
#: contrib/humanize/templatetags/humanize.py:50
|
#: contrib/humanize/templatetags/humanize.py:50
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value).1f billion"
|
msgid "%(value).1f billion"
|
||||||
msgid_plural "%(value).1f billion"
|
msgid_plural "%(value).1f billion"
|
||||||
msgstr[0] "%(value).1f miliard"
|
msgstr[0] "%(value).1f miliard"
|
||||||
msgstr[1] "%(value).1f miliardów"
|
msgstr[1] "%(value).1f miliardy"
|
||||||
|
msgstr[2] "%(value).1f miliardów"
|
||||||
|
|
||||||
#: contrib/humanize/templatetags/humanize.py:53
|
#: contrib/humanize/templatetags/humanize.py:53
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value).1f trillion"
|
msgid "%(value).1f trillion"
|
||||||
msgid_plural "%(value).1f trillion"
|
msgid_plural "%(value).1f trillion"
|
||||||
msgstr[0] "%(value).1f bilion"
|
msgstr[0] "%(value).1f bilion"
|
||||||
msgstr[1] "%(value).1f bilionów"
|
msgstr[1] "%(value).1f biliony"
|
||||||
|
msgstr[2] "%(value).1f bilionów"
|
||||||
|
|
||||||
#: contrib/humanize/templatetags/humanize.py:68
|
#: contrib/humanize/templatetags/humanize.py:68
|
||||||
msgid "one"
|
msgid "one"
|
||||||
@ -987,6 +1000,15 @@ msgstr[0] ""
|
|||||||
"\n"
|
"\n"
|
||||||
"%(text)s"
|
"%(text)s"
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
"Ten komentarz został wysłany przez użytkownika, który wysłał mniej niż %"
|
||||||
|
"(count)s komentarze:\n"
|
||||||
|
"\n"
|
||||||
|
"%(text)s"
|
||||||
|
msgstr[2] ""
|
||||||
|
"Ten komentarz został wysłany przez użytkownika, który wysłał mniej niż %"
|
||||||
|
"(count)s komentarzy:\n"
|
||||||
|
"\n"
|
||||||
|
"%(text)s"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:116
|
#: contrib/comments/views/comments.py:116
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1574,7 +1596,8 @@ msgstr "Szukaj"
|
|||||||
msgid "1 result"
|
msgid "1 result"
|
||||||
msgid_plural "%(counter)s results"
|
msgid_plural "%(counter)s results"
|
||||||
msgstr[0] "1 wynik"
|
msgstr[0] "1 wynik"
|
||||||
msgstr[1] "%(counter)s wyników"
|
msgstr[1] "%(counter)s wyniki"
|
||||||
|
msgstr[2] "%(counter)s wyników"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/search_form.html:10
|
#: contrib/admin/templates/admin/search_form.html:10
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1681,6 +1704,7 @@ msgid "Please correct the error below."
|
|||||||
msgid_plural "Please correct the errors below."
|
msgid_plural "Please correct the errors below."
|
||||||
msgstr[0] "Proszę popraw poniższy błąd"
|
msgstr[0] "Proszę popraw poniższy błąd"
|
||||||
msgstr[1] "Proszę popraw poniższe błędy"
|
msgstr[1] "Proszę popraw poniższe błędy"
|
||||||
|
msgstr[2] "Proszę popraw poniższe błędy"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:50
|
#: contrib/admin/templates/admin/change_form.html:50
|
||||||
msgid "Ordering"
|
msgid "Ordering"
|
||||||
@ -2077,7 +2101,6 @@ msgstr ""
|
|||||||
msgid "user permissions"
|
msgid "user permissions"
|
||||||
msgstr "uprawnienia użytkownika"
|
msgstr "uprawnienia użytkownika"
|
||||||
|
|
||||||
# kurwa
|
|
||||||
#: contrib/auth/models.py:115
|
#: contrib/auth/models.py:115
|
||||||
msgid "user"
|
msgid "user"
|
||||||
msgstr "użytkownik"
|
msgstr "użytkownik"
|
||||||
@ -2831,37 +2854,43 @@ msgstr "Gru."
|
|||||||
msgid "year"
|
msgid "year"
|
||||||
msgid_plural "years"
|
msgid_plural "years"
|
||||||
msgstr[0] "rok"
|
msgstr[0] "rok"
|
||||||
msgstr[1] "lat"
|
msgstr[1] "lata"
|
||||||
|
msgstr[2] "lat"
|
||||||
|
|
||||||
#: utils/timesince.py:13
|
#: utils/timesince.py:13
|
||||||
msgid "month"
|
msgid "month"
|
||||||
msgid_plural "months"
|
msgid_plural "months"
|
||||||
msgstr[0] "miesiąc"
|
msgstr[0] "miesiąc"
|
||||||
msgstr[1] "miesięcy"
|
msgstr[1] "miesięce"
|
||||||
|
msgstr[2] "miesięcy"
|
||||||
|
|
||||||
#: utils/timesince.py:14
|
#: utils/timesince.py:14
|
||||||
msgid "week"
|
msgid "week"
|
||||||
msgid_plural "weeks"
|
msgid_plural "weeks"
|
||||||
msgstr[0] "tydzień"
|
msgstr[0] "tydzień"
|
||||||
msgstr[1] "tygodni"
|
msgstr[1] "tygodnie"
|
||||||
|
msgstr[2] "tygodni"
|
||||||
|
|
||||||
#: utils/timesince.py:15
|
#: utils/timesince.py:15
|
||||||
msgid "day"
|
msgid "day"
|
||||||
msgid_plural "days"
|
msgid_plural "days"
|
||||||
msgstr[0] "dzień"
|
msgstr[0] "dzień"
|
||||||
msgstr[1] "dni"
|
msgstr[1] "dni"
|
||||||
|
msgstr[2] "dni"
|
||||||
|
|
||||||
#: utils/timesince.py:16
|
#: utils/timesince.py:16
|
||||||
msgid "hour"
|
msgid "hour"
|
||||||
msgid_plural "hours"
|
msgid_plural "hours"
|
||||||
msgstr[0] "godzina"
|
msgstr[0] "godzina"
|
||||||
msgstr[1] "godzin"
|
msgstr[1] "godziny"
|
||||||
|
msgstr[2] "godzin"
|
||||||
|
|
||||||
#: utils/timesince.py:17
|
#: utils/timesince.py:17
|
||||||
msgid "minute"
|
msgid "minute"
|
||||||
msgid_plural "minutes"
|
msgid_plural "minutes"
|
||||||
msgstr[0] "minuta"
|
msgstr[0] "minuta"
|
||||||
msgstr[1] "minut"
|
msgstr[1] "minuty"
|
||||||
|
msgstr[2] "minut"
|
||||||
|
|
||||||
#: utils/timesince.py:40
|
#: utils/timesince.py:40
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -2880,7 +2909,7 @@ msgstr ", %(number)d %(type)s"
|
|||||||
|
|
||||||
#: utils/dateformat.py:40
|
#: utils/dateformat.py:40
|
||||||
msgid "p.m."
|
msgid "p.m."
|
||||||
msgstr "popołudniu"
|
msgstr "po południu"
|
||||||
|
|
||||||
#: utils/dateformat.py:41
|
#: utils/dateformat.py:41
|
||||||
msgid "a.m."
|
msgid "a.m."
|
||||||
@ -2888,7 +2917,7 @@ msgstr "rano"
|
|||||||
|
|
||||||
#: utils/dateformat.py:46
|
#: utils/dateformat.py:46
|
||||||
msgid "PM"
|
msgid "PM"
|
||||||
msgstr "popołudniu"
|
msgstr "po południu"
|
||||||
|
|
||||||
#: utils/dateformat.py:47
|
#: utils/dateformat.py:47
|
||||||
msgid "AM"
|
msgid "AM"
|
||||||
@ -2931,13 +2960,13 @@ msgstr "tak,nie,może"
|
|||||||
msgid "%(size)d byte"
|
msgid "%(size)d byte"
|
||||||
msgid_plural "%(size)d bytes"
|
msgid_plural "%(size)d bytes"
|
||||||
msgstr[0] "%(size)d bajt"
|
msgstr[0] "%(size)d bajt"
|
||||||
msgstr[1] "%(size)d bajtów"
|
msgstr[1] "%(size)d bajty"
|
||||||
msgstr[2] ""
|
msgstr[2] "%(size)d bajtów"
|
||||||
|
|
||||||
#: template/defaultfilters.py:522
|
#: template/defaultfilters.py:522
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%.1f KB"
|
msgid "%.1f KB"
|
||||||
msgstr "%.1f kB"
|
msgstr "%.1f KB"
|
||||||
|
|
||||||
#: template/defaultfilters.py:524
|
#: template/defaultfilters.py:524
|
||||||
#, python-format
|
#, python-format
|
||||||
|
Binary file not shown.
@ -40,7 +40,6 @@ msgid "Chosen %s"
|
|||||||
msgstr "Wybrano %s"
|
msgstr "Wybrano %s"
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:54
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
#, fuzzy
|
|
||||||
msgid "Select your choice(s) and click "
|
msgid "Select your choice(s) and click "
|
||||||
msgstr "Zaznacz swój wybór i kliknij "
|
msgstr "Zaznacz swój wybór i kliknij "
|
||||||
|
|
||||||
|
Binary file not shown.
@ -23,13 +23,13 @@ msgstr "id obiect"
|
|||||||
|
|
||||||
#: contrib/comments/models.py:68
|
#: contrib/comments/models.py:68
|
||||||
msgid "headline"
|
msgid "headline"
|
||||||
msgstr ""
|
msgstr "titlu"
|
||||||
|
|
||||||
#: contrib/comments/models.py:69 contrib/comments/models.py:90
|
#: contrib/comments/models.py:69 contrib/comments/models.py:90
|
||||||
#: contrib/comments/models.py:167
|
#: contrib/comments/models.py:167
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid "comment"
|
msgid "comment"
|
||||||
msgstr "conţinut"
|
msgstr "comentariu"
|
||||||
|
|
||||||
#: contrib/comments/models.py:70
|
#: contrib/comments/models.py:70
|
||||||
msgid "rating #1"
|
msgid "rating #1"
|
||||||
@ -69,20 +69,19 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/comments/models.py:83 contrib/comments/models.py:169
|
#: contrib/comments/models.py:83 contrib/comments/models.py:169
|
||||||
msgid "date/time submitted"
|
msgid "date/time submitted"
|
||||||
msgstr ""
|
msgstr "data/ora crearii"
|
||||||
|
|
||||||
#: contrib/comments/models.py:84 contrib/comments/models.py:170
|
#: contrib/comments/models.py:84 contrib/comments/models.py:170
|
||||||
msgid "is public"
|
msgid "is public"
|
||||||
msgstr ""
|
msgstr "public"
|
||||||
|
|
||||||
#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
|
#: contrib/comments/models.py:85 contrib/admin/views/doc.py:289
|
||||||
#, fuzzy
|
|
||||||
msgid "IP address"
|
msgid "IP address"
|
||||||
msgstr "adresa email"
|
msgstr "adresa ip"
|
||||||
|
|
||||||
#: contrib/comments/models.py:86
|
#: contrib/comments/models.py:86
|
||||||
msgid "is removed"
|
msgid "is removed"
|
||||||
msgstr ""
|
msgstr "sters"
|
||||||
|
|
||||||
#: contrib/comments/models.py:86
|
#: contrib/comments/models.py:86
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -122,7 +121,7 @@ msgstr "adresa email"
|
|||||||
|
|
||||||
#: contrib/comments/models.py:173
|
#: contrib/comments/models.py:173
|
||||||
msgid "approved by staff"
|
msgid "approved by staff"
|
||||||
msgstr ""
|
msgstr "aprobat de echipa"
|
||||||
|
|
||||||
#: contrib/comments/models.py:176
|
#: contrib/comments/models.py:176
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -282,9 +281,8 @@ msgid "Password:"
|
|||||||
msgstr "Parola:"
|
msgstr "Parola:"
|
||||||
|
|
||||||
#: contrib/comments/templates/comments/form.html:6
|
#: contrib/comments/templates/comments/form.html:6
|
||||||
#, fuzzy
|
|
||||||
msgid "Forgotten your password?"
|
msgid "Forgotten your password?"
|
||||||
msgstr "Schimbă-mi parola"
|
msgstr "Ai uitat parola?"
|
||||||
|
|
||||||
#: contrib/comments/templates/comments/form.html:8
|
#: contrib/comments/templates/comments/form.html:8
|
||||||
#: contrib/admin/templates/admin/object_history.html:3
|
#: contrib/admin/templates/admin/object_history.html:3
|
||||||
@ -338,9 +336,8 @@ msgid "Preview comment"
|
|||||||
msgstr "permite comentarii"
|
msgstr "permite comentarii"
|
||||||
|
|
||||||
#: contrib/comments/templates/comments/freeform.html:4
|
#: contrib/comments/templates/comments/freeform.html:4
|
||||||
#, fuzzy
|
|
||||||
msgid "Your name:"
|
msgid "Your name:"
|
||||||
msgstr "nume utilizator"
|
msgstr "numele dumneavoastra"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:40
|
#: contrib/admin/filterspecs.py:40
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -352,41 +349,39 @@ msgstr ""
|
|||||||
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
|
#: contrib/admin/filterspecs.py:70 contrib/admin/filterspecs.py:88
|
||||||
#: contrib/admin/filterspecs.py:143
|
#: contrib/admin/filterspecs.py:143
|
||||||
msgid "All"
|
msgid "All"
|
||||||
msgstr ""
|
msgstr "tot"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:109
|
#: contrib/admin/filterspecs.py:109
|
||||||
msgid "Any date"
|
msgid "Any date"
|
||||||
msgstr ""
|
msgstr "orice data"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:110
|
#: contrib/admin/filterspecs.py:110
|
||||||
#, fuzzy
|
|
||||||
msgid "Today"
|
msgid "Today"
|
||||||
msgstr "Luni"
|
msgstr "Astazi"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:113
|
#: contrib/admin/filterspecs.py:113
|
||||||
msgid "Past 7 days"
|
msgid "Past 7 days"
|
||||||
msgstr ""
|
msgstr "Ultimele 7 zile"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:115
|
#: contrib/admin/filterspecs.py:115
|
||||||
msgid "This month"
|
msgid "This month"
|
||||||
msgstr ""
|
msgstr "Luna aceasta"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:117
|
#: contrib/admin/filterspecs.py:117
|
||||||
msgid "This year"
|
msgid "This year"
|
||||||
msgstr ""
|
msgstr "Anul acesta"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:143
|
#: contrib/admin/filterspecs.py:143
|
||||||
msgid "Yes"
|
msgid "Yes"
|
||||||
msgstr ""
|
msgstr "Da"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:143
|
#: contrib/admin/filterspecs.py:143
|
||||||
#, fuzzy
|
|
||||||
msgid "No"
|
msgid "No"
|
||||||
msgstr "Noi."
|
msgstr "Nu"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:150
|
#: contrib/admin/filterspecs.py:150
|
||||||
msgid "Unknown"
|
msgid "Unknown"
|
||||||
msgstr ""
|
msgstr "Necunoscut"
|
||||||
|
|
||||||
#: contrib/admin/models.py:16
|
#: contrib/admin/models.py:16
|
||||||
msgid "action time"
|
msgid "action time"
|
||||||
@ -418,7 +413,7 @@ msgstr "intrări log"
|
|||||||
|
|
||||||
#: contrib/admin/templatetags/admin_list.py:228
|
#: contrib/admin/templatetags/admin_list.py:228
|
||||||
msgid "All dates"
|
msgid "All dates"
|
||||||
msgstr ""
|
msgstr "Toate datele"
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
|
#: contrib/admin/views/decorators.py:9 contrib/auth/forms.py:36
|
||||||
#: contrib/auth/forms.py:41
|
#: contrib/auth/forms.py:41
|
||||||
@ -426,6 +421,8 @@ msgid ""
|
|||||||
"Please enter a correct username and password. Note that both fields are case-"
|
"Please enter a correct username and password. Note that both fields are case-"
|
||||||
"sensitive."
|
"sensitive."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Va rugam sa introduceti username-ul si parola corecta. Aveti grija deoarece"
|
||||||
|
"casutele sunt case sensitive."
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:23
|
#: contrib/admin/views/decorators.py:23
|
||||||
#: contrib/admin/templates/admin/login.html:25
|
#: contrib/admin/templates/admin/login.html:25
|
||||||
@ -437,16 +434,21 @@ msgid ""
|
|||||||
"Please log in again, because your session has expired. Don't worry: Your "
|
"Please log in again, because your session has expired. Don't worry: Your "
|
||||||
"submission has been saved."
|
"submission has been saved."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Va rugam sa va inregistrati din nou, deoarece sesiunea a expirat. Nu va "
|
||||||
|
"faceti griji datele au fost salvate."
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:68
|
#: contrib/admin/views/decorators.py:68
|
||||||
msgid ""
|
msgid ""
|
||||||
"Looks like your browser isn't configured to accept cookies. Please enable "
|
"Looks like your browser isn't configured to accept cookies. Please enable "
|
||||||
"cookies, reload this page, and try again."
|
"cookies, reload this page, and try again."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Se pare ca browserul dumneavostra nu este configurat sa accepte cookies. Va "
|
||||||
|
"rugam sa va setati browserul sa accepte cookies, dati un reload la pagina si "
|
||||||
|
"incercati din nou."
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:82
|
#: contrib/admin/views/decorators.py:82
|
||||||
msgid "Usernames cannot contain the '@' character."
|
msgid "Usernames cannot contain the '@' character."
|
||||||
msgstr ""
|
msgstr "Username-ul nu are voie sa contina caracterul '@'."
|
||||||
|
|
||||||
#: contrib/admin/views/decorators.py:84
|
#: contrib/admin/views/decorators.py:84
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -461,61 +463,62 @@ msgstr "Administrare Django"
|
|||||||
#: contrib/admin/views/main.py:260
|
#: contrib/admin/views/main.py:260
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
msgid "The %(name)s \"%(obj)s\" was added successfully."
|
||||||
msgstr ""
|
msgstr "%(name)s \"%(obj)s\" a fost inserat cu succes."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
|
#: contrib/admin/views/main.py:264 contrib/admin/views/main.py:348
|
||||||
msgid "You may edit it again below."
|
msgid "You may edit it again below."
|
||||||
msgstr ""
|
msgstr "Va puteti edita datele din nou mai jos."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
|
#: contrib/admin/views/main.py:272 contrib/admin/views/main.py:357
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "You may add another %s below."
|
msgid "You may add another %s below."
|
||||||
msgstr ""
|
msgstr "Mai puteti adauga un alt %s mai jos."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:290
|
#: contrib/admin/views/main.py:290
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Add %s"
|
msgid "Add %s"
|
||||||
msgstr "Adaugă"
|
msgstr "Adaugă %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:336
|
#: contrib/admin/views/main.py:336
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Added %s."
|
msgid "Added %s."
|
||||||
msgstr ""
|
msgstr "Adaugat %s."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
|
#: contrib/admin/views/main.py:336 contrib/admin/views/main.py:338
|
||||||
#: contrib/admin/views/main.py:340
|
#: contrib/admin/views/main.py:340
|
||||||
msgid "and"
|
msgid "and"
|
||||||
msgstr ""
|
msgstr "si"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:338
|
#: contrib/admin/views/main.py:338
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Changed %s."
|
msgid "Changed %s."
|
||||||
msgstr "Schimbă"
|
msgstr "Schimbă %s."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:340
|
#: contrib/admin/views/main.py:340
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Deleted %s."
|
msgid "Deleted %s."
|
||||||
msgstr ""
|
msgstr "Am sters %s."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:343
|
#: contrib/admin/views/main.py:343
|
||||||
msgid "No fields changed."
|
msgid "No fields changed."
|
||||||
msgstr ""
|
msgstr "Nu s-a facut nicio schimbare."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:346
|
#: contrib/admin/views/main.py:346
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
msgid "The %(name)s \"%(obj)s\" was changed successfully."
|
||||||
msgstr ""
|
msgstr "%(name)s \"%(obj)s\" au fost modificate cu succes."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:354
|
#: contrib/admin/views/main.py:354
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
"The %(name)s \"%(obj)s\" was added successfully. You may edit it again below."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"%(name)s \"%(obj)s\" au fost adaugate cu succes. Le puteti edita mai jos."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:392
|
#: contrib/admin/views/main.py:392
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Change %s"
|
msgid "Change %s"
|
||||||
msgstr "Schimbă"
|
msgstr "Schimbă %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:470
|
#: contrib/admin/views/main.py:470
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -530,16 +533,16 @@ msgstr ""
|
|||||||
#: contrib/admin/views/main.py:508
|
#: contrib/admin/views/main.py:508
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
msgid "The %(name)s \"%(obj)s\" was deleted successfully."
|
||||||
msgstr ""
|
msgstr "%(name)s \"%(obj)s\" au fost sterse cu succes."
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:511
|
#: contrib/admin/views/main.py:511
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
msgstr ""
|
msgstr "Sunteti sigur?"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:533
|
#: contrib/admin/views/main.py:533
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Change history: %s"
|
msgid "Change history: %s"
|
||||||
msgstr "Schimbă parola"
|
msgstr "Schimbari facute: %s"
|
||||||
|
|
||||||
#: contrib/admin/views/main.py:565
|
#: contrib/admin/views/main.py:565
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -549,13 +552,13 @@ msgstr ""
|
|||||||
#: contrib/admin/views/main.py:565
|
#: contrib/admin/views/main.py:565
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Select %s to change"
|
msgid "Select %s to change"
|
||||||
msgstr ""
|
msgstr "Selecteaza %s pentru schimbare"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
|
#: contrib/admin/views/doc.py:277 contrib/admin/views/doc.py:286
|
||||||
#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
|
#: contrib/admin/views/doc.py:288 contrib/admin/views/doc.py:294
|
||||||
#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
|
#: contrib/admin/views/doc.py:295 contrib/admin/views/doc.py:297
|
||||||
msgid "Integer"
|
msgid "Integer"
|
||||||
msgstr ""
|
msgstr "Intreg"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:278
|
#: contrib/admin/views/doc.py:278
|
||||||
msgid "Boolean (Either True or False)"
|
msgid "Boolean (Either True or False)"
|
||||||
@ -564,26 +567,23 @@ msgstr ""
|
|||||||
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
|
#: contrib/admin/views/doc.py:279 contrib/admin/views/doc.py:296
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "String (up to %(maxlength)s)"
|
msgid "String (up to %(maxlength)s)"
|
||||||
msgstr ""
|
msgstr "String (pana la %(maxlength)s caractere)"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:280
|
#: contrib/admin/views/doc.py:280
|
||||||
msgid "Comma-separated integers"
|
msgid "Comma-separated integers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:281
|
#: contrib/admin/views/doc.py:281
|
||||||
#, fuzzy
|
|
||||||
msgid "Date (without time)"
|
msgid "Date (without time)"
|
||||||
msgstr "timp acţiune"
|
msgstr "Data (fara ora)"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:282
|
#: contrib/admin/views/doc.py:282
|
||||||
#, fuzzy
|
|
||||||
msgid "Date (with time)"
|
msgid "Date (with time)"
|
||||||
msgstr "Dată/oră"
|
msgstr "Data (cu ora)"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:283
|
#: contrib/admin/views/doc.py:283
|
||||||
#, fuzzy
|
|
||||||
msgid "E-mail address"
|
msgid "E-mail address"
|
||||||
msgstr "Adresa email:"
|
msgstr "Adresa email"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
|
#: contrib/admin/views/doc.py:284 contrib/admin/views/doc.py:287
|
||||||
msgid "File path"
|
msgid "File path"
|
||||||
@ -603,9 +603,8 @@ msgid "Relation to parent model"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:293
|
#: contrib/admin/views/doc.py:293
|
||||||
#, fuzzy
|
|
||||||
msgid "Phone number"
|
msgid "Phone number"
|
||||||
msgstr "Introduceţi un număr întreg."
|
msgstr "Numar de telefon"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:298
|
#: contrib/admin/views/doc.py:298
|
||||||
msgid "Text"
|
msgid "Text"
|
||||||
@ -613,7 +612,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/admin/views/doc.py:299
|
#: contrib/admin/views/doc.py:299
|
||||||
msgid "Time"
|
msgid "Time"
|
||||||
msgstr ""
|
msgstr "Timp"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
|
#: contrib/admin/views/doc.py:300 contrib/flatpages/models.py:7
|
||||||
msgid "URL"
|
msgid "URL"
|
||||||
@ -636,7 +635,7 @@ msgstr ""
|
|||||||
#: contrib/admin/templates/registration/password_change_form.html:3
|
#: contrib/admin/templates/registration/password_change_form.html:3
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
|
||||||
msgid "Documentation"
|
msgid "Documentation"
|
||||||
msgstr ""
|
msgstr "Documentatie"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/object_history.html:3
|
#: contrib/admin/templates/admin/object_history.html:3
|
||||||
#: contrib/admin/templates/admin/change_list.html:5
|
#: contrib/admin/templates/admin/change_list.html:5
|
||||||
@ -770,9 +769,9 @@ msgid "None available"
|
|||||||
msgstr "Indisponibil"
|
msgstr "Indisponibil"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_list.html:11
|
#: contrib/admin/templates/admin/change_list.html:11
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Add %(name)s"
|
msgid "Add %(name)s"
|
||||||
msgstr "Adaugă"
|
msgstr "Adaugă %(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>?"
|
||||||
@ -785,7 +784,7 @@ msgstr "Bine ai venit,"
|
|||||||
#: contrib/admin/templates/admin/delete_confirmation.html:9
|
#: contrib/admin/templates/admin/delete_confirmation.html:9
|
||||||
#: contrib/admin/templates/admin/submit_line.html:3
|
#: contrib/admin/templates/admin/submit_line.html:3
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr ""
|
msgstr "Sterge"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/delete_confirmation.html:14
|
#: contrib/admin/templates/admin/delete_confirmation.html:14
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -814,7 +813,7 @@ msgstr "Da, sînt sigur"
|
|||||||
#: contrib/admin/templates/admin/filter.html:2
|
#: contrib/admin/templates/admin/filter.html:2
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid " By %(title)s "
|
msgid " By %(title)s "
|
||||||
msgstr ""
|
msgstr " Dupa %(title)s "
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/search_form.html:8
|
#: contrib/admin/templates/admin/search_form.html:8
|
||||||
msgid "Go"
|
msgid "Go"
|
||||||
@ -827,33 +826,32 @@ msgstr ""
|
|||||||
#: contrib/admin/templates/admin/change_form.html:30
|
#: contrib/admin/templates/admin/change_form.html:30
|
||||||
msgid "Please correct the error below."
|
msgid "Please correct the error below."
|
||||||
msgid_plural "Please correct the errors below."
|
msgid_plural "Please correct the errors below."
|
||||||
msgstr[0] ""
|
msgstr[0] "Va rugam sa corectati eroarea de mai jos"
|
||||||
msgstr[1] ""
|
msgstr[1] "Va rugam sa corectati erorile de mai jos"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:48
|
#: contrib/admin/templates/admin/change_form.html:48
|
||||||
msgid "Ordering"
|
msgid "Ordering"
|
||||||
msgstr ""
|
msgstr "Ordonate dupa"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:51
|
#: contrib/admin/templates/admin/change_form.html:51
|
||||||
msgid "Order:"
|
msgid "Order:"
|
||||||
msgstr ""
|
msgstr "Ordonare:"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/submit_line.html:4
|
#: contrib/admin/templates/admin/submit_line.html:4
|
||||||
msgid "Save as new"
|
msgid "Save as new"
|
||||||
msgstr ""
|
msgstr "Salvati ca nou"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/submit_line.html:5
|
#: contrib/admin/templates/admin/submit_line.html:5
|
||||||
msgid "Save and add another"
|
msgid "Save and add another"
|
||||||
msgstr ""
|
msgstr "Salvati si adaugati altul"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/submit_line.html:6
|
#: contrib/admin/templates/admin/submit_line.html:6
|
||||||
msgid "Save and continue editing"
|
msgid "Save and continue editing"
|
||||||
msgstr ""
|
msgstr "Salvati si continuati"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/submit_line.html:7
|
#: contrib/admin/templates/admin/submit_line.html:7
|
||||||
#, fuzzy
|
|
||||||
msgid "Save"
|
msgid "Save"
|
||||||
msgstr "activ"
|
msgstr "Salveaza"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_done.html:4
|
#: contrib/admin/templates/registration/password_change_done.html:4
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:4
|
#: contrib/admin/templates/registration/password_change_form.html:4
|
||||||
@ -1133,24 +1131,20 @@ msgid "codename"
|
|||||||
msgstr "nume cod"
|
msgstr "nume cod"
|
||||||
|
|
||||||
#: contrib/auth/models.py:17
|
#: contrib/auth/models.py:17
|
||||||
#, fuzzy
|
|
||||||
msgid "permission"
|
msgid "permission"
|
||||||
msgstr "Permisiune"
|
msgstr "permisiune"
|
||||||
|
|
||||||
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
#: contrib/auth/models.py:18 contrib/auth/models.py:27
|
||||||
#, fuzzy
|
|
||||||
msgid "permissions"
|
msgid "permissions"
|
||||||
msgstr "Permisiuni"
|
msgstr "permisiuni"
|
||||||
|
|
||||||
#: contrib/auth/models.py:29
|
#: contrib/auth/models.py:29
|
||||||
#, fuzzy
|
|
||||||
msgid "group"
|
msgid "group"
|
||||||
msgstr "Grup"
|
msgstr "grup"
|
||||||
|
|
||||||
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
#: contrib/auth/models.py:30 contrib/auth/models.py:65
|
||||||
#, fuzzy
|
|
||||||
msgid "groups"
|
msgid "groups"
|
||||||
msgstr "Grupuri"
|
msgstr "grupuri"
|
||||||
|
|
||||||
#: contrib/auth/models.py:55
|
#: contrib/auth/models.py:55
|
||||||
msgid "username"
|
msgid "username"
|
||||||
@ -1209,19 +1203,16 @@ msgstr ""
|
|||||||
"permisiunile alocate fiecărui grup din care el/ea face parte."
|
"permisiunile alocate fiecărui grup din care el/ea face parte."
|
||||||
|
|
||||||
#: contrib/auth/models.py:67
|
#: contrib/auth/models.py:67
|
||||||
#, fuzzy
|
|
||||||
msgid "user permissions"
|
msgid "user permissions"
|
||||||
msgstr "Permisiuni"
|
msgstr "permisiuni utilizator"
|
||||||
|
|
||||||
#: contrib/auth/models.py:70
|
#: contrib/auth/models.py:70
|
||||||
#, fuzzy
|
|
||||||
msgid "user"
|
msgid "user"
|
||||||
msgstr "Utilizator"
|
msgstr "utilizator"
|
||||||
|
|
||||||
#: contrib/auth/models.py:71
|
#: contrib/auth/models.py:71
|
||||||
#, fuzzy
|
|
||||||
msgid "users"
|
msgid "users"
|
||||||
msgstr "Utilizatori"
|
msgstr "utilizatori"
|
||||||
|
|
||||||
#: contrib/auth/models.py:76
|
#: contrib/auth/models.py:76
|
||||||
msgid "Personal info"
|
msgid "Personal info"
|
||||||
@ -1240,15 +1231,16 @@ msgid "Groups"
|
|||||||
msgstr "Grupuri"
|
msgstr "Grupuri"
|
||||||
|
|
||||||
#: contrib/auth/models.py:219
|
#: contrib/auth/models.py:219
|
||||||
#, fuzzy
|
|
||||||
msgid "message"
|
msgid "message"
|
||||||
msgstr "Mesaj"
|
msgstr "mesaj"
|
||||||
|
|
||||||
#: contrib/auth/forms.py:30
|
#: contrib/auth/forms.py:30
|
||||||
msgid ""
|
msgid ""
|
||||||
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
|
"Your Web browser doesn't appear to have cookies enabled. Cookies are "
|
||||||
"required for logging in."
|
"required for logging in."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Se pare ca browserul dumneavoastra nu suporta cookies. Aveti nevoie de un "
|
||||||
|
"browser care suporta cookies ca sa va logati."
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:25
|
#: contrib/contenttypes/models.py:25
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -1277,7 +1269,7 @@ msgstr "data expirare"
|
|||||||
|
|
||||||
#: contrib/sessions/models.py:41
|
#: contrib/sessions/models.py:41
|
||||||
msgid "session"
|
msgid "session"
|
||||||
msgstr "seiune"
|
msgstr "sesiune"
|
||||||
|
|
||||||
#: contrib/sessions/models.py:42
|
#: contrib/sessions/models.py:42
|
||||||
msgid "sessions"
|
msgid "sessions"
|
||||||
@ -1389,7 +1381,7 @@ msgstr "Decembrie"
|
|||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "jan"
|
msgid "jan"
|
||||||
msgstr ""
|
msgstr "ian"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "feb"
|
msgid "feb"
|
||||||
@ -1404,17 +1396,16 @@ msgid "apr"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
#, fuzzy
|
|
||||||
msgid "may"
|
msgid "may"
|
||||||
msgstr "Mai"
|
msgstr "mai"
|
||||||
|
|
||||||
#: utils/dates.py:19
|
#: utils/dates.py:19
|
||||||
msgid "jun"
|
msgid "jun"
|
||||||
msgstr ""
|
msgstr "iun"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "jul"
|
msgid "jul"
|
||||||
msgstr ""
|
msgstr "iul"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "aug"
|
msgid "aug"
|
||||||
@ -1430,7 +1421,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "nov"
|
msgid "nov"
|
||||||
msgstr ""
|
msgstr "noi"
|
||||||
|
|
||||||
#: utils/dates.py:20
|
#: utils/dates.py:20
|
||||||
msgid "dec"
|
msgid "dec"
|
||||||
@ -1467,40 +1458,38 @@ msgstr "Dec."
|
|||||||
#: utils/timesince.py:12
|
#: utils/timesince.py:12
|
||||||
msgid "year"
|
msgid "year"
|
||||||
msgid_plural "years"
|
msgid_plural "years"
|
||||||
msgstr[0] ""
|
msgstr[0] "an"
|
||||||
msgstr[1] ""
|
msgstr[1] "ani"
|
||||||
|
|
||||||
#: utils/timesince.py:13
|
#: utils/timesince.py:13
|
||||||
msgid "month"
|
msgid "month"
|
||||||
msgid_plural "months"
|
msgid_plural "months"
|
||||||
msgstr[0] ""
|
msgstr[0] "luna"
|
||||||
msgstr[1] ""
|
msgstr[1] "luni"
|
||||||
|
|
||||||
#: utils/timesince.py:14
|
#: utils/timesince.py:14
|
||||||
msgid "week"
|
msgid "week"
|
||||||
msgid_plural "weeks"
|
msgid_plural "weeks"
|
||||||
msgstr[0] ""
|
msgstr[0] "saptamana"
|
||||||
msgstr[1] ""
|
msgstr[1] "saptamani"
|
||||||
|
|
||||||
#: utils/timesince.py:15
|
#: utils/timesince.py:15
|
||||||
#, fuzzy
|
|
||||||
msgid "day"
|
msgid "day"
|
||||||
msgid_plural "days"
|
msgid_plural "days"
|
||||||
msgstr[0] "Mai"
|
msgstr[0] "zi"
|
||||||
msgstr[1] "Mai"
|
msgstr[1] "zile"
|
||||||
|
|
||||||
#: utils/timesince.py:16
|
#: utils/timesince.py:16
|
||||||
msgid "hour"
|
msgid "hour"
|
||||||
msgid_plural "hours"
|
msgid_plural "hours"
|
||||||
msgstr[0] ""
|
msgstr[0] "ora"
|
||||||
msgstr[1] ""
|
msgstr[1] "ore"
|
||||||
|
|
||||||
#: utils/timesince.py:17
|
#: utils/timesince.py:17
|
||||||
#, fuzzy
|
|
||||||
msgid "minute"
|
msgid "minute"
|
||||||
msgid_plural "minutes"
|
msgid_plural "minutes"
|
||||||
msgstr[0] "sit"
|
msgstr[0] "minut"
|
||||||
msgstr[1] "sit"
|
msgstr[1] "minute"
|
||||||
|
|
||||||
#: conf/global_settings.py:37
|
#: conf/global_settings.py:37
|
||||||
msgid "Bengali"
|
msgid "Bengali"
|
||||||
@ -1545,7 +1534,7 @@ msgstr "Galiciană"
|
|||||||
|
|
||||||
#: conf/global_settings.py:47
|
#: conf/global_settings.py:47
|
||||||
msgid "Hungarian"
|
msgid "Hungarian"
|
||||||
msgstr ""
|
msgstr "Ungara"
|
||||||
|
|
||||||
#: conf/global_settings.py:48
|
#: conf/global_settings.py:48
|
||||||
msgid "Hebrew"
|
msgid "Hebrew"
|
||||||
@ -1577,7 +1566,7 @@ msgstr "Braziliană"
|
|||||||
|
|
||||||
#: conf/global_settings.py:55
|
#: conf/global_settings.py:55
|
||||||
msgid "Romanian"
|
msgid "Romanian"
|
||||||
msgstr ""
|
msgstr "Romana"
|
||||||
|
|
||||||
#: conf/global_settings.py:56
|
#: conf/global_settings.py:56
|
||||||
msgid "Russian"
|
msgid "Russian"
|
||||||
@ -1750,7 +1739,7 @@ msgstr[1] "Îngrijiţi-vă limbajul! Cuvintele %s nu sînt permise aici."
|
|||||||
#: core/validators.py:236
|
#: core/validators.py:236
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "This field must match the '%s' field."
|
msgid "This field must match the '%s' field."
|
||||||
msgstr ""
|
msgstr "Acest camp trebuie sa fie identic cu '%s'."
|
||||||
|
|
||||||
#: core/validators.py:255
|
#: core/validators.py:255
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -1897,9 +1886,8 @@ msgstr ""
|
|||||||
#: 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:542 db/models/fields/__init__.py:553
|
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553
|
||||||
#: forms/__init__.py:346
|
#: forms/__init__.py:346
|
||||||
#, fuzzy
|
|
||||||
msgid "This field is required."
|
msgid "This field is required."
|
||||||
msgstr "Cîmpul este invalid."
|
msgstr "Campul acesta trebuie completat obligatoriu."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:337
|
#: db/models/fields/__init__.py:337
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -1917,14 +1905,13 @@ msgid "This field cannot be null."
|
|||||||
msgstr "Cîmpul este invalid."
|
msgstr "Cîmpul este invalid."
|
||||||
|
|
||||||
#: db/models/fields/__init__.py:562
|
#: db/models/fields/__init__.py:562
|
||||||
#, fuzzy
|
|
||||||
msgid "Enter a valid filename."
|
msgid "Enter a valid filename."
|
||||||
msgstr "Introduceţi o adresă de email validă."
|
msgstr "Introduceti un nume de fisier valid."
|
||||||
|
|
||||||
#: db/models/fields/related.py:43
|
#: db/models/fields/related.py:43
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid %s."
|
msgid "Please enter a valid %s."
|
||||||
msgstr "Introduceţi vă rog o adresă IP validă."
|
msgstr "Introduceti va rog un %s valid."
|
||||||
|
|
||||||
#: db/models/fields/related.py:579
|
#: db/models/fields/related.py:579
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -1953,6 +1940,7 @@ msgid "Ensure your text is less than %s character."
|
|||||||
msgid_plural "Ensure your text is less than %s characters."
|
msgid_plural "Ensure your text is less than %s characters."
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
"Va rugam asigurati-va ca textul dumneavoastra are mai putin de %s caractere."
|
||||||
|
|
||||||
#: forms/__init__.py:385
|
#: forms/__init__.py:385
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -1966,7 +1954,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: forms/__init__.py:645
|
#: forms/__init__.py:645
|
||||||
msgid "The submitted file is empty."
|
msgid "The submitted file is empty."
|
||||||
msgstr ""
|
msgstr "Fisierul uploadat este gol"
|
||||||
|
|
||||||
#: forms/__init__.py:699
|
#: forms/__init__.py:699
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -1985,7 +1973,7 @@ msgstr "Introduceţi un număr întreg."
|
|||||||
|
|
||||||
#: template/defaultfilters.py:379
|
#: template/defaultfilters.py:379
|
||||||
msgid "yes,no,maybe"
|
msgid "yes,no,maybe"
|
||||||
msgstr ""
|
msgstr "da,nu,poate"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#~ msgid "Comments"
|
#~ msgid "Comments"
|
||||||
|
BIN
django/conf/locale/ro/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/ro/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
118
django/conf/locale/ro/LC_MESSAGES/djangojs.po
Normal file
118
django/conf/locale/ro/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-06-28 17:36+1000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Now"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr ""
|
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
@ -2,9 +2,6 @@
|
|||||||
# Copyright (C) 2005
|
# Copyright (C) 2005
|
||||||
# This file is distributed under the same license as the Django package.
|
# This file is distributed under the same license as the Django package.
|
||||||
#
|
#
|
||||||
#
|
|
||||||
# Robin Sonefors <ozamosi@blinkenlights.se>, 2005.
|
|
||||||
# Mikko Hellsing <mikko@sorl.net>, 2007.
|
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: djangojs\n"
|
"Project-Id-Version: djangojs\n"
|
||||||
|
BIN
django/conf/locale/uk/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/uk/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
118
django/conf/locale/uk/LC_MESSAGES/djangojs.po
Normal file
118
django/conf/locale/uk/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-06-28 17:36+1000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Now"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr ""
|
BIN
django/conf/locale/zh_TW/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/zh_TW/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
118
django/conf/locale/zh_TW/LC_MESSAGES/djangojs.po
Normal file
118
django/conf/locale/zh_TW/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-06-28 17:36+1000\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
msgid ""
|
||||||
|
"January February March April May June July August September October November "
|
||||||
|
"December"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:33
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Now"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
|
||||||
|
msgid "Today"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
|
||||||
|
msgid "Show"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
|
||||||
|
msgid "Hide"
|
||||||
|
msgstr ""
|
@ -9,7 +9,7 @@ ADMINS = (
|
|||||||
|
|
||||||
MANAGERS = ADMINS
|
MANAGERS = ADMINS
|
||||||
|
|
||||||
DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'.
|
DATABASE_ENGINE = '' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
|
||||||
DATABASE_NAME = '' # Or path to database file if using sqlite3.
|
DATABASE_NAME = '' # Or path to database file if using sqlite3.
|
||||||
DATABASE_USER = '' # Not used with sqlite3.
|
DATABASE_USER = '' # Not used with sqlite3.
|
||||||
DATABASE_PASSWORD = '' # Not used with sqlite3.
|
DATABASE_PASSWORD = '' # Not used with sqlite3.
|
||||||
|
@ -30,7 +30,12 @@ function dismissRelatedLookupPopup(win, chosenId) {
|
|||||||
function showAddAnotherPopup(triggeringLink) {
|
function showAddAnotherPopup(triggeringLink) {
|
||||||
var name = triggeringLink.id.replace(/^add_/, '');
|
var name = triggeringLink.id.replace(/^add_/, '');
|
||||||
name = name.replace(/\./g, '___');
|
name = name.replace(/\./g, '___');
|
||||||
var win = window.open(triggeringLink.href + '?_popup=1', name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
href = triggeringLink.href
|
||||||
|
if (href.indexOf('?') == -1)
|
||||||
|
href += '?_popup=1';
|
||||||
|
else
|
||||||
|
href += '&_popup=1';
|
||||||
|
var win = window.open(href, name, 'height=500,width=800,resizable=yes,scrollbars=yes');
|
||||||
win.focus();
|
win.focus();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ DELETION = 3
|
|||||||
|
|
||||||
class LogEntryManager(models.Manager):
|
class LogEntryManager(models.Manager):
|
||||||
def log_action(self, user_id, content_type_id, object_id, object_repr, action_flag, change_message=''):
|
def log_action(self, user_id, content_type_id, object_id, object_repr, action_flag, change_message=''):
|
||||||
e = self.model(None, None, user_id, content_type_id, object_id, object_repr[:200], action_flag, change_message)
|
e = self.model(None, None, user_id, content_type_id, str(object_id), object_repr[:200], action_flag, change_message)
|
||||||
e.save()
|
e.save()
|
||||||
|
|
||||||
class LogEntry(models.Model):
|
class LogEntry(models.Model):
|
||||||
|
@ -14,6 +14,11 @@ from django.utils.html import escape
|
|||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
import operator
|
import operator
|
||||||
|
|
||||||
|
try:
|
||||||
|
set
|
||||||
|
except NameError:
|
||||||
|
from sets import Set as set # Python 2.3 fallback
|
||||||
|
|
||||||
# The system will display a "Show all" link on the change list only if the
|
# The system will display a "Show all" link on the change list only if the
|
||||||
# total result count is less than or equal to this setting.
|
# total result count is less than or equal to this setting.
|
||||||
MAX_SHOW_ALL_ALLOWED = 200
|
MAX_SHOW_ALL_ALLOWED = 200
|
||||||
|
@ -79,32 +79,32 @@ class PasswordResetForm(oldforms.Manipulator):
|
|||||||
|
|
||||||
def isValidUserEmail(self, new_data, all_data):
|
def isValidUserEmail(self, new_data, all_data):
|
||||||
"Validates that a user exists with the given e-mail address"
|
"Validates that a user exists with the given e-mail address"
|
||||||
try:
|
self.users_cache = list(User.objects.filter(email__iexact=new_data))
|
||||||
self.user_cache = User.objects.get(email__iexact=new_data)
|
if len(self.users_cache) == 0:
|
||||||
except User.DoesNotExist:
|
|
||||||
raise validators.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?")
|
raise validators.ValidationError, _("That e-mail address doesn't have an associated user account. Are you sure you've registered?")
|
||||||
|
|
||||||
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
|
def save(self, domain_override=None, email_template_name='registration/password_reset_email.html'):
|
||||||
"Calculates a new password randomly and sends it to the user"
|
"Calculates a new password randomly and sends it to the user"
|
||||||
from django.core.mail import send_mail
|
from django.core.mail import send_mail
|
||||||
new_pass = User.objects.make_random_password()
|
for user in self.users_cache:
|
||||||
self.user_cache.set_password(new_pass)
|
new_pass = User.objects.make_random_password()
|
||||||
self.user_cache.save()
|
user.set_password(new_pass)
|
||||||
if not domain_override:
|
user.save()
|
||||||
current_site = Site.objects.get_current()
|
if not domain_override:
|
||||||
site_name = current_site.name
|
current_site = Site.objects.get_current()
|
||||||
domain = current_site.domain
|
site_name = current_site.name
|
||||||
else:
|
domain = current_site.domain
|
||||||
site_name = domain = domain_override
|
else:
|
||||||
t = loader.get_template(email_template_name)
|
site_name = domain = domain_override
|
||||||
c = {
|
t = loader.get_template(email_template_name)
|
||||||
'new_password': new_pass,
|
c = {
|
||||||
'email': self.user_cache.email,
|
'new_password': new_pass,
|
||||||
'domain': domain,
|
'email': user.email,
|
||||||
'site_name': site_name,
|
'domain': domain,
|
||||||
'user': self.user_cache,
|
'site_name': site_name,
|
||||||
}
|
'user': user,
|
||||||
send_mail('Password reset on %s' % site_name, t.render(Context(c)), None, [self.user_cache.email])
|
}
|
||||||
|
send_mail('Password reset on %s' % site_name, t.render(Context(c)), None, [user.email])
|
||||||
|
|
||||||
class PasswordChangeForm(oldforms.Manipulator):
|
class PasswordChangeForm(oldforms.Manipulator):
|
||||||
"A form that lets a user change his password."
|
"A form that lets a user change his password."
|
||||||
|
@ -5,6 +5,11 @@ from django.contrib.contenttypes.models import ContentType
|
|||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
try:
|
||||||
|
set
|
||||||
|
except NameError:
|
||||||
|
from sets import Set as set # Python 2.3 fallback
|
||||||
|
|
||||||
def check_password(raw_password, enc_password):
|
def check_password(raw_password, enc_password):
|
||||||
"""
|
"""
|
||||||
Returns a boolean of whether the raw_password was correct. Handles
|
Returns a boolean of whether the raw_password was correct. Handles
|
||||||
@ -160,7 +165,6 @@ class User(models.Model):
|
|||||||
def get_group_permissions(self):
|
def get_group_permissions(self):
|
||||||
"Returns a list of permission strings that this user has through his/her groups."
|
"Returns a list of permission strings that this user has through his/her groups."
|
||||||
if not hasattr(self, '_group_perm_cache'):
|
if not hasattr(self, '_group_perm_cache'):
|
||||||
import sets
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
# The SQL below works out to the following, after DB quoting:
|
# The SQL below works out to the following, after DB quoting:
|
||||||
# cursor.execute("""
|
# cursor.execute("""
|
||||||
@ -185,13 +189,12 @@ class User(models.Model):
|
|||||||
backend.quote_name('id'), backend.quote_name('content_type_id'),
|
backend.quote_name('id'), backend.quote_name('content_type_id'),
|
||||||
backend.quote_name('user_id'),)
|
backend.quote_name('user_id'),)
|
||||||
cursor.execute(sql, [self.id])
|
cursor.execute(sql, [self.id])
|
||||||
self._group_perm_cache = sets.Set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
|
self._group_perm_cache = set(["%s.%s" % (row[0], row[1]) for row in cursor.fetchall()])
|
||||||
return self._group_perm_cache
|
return self._group_perm_cache
|
||||||
|
|
||||||
def get_all_permissions(self):
|
def get_all_permissions(self):
|
||||||
if not hasattr(self, '_perm_cache'):
|
if not hasattr(self, '_perm_cache'):
|
||||||
import sets
|
self._perm_cache = set(["%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.select_related()])
|
||||||
self._perm_cache = sets.Set(["%s.%s" % (p.content_type.app_label, p.codename) for p in self.user_permissions.select_related()])
|
|
||||||
self._perm_cache.update(self.get_group_permissions())
|
self._perm_cache.update(self.get_group_permissions())
|
||||||
return self._perm_cache
|
return self._perm_cache
|
||||||
|
|
||||||
|
@ -32,10 +32,10 @@
|
|||||||
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
|
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="quiet">(None)</p>
|
<p class="quiet">(None)</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -19,7 +19,7 @@ class RedirectFallbackMiddleware(object):
|
|||||||
except Redirect.DoesNotExist:
|
except Redirect.DoesNotExist:
|
||||||
pass
|
pass
|
||||||
if r is not None:
|
if r is not None:
|
||||||
if r == '':
|
if r.new_path == '':
|
||||||
return http.HttpResponseGone()
|
return http.HttpResponseGone()
|
||||||
return http.HttpResponsePermanentRedirect(r.new_path)
|
return http.HttpResponsePermanentRedirect(r.new_path)
|
||||||
|
|
||||||
|
@ -3,10 +3,13 @@ Tools for sending email.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from email import Charset, Encoders
|
||||||
from email.MIMEText import MIMEText
|
from email.MIMEText import MIMEText
|
||||||
|
from email.MIMEMultipart import MIMEMultipart
|
||||||
|
from email.MIMEBase import MIMEBase
|
||||||
from email.Header import Header
|
from email.Header import Header
|
||||||
from email.Utils import formatdate
|
from email.Utils import formatdate
|
||||||
from email import Charset
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
import smtplib
|
import smtplib
|
||||||
import socket
|
import socket
|
||||||
@ -17,6 +20,10 @@ import random
|
|||||||
# some spam filters.
|
# some spam filters.
|
||||||
Charset.add_charset('utf-8', Charset.SHORTEST, Charset.QP, 'utf-8')
|
Charset.add_charset('utf-8', Charset.SHORTEST, Charset.QP, 'utf-8')
|
||||||
|
|
||||||
|
# Default MIME type to use on attachments (if it is not explicitly given
|
||||||
|
# and cannot be guessed).
|
||||||
|
DEFAULT_ATTACHMENT_MIME_TYPE = 'application/octet-stream'
|
||||||
|
|
||||||
# Cache the hostname, but do it lazily: socket.getfqdn() can take a couple of
|
# Cache the hostname, but do it lazily: socket.getfqdn() can take a couple of
|
||||||
# seconds, which slows down the restart of the server.
|
# seconds, which slows down the restart of the server.
|
||||||
class CachedDnsName(object):
|
class CachedDnsName(object):
|
||||||
@ -55,14 +62,22 @@ def make_msgid(idstring=None):
|
|||||||
class BadHeaderError(ValueError):
|
class BadHeaderError(ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class SafeMIMEText(MIMEText):
|
class SafeHeaderMixin(object):
|
||||||
def __setitem__(self, name, val):
|
def __setitem__(self, name, val):
|
||||||
"Forbids multi-line headers, to prevent header injection."
|
"Forbids multi-line headers, to prevent header injection."
|
||||||
if '\n' in val or '\r' in val:
|
if '\n' in val or '\r' in val:
|
||||||
raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name)
|
raise BadHeaderError, "Header values can't contain newlines (got %r for header %r)" % (val, name)
|
||||||
if name == "Subject":
|
if name == "Subject":
|
||||||
val = Header(val, settings.DEFAULT_CHARSET)
|
val = Header(val, settings.DEFAULT_CHARSET)
|
||||||
MIMEText.__setitem__(self, name, val)
|
# Note: using super() here is safe; any __setitem__ overrides must use
|
||||||
|
# the same argument signature.
|
||||||
|
super(SafeHeaderMixin, self).__setitem__(name, val)
|
||||||
|
|
||||||
|
class SafeMIMEText(MIMEText, SafeHeaderMixin):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class SafeMIMEMultipart(MIMEMultipart, SafeHeaderMixin):
|
||||||
|
pass
|
||||||
|
|
||||||
class SMTPConnection(object):
|
class SMTPConnection(object):
|
||||||
"""
|
"""
|
||||||
@ -154,12 +169,19 @@ class EmailMessage(object):
|
|||||||
"""
|
"""
|
||||||
A container for email information.
|
A container for email information.
|
||||||
"""
|
"""
|
||||||
def __init__(self, subject='', body='', from_email=None, to=None, bcc=None, connection=None):
|
content_subtype = 'plain'
|
||||||
|
multipart_subtype = 'mixed'
|
||||||
|
encoding = None # None => use settings default
|
||||||
|
|
||||||
|
def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
|
||||||
|
connection=None, attachments=None, headers=None):
|
||||||
self.to = to or []
|
self.to = to or []
|
||||||
self.bcc = bcc or []
|
self.bcc = bcc or []
|
||||||
self.from_email = from_email or settings.DEFAULT_FROM_EMAIL
|
self.from_email = from_email or settings.DEFAULT_FROM_EMAIL
|
||||||
self.subject = subject
|
self.subject = subject
|
||||||
self.body = body
|
self.body = body
|
||||||
|
self.attachments = attachments or []
|
||||||
|
self.extra_headers = headers or {}
|
||||||
self.connection = connection
|
self.connection = connection
|
||||||
|
|
||||||
def get_connection(self, fail_silently=False):
|
def get_connection(self, fail_silently=False):
|
||||||
@ -168,7 +190,18 @@ class EmailMessage(object):
|
|||||||
return self.connection
|
return self.connection
|
||||||
|
|
||||||
def message(self):
|
def message(self):
|
||||||
msg = SafeMIMEText(self.body, 'plain', settings.DEFAULT_CHARSET)
|
encoding = self.encoding or settings.DEFAULT_CHARSET
|
||||||
|
msg = SafeMIMEText(self.body, self.content_subtype, encoding)
|
||||||
|
if self.attachments:
|
||||||
|
body_msg = msg
|
||||||
|
msg = SafeMIMEMultipart(_subtype=self.multipart_subtype)
|
||||||
|
if self.body:
|
||||||
|
msg.attach(body_msg)
|
||||||
|
for attachment in self.attachments:
|
||||||
|
if isinstance(attachment, MIMEBase):
|
||||||
|
msg.attach(attachment)
|
||||||
|
else:
|
||||||
|
msg.attach(self._create_attachment(*attachment))
|
||||||
msg['Subject'] = self.subject
|
msg['Subject'] = self.subject
|
||||||
msg['From'] = self.from_email
|
msg['From'] = self.from_email
|
||||||
msg['To'] = ', '.join(self.to)
|
msg['To'] = ', '.join(self.to)
|
||||||
@ -176,6 +209,8 @@ class EmailMessage(object):
|
|||||||
msg['Message-ID'] = make_msgid()
|
msg['Message-ID'] = make_msgid()
|
||||||
if self.bcc:
|
if self.bcc:
|
||||||
msg['Bcc'] = ', '.join(self.bcc)
|
msg['Bcc'] = ', '.join(self.bcc)
|
||||||
|
for name, value in self.extra_headers.items():
|
||||||
|
msg[name] = value
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def recipients(self):
|
def recipients(self):
|
||||||
@ -189,6 +224,61 @@ class EmailMessage(object):
|
|||||||
"""Send the email message."""
|
"""Send the email message."""
|
||||||
return self.get_connection(fail_silently).send_messages([self])
|
return self.get_connection(fail_silently).send_messages([self])
|
||||||
|
|
||||||
|
def attach(self, filename=None, content=None, mimetype=None):
|
||||||
|
"""
|
||||||
|
Attaches a file with the given filename and content. The filename can
|
||||||
|
be omitted (useful for multipart/alternative messages) and the mimetype
|
||||||
|
is guessed, if not provided.
|
||||||
|
|
||||||
|
If the first parameter is a MIMEBase subclass it is inserted directly
|
||||||
|
into the resulting message attachments.
|
||||||
|
"""
|
||||||
|
if isinstance(filename, MIMEBase):
|
||||||
|
assert content == mimetype == None
|
||||||
|
self.attachements.append(filename)
|
||||||
|
else:
|
||||||
|
assert content is not None
|
||||||
|
self.attachments.append((filename, content, mimetype))
|
||||||
|
|
||||||
|
def attach_file(self, path, mimetype=None):
|
||||||
|
"""Attaches a file from the filesystem."""
|
||||||
|
filename = os.path.basename(path)
|
||||||
|
content = open(path, 'rb').read()
|
||||||
|
self.attach(filename, content, mimetype)
|
||||||
|
|
||||||
|
def _create_attachment(self, filename, content, mimetype=None):
|
||||||
|
"""
|
||||||
|
Convert the filename, content, mimetype triple into a MIME attachment
|
||||||
|
object.
|
||||||
|
"""
|
||||||
|
if mimetype is None:
|
||||||
|
mimetype, _ = mimetypes.guess_type(filename)
|
||||||
|
if mimetype is None:
|
||||||
|
mimetype = DEFAULT_ATTACHMENT_MIME_TYPE
|
||||||
|
basetype, subtype = mimetype.split('/', 1)
|
||||||
|
if basetype == 'text':
|
||||||
|
attachment = SafeMIMEText(content, subtype, settings.DEFAULT_CHARSET)
|
||||||
|
else:
|
||||||
|
# Encode non-text attachments with base64.
|
||||||
|
attachment = MIMEBase(basetype, subtype)
|
||||||
|
attachment.set_payload(content)
|
||||||
|
Encoders.encode_base64(attachment)
|
||||||
|
if filename:
|
||||||
|
attachment.add_header('Content-Disposition', 'attachment', filename=filename)
|
||||||
|
return attachment
|
||||||
|
|
||||||
|
class EmailMultiAlternatives(EmailMessage):
|
||||||
|
"""
|
||||||
|
A version of EmailMessage that makes it easy to send multipart/alternative
|
||||||
|
messages. For example, including text and HTML versions of the text is
|
||||||
|
made easier.
|
||||||
|
"""
|
||||||
|
multipart_subtype = 'alternative'
|
||||||
|
|
||||||
|
def attach_alternative(self, content, mimetype=None):
|
||||||
|
"""Attach an alternative content representation."""
|
||||||
|
self.attach(content=content, mimetype=mimetype)
|
||||||
|
|
||||||
def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None):
|
def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None):
|
||||||
"""
|
"""
|
||||||
Easy wrapper for sending a single message to a recipient list. All members
|
Easy wrapper for sending a single message to a recipient list. All members
|
||||||
|
@ -7,9 +7,10 @@ from optparse import OptionParser
|
|||||||
from django.utils import termcolors
|
from django.utils import termcolors
|
||||||
import os, re, shutil, sys, textwrap
|
import os, re, shutil, sys, textwrap
|
||||||
|
|
||||||
# For Python 2.3
|
try:
|
||||||
if not hasattr(__builtins__, 'set'):
|
set
|
||||||
from sets import Set as set
|
except NameError:
|
||||||
|
from sets import Set as set # Python 2.3 fallback
|
||||||
|
|
||||||
# For backwards compatibility: get_version() used to be in this module.
|
# For backwards compatibility: get_version() used to be in this module.
|
||||||
get_version = django.get_version
|
get_version = django.get_version
|
||||||
@ -58,12 +59,16 @@ def _is_valid_dir_name(s):
|
|||||||
|
|
||||||
def _get_installed_models(table_list):
|
def _get_installed_models(table_list):
|
||||||
"Gets a set of all models that are installed, given a list of existing tables"
|
"Gets a set of all models that are installed, given a list of existing tables"
|
||||||
from django.db import models
|
from django.db import backend, models
|
||||||
all_models = []
|
all_models = []
|
||||||
for app in models.get_apps():
|
for app in models.get_apps():
|
||||||
for model in models.get_models(app):
|
for model in models.get_models(app):
|
||||||
all_models.append(model)
|
all_models.append(model)
|
||||||
return set([m for m in all_models if m._meta.db_table in table_list])
|
if backend.uses_case_insensitive_names:
|
||||||
|
converter = str.upper
|
||||||
|
else:
|
||||||
|
converter = lambda x: x
|
||||||
|
return set([m for m in all_models if converter(m._meta.db_table) in map(converter, table_list)])
|
||||||
|
|
||||||
def _get_table_list():
|
def _get_table_list():
|
||||||
"Gets a list of all db tables that are physically installed."
|
"Gets a list of all db tables that are physically installed."
|
||||||
@ -99,6 +104,7 @@ get_rel_data_type = lambda f: (f.get_internal_type() in ('AutoField', 'PositiveI
|
|||||||
def get_sql_create(app):
|
def get_sql_create(app):
|
||||||
"Returns a list of the CREATE TABLE SQL statements for the given app."
|
"Returns a list of the CREATE TABLE SQL statements for the given app."
|
||||||
from django.db import get_creation_module, models
|
from django.db import get_creation_module, models
|
||||||
|
|
||||||
data_types = get_creation_module().DATA_TYPES
|
data_types = get_creation_module().DATA_TYPES
|
||||||
|
|
||||||
if not data_types:
|
if not data_types:
|
||||||
@ -170,15 +176,20 @@ def _get_sql_model_create(model, known_models=set()):
|
|||||||
rel_field = f
|
rel_field = f
|
||||||
data_type = f.get_internal_type()
|
data_type = f.get_internal_type()
|
||||||
col_type = data_types[data_type]
|
col_type = data_types[data_type]
|
||||||
|
tablespace = f.db_tablespace or opts.db_tablespace
|
||||||
if col_type is not None:
|
if col_type is not None:
|
||||||
# Make the definition (e.g. 'foo VARCHAR(30)') for this field.
|
# Make the definition (e.g. 'foo VARCHAR(30)') for this field.
|
||||||
field_output = [style.SQL_FIELD(backend.quote_name(f.column)),
|
field_output = [style.SQL_FIELD(backend.quote_name(f.column)),
|
||||||
style.SQL_COLTYPE(col_type % rel_field.__dict__)]
|
style.SQL_COLTYPE(col_type % rel_field.__dict__)]
|
||||||
field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')))
|
field_output.append(style.SQL_KEYWORD('%sNULL' % (not f.null and 'NOT ' or '')))
|
||||||
if f.unique:
|
if f.unique and (not f.primary_key or backend.allows_unique_and_pk):
|
||||||
field_output.append(style.SQL_KEYWORD('UNIQUE'))
|
field_output.append(style.SQL_KEYWORD('UNIQUE'))
|
||||||
if f.primary_key:
|
if f.primary_key:
|
||||||
field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
|
field_output.append(style.SQL_KEYWORD('PRIMARY KEY'))
|
||||||
|
if tablespace and backend.supports_tablespaces and (f.unique or f.primary_key) and backend.autoindexes_primary_keys:
|
||||||
|
# We must specify the index tablespace inline, because we
|
||||||
|
# won't be generating a CREATE INDEX statement for this field.
|
||||||
|
field_output.append(backend.get_tablespace_sql(tablespace, inline=True))
|
||||||
if f.rel:
|
if f.rel:
|
||||||
if f.rel.to in known_models:
|
if f.rel.to in known_models:
|
||||||
field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
|
field_output.append(style.SQL_KEYWORD('REFERENCES') + ' ' + \
|
||||||
@ -202,9 +213,19 @@ def _get_sql_model_create(model, known_models=set()):
|
|||||||
full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(backend.quote_name(opts.db_table)) + ' (']
|
full_statement = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + style.SQL_TABLE(backend.quote_name(opts.db_table)) + ' (']
|
||||||
for i, line in enumerate(table_output): # Combine and add commas.
|
for i, line in enumerate(table_output): # Combine and add commas.
|
||||||
full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))
|
full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))
|
||||||
full_statement.append(');')
|
full_statement.append(')')
|
||||||
|
if opts.db_tablespace and backend.supports_tablespaces:
|
||||||
|
full_statement.append(backend.get_tablespace_sql(opts.db_tablespace))
|
||||||
|
full_statement.append(';')
|
||||||
final_output.append('\n'.join(full_statement))
|
final_output.append('\n'.join(full_statement))
|
||||||
|
|
||||||
|
if opts.has_auto_field and hasattr(backend, 'get_autoinc_sql'):
|
||||||
|
# Add any extra SQL needed to support auto-incrementing primary keys
|
||||||
|
autoinc_sql = backend.get_autoinc_sql(opts.db_table)
|
||||||
|
if autoinc_sql:
|
||||||
|
for stmt in autoinc_sql:
|
||||||
|
final_output.append(stmt)
|
||||||
|
|
||||||
return final_output, pending_references
|
return final_output, pending_references
|
||||||
|
|
||||||
def _get_sql_for_pending_references(model, pending_references):
|
def _get_sql_for_pending_references(model, pending_references):
|
||||||
@ -212,6 +233,7 @@ def _get_sql_for_pending_references(model, pending_references):
|
|||||||
Get any ALTER TABLE statements to add constraints after the fact.
|
Get any ALTER TABLE statements to add constraints after the fact.
|
||||||
"""
|
"""
|
||||||
from django.db import backend, get_creation_module
|
from django.db import backend, get_creation_module
|
||||||
|
from django.db.backends.util import truncate_name
|
||||||
data_types = get_creation_module().DATA_TYPES
|
data_types = get_creation_module().DATA_TYPES
|
||||||
|
|
||||||
final_output = []
|
final_output = []
|
||||||
@ -228,7 +250,7 @@ def _get_sql_for_pending_references(model, pending_references):
|
|||||||
# So we are careful with character usage here.
|
# So we are careful with character usage here.
|
||||||
r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
|
r_name = '%s_refs_%s_%x' % (r_col, col, abs(hash((r_table, table))))
|
||||||
final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \
|
final_output.append(style.SQL_KEYWORD('ALTER TABLE') + ' %s ADD CONSTRAINT %s FOREIGN KEY (%s) REFERENCES %s (%s)%s;' % \
|
||||||
(backend.quote_name(r_table), r_name,
|
(backend.quote_name(r_table), truncate_name(r_name, backend.get_max_name_length()),
|
||||||
backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col),
|
backend.quote_name(r_col), backend.quote_name(table), backend.quote_name(col),
|
||||||
backend.get_deferrable_sql()))
|
backend.get_deferrable_sql()))
|
||||||
del pending_references[model]
|
del pending_references[model]
|
||||||
@ -244,12 +266,18 @@ def _get_many_to_many_sql_for_model(model):
|
|||||||
final_output = []
|
final_output = []
|
||||||
for f in opts.many_to_many:
|
for f in opts.many_to_many:
|
||||||
if not isinstance(f.rel, generic.GenericRel):
|
if not isinstance(f.rel, generic.GenericRel):
|
||||||
|
tablespace = f.db_tablespace or opts.db_tablespace
|
||||||
|
if tablespace and backend.supports_tablespaces and backend.autoindexes_primary_keys:
|
||||||
|
tablespace_sql = ' ' + backend.get_tablespace_sql(tablespace, inline=True)
|
||||||
|
else:
|
||||||
|
tablespace_sql = ''
|
||||||
table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \
|
table_output = [style.SQL_KEYWORD('CREATE TABLE') + ' ' + \
|
||||||
style.SQL_TABLE(backend.quote_name(f.m2m_db_table())) + ' (']
|
style.SQL_TABLE(backend.quote_name(f.m2m_db_table())) + ' (']
|
||||||
table_output.append(' %s %s %s,' % \
|
table_output.append(' %s %s %s%s,' % \
|
||||||
(style.SQL_FIELD(backend.quote_name('id')),
|
(style.SQL_FIELD(backend.quote_name('id')),
|
||||||
style.SQL_COLTYPE(data_types['AutoField']),
|
style.SQL_COLTYPE(data_types['AutoField']),
|
||||||
style.SQL_KEYWORD('NOT NULL PRIMARY KEY')))
|
style.SQL_KEYWORD('NOT NULL PRIMARY KEY'),
|
||||||
|
tablespace_sql))
|
||||||
table_output.append(' %s %s %s %s (%s)%s,' % \
|
table_output.append(' %s %s %s %s (%s)%s,' % \
|
||||||
(style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
|
(style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
|
||||||
style.SQL_COLTYPE(data_types[get_rel_data_type(opts.pk)] % opts.pk.__dict__),
|
style.SQL_COLTYPE(data_types[get_rel_data_type(opts.pk)] % opts.pk.__dict__),
|
||||||
@ -264,17 +292,30 @@ def _get_many_to_many_sql_for_model(model):
|
|||||||
style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)),
|
style.SQL_TABLE(backend.quote_name(f.rel.to._meta.db_table)),
|
||||||
style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column)),
|
style.SQL_FIELD(backend.quote_name(f.rel.to._meta.pk.column)),
|
||||||
backend.get_deferrable_sql()))
|
backend.get_deferrable_sql()))
|
||||||
table_output.append(' %s (%s, %s)' % \
|
table_output.append(' %s (%s, %s)%s' % \
|
||||||
(style.SQL_KEYWORD('UNIQUE'),
|
(style.SQL_KEYWORD('UNIQUE'),
|
||||||
style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
|
style.SQL_FIELD(backend.quote_name(f.m2m_column_name())),
|
||||||
style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name()))))
|
style.SQL_FIELD(backend.quote_name(f.m2m_reverse_name())),
|
||||||
table_output.append(');')
|
tablespace_sql))
|
||||||
|
table_output.append(')')
|
||||||
|
if opts.db_tablespace and backend.supports_tablespaces:
|
||||||
|
# f.db_tablespace is only for indices, so ignore its value here.
|
||||||
|
table_output.append(backend.get_tablespace_sql(opts.db_tablespace))
|
||||||
|
table_output.append(';')
|
||||||
final_output.append('\n'.join(table_output))
|
final_output.append('\n'.join(table_output))
|
||||||
|
|
||||||
|
# Add any extra SQL needed to support auto-incrementing PKs
|
||||||
|
autoinc_sql = backend.get_autoinc_sql(f.m2m_db_table())
|
||||||
|
if autoinc_sql:
|
||||||
|
for stmt in autoinc_sql:
|
||||||
|
final_output.append(stmt)
|
||||||
|
|
||||||
return final_output
|
return final_output
|
||||||
|
|
||||||
def get_sql_delete(app):
|
def get_sql_delete(app):
|
||||||
"Returns a list of the DROP TABLE SQL statements for the given app."
|
"Returns a list of the DROP TABLE SQL statements for the given app."
|
||||||
from django.db import backend, connection, models, get_introspection_module
|
from django.db import backend, connection, models, get_introspection_module
|
||||||
|
from django.db.backends.util import truncate_name
|
||||||
introspection = get_introspection_module()
|
introspection = get_introspection_module()
|
||||||
|
|
||||||
# This should work even if a connection isn't available
|
# This should work even if a connection isn't available
|
||||||
@ -288,6 +329,10 @@ def get_sql_delete(app):
|
|||||||
table_names = introspection.get_table_list(cursor)
|
table_names = introspection.get_table_list(cursor)
|
||||||
else:
|
else:
|
||||||
table_names = []
|
table_names = []
|
||||||
|
if backend.uses_case_insensitive_names:
|
||||||
|
table_name_converter = str.upper
|
||||||
|
else:
|
||||||
|
table_name_converter = lambda x: x
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
|
|
||||||
@ -297,7 +342,7 @@ def get_sql_delete(app):
|
|||||||
references_to_delete = {}
|
references_to_delete = {}
|
||||||
app_models = models.get_models(app)
|
app_models = models.get_models(app)
|
||||||
for model in app_models:
|
for model in app_models:
|
||||||
if cursor and model._meta.db_table in table_names:
|
if cursor and table_name_converter(model._meta.db_table) in table_names:
|
||||||
# The table exists, so it needs to be dropped
|
# The table exists, so it needs to be dropped
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
for f in opts.fields:
|
for f in opts.fields:
|
||||||
@ -307,7 +352,7 @@ def get_sql_delete(app):
|
|||||||
to_delete.add(model)
|
to_delete.add(model)
|
||||||
|
|
||||||
for model in app_models:
|
for model in app_models:
|
||||||
if cursor and model._meta.db_table in table_names:
|
if cursor and table_name_converter(model._meta.db_table) in table_names:
|
||||||
# Drop the table now
|
# Drop the table now
|
||||||
output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'),
|
output.append('%s %s;' % (style.SQL_KEYWORD('DROP TABLE'),
|
||||||
style.SQL_TABLE(backend.quote_name(model._meta.db_table))))
|
style.SQL_TABLE(backend.quote_name(model._meta.db_table))))
|
||||||
@ -317,20 +362,26 @@ def get_sql_delete(app):
|
|||||||
col = f.column
|
col = f.column
|
||||||
r_table = model._meta.db_table
|
r_table = model._meta.db_table
|
||||||
r_col = model._meta.get_field(f.rel.field_name).column
|
r_col = model._meta.get_field(f.rel.field_name).column
|
||||||
|
r_name = '%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table))))
|
||||||
output.append('%s %s %s %s;' % \
|
output.append('%s %s %s %s;' % \
|
||||||
(style.SQL_KEYWORD('ALTER TABLE'),
|
(style.SQL_KEYWORD('ALTER TABLE'),
|
||||||
style.SQL_TABLE(backend.quote_name(table)),
|
style.SQL_TABLE(backend.quote_name(table)),
|
||||||
style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
|
style.SQL_KEYWORD(backend.get_drop_foreignkey_sql()),
|
||||||
style.SQL_FIELD(backend.quote_name('%s_refs_%s_%x' % (col, r_col, abs(hash((table, r_table))))))))
|
style.SQL_FIELD(truncate_name(r_name, backend.get_max_name_length()))))
|
||||||
del references_to_delete[model]
|
del references_to_delete[model]
|
||||||
|
if model._meta.has_auto_field and hasattr(backend, 'get_drop_sequence'):
|
||||||
|
output.append(backend.get_drop_sequence(model._meta.db_table))
|
||||||
|
|
||||||
# Output DROP TABLE statements for many-to-many tables.
|
# Output DROP TABLE statements for many-to-many tables.
|
||||||
for model in app_models:
|
for model in app_models:
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
for f in opts.many_to_many:
|
for f in opts.many_to_many:
|
||||||
if cursor and f.m2m_db_table() in table_names:
|
if cursor and table_name_converter(f.m2m_db_table()) in table_names:
|
||||||
output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'),
|
output.append("%s %s;" % (style.SQL_KEYWORD('DROP TABLE'),
|
||||||
style.SQL_TABLE(backend.quote_name(f.m2m_db_table()))))
|
style.SQL_TABLE(backend.quote_name(f.m2m_db_table()))))
|
||||||
|
if hasattr(backend, 'get_drop_sequence'):
|
||||||
|
output.append(backend.get_drop_sequence("%s_%s" % (model._meta.db_table, f.column)))
|
||||||
|
|
||||||
|
|
||||||
app_label = app_models[0]._meta.app_label
|
app_label = app_models[0]._meta.app_label
|
||||||
|
|
||||||
@ -429,14 +480,20 @@ def get_sql_indexes_for_model(model):
|
|||||||
output = []
|
output = []
|
||||||
|
|
||||||
for f in model._meta.fields:
|
for f in model._meta.fields:
|
||||||
if f.db_index:
|
if f.db_index and not ((f.primary_key or f.unique) and backend.autoindexes_primary_keys):
|
||||||
unique = f.unique and 'UNIQUE ' or ''
|
unique = f.unique and 'UNIQUE ' or ''
|
||||||
|
tablespace = f.db_tablespace or model._meta.db_tablespace
|
||||||
|
if tablespace and backend.supports_tablespaces:
|
||||||
|
tablespace_sql = ' ' + backend.get_tablespace_sql(tablespace)
|
||||||
|
else:
|
||||||
|
tablespace_sql = ''
|
||||||
output.append(
|
output.append(
|
||||||
style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
|
style.SQL_KEYWORD('CREATE %sINDEX' % unique) + ' ' + \
|
||||||
style.SQL_TABLE(backend.quote_name('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \
|
style.SQL_TABLE(backend.quote_name('%s_%s' % (model._meta.db_table, f.column))) + ' ' + \
|
||||||
style.SQL_KEYWORD('ON') + ' ' + \
|
style.SQL_KEYWORD('ON') + ' ' + \
|
||||||
style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \
|
style.SQL_TABLE(backend.quote_name(model._meta.db_table)) + ' ' + \
|
||||||
"(%s);" % style.SQL_FIELD(backend.quote_name(f.column))
|
"(%s)" % style.SQL_FIELD(backend.quote_name(f.column)) + \
|
||||||
|
"%s;" % tablespace_sql
|
||||||
)
|
)
|
||||||
return output
|
return output
|
||||||
|
|
||||||
@ -460,7 +517,7 @@ def _emit_post_sync_signal(created_models, verbosity, interactive):
|
|||||||
|
|
||||||
def syncdb(verbosity=1, interactive=True):
|
def syncdb(verbosity=1, interactive=True):
|
||||||
"Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
|
"Creates the database tables for all apps in INSTALLED_APPS whose tables haven't already been created."
|
||||||
from django.db import connection, transaction, models, get_creation_module
|
from django.db import backend, connection, transaction, models, get_creation_module
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
disable_termcolors()
|
disable_termcolors()
|
||||||
@ -483,6 +540,10 @@ def syncdb(verbosity=1, interactive=True):
|
|||||||
# Get a list of all existing database tables,
|
# Get a list of all existing database tables,
|
||||||
# so we know what needs to be added.
|
# so we know what needs to be added.
|
||||||
table_list = _get_table_list()
|
table_list = _get_table_list()
|
||||||
|
if backend.uses_case_insensitive_names:
|
||||||
|
table_name_converter = str.upper
|
||||||
|
else:
|
||||||
|
table_name_converter = lambda x: x
|
||||||
|
|
||||||
# Get a list of already installed *models* so that references work right.
|
# Get a list of already installed *models* so that references work right.
|
||||||
seen_models = _get_installed_models(table_list)
|
seen_models = _get_installed_models(table_list)
|
||||||
@ -497,7 +558,7 @@ def syncdb(verbosity=1, interactive=True):
|
|||||||
# Create the model's database table, if it doesn't already exist.
|
# Create the model's database table, if it doesn't already exist.
|
||||||
if verbosity >= 2:
|
if verbosity >= 2:
|
||||||
print "Processing %s.%s model" % (app_name, model._meta.object_name)
|
print "Processing %s.%s model" % (app_name, model._meta.object_name)
|
||||||
if model._meta.db_table in table_list:
|
if table_name_converter(model._meta.db_table) in table_list:
|
||||||
continue
|
continue
|
||||||
sql, references = _get_sql_model_create(model, seen_models)
|
sql, references = _get_sql_model_create(model, seen_models)
|
||||||
seen_models.add(model)
|
seen_models.add(model)
|
||||||
@ -509,7 +570,7 @@ def syncdb(verbosity=1, interactive=True):
|
|||||||
print "Creating table %s" % model._meta.db_table
|
print "Creating table %s" % model._meta.db_table
|
||||||
for statement in sql:
|
for statement in sql:
|
||||||
cursor.execute(statement)
|
cursor.execute(statement)
|
||||||
table_list.append(model._meta.db_table)
|
table_list.append(table_name_converter(model._meta.db_table))
|
||||||
|
|
||||||
# Create the m2m tables. This must be done after all tables have been created
|
# Create the m2m tables. This must be done after all tables have been created
|
||||||
# to ensure that all referred tables will exist.
|
# to ensure that all referred tables will exist.
|
||||||
@ -828,7 +889,7 @@ def inspectdb():
|
|||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
indexes = {}
|
indexes = {}
|
||||||
for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)):
|
for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)):
|
||||||
att_name = row[0]
|
att_name = row[0].lower()
|
||||||
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
|
comment_notes = [] # Holds Field notes, to be displayed in a Python comment.
|
||||||
extra_params = {} # Holds Field parameters such as 'db_column'.
|
extra_params = {} # Holds Field parameters such as 'db_column'.
|
||||||
|
|
||||||
@ -1628,7 +1689,9 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
|||||||
if not mod_list:
|
if not mod_list:
|
||||||
parser.print_usage_and_exit()
|
parser.print_usage_and_exit()
|
||||||
if action not in NO_SQL_TRANSACTION:
|
if action not in NO_SQL_TRANSACTION:
|
||||||
print style.SQL_KEYWORD("BEGIN;")
|
from django.db import backend
|
||||||
|
if backend.get_start_transaction_sql():
|
||||||
|
print style.SQL_KEYWORD(backend.get_start_transaction_sql())
|
||||||
for mod in mod_list:
|
for mod in mod_list:
|
||||||
if action == 'reset':
|
if action == 'reset':
|
||||||
output = action_mapping[action](mod, options.interactive)
|
output = action_mapping[action](mod, options.interactive)
|
||||||
|
@ -9,7 +9,7 @@ been reviewed for security issues. Don't use it for production use.
|
|||||||
|
|
||||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
|
||||||
from types import ListType, StringType
|
from types import ListType, StringType
|
||||||
import os, re, sys, time, urllib
|
import os, re, sys, time, urllib, mimetypes
|
||||||
|
|
||||||
__version__ = "0.1"
|
__version__ = "0.1"
|
||||||
__all__ = ['WSGIServer','WSGIRequestHandler','demo_app']
|
__all__ = ['WSGIServer','WSGIRequestHandler','demo_app']
|
||||||
@ -630,6 +630,9 @@ class AdminMediaHandler(object):
|
|||||||
else:
|
else:
|
||||||
status = '200 OK'
|
status = '200 OK'
|
||||||
headers = {}
|
headers = {}
|
||||||
|
mime_type = mimetypes.guess_type(file_path)[0]
|
||||||
|
if mime_type:
|
||||||
|
headers['Content-Type'] = mime_type
|
||||||
output = [fp.read()]
|
output = [fp.read()]
|
||||||
fp.close()
|
fp.close()
|
||||||
start_response(status, headers.items())
|
start_response(status, headers.items())
|
||||||
|
@ -9,8 +9,17 @@ a string) and returns a tuple in this format:
|
|||||||
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
|
from django.core.exceptions import ImproperlyConfigured, ViewDoesNotExist
|
||||||
|
from django.utils.functional import memoize
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
try:
|
||||||
|
reversed
|
||||||
|
except NameError:
|
||||||
|
from django.utils.itercompat import reversed # Python 2.3 fallback
|
||||||
|
|
||||||
|
_resolver_cache = {} # Maps urlconf modules to RegexURLResolver instances.
|
||||||
|
_callable_cache = {} # Maps view and url pattern names to their view functions.
|
||||||
|
|
||||||
class Resolver404(Http404):
|
class Resolver404(Http404):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -18,6 +27,34 @@ class NoReverseMatch(Exception):
|
|||||||
# Don't make this raise an error when used in a template.
|
# Don't make this raise an error when used in a template.
|
||||||
silent_variable_failure = True
|
silent_variable_failure = True
|
||||||
|
|
||||||
|
def get_callable(lookup_view, can_fail=False):
|
||||||
|
"""
|
||||||
|
Convert a string version of a function name to the callable object.
|
||||||
|
|
||||||
|
If the lookup_view is not an import path, it is assumed to be a URL pattern
|
||||||
|
label and the original string is returned.
|
||||||
|
|
||||||
|
If can_fail is True, lookup_view might be a URL pattern label, so errors
|
||||||
|
during the import fail and the string is returned.
|
||||||
|
"""
|
||||||
|
if not callable(lookup_view):
|
||||||
|
mod_name, func_name = get_mod_func(lookup_view)
|
||||||
|
try:
|
||||||
|
if func_name != '':
|
||||||
|
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
|
||||||
|
except (ImportError, AttributeError):
|
||||||
|
if not can_fail:
|
||||||
|
raise
|
||||||
|
return lookup_view
|
||||||
|
get_callable = memoize(get_callable, _callable_cache)
|
||||||
|
|
||||||
|
def get_resolver(urlconf):
|
||||||
|
if urlconf is None:
|
||||||
|
from django.conf import settings
|
||||||
|
urlconf = settings.ROOT_URLCONF
|
||||||
|
return RegexURLResolver(r'^/', urlconf)
|
||||||
|
get_resolver = memoize(get_resolver, _resolver_cache)
|
||||||
|
|
||||||
def get_mod_func(callback):
|
def get_mod_func(callback):
|
||||||
# Converts 'django.views.news.stories.story_detail' to
|
# Converts 'django.views.news.stories.story_detail' to
|
||||||
# ['django.views.news.stories', 'story_detail']
|
# ['django.views.news.stories', 'story_detail']
|
||||||
@ -129,12 +166,13 @@ class RegexURLPattern(object):
|
|||||||
def _get_callback(self):
|
def _get_callback(self):
|
||||||
if self._callback is not None:
|
if self._callback is not None:
|
||||||
return self._callback
|
return self._callback
|
||||||
mod_name, func_name = get_mod_func(self._callback_str)
|
|
||||||
try:
|
try:
|
||||||
self._callback = getattr(__import__(mod_name, {}, {}, ['']), func_name)
|
self._callback = get_callable(self._callback_str)
|
||||||
except ImportError, e:
|
except ImportError, e:
|
||||||
|
mod_name, _ = get_mod_func(self._callback_str)
|
||||||
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
|
raise ViewDoesNotExist, "Could not import %s. Error was: %s" % (mod_name, str(e))
|
||||||
except AttributeError, e:
|
except AttributeError, e:
|
||||||
|
mod_name, func_name = get_mod_func(self._callback_str)
|
||||||
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
|
raise ViewDoesNotExist, "Tried %s in module %s. Error was: %s" % (func_name, mod_name, str(e))
|
||||||
return self._callback
|
return self._callback
|
||||||
callback = property(_get_callback)
|
callback = property(_get_callback)
|
||||||
@ -160,6 +198,19 @@ class RegexURLResolver(object):
|
|||||||
self.urlconf_name = urlconf_name
|
self.urlconf_name = urlconf_name
|
||||||
self.callback = None
|
self.callback = None
|
||||||
self.default_kwargs = default_kwargs or {}
|
self.default_kwargs = default_kwargs or {}
|
||||||
|
self._reverse_dict = {}
|
||||||
|
|
||||||
|
def _get_reverse_dict(self):
|
||||||
|
if not self._reverse_dict and hasattr(self.urlconf_module, 'urlpatterns'):
|
||||||
|
for pattern in reversed(self.urlconf_module.urlpatterns):
|
||||||
|
if isinstance(pattern, RegexURLResolver):
|
||||||
|
for key, value in pattern.reverse_dict.iteritems():
|
||||||
|
self._reverse_dict[key] = (pattern,) + value
|
||||||
|
else:
|
||||||
|
self._reverse_dict[pattern.callback] = (pattern,)
|
||||||
|
self._reverse_dict[pattern.name] = (pattern,)
|
||||||
|
return self._reverse_dict
|
||||||
|
reverse_dict = property(_get_reverse_dict)
|
||||||
|
|
||||||
def resolve(self, path):
|
def resolve(self, path):
|
||||||
tried = []
|
tried = []
|
||||||
@ -209,24 +260,12 @@ class RegexURLResolver(object):
|
|||||||
return self._resolve_special('500')
|
return self._resolve_special('500')
|
||||||
|
|
||||||
def reverse(self, lookup_view, *args, **kwargs):
|
def reverse(self, lookup_view, *args, **kwargs):
|
||||||
if not callable(lookup_view):
|
try:
|
||||||
mod_name, func_name = get_mod_func(lookup_view)
|
lookup_view = get_callable(lookup_view, True)
|
||||||
try:
|
except (ImportError, AttributeError):
|
||||||
lookup_view = getattr(__import__(mod_name, {}, {}, ['']), func_name)
|
raise NoReverseMatch
|
||||||
except (ImportError, AttributeError):
|
if lookup_view in self.reverse_dict:
|
||||||
if func_name != '':
|
return ''.join([reverse_helper(part.regex, *args, **kwargs) for part in self.reverse_dict[lookup_view]])
|
||||||
raise NoReverseMatch
|
|
||||||
for pattern in self.urlconf_module.urlpatterns:
|
|
||||||
if isinstance(pattern, RegexURLResolver):
|
|
||||||
try:
|
|
||||||
return pattern.reverse_helper(lookup_view, *args, **kwargs)
|
|
||||||
except NoReverseMatch:
|
|
||||||
continue
|
|
||||||
elif pattern.callback == lookup_view or pattern.name == lookup_view:
|
|
||||||
try:
|
|
||||||
return pattern.reverse_helper(*args, **kwargs)
|
|
||||||
except NoReverseMatch:
|
|
||||||
continue
|
|
||||||
raise NoReverseMatch
|
raise NoReverseMatch
|
||||||
|
|
||||||
def reverse_helper(self, lookup_view, *args, **kwargs):
|
def reverse_helper(self, lookup_view, *args, **kwargs):
|
||||||
@ -235,17 +274,10 @@ class RegexURLResolver(object):
|
|||||||
return result + sub_match
|
return result + sub_match
|
||||||
|
|
||||||
def resolve(path, urlconf=None):
|
def resolve(path, urlconf=None):
|
||||||
if urlconf is None:
|
return get_resolver(urlconf).resolve(path)
|
||||||
from django.conf import settings
|
|
||||||
urlconf = settings.ROOT_URLCONF
|
|
||||||
resolver = RegexURLResolver(r'^/', urlconf)
|
|
||||||
return resolver.resolve(path)
|
|
||||||
|
|
||||||
def reverse(viewname, urlconf=None, args=None, kwargs=None):
|
def reverse(viewname, urlconf=None, args=None, kwargs=None):
|
||||||
args = args or []
|
args = args or []
|
||||||
kwargs = kwargs or {}
|
kwargs = kwargs or {}
|
||||||
if urlconf is None:
|
return '/' + get_resolver(urlconf).reverse(viewname, *args, **kwargs)
|
||||||
from django.conf import settings
|
|
||||||
urlconf = settings.ROOT_URLCONF
|
|
||||||
resolver = RegexURLResolver(r'^/', urlconf)
|
|
||||||
return '/' + resolver.reverse(viewname, *args, **kwargs)
|
|
||||||
|
@ -89,7 +89,14 @@ class DatabaseWrapper(local):
|
|||||||
self.connection.close()
|
self.connection.close()
|
||||||
self.connection = None
|
self.connection = None
|
||||||
|
|
||||||
|
allows_group_by_ordinal = True
|
||||||
|
allows_unique_and_pk = True
|
||||||
|
autoindexes_primary_keys = True
|
||||||
|
needs_datetime_string_cast = True
|
||||||
|
needs_upper_for_iops = False
|
||||||
supports_constraints = True
|
supports_constraints = True
|
||||||
|
supports_tablespaces = True
|
||||||
|
uses_case_insensitive_names = False
|
||||||
|
|
||||||
def quote_name(name):
|
def quote_name(name):
|
||||||
if name.startswith('[') and name.endswith(']'):
|
if name.startswith('[') and name.endswith(']'):
|
||||||
@ -117,6 +124,9 @@ def get_date_trunc_sql(lookup_type, field_name):
|
|||||||
if lookup_type=='day':
|
if lookup_type=='day':
|
||||||
return "Convert(datetime, Convert(varchar(12), %s))" % field_name
|
return "Convert(datetime, Convert(varchar(12), %s))" % field_name
|
||||||
|
|
||||||
|
def get_datetime_cast_sql():
|
||||||
|
return None
|
||||||
|
|
||||||
def get_limit_offset_sql(limit, offset=None):
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
# TODO: This is a guess. Make sure this is correct.
|
# TODO: This is a guess. Make sure this is correct.
|
||||||
sql = "LIMIT %s" % limit
|
sql = "LIMIT %s" % limit
|
||||||
@ -139,6 +149,18 @@ def get_drop_foreignkey_sql():
|
|||||||
def get_pk_default_value():
|
def get_pk_default_value():
|
||||||
return "DEFAULT"
|
return "DEFAULT"
|
||||||
|
|
||||||
|
def get_max_name_length():
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_start_transaction_sql():
|
||||||
|
return "BEGIN;"
|
||||||
|
|
||||||
|
def get_tablespace_sql(tablespace, inline=False):
|
||||||
|
return "ON %s" % quote_name(tablespace)
|
||||||
|
|
||||||
|
def get_autoinc_sql(table):
|
||||||
|
return None
|
||||||
|
|
||||||
def get_sql_flush(style, tables, sequences):
|
def get_sql_flush(style, tables, sequences):
|
||||||
"""Return a list of SQL statements required to remove all data from
|
"""Return a list of SQL statements required to remove all data from
|
||||||
all tables in the database (without actually removing the tables
|
all tables in the database (without actually removing the tables
|
||||||
|
@ -33,6 +33,7 @@ class DatabaseWrapper:
|
|||||||
pass # close()
|
pass # close()
|
||||||
|
|
||||||
supports_constraints = False
|
supports_constraints = False
|
||||||
|
supports_tablespaces = False
|
||||||
quote_name = complain
|
quote_name = complain
|
||||||
dictfetchone = complain
|
dictfetchone = complain
|
||||||
dictfetchmany = complain
|
dictfetchmany = complain
|
||||||
@ -40,11 +41,16 @@ dictfetchall = complain
|
|||||||
get_last_insert_id = complain
|
get_last_insert_id = complain
|
||||||
get_date_extract_sql = complain
|
get_date_extract_sql = complain
|
||||||
get_date_trunc_sql = complain
|
get_date_trunc_sql = complain
|
||||||
|
get_datetime_cast_sql = complain
|
||||||
get_limit_offset_sql = complain
|
get_limit_offset_sql = complain
|
||||||
get_random_function_sql = complain
|
get_random_function_sql = complain
|
||||||
get_deferrable_sql = complain
|
get_deferrable_sql = complain
|
||||||
get_fulltext_search_sql = complain
|
get_fulltext_search_sql = complain
|
||||||
get_drop_foreignkey_sql = complain
|
get_drop_foreignkey_sql = complain
|
||||||
|
get_pk_default_value = complain
|
||||||
|
get_max_name_length = ignore
|
||||||
|
get_start_transaction_sql = complain
|
||||||
|
get_autoinc_sql = complain
|
||||||
get_sql_flush = complain
|
get_sql_flush = complain
|
||||||
get_sql_sequence_reset = complain
|
get_sql_sequence_reset = complain
|
||||||
|
|
||||||
|
@ -134,7 +134,14 @@ class DatabaseWrapper(local):
|
|||||||
self.server_version = tuple([int(x) for x in m.groups()])
|
self.server_version = tuple([int(x) for x in m.groups()])
|
||||||
return self.server_version
|
return self.server_version
|
||||||
|
|
||||||
|
allows_group_by_ordinal = True
|
||||||
|
allows_unique_and_pk = True
|
||||||
|
autoindexes_primary_keys = False
|
||||||
|
needs_datetime_string_cast = True # MySQLdb requires a typecast for dates
|
||||||
|
needs_upper_for_iops = False
|
||||||
supports_constraints = True
|
supports_constraints = True
|
||||||
|
supports_tablespaces = False
|
||||||
|
uses_case_insensitive_names = False
|
||||||
|
|
||||||
def quote_name(name):
|
def quote_name(name):
|
||||||
if name.startswith("`") and name.endswith("`"):
|
if name.startswith("`") and name.endswith("`"):
|
||||||
@ -167,6 +174,9 @@ def get_date_trunc_sql(lookup_type, field_name):
|
|||||||
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
|
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
def get_datetime_cast_sql():
|
||||||
|
return None
|
||||||
|
|
||||||
def get_limit_offset_sql(limit, offset=None):
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
sql = "LIMIT "
|
sql = "LIMIT "
|
||||||
if offset and offset != 0:
|
if offset and offset != 0:
|
||||||
@ -188,6 +198,15 @@ def get_drop_foreignkey_sql():
|
|||||||
def get_pk_default_value():
|
def get_pk_default_value():
|
||||||
return "DEFAULT"
|
return "DEFAULT"
|
||||||
|
|
||||||
|
def get_max_name_length():
|
||||||
|
return None;
|
||||||
|
|
||||||
|
def get_start_transaction_sql():
|
||||||
|
return "BEGIN;"
|
||||||
|
|
||||||
|
def get_autoinc_sql(table):
|
||||||
|
return None
|
||||||
|
|
||||||
def get_sql_flush(style, tables, sequences):
|
def get_sql_flush(style, tables, sequences):
|
||||||
"""Return a list of SQL statements required to remove all data from
|
"""Return a list of SQL statements required to remove all data from
|
||||||
all tables in the database (without actually removing the tables
|
all tables in the database (without actually removing the tables
|
||||||
@ -228,6 +247,8 @@ OPERATOR_MAPPING = {
|
|||||||
'iexact': 'LIKE %s',
|
'iexact': 'LIKE %s',
|
||||||
'contains': 'LIKE BINARY %s',
|
'contains': 'LIKE BINARY %s',
|
||||||
'icontains': 'LIKE %s',
|
'icontains': 'LIKE %s',
|
||||||
|
'regex': 'REGEXP BINARY %s',
|
||||||
|
'iregex': 'REGEXP %s',
|
||||||
'gt': '> %s',
|
'gt': '> %s',
|
||||||
'gte': '>= %s',
|
'gte': '>= %s',
|
||||||
'lt': '< %s',
|
'lt': '< %s',
|
||||||
|
@ -135,7 +135,14 @@ class DatabaseWrapper(local):
|
|||||||
self.server_version = tuple([int(x) for x in m.groups()])
|
self.server_version = tuple([int(x) for x in m.groups()])
|
||||||
return self.server_version
|
return self.server_version
|
||||||
|
|
||||||
|
allows_group_by_ordinal = True
|
||||||
|
allows_unique_and_pk = True
|
||||||
|
autoindexes_primary_keys = False
|
||||||
|
needs_datetime_string_cast = True # MySQLdb requires a typecast for dates
|
||||||
|
needs_upper_for_iops = False
|
||||||
supports_constraints = True
|
supports_constraints = True
|
||||||
|
supports_tablespaces = False
|
||||||
|
uses_case_insensitive_names = False
|
||||||
|
|
||||||
def quote_name(name):
|
def quote_name(name):
|
||||||
if name.startswith("`") and name.endswith("`"):
|
if name.startswith("`") and name.endswith("`"):
|
||||||
@ -168,6 +175,9 @@ def get_date_trunc_sql(lookup_type, field_name):
|
|||||||
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
|
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
|
||||||
return sql
|
return sql
|
||||||
|
|
||||||
|
def get_datetime_cast_sql():
|
||||||
|
return None
|
||||||
|
|
||||||
def get_limit_offset_sql(limit, offset=None):
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
sql = "LIMIT "
|
sql = "LIMIT "
|
||||||
if offset and offset != 0:
|
if offset and offset != 0:
|
||||||
@ -189,6 +199,15 @@ def get_drop_foreignkey_sql():
|
|||||||
def get_pk_default_value():
|
def get_pk_default_value():
|
||||||
return "DEFAULT"
|
return "DEFAULT"
|
||||||
|
|
||||||
|
def get_max_name_length():
|
||||||
|
return None;
|
||||||
|
|
||||||
|
def get_start_transaction_sql():
|
||||||
|
return "BEGIN;"
|
||||||
|
|
||||||
|
def get_autoinc_sql(table):
|
||||||
|
return None
|
||||||
|
|
||||||
def get_sql_flush(style, tables, sequences):
|
def get_sql_flush(style, tables, sequences):
|
||||||
"""Return a list of SQL statements required to remove all data from
|
"""Return a list of SQL statements required to remove all data from
|
||||||
all tables in the database (without actually removing the tables
|
all tables in the database (without actually removing the tables
|
||||||
@ -229,6 +248,8 @@ OPERATOR_MAPPING = {
|
|||||||
'iexact': 'LIKE %s',
|
'iexact': 'LIKE %s',
|
||||||
'contains': 'LIKE BINARY %s',
|
'contains': 'LIKE BINARY %s',
|
||||||
'icontains': 'LIKE %s',
|
'icontains': 'LIKE %s',
|
||||||
|
'regex': 'REGEXP BINARY %s',
|
||||||
|
'iregex': 'REGEXP %s',
|
||||||
'gt': '> %s',
|
'gt': '> %s',
|
||||||
'gte': '>= %s',
|
'gte': '>= %s',
|
||||||
'lt': '< %s',
|
'lt': '< %s',
|
||||||
|
@ -4,12 +4,16 @@ Oracle database backend for Django.
|
|||||||
Requires cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/
|
Requires cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.db.backends import util
|
from django.db.backends import util
|
||||||
try:
|
try:
|
||||||
import cx_Oracle as Database
|
import cx_Oracle as Database
|
||||||
except ImportError, e:
|
except ImportError, e:
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
raise ImproperlyConfigured, "Error loading cx_Oracle module: %s" % e
|
raise ImproperlyConfigured, "Error loading cx_Oracle module: %s" % e
|
||||||
|
import datetime
|
||||||
|
from django.utils.datastructures import SortedDict
|
||||||
|
|
||||||
|
|
||||||
DatabaseError = Database.Error
|
DatabaseError = Database.Error
|
||||||
IntegrityError = Database.IntegrityError
|
IntegrityError = Database.IntegrityError
|
||||||
@ -31,7 +35,6 @@ class DatabaseWrapper(local):
|
|||||||
return self.connection is not None
|
return self.connection is not None
|
||||||
|
|
||||||
def cursor(self):
|
def cursor(self):
|
||||||
from django.conf import settings
|
|
||||||
if not self._valid_connection():
|
if not self._valid_connection():
|
||||||
if len(settings.DATABASE_HOST.strip()) == 0:
|
if len(settings.DATABASE_HOST.strip()) == 0:
|
||||||
settings.DATABASE_HOST = 'localhost'
|
settings.DATABASE_HOST = 'localhost'
|
||||||
@ -41,25 +44,37 @@ class DatabaseWrapper(local):
|
|||||||
else:
|
else:
|
||||||
conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)
|
conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME)
|
||||||
self.connection = Database.connect(conn_string, **self.options)
|
self.connection = Database.connect(conn_string, **self.options)
|
||||||
return FormatStylePlaceholderCursor(self.connection)
|
cursor = FormatStylePlaceholderCursor(self.connection)
|
||||||
|
# default arraysize of 1 is highly sub-optimal
|
||||||
|
cursor.arraysize = 100
|
||||||
|
# set oracle date to ansi date format
|
||||||
|
cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD'")
|
||||||
|
cursor.execute("ALTER SESSION SET NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'")
|
||||||
|
if settings.DEBUG:
|
||||||
|
return util.CursorDebugWrapper(cursor, self)
|
||||||
|
return cursor
|
||||||
|
|
||||||
def _commit(self):
|
def _commit(self):
|
||||||
if self.connection is not None:
|
if self.connection is not None:
|
||||||
self.connection.commit()
|
return self.connection.commit()
|
||||||
|
|
||||||
def _rollback(self):
|
def _rollback(self):
|
||||||
if self.connection is not None:
|
if self.connection is not None:
|
||||||
try:
|
return self.connection.rollback()
|
||||||
self.connection.rollback()
|
|
||||||
except Database.NotSupportedError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.connection is not None:
|
if self.connection is not None:
|
||||||
self.connection.close()
|
self.connection.close()
|
||||||
self.connection = None
|
self.connection = None
|
||||||
|
|
||||||
|
allows_group_by_ordinal = False
|
||||||
|
allows_unique_and_pk = False # Suppress UNIQUE/PK for Oracle (ORA-02259)
|
||||||
|
autoindexes_primary_keys = True
|
||||||
|
needs_datetime_string_cast = False
|
||||||
|
needs_upper_for_iops = True
|
||||||
supports_constraints = True
|
supports_constraints = True
|
||||||
|
supports_tablespaces = True
|
||||||
|
uses_case_insensitive_names = True
|
||||||
|
|
||||||
class FormatStylePlaceholderCursor(Database.Cursor):
|
class FormatStylePlaceholderCursor(Database.Cursor):
|
||||||
"""
|
"""
|
||||||
@ -67,45 +82,75 @@ class FormatStylePlaceholderCursor(Database.Cursor):
|
|||||||
This fixes it -- but note that if you want to use a literal "%s" in a query,
|
This fixes it -- but note that if you want to use a literal "%s" in a query,
|
||||||
you'll need to use "%%s".
|
you'll need to use "%%s".
|
||||||
"""
|
"""
|
||||||
|
def _rewrite_args(self, query, params=None):
|
||||||
|
if params is None:
|
||||||
|
params = []
|
||||||
|
else:
|
||||||
|
# cx_Oracle can't handle unicode parameters, so cast to str for now
|
||||||
|
for i, param in enumerate(params):
|
||||||
|
if type(param) == unicode:
|
||||||
|
try:
|
||||||
|
params[i] = param.encode('utf-8')
|
||||||
|
except UnicodeError:
|
||||||
|
params[i] = str(param)
|
||||||
|
args = [(':arg%d' % i) for i in range(len(params))]
|
||||||
|
query = query % tuple(args)
|
||||||
|
# cx_Oracle wants no trailing ';' for SQL statements. For PL/SQL, it
|
||||||
|
# it does want a trailing ';' but not a trailing '/'. However, these
|
||||||
|
# characters must be included in the original query in case the query
|
||||||
|
# is being passed to SQL*Plus.
|
||||||
|
if query.endswith(';') or query.endswith('/'):
|
||||||
|
query = query[:-1]
|
||||||
|
return query, params
|
||||||
|
|
||||||
def execute(self, query, params=None):
|
def execute(self, query, params=None):
|
||||||
if params is None: params = []
|
query, params = self._rewrite_args(query, params)
|
||||||
query = self.convert_arguments(query, len(params))
|
|
||||||
return Database.Cursor.execute(self, query, params)
|
return Database.Cursor.execute(self, query, params)
|
||||||
|
|
||||||
def executemany(self, query, params=None):
|
def executemany(self, query, params=None):
|
||||||
if params is None: params = []
|
query, params = self._rewrite_args(query, params)
|
||||||
query = self.convert_arguments(query, len(params[0]))
|
|
||||||
return Database.Cursor.executemany(self, query, params)
|
return Database.Cursor.executemany(self, query, params)
|
||||||
|
|
||||||
def convert_arguments(self, query, num_params):
|
|
||||||
# replace occurances of "%s" with ":arg" - Oracle requires colons for parameter placeholders.
|
|
||||||
args = [':arg' for i in range(num_params)]
|
|
||||||
return query % tuple(args)
|
|
||||||
|
|
||||||
def quote_name(name):
|
def quote_name(name):
|
||||||
return name
|
# SQL92 requires delimited (quoted) names to be case-sensitive. When
|
||||||
|
# not quoted, Oracle has case-insensitive behavior for identifiers, but
|
||||||
|
# always defaults to uppercase.
|
||||||
|
# We simplify things by making Oracle identifiers always uppercase.
|
||||||
|
if not name.startswith('"') and not name.endswith('"'):
|
||||||
|
name = '"%s"' % util.truncate_name(name.upper(), get_max_name_length())
|
||||||
|
return name.upper()
|
||||||
|
|
||||||
dictfetchone = util.dictfetchone
|
dictfetchone = util.dictfetchone
|
||||||
dictfetchmany = util.dictfetchmany
|
dictfetchmany = util.dictfetchmany
|
||||||
dictfetchall = util.dictfetchall
|
dictfetchall = util.dictfetchall
|
||||||
|
|
||||||
def get_last_insert_id(cursor, table_name, pk_name):
|
def get_last_insert_id(cursor, table_name, pk_name):
|
||||||
query = "SELECT %s_sq.currval from dual" % table_name
|
sq_name = util.truncate_name(table_name, get_max_name_length()-3)
|
||||||
cursor.execute(query)
|
cursor.execute('SELECT %s_sq.currval FROM dual' % sq_name)
|
||||||
return cursor.fetchone()[0]
|
return cursor.fetchone()[0]
|
||||||
|
|
||||||
def get_date_extract_sql(lookup_type, table_name):
|
def get_date_extract_sql(lookup_type, table_name):
|
||||||
# lookup_type is 'year', 'month', 'day'
|
# lookup_type is 'year', 'month', 'day'
|
||||||
# http://www.psoug.org/reference/date_func.html
|
# http://download-east.oracle.com/docs/cd/B10501_01/server.920/a96540/functions42a.htm#1017163
|
||||||
return "EXTRACT(%s FROM %s)" % (lookup_type, table_name)
|
return "EXTRACT(%s FROM %s)" % (lookup_type, table_name)
|
||||||
|
|
||||||
def get_date_trunc_sql(lookup_type, field_name):
|
def get_date_trunc_sql(lookup_type, field_name):
|
||||||
return "EXTRACT(%s FROM TRUNC(%s))" % (lookup_type, field_name)
|
# lookup_type is 'year', 'month', 'day'
|
||||||
|
# Oracle uses TRUNC() for both dates and numbers.
|
||||||
|
# http://download-east.oracle.com/docs/cd/B10501_01/server.920/a96540/functions155a.htm#SQLRF06151
|
||||||
|
if lookup_type == 'day':
|
||||||
|
sql = 'TRUNC(%s)' % (field_name,)
|
||||||
|
else:
|
||||||
|
sql = "TRUNC(%s, '%s')" % (field_name, lookup_type)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
def get_datetime_cast_sql():
|
||||||
|
return "TO_TIMESTAMP(%s, 'YYYY-MM-DD HH24:MI:SS.FF')"
|
||||||
|
|
||||||
def get_limit_offset_sql(limit, offset=None):
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
# Limits and offset are too complicated to be handled here.
|
# Limits and offset are too complicated to be handled here.
|
||||||
# Instead, they are handled in django/db/query.py.
|
# Instead, they are handled in django/db/backends/oracle/query.py.
|
||||||
pass
|
return ""
|
||||||
|
|
||||||
def get_random_function_sql():
|
def get_random_function_sql():
|
||||||
return "DBMS_RANDOM.RANDOM"
|
return "DBMS_RANDOM.RANDOM"
|
||||||
@ -117,40 +162,363 @@ def get_fulltext_search_sql(field_name):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def get_drop_foreignkey_sql():
|
def get_drop_foreignkey_sql():
|
||||||
return "DROP FOREIGN KEY"
|
return "DROP CONSTRAINT"
|
||||||
|
|
||||||
def get_pk_default_value():
|
def get_pk_default_value():
|
||||||
return "DEFAULT"
|
return "DEFAULT"
|
||||||
|
|
||||||
|
def get_max_name_length():
|
||||||
|
return 30
|
||||||
|
|
||||||
|
def get_start_transaction_sql():
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_tablespace_sql(tablespace, inline=False):
|
||||||
|
return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), quote_name(tablespace))
|
||||||
|
|
||||||
|
def get_autoinc_sql(table):
|
||||||
|
# To simulate auto-incrementing primary keys in Oracle, we have to
|
||||||
|
# create a sequence and a trigger.
|
||||||
|
sq_name = get_sequence_name(table)
|
||||||
|
tr_name = get_trigger_name(table)
|
||||||
|
sequence_sql = 'CREATE SEQUENCE %s;' % sq_name
|
||||||
|
trigger_sql = """CREATE OR REPLACE TRIGGER %s
|
||||||
|
BEFORE INSERT ON %s
|
||||||
|
FOR EACH ROW
|
||||||
|
WHEN (new.id IS NULL)
|
||||||
|
BEGIN
|
||||||
|
SELECT %s.nextval INTO :new.id FROM dual;
|
||||||
|
END;
|
||||||
|
/""" % (tr_name, quote_name(table), sq_name)
|
||||||
|
return sequence_sql, trigger_sql
|
||||||
|
|
||||||
|
def get_drop_sequence(table):
|
||||||
|
return "DROP SEQUENCE %s;" % quote_name(get_sequence_name(table))
|
||||||
|
|
||||||
|
def _get_sequence_reset_sql():
|
||||||
|
# TODO: colorize this SQL code with style.SQL_KEYWORD(), etc.
|
||||||
|
return """
|
||||||
|
DECLARE
|
||||||
|
startvalue integer;
|
||||||
|
cval integer;
|
||||||
|
BEGIN
|
||||||
|
LOCK TABLE %(table)s IN SHARE MODE;
|
||||||
|
SELECT NVL(MAX(id), 0) INTO startvalue FROM %(table)s;
|
||||||
|
SELECT %(sequence)s.nextval INTO cval FROM dual;
|
||||||
|
cval := startvalue - cval;
|
||||||
|
IF cval != 0 THEN
|
||||||
|
EXECUTE IMMEDIATE 'ALTER SEQUENCE %(sequence)s MINVALUE 0 INCREMENT BY '||cval;
|
||||||
|
SELECT %(sequence)s.nextval INTO cval FROM dual;
|
||||||
|
EXECUTE IMMEDIATE 'ALTER SEQUENCE %(sequence)s INCREMENT BY 1';
|
||||||
|
END IF;
|
||||||
|
COMMIT;
|
||||||
|
END;
|
||||||
|
/"""
|
||||||
|
|
||||||
def get_sql_flush(style, tables, sequences):
|
def get_sql_flush(style, tables, sequences):
|
||||||
"""Return a list of SQL statements required to remove all data from
|
"""Return a list of SQL statements required to remove all data from
|
||||||
all tables in the database (without actually removing the tables
|
all tables in the database (without actually removing the tables
|
||||||
themselves) and put the database in an empty 'initial' state
|
themselves) and put the database in an empty 'initial' state
|
||||||
"""
|
"""
|
||||||
# Return a list of 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
|
# Return a list of 'TRUNCATE x;', 'TRUNCATE y;',
|
||||||
# TODO - SQL not actually tested against Oracle yet!
|
# 'TRUNCATE z;'... style SQL statements
|
||||||
# TODO - autoincrement indices reset required? See other get_sql_flush() implementations
|
if tables:
|
||||||
sql = ['%s %s;' % \
|
# Oracle does support TRUNCATE, but it seems to get us into
|
||||||
(style.SQL_KEYWORD('TRUNCATE'),
|
# FK referential trouble, whereas DELETE FROM table works.
|
||||||
style.SQL_FIELD(quote_name(table))
|
sql = ['%s %s %s;' % \
|
||||||
) for table in tables]
|
(style.SQL_KEYWORD('DELETE'),
|
||||||
|
style.SQL_KEYWORD('FROM'),
|
||||||
|
style.SQL_FIELD(quote_name(table))
|
||||||
|
) for table in tables]
|
||||||
|
# Since we've just deleted all the rows, running our sequence
|
||||||
|
# ALTER code will reset the sequence to 0.
|
||||||
|
for sequence_info in sequences:
|
||||||
|
table_name = sequence_info['table']
|
||||||
|
seq_name = get_sequence_name(table_name)
|
||||||
|
query = _get_sequence_reset_sql() % {'sequence':seq_name,
|
||||||
|
'table':quote_name(table_name)}
|
||||||
|
sql.append(query)
|
||||||
|
return sql
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_sequence_name(table):
|
||||||
|
name_length = get_max_name_length() - 3
|
||||||
|
return '%s_SQ' % util.truncate_name(table, name_length).upper()
|
||||||
|
|
||||||
def get_sql_sequence_reset(style, model_list):
|
def get_sql_sequence_reset(style, model_list):
|
||||||
"Returns a list of the SQL statements to reset sequences for the given models."
|
"Returns a list of the SQL statements to reset sequences for the given models."
|
||||||
# No sequence reset required
|
from django.db import models
|
||||||
return []
|
output = []
|
||||||
|
query = _get_sequence_reset_sql()
|
||||||
|
for model in model_list:
|
||||||
|
for f in model._meta.fields:
|
||||||
|
if isinstance(f, models.AutoField):
|
||||||
|
sequence_name = get_sequence_name(model._meta.db_table)
|
||||||
|
output.append(query % {'sequence':sequence_name,
|
||||||
|
'table':model._meta.db_table})
|
||||||
|
break # Only one AutoField is allowed per model, so don't bother continuing.
|
||||||
|
for f in model._meta.many_to_many:
|
||||||
|
sequence_name = get_sequence_name(f.m2m_db_table())
|
||||||
|
output.append(query % {'sequence':sequence_name,
|
||||||
|
'table':f.m2m_db_table()})
|
||||||
|
return output
|
||||||
|
|
||||||
|
def get_trigger_name(table):
|
||||||
|
name_length = get_max_name_length() - 3
|
||||||
|
return '%s_TR' % util.truncate_name(table, name_length).upper()
|
||||||
|
|
||||||
|
def get_query_set_class(DefaultQuerySet):
|
||||||
|
"Create a custom QuerySet class for Oracle."
|
||||||
|
|
||||||
|
from django.db import backend, connection
|
||||||
|
from django.db.models.query import EmptyResultSet, GET_ITERATOR_CHUNK_SIZE, quote_only_if_word
|
||||||
|
|
||||||
|
class OracleQuerySet(DefaultQuerySet):
|
||||||
|
|
||||||
|
def iterator(self):
|
||||||
|
"Performs the SELECT database lookup of this QuerySet."
|
||||||
|
|
||||||
|
from django.db.models.query import get_cached_row
|
||||||
|
|
||||||
|
# self._select is a dictionary, and dictionaries' key order is
|
||||||
|
# undefined, so we convert it to a list of tuples.
|
||||||
|
extra_select = self._select.items()
|
||||||
|
|
||||||
|
full_query = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
select, sql, params, full_query = self._get_sql_clause(get_full_query=True)
|
||||||
|
except TypeError:
|
||||||
|
select, sql, params = self._get_sql_clause()
|
||||||
|
except EmptyResultSet:
|
||||||
|
raise StopIteration
|
||||||
|
if not full_query:
|
||||||
|
full_query = "SELECT %s%s\n%s" % \
|
||||||
|
((self._distinct and "DISTINCT " or ""),
|
||||||
|
', '.join(select), sql)
|
||||||
|
|
||||||
|
cursor = connection.cursor()
|
||||||
|
cursor.execute(full_query, params)
|
||||||
|
|
||||||
|
fill_cache = self._select_related
|
||||||
|
fields = self.model._meta.fields
|
||||||
|
index_end = len(fields)
|
||||||
|
|
||||||
|
# so here's the logic;
|
||||||
|
# 1. retrieve each row in turn
|
||||||
|
# 2. convert NCLOBs
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
|
||||||
|
if not rows:
|
||||||
|
raise StopIteration
|
||||||
|
for row in rows:
|
||||||
|
row = self.resolve_columns(row, fields)
|
||||||
|
if fill_cache:
|
||||||
|
obj, index_end = get_cached_row(klass=self.model, row=row,
|
||||||
|
index_start=0, max_depth=self._max_related_depth)
|
||||||
|
else:
|
||||||
|
obj = self.model(*row[:index_end])
|
||||||
|
for i, k in enumerate(extra_select):
|
||||||
|
setattr(obj, k[0], row[index_end+i])
|
||||||
|
yield obj
|
||||||
|
|
||||||
|
|
||||||
|
def _get_sql_clause(self, get_full_query=False):
|
||||||
|
from django.db.models.query import fill_table_cache, \
|
||||||
|
handle_legacy_orderlist, orderfield2column
|
||||||
|
|
||||||
|
opts = self.model._meta
|
||||||
|
|
||||||
|
# Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z.
|
||||||
|
select = ["%s.%s" % (backend.quote_name(opts.db_table), backend.quote_name(f.column)) for f in opts.fields]
|
||||||
|
tables = [quote_only_if_word(t) for t in self._tables]
|
||||||
|
joins = SortedDict()
|
||||||
|
where = self._where[:]
|
||||||
|
params = self._params[:]
|
||||||
|
|
||||||
|
# Convert self._filters into SQL.
|
||||||
|
joins2, where2, params2 = self._filters.get_sql(opts)
|
||||||
|
joins.update(joins2)
|
||||||
|
where.extend(where2)
|
||||||
|
params.extend(params2)
|
||||||
|
|
||||||
|
# Add additional tables and WHERE clauses based on select_related.
|
||||||
|
if self._select_related:
|
||||||
|
fill_table_cache(opts, select, tables, where, opts.db_table, [opts.db_table])
|
||||||
|
|
||||||
|
# Add any additional SELECTs.
|
||||||
|
if self._select:
|
||||||
|
select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
|
||||||
|
|
||||||
|
# Start composing the body of the SQL statement.
|
||||||
|
sql = [" FROM", backend.quote_name(opts.db_table)]
|
||||||
|
|
||||||
|
# Compose the join dictionary into SQL describing the joins.
|
||||||
|
if joins:
|
||||||
|
sql.append(" ".join(["%s %s %s ON %s" % (join_type, table, alias, condition)
|
||||||
|
for (alias, (table, join_type, condition)) in joins.items()]))
|
||||||
|
|
||||||
|
# Compose the tables clause into SQL.
|
||||||
|
if tables:
|
||||||
|
sql.append(", " + ", ".join(tables))
|
||||||
|
|
||||||
|
# Compose the where clause into SQL.
|
||||||
|
if where:
|
||||||
|
sql.append(where and "WHERE " + " AND ".join(where))
|
||||||
|
|
||||||
|
# ORDER BY clause
|
||||||
|
order_by = []
|
||||||
|
if self._order_by is not None:
|
||||||
|
ordering_to_use = self._order_by
|
||||||
|
else:
|
||||||
|
ordering_to_use = opts.ordering
|
||||||
|
for f in handle_legacy_orderlist(ordering_to_use):
|
||||||
|
if f == '?': # Special case.
|
||||||
|
order_by.append(backend.get_random_function_sql())
|
||||||
|
else:
|
||||||
|
if f.startswith('-'):
|
||||||
|
col_name = f[1:]
|
||||||
|
order = "DESC"
|
||||||
|
else:
|
||||||
|
col_name = f
|
||||||
|
order = "ASC"
|
||||||
|
if "." in col_name:
|
||||||
|
table_prefix, col_name = col_name.split('.', 1)
|
||||||
|
table_prefix = backend.quote_name(table_prefix) + '.'
|
||||||
|
else:
|
||||||
|
# Use the database table as a column prefix if it wasn't given,
|
||||||
|
# and if the requested column isn't a custom SELECT.
|
||||||
|
if "." not in col_name and col_name not in (self._select or ()):
|
||||||
|
table_prefix = backend.quote_name(opts.db_table) + '.'
|
||||||
|
else:
|
||||||
|
table_prefix = ''
|
||||||
|
order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order))
|
||||||
|
if order_by:
|
||||||
|
sql.append("ORDER BY " + ", ".join(order_by))
|
||||||
|
|
||||||
|
# Look for column name collisions in the select elements
|
||||||
|
# and fix them with an AS alias. This allows us to do a
|
||||||
|
# SELECT * later in the paging query.
|
||||||
|
cols = [clause.split('.')[-1] for clause in select]
|
||||||
|
for index, col in enumerate(cols):
|
||||||
|
if cols.count(col) > 1:
|
||||||
|
col = '%s%d' % (col.replace('"', ''), index)
|
||||||
|
cols[index] = col
|
||||||
|
select[index] = '%s AS %s' % (select[index], col)
|
||||||
|
|
||||||
|
# LIMIT and OFFSET clauses
|
||||||
|
# To support limits and offsets, Oracle requires some funky rewriting of an otherwise normal looking query.
|
||||||
|
select_clause = ",".join(select)
|
||||||
|
distinct = (self._distinct and "DISTINCT " or "")
|
||||||
|
|
||||||
|
if order_by:
|
||||||
|
order_by_clause = " OVER (ORDER BY %s )" % (", ".join(order_by))
|
||||||
|
else:
|
||||||
|
#Oracle's row_number() function always requires an order-by clause.
|
||||||
|
#So we need to define a default order-by, since none was provided.
|
||||||
|
order_by_clause = " OVER (ORDER BY %s.%s)" % \
|
||||||
|
(backend.quote_name(opts.db_table),
|
||||||
|
backend.quote_name(opts.fields[0].db_column or opts.fields[0].column))
|
||||||
|
# limit_and_offset_clause
|
||||||
|
if self._limit is None:
|
||||||
|
assert self._offset is None, "'offset' is not allowed without 'limit'"
|
||||||
|
|
||||||
|
if self._offset is not None:
|
||||||
|
offset = int(self._offset)
|
||||||
|
else:
|
||||||
|
offset = 0
|
||||||
|
if self._limit is not None:
|
||||||
|
limit = int(self._limit)
|
||||||
|
else:
|
||||||
|
limit = None
|
||||||
|
|
||||||
|
limit_and_offset_clause = ''
|
||||||
|
if limit is not None:
|
||||||
|
limit_and_offset_clause = "WHERE rn > %s AND rn <= %s" % (offset, limit+offset)
|
||||||
|
elif offset:
|
||||||
|
limit_and_offset_clause = "WHERE rn > %s" % (offset)
|
||||||
|
|
||||||
|
if len(limit_and_offset_clause) > 0:
|
||||||
|
fmt = \
|
||||||
|
"""SELECT * FROM
|
||||||
|
(SELECT %s%s,
|
||||||
|
ROW_NUMBER()%s AS rn
|
||||||
|
%s)
|
||||||
|
%s"""
|
||||||
|
full_query = fmt % (distinct, select_clause,
|
||||||
|
order_by_clause, ' '.join(sql).strip(),
|
||||||
|
limit_and_offset_clause)
|
||||||
|
else:
|
||||||
|
full_query = None
|
||||||
|
|
||||||
|
if get_full_query:
|
||||||
|
return select, " ".join(sql), params, full_query
|
||||||
|
else:
|
||||||
|
return select, " ".join(sql), params
|
||||||
|
|
||||||
|
def resolve_columns(self, row, fields=()):
|
||||||
|
from django.db.models.fields import DateField, DateTimeField, \
|
||||||
|
TimeField, BooleanField, NullBooleanField, DecimalField, Field
|
||||||
|
values = []
|
||||||
|
for value, field in map(None, row, fields):
|
||||||
|
if isinstance(value, Database.LOB):
|
||||||
|
value = value.read()
|
||||||
|
# Oracle stores empty strings as null. We need to undo this in
|
||||||
|
# order to adhere to the Django convention of using the empty
|
||||||
|
# string instead of null, but only if the field accepts the
|
||||||
|
# empty string.
|
||||||
|
if value is None and isinstance(field, Field) and field.empty_strings_allowed:
|
||||||
|
value = ''
|
||||||
|
# Convert 1 or 0 to True or False
|
||||||
|
elif value in (1, 0) and isinstance(field, (BooleanField, NullBooleanField)):
|
||||||
|
value = bool(value)
|
||||||
|
# Convert floats to decimals
|
||||||
|
elif value is not None and isinstance(field, DecimalField):
|
||||||
|
value = util.typecast_decimal(field.format_number(value))
|
||||||
|
# cx_Oracle always returns datetime.datetime objects for
|
||||||
|
# DATE and TIMESTAMP columns, but Django wants to see a
|
||||||
|
# python datetime.date, .time, or .datetime. We use the type
|
||||||
|
# of the Field to determine which to cast to, but it's not
|
||||||
|
# always available.
|
||||||
|
# As a workaround, we cast to date if all the time-related
|
||||||
|
# values are 0, or to time if the date is 1/1/1900.
|
||||||
|
# This could be cleaned a bit by adding a method to the Field
|
||||||
|
# classes to normalize values from the database (the to_python
|
||||||
|
# method is used for validation and isn't what we want here).
|
||||||
|
elif isinstance(value, Database.Timestamp):
|
||||||
|
# In Python 2.3, the cx_Oracle driver returns its own
|
||||||
|
# Timestamp object that we must convert to a datetime class.
|
||||||
|
if not isinstance(value, datetime.datetime):
|
||||||
|
value = datetime.datetime(value.year, value.month, value.day, value.hour,
|
||||||
|
value.minute, value.second, value.fsecond)
|
||||||
|
if isinstance(field, DateTimeField):
|
||||||
|
pass # DateTimeField subclasses DateField so must be checked first.
|
||||||
|
elif isinstance(field, DateField):
|
||||||
|
value = value.date()
|
||||||
|
elif isinstance(field, TimeField) or (value.year == 1900 and value.month == value.day == 1):
|
||||||
|
value = value.time()
|
||||||
|
elif value.hour == value.minute == value.second == value.microsecond == 0:
|
||||||
|
value = value.date()
|
||||||
|
values.append(value)
|
||||||
|
return values
|
||||||
|
|
||||||
|
return OracleQuerySet
|
||||||
|
|
||||||
|
|
||||||
OPERATOR_MAPPING = {
|
OPERATOR_MAPPING = {
|
||||||
'exact': '= %s',
|
'exact': '= %s',
|
||||||
'iexact': 'LIKE %s',
|
'iexact': '= UPPER(%s)',
|
||||||
'contains': 'LIKE %s',
|
'contains': "LIKE %s ESCAPE '\\'",
|
||||||
'icontains': 'LIKE %s',
|
'icontains': "LIKE UPPER(%s) ESCAPE '\\'",
|
||||||
'gt': '> %s',
|
'gt': '> %s',
|
||||||
'gte': '>= %s',
|
'gte': '>= %s',
|
||||||
'lt': '< %s',
|
'lt': '< %s',
|
||||||
'lte': '<= %s',
|
'lte': '<= %s',
|
||||||
'startswith': 'LIKE %s',
|
'startswith': "LIKE %s ESCAPE '\\'",
|
||||||
'endswith': 'LIKE %s',
|
'endswith': "LIKE %s ESCAPE '\\'",
|
||||||
'istartswith': 'LIKE %s',
|
'istartswith': "LIKE UPPER(%s) ESCAPE '\\'",
|
||||||
'iendswith': 'LIKE %s',
|
'iendswith': "LIKE UPPER(%s) ESCAPE '\\'",
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,10 @@ from django.conf import settings
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
def runshell():
|
def runshell():
|
||||||
args = ''
|
dsn = settings.DATABASE_USER
|
||||||
args += settings.DATABASE_USER
|
|
||||||
if settings.DATABASE_PASSWORD:
|
if settings.DATABASE_PASSWORD:
|
||||||
args += "/%s" % settings.DATABASE_PASSWORD
|
dsn += "/%s" % settings.DATABASE_PASSWORD
|
||||||
args += "@%s" % settings.DATABASE_NAME
|
if settings.DATABASE_NAME:
|
||||||
os.execvp('sqlplus', args)
|
dsn += "@%s" % settings.DATABASE_NAME
|
||||||
|
args = ["sqlplus", "-L", dsn]
|
||||||
|
os.execvp("sqlplus", args)
|
||||||
|
@ -1,26 +1,304 @@
|
|||||||
|
import sys, time
|
||||||
|
from django.core import management
|
||||||
|
|
||||||
|
# This dictionary maps Field objects to their associated Oracle column
|
||||||
|
# types, as strings. Column-type strings can contain format strings; they'll
|
||||||
|
# be interpolated against the values of Field.__dict__ before being output.
|
||||||
|
# If a column type is set to None, it won't be included in the output.
|
||||||
DATA_TYPES = {
|
DATA_TYPES = {
|
||||||
'AutoField': 'number(38)',
|
'AutoField': 'NUMBER(11)',
|
||||||
'BooleanField': 'number(1)',
|
'BooleanField': 'NUMBER(1) CHECK (%(column)s IN (0,1))',
|
||||||
'CharField': 'varchar2(%(maxlength)s)',
|
'CharField': 'VARCHAR2(%(maxlength)s)',
|
||||||
'CommaSeparatedIntegerField': 'varchar2(%(maxlength)s)',
|
'CommaSeparatedIntegerField': 'VARCHAR2(%(maxlength)s)',
|
||||||
'DateField': 'date',
|
'DateField': 'DATE',
|
||||||
'DateTimeField': 'date',
|
'DateTimeField': 'TIMESTAMP',
|
||||||
'DecimalField': 'number(%(max_digits)s, %(decimal_places)s)',
|
'DecimalField': 'NUMBER(%(max_digits)s, %(decimal_places)s)',
|
||||||
'FileField': 'varchar2(100)',
|
'FileField': 'VARCHAR2(100)',
|
||||||
'FilePathField': 'varchar2(100)',
|
'FilePathField': 'VARCHAR2(100)',
|
||||||
'FloatField': 'double precision',
|
'FloatField': 'DOUBLE PRECISION',
|
||||||
'ImageField': 'varchar2(100)',
|
'ImageField': 'VARCHAR2(100)',
|
||||||
'IntegerField': 'integer',
|
'IntegerField': 'NUMBER(11)',
|
||||||
'IPAddressField': 'char(15)',
|
'IPAddressField': 'VARCHAR2(15)',
|
||||||
'ManyToManyField': None,
|
'ManyToManyField': None,
|
||||||
'NullBooleanField': 'integer',
|
'NullBooleanField': 'NUMBER(1) CHECK ((%(column)s IN (0,1)) OR (%(column)s IS NULL))',
|
||||||
'OneToOneField': 'integer',
|
'OneToOneField': 'NUMBER(11)',
|
||||||
'PhoneNumberField': 'varchar(20)',
|
'PhoneNumberField': 'VARCHAR2(20)',
|
||||||
'PositiveIntegerField': 'integer',
|
'PositiveIntegerField': 'NUMBER(11) CHECK (%(column)s >= 0)',
|
||||||
'PositiveSmallIntegerField': 'smallint',
|
'PositiveSmallIntegerField': 'NUMBER(11) CHECK (%(column)s >= 0)',
|
||||||
'SlugField': 'varchar(50)',
|
'SlugField': 'VARCHAR2(50)',
|
||||||
'SmallIntegerField': 'smallint',
|
'SmallIntegerField': 'NUMBER(11)',
|
||||||
'TextField': 'long',
|
'TextField': 'NCLOB',
|
||||||
'TimeField': 'timestamp',
|
'TimeField': 'TIMESTAMP',
|
||||||
'USStateField': 'varchar(2)',
|
'URLField': 'VARCHAR2(200)',
|
||||||
|
'USStateField': 'CHAR(2)',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_DATABASE_PREFIX = 'test_'
|
||||||
|
PASSWORD = 'Im_a_lumberjack'
|
||||||
|
REMEMBER = {}
|
||||||
|
|
||||||
|
|
||||||
|
def create_test_db(settings, connection, backend, verbosity=1, autoclobber=False):
|
||||||
|
|
||||||
|
TEST_DATABASE_NAME = _test_database_name(settings)
|
||||||
|
TEST_DATABASE_USER = _test_database_user(settings)
|
||||||
|
TEST_DATABASE_PASSWD = _test_database_passwd(settings)
|
||||||
|
TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings)
|
||||||
|
TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings)
|
||||||
|
|
||||||
|
parameters = {
|
||||||
|
'dbname': TEST_DATABASE_NAME,
|
||||||
|
'user': TEST_DATABASE_USER,
|
||||||
|
'password': TEST_DATABASE_PASSWD,
|
||||||
|
'tblspace': TEST_DATABASE_TBLSPACE,
|
||||||
|
'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP,
|
||||||
|
}
|
||||||
|
|
||||||
|
REMEMBER['user'] = settings.DATABASE_USER
|
||||||
|
REMEMBER['passwd'] = settings.DATABASE_PASSWORD
|
||||||
|
|
||||||
|
cursor = connection.cursor()
|
||||||
|
if _test_database_create(settings):
|
||||||
|
if verbosity >= 1:
|
||||||
|
print 'Creating test database...'
|
||||||
|
try:
|
||||||
|
_create_test_db(cursor, parameters, verbosity)
|
||||||
|
except Exception, e:
|
||||||
|
sys.stderr.write("Got an error creating the test database: %s\n" % e)
|
||||||
|
if not autoclobber:
|
||||||
|
confirm = raw_input("It appears the test database, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_NAME)
|
||||||
|
if autoclobber or confirm == 'yes':
|
||||||
|
try:
|
||||||
|
if verbosity >= 1:
|
||||||
|
print "Destroying old test database..."
|
||||||
|
_destroy_test_db(cursor, parameters, verbosity)
|
||||||
|
if verbosity >= 1:
|
||||||
|
print "Creating test database..."
|
||||||
|
_create_test_db(cursor, parameters, verbosity)
|
||||||
|
except Exception, e:
|
||||||
|
sys.stderr.write("Got an error recreating the test database: %s\n" % e)
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
print "Tests cancelled."
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if _test_user_create(settings):
|
||||||
|
if verbosity >= 1:
|
||||||
|
print "Creating test user..."
|
||||||
|
try:
|
||||||
|
_create_test_user(cursor, parameters, verbosity)
|
||||||
|
except Exception, e:
|
||||||
|
sys.stderr.write("Got an error creating the test user: %s\n" % e)
|
||||||
|
if not autoclobber:
|
||||||
|
confirm = raw_input("It appears the test user, %s, already exists. Type 'yes' to delete it, or 'no' to cancel: " % TEST_DATABASE_USER)
|
||||||
|
if autoclobber or confirm == 'yes':
|
||||||
|
try:
|
||||||
|
if verbosity >= 1:
|
||||||
|
print "Destroying old test user..."
|
||||||
|
_destroy_test_user(cursor, parameters, verbosity)
|
||||||
|
if verbosity >= 1:
|
||||||
|
print "Creating test user..."
|
||||||
|
_create_test_user(cursor, parameters, verbosity)
|
||||||
|
except Exception, e:
|
||||||
|
sys.stderr.write("Got an error recreating the test user: %s\n" % e)
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
print "Tests cancelled."
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
connection.close()
|
||||||
|
settings.DATABASE_USER = TEST_DATABASE_USER
|
||||||
|
settings.DATABASE_PASSWORD = TEST_DATABASE_PASSWD
|
||||||
|
|
||||||
|
management.syncdb(verbosity, interactive=False)
|
||||||
|
|
||||||
|
# Get a cursor (even though we don't need one yet). This has
|
||||||
|
# the side effect of initializing the test database.
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
|
||||||
|
def destroy_test_db(settings, connection, backend, old_database_name, verbosity=1):
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
TEST_DATABASE_NAME = _test_database_name(settings)
|
||||||
|
TEST_DATABASE_USER = _test_database_user(settings)
|
||||||
|
TEST_DATABASE_PASSWD = _test_database_passwd(settings)
|
||||||
|
TEST_DATABASE_TBLSPACE = _test_database_tblspace(settings)
|
||||||
|
TEST_DATABASE_TBLSPACE_TMP = _test_database_tblspace_tmp(settings)
|
||||||
|
|
||||||
|
settings.DATABASE_NAME = old_database_name
|
||||||
|
settings.DATABASE_USER = REMEMBER['user']
|
||||||
|
settings.DATABASE_PASSWORD = REMEMBER['passwd']
|
||||||
|
|
||||||
|
parameters = {
|
||||||
|
'dbname': TEST_DATABASE_NAME,
|
||||||
|
'user': TEST_DATABASE_USER,
|
||||||
|
'password': TEST_DATABASE_PASSWD,
|
||||||
|
'tblspace': TEST_DATABASE_TBLSPACE,
|
||||||
|
'tblspace_temp': TEST_DATABASE_TBLSPACE_TMP,
|
||||||
|
}
|
||||||
|
|
||||||
|
REMEMBER['user'] = settings.DATABASE_USER
|
||||||
|
REMEMBER['passwd'] = settings.DATABASE_PASSWORD
|
||||||
|
|
||||||
|
cursor = connection.cursor()
|
||||||
|
time.sleep(1) # To avoid "database is being accessed by other users" errors.
|
||||||
|
if _test_user_create(settings):
|
||||||
|
if verbosity >= 1:
|
||||||
|
print 'Destroying test user...'
|
||||||
|
_destroy_test_user(cursor, parameters, verbosity)
|
||||||
|
if _test_database_create(settings):
|
||||||
|
if verbosity >= 1:
|
||||||
|
print 'Destroying test database...'
|
||||||
|
_destroy_test_db(cursor, parameters, verbosity)
|
||||||
|
connection.close()
|
||||||
|
|
||||||
|
|
||||||
|
def _create_test_db(cursor, parameters, verbosity):
|
||||||
|
if verbosity >= 2:
|
||||||
|
print "_create_test_db(): dbname = %s" % parameters['dbname']
|
||||||
|
statements = [
|
||||||
|
"""CREATE TABLESPACE %(tblspace)s
|
||||||
|
DATAFILE '%(tblspace)s.dbf' SIZE 20M
|
||||||
|
REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M
|
||||||
|
""",
|
||||||
|
"""CREATE TEMPORARY TABLESPACE %(tblspace_temp)s
|
||||||
|
TEMPFILE '%(tblspace_temp)s.dbf' SIZE 20M
|
||||||
|
REUSE AUTOEXTEND ON NEXT 10M MAXSIZE 100M
|
||||||
|
""",
|
||||||
|
]
|
||||||
|
_execute_statements(cursor, statements, parameters, verbosity)
|
||||||
|
|
||||||
|
|
||||||
|
def _create_test_user(cursor, parameters, verbosity):
|
||||||
|
if verbosity >= 2:
|
||||||
|
print "_create_test_user(): username = %s" % parameters['user']
|
||||||
|
statements = [
|
||||||
|
"""CREATE USER %(user)s
|
||||||
|
IDENTIFIED BY %(password)s
|
||||||
|
DEFAULT TABLESPACE %(tblspace)s
|
||||||
|
TEMPORARY TABLESPACE %(tblspace_temp)s
|
||||||
|
""",
|
||||||
|
"""GRANT CONNECT, RESOURCE TO %(user)s""",
|
||||||
|
]
|
||||||
|
_execute_statements(cursor, statements, parameters, verbosity)
|
||||||
|
|
||||||
|
|
||||||
|
def _destroy_test_db(cursor, parameters, verbosity):
|
||||||
|
if verbosity >= 2:
|
||||||
|
print "_destroy_test_db(): dbname=%s" % parameters['dbname']
|
||||||
|
statements = [
|
||||||
|
'DROP TABLESPACE %(tblspace)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS',
|
||||||
|
'DROP TABLESPACE %(tblspace_temp)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS',
|
||||||
|
]
|
||||||
|
_execute_statements(cursor, statements, parameters, verbosity)
|
||||||
|
|
||||||
|
|
||||||
|
def _destroy_test_user(cursor, parameters, verbosity):
|
||||||
|
if verbosity >= 2:
|
||||||
|
print "_destroy_test_user(): user=%s" % parameters['user']
|
||||||
|
print "Be patient. This can take some time..."
|
||||||
|
statements = [
|
||||||
|
'DROP USER %(user)s CASCADE',
|
||||||
|
]
|
||||||
|
_execute_statements(cursor, statements, parameters, verbosity)
|
||||||
|
|
||||||
|
|
||||||
|
def _execute_statements(cursor, statements, parameters, verbosity):
|
||||||
|
for template in statements:
|
||||||
|
stmt = template % parameters
|
||||||
|
if verbosity >= 2:
|
||||||
|
print stmt
|
||||||
|
try:
|
||||||
|
cursor.execute(stmt)
|
||||||
|
except Exception, err:
|
||||||
|
sys.stderr.write("Failed (%s)\n" % (err))
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
def _test_database_name(settings):
|
||||||
|
name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME
|
||||||
|
try:
|
||||||
|
if settings.TEST_DATABASE_NAME:
|
||||||
|
name = settings.TEST_DATABASE_NAME
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def _test_database_create(settings):
|
||||||
|
name = True
|
||||||
|
try:
|
||||||
|
if settings.TEST_DATABASE_CREATE:
|
||||||
|
name = True
|
||||||
|
else:
|
||||||
|
name = False
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def _test_user_create(settings):
|
||||||
|
name = True
|
||||||
|
try:
|
||||||
|
if settings.TEST_USER_CREATE:
|
||||||
|
name = True
|
||||||
|
else:
|
||||||
|
name = False
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def _test_database_user(settings):
|
||||||
|
name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME
|
||||||
|
try:
|
||||||
|
if settings.TEST_DATABASE_USER:
|
||||||
|
name = settings.TEST_DATABASE_USER
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def _test_database_passwd(settings):
|
||||||
|
name = PASSWORD
|
||||||
|
try:
|
||||||
|
if settings.TEST_DATABASE_PASSWD:
|
||||||
|
name = settings.TEST_DATABASE_PASSWD
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def _test_database_tblspace(settings):
|
||||||
|
name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME
|
||||||
|
try:
|
||||||
|
if settings.TEST_DATABASE_TBLSPACE:
|
||||||
|
name = settings.TEST_DATABASE_TBLSPACE
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def _test_database_tblspace_tmp(settings):
|
||||||
|
name = TEST_DATABASE_PREFIX + settings.DATABASE_NAME + '_temp'
|
||||||
|
try:
|
||||||
|
if settings.TEST_DATABASE_TBLSPACE_TMP:
|
||||||
|
name = settings.TEST_DATABASE_TBLSPACE_TMP
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
return name
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
|
from django.db.backends.oracle.base import quote_name
|
||||||
import re
|
import re
|
||||||
|
import cx_Oracle
|
||||||
|
|
||||||
|
|
||||||
foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
|
foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
|
||||||
|
|
||||||
def get_table_list(cursor):
|
def get_table_list(cursor):
|
||||||
"Returns a list of table names in the current database."
|
"Returns a list of table names in the current database."
|
||||||
cursor.execute("SELECT TABLE_NAME FROM USER_TABLES")
|
cursor.execute("SELECT TABLE_NAME FROM USER_TABLES")
|
||||||
return [row[0] for row in cursor.fetchall()]
|
return [row[0].upper() for row in cursor.fetchall()]
|
||||||
|
|
||||||
def get_table_description(cursor, table_name):
|
def get_table_description(cursor, table_name):
|
||||||
return table_name
|
"Returns a description of the table, with the DB-API cursor.description interface."
|
||||||
|
cursor.execute("SELECT * FROM %s WHERE ROWNUM < 2" % quote_name(table_name))
|
||||||
|
return cursor.description
|
||||||
|
|
||||||
def _name_to_index(cursor, table_name):
|
def _name_to_index(cursor, table_name):
|
||||||
"""
|
"""
|
||||||
@ -22,7 +27,24 @@ def get_relations(cursor, table_name):
|
|||||||
Returns a dictionary of {field_index: (field_index_other_table, other_table)}
|
Returns a dictionary of {field_index: (field_index_other_table, other_table)}
|
||||||
representing all relationships to the given table. Indexes are 0-based.
|
representing all relationships to the given table. Indexes are 0-based.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
cursor.execute("""
|
||||||
|
SELECT ta.column_id - 1, tb.table_name, tb.column_id - 1
|
||||||
|
FROM user_constraints, USER_CONS_COLUMNS ca, USER_CONS_COLUMNS cb,
|
||||||
|
user_tab_cols ta, user_tab_cols tb
|
||||||
|
WHERE user_constraints.table_name = %s AND
|
||||||
|
ta.table_name = %s AND
|
||||||
|
ta.column_name = ca.column_name AND
|
||||||
|
ca.table_name = %s AND
|
||||||
|
user_constraints.constraint_name = ca.constraint_name AND
|
||||||
|
user_constraints.r_constraint_name = cb.constraint_name AND
|
||||||
|
cb.table_name = tb.table_name AND
|
||||||
|
cb.column_name = tb.column_name AND
|
||||||
|
ca.position = cb.position""", [table_name, table_name, table_name])
|
||||||
|
|
||||||
|
relations = {}
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
relations[row[0]] = (row[2], row[1])
|
||||||
|
return relations
|
||||||
|
|
||||||
def get_indexes(cursor, table_name):
|
def get_indexes(cursor, table_name):
|
||||||
"""
|
"""
|
||||||
@ -31,20 +53,46 @@ def get_indexes(cursor, table_name):
|
|||||||
{'primary_key': boolean representing whether it's the primary key,
|
{'primary_key': boolean representing whether it's the primary key,
|
||||||
'unique': boolean representing whether it's a unique index}
|
'unique': boolean representing whether it's a unique index}
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
# This query retrieves each index on the given table, including the
|
||||||
|
# first associated field name
|
||||||
|
# "We were in the nick of time; you were in great peril!"
|
||||||
|
sql = """
|
||||||
|
WITH primarycols AS (
|
||||||
|
SELECT user_cons_columns.table_name, user_cons_columns.column_name, 1 AS PRIMARYCOL
|
||||||
|
FROM user_cons_columns, user_constraints
|
||||||
|
WHERE user_cons_columns.constraint_name = user_constraints.constraint_name AND
|
||||||
|
user_constraints.constraint_type = 'P' AND
|
||||||
|
user_cons_columns.table_name = %s),
|
||||||
|
uniquecols AS (
|
||||||
|
SELECT user_ind_columns.table_name, user_ind_columns.column_name, 1 AS UNIQUECOL
|
||||||
|
FROM user_indexes, user_ind_columns
|
||||||
|
WHERE uniqueness = 'UNIQUE' AND
|
||||||
|
user_indexes.index_name = user_ind_columns.index_name AND
|
||||||
|
user_ind_columns.table_name = %s)
|
||||||
|
SELECT allcols.column_name, primarycols.primarycol, uniquecols.UNIQUECOL
|
||||||
|
FROM (SELECT column_name FROM primarycols UNION SELECT column_name FROM
|
||||||
|
uniquecols) allcols,
|
||||||
|
primarycols, uniquecols
|
||||||
|
WHERE allcols.column_name = primarycols.column_name (+) AND
|
||||||
|
allcols.column_name = uniquecols.column_name (+)
|
||||||
|
"""
|
||||||
|
cursor.execute(sql, [table_name, table_name])
|
||||||
|
indexes = {}
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
# row[1] (idx.indkey) is stored in the DB as an array. It comes out as
|
||||||
|
# a string of space-separated integers. This designates the field
|
||||||
|
# indexes (1-based) of the fields that have indexes on the table.
|
||||||
|
# Here, we skip any indexes across multiple fields.
|
||||||
|
indexes[row[0]] = {'primary_key': row[1], 'unique': row[2]}
|
||||||
|
return indexes
|
||||||
|
|
||||||
# Maps type codes to Django Field types.
|
# Maps type objects to Django Field types.
|
||||||
DATA_TYPES_REVERSE = {
|
DATA_TYPES_REVERSE = {
|
||||||
16: 'BooleanField',
|
cx_Oracle.CLOB: 'TextField',
|
||||||
21: 'SmallIntegerField',
|
cx_Oracle.DATETIME: 'DateTimeField',
|
||||||
23: 'IntegerField',
|
cx_Oracle.FIXED_CHAR: 'CharField',
|
||||||
25: 'TextField',
|
cx_Oracle.NCLOB: 'TextField',
|
||||||
869: 'IPAddressField',
|
cx_Oracle.NUMBER: 'DecimalField',
|
||||||
1043: 'CharField',
|
cx_Oracle.STRING: 'CharField',
|
||||||
1082: 'DateField',
|
cx_Oracle.TIMESTAMP: 'DateTimeField',
|
||||||
1083: 'TimeField',
|
|
||||||
1114: 'DateTimeField',
|
|
||||||
1184: 'DateTimeField',
|
|
||||||
1266: 'TimeField',
|
|
||||||
1700: 'DecimalField',
|
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,14 @@ class DatabaseWrapper(local):
|
|||||||
self.connection.close()
|
self.connection.close()
|
||||||
self.connection = None
|
self.connection = None
|
||||||
|
|
||||||
|
allows_group_by_ordinal = True
|
||||||
|
allows_unique_and_pk = True
|
||||||
|
autoindexes_primary_keys = True
|
||||||
|
needs_datetime_string_cast = True
|
||||||
|
needs_upper_for_iops = False
|
||||||
supports_constraints = True
|
supports_constraints = True
|
||||||
|
supports_tablespaces = False
|
||||||
|
uses_case_insensitive_names = False
|
||||||
|
|
||||||
def quote_name(name):
|
def quote_name(name):
|
||||||
if name.startswith('"') and name.endswith('"'):
|
if name.startswith('"') and name.endswith('"'):
|
||||||
@ -138,6 +145,9 @@ def get_date_trunc_sql(lookup_type, field_name):
|
|||||||
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
|
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
|
||||||
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
|
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
|
||||||
|
|
||||||
|
def get_datetime_cast_sql():
|
||||||
|
return None
|
||||||
|
|
||||||
def get_limit_offset_sql(limit, offset=None):
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
sql = "LIMIT %s" % limit
|
sql = "LIMIT %s" % limit
|
||||||
if offset and offset != 0:
|
if offset and offset != 0:
|
||||||
@ -159,6 +169,15 @@ def get_drop_foreignkey_sql():
|
|||||||
def get_pk_default_value():
|
def get_pk_default_value():
|
||||||
return "DEFAULT"
|
return "DEFAULT"
|
||||||
|
|
||||||
|
def get_max_name_length():
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_start_transaction_sql():
|
||||||
|
return "BEGIN;"
|
||||||
|
|
||||||
|
def get_autoinc_sql(table):
|
||||||
|
return None
|
||||||
|
|
||||||
def get_sql_flush(style, tables, sequences):
|
def get_sql_flush(style, tables, sequences):
|
||||||
"""Return a list of SQL statements required to remove all data from
|
"""Return a list of SQL statements required to remove all data from
|
||||||
all tables in the database (without actually removing the tables
|
all tables in the database (without actually removing the tables
|
||||||
@ -261,6 +280,8 @@ OPERATOR_MAPPING = {
|
|||||||
'iexact': 'ILIKE %s',
|
'iexact': 'ILIKE %s',
|
||||||
'contains': 'LIKE %s',
|
'contains': 'LIKE %s',
|
||||||
'icontains': 'ILIKE %s',
|
'icontains': 'ILIKE %s',
|
||||||
|
'regex': '~ %s',
|
||||||
|
'iregex': '~* %s',
|
||||||
'gt': '> %s',
|
'gt': '> %s',
|
||||||
'gte': '>= %s',
|
'gte': '>= %s',
|
||||||
'lt': '< %s',
|
'lt': '< %s',
|
||||||
|
@ -73,7 +73,14 @@ class DatabaseWrapper(local):
|
|||||||
self.connection.close()
|
self.connection.close()
|
||||||
self.connection = None
|
self.connection = None
|
||||||
|
|
||||||
|
allows_group_by_ordinal = True
|
||||||
|
allows_unique_and_pk = True
|
||||||
|
autoindexes_primary_keys = True
|
||||||
|
needs_datetime_string_cast = False
|
||||||
|
needs_upper_for_iops = False
|
||||||
supports_constraints = True
|
supports_constraints = True
|
||||||
|
supports_tablespaces = False
|
||||||
|
uses_case_insensitive_names = False
|
||||||
|
|
||||||
def quote_name(name):
|
def quote_name(name):
|
||||||
if name.startswith('"') and name.endswith('"'):
|
if name.startswith('"') and name.endswith('"'):
|
||||||
@ -98,6 +105,9 @@ def get_date_trunc_sql(lookup_type, field_name):
|
|||||||
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
|
# http://www.postgresql.org/docs/8.0/static/functions-datetime.html#FUNCTIONS-DATETIME-TRUNC
|
||||||
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
|
return "DATE_TRUNC('%s', %s)" % (lookup_type, field_name)
|
||||||
|
|
||||||
|
def get_datetime_cast_sql():
|
||||||
|
return None
|
||||||
|
|
||||||
def get_limit_offset_sql(limit, offset=None):
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
sql = "LIMIT %s" % limit
|
sql = "LIMIT %s" % limit
|
||||||
if offset and offset != 0:
|
if offset and offset != 0:
|
||||||
@ -119,6 +129,15 @@ def get_drop_foreignkey_sql():
|
|||||||
def get_pk_default_value():
|
def get_pk_default_value():
|
||||||
return "DEFAULT"
|
return "DEFAULT"
|
||||||
|
|
||||||
|
def get_max_name_length():
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_start_transaction_sql():
|
||||||
|
return "BEGIN;"
|
||||||
|
|
||||||
|
def get_autoinc_sql(table):
|
||||||
|
return None
|
||||||
|
|
||||||
def get_sql_flush(style, tables, sequences):
|
def get_sql_flush(style, tables, sequences):
|
||||||
"""Return a list of SQL statements required to remove all data from
|
"""Return a list of SQL statements required to remove all data from
|
||||||
all tables in the database (without actually removing the tables
|
all tables in the database (without actually removing the tables
|
||||||
@ -206,6 +225,8 @@ OPERATOR_MAPPING = {
|
|||||||
'iexact': 'ILIKE %s',
|
'iexact': 'ILIKE %s',
|
||||||
'contains': 'LIKE %s',
|
'contains': 'LIKE %s',
|
||||||
'icontains': 'ILIKE %s',
|
'icontains': 'ILIKE %s',
|
||||||
|
'regex': '~ %s',
|
||||||
|
'iregex': '~* %s',
|
||||||
'gt': '> %s',
|
'gt': '> %s',
|
||||||
'gte': '>= %s',
|
'gte': '>= %s',
|
||||||
'lt': '< %s',
|
'lt': '< %s',
|
||||||
|
@ -64,9 +64,10 @@ class DatabaseWrapper(local):
|
|||||||
}
|
}
|
||||||
kwargs.update(self.options)
|
kwargs.update(self.options)
|
||||||
self.connection = Database.connect(**kwargs)
|
self.connection = Database.connect(**kwargs)
|
||||||
# Register extract and date_trunc functions.
|
# Register extract, date_trunc, and regexp functions.
|
||||||
self.connection.create_function("django_extract", 2, _sqlite_extract)
|
self.connection.create_function("django_extract", 2, _sqlite_extract)
|
||||||
self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc)
|
self.connection.create_function("django_date_trunc", 2, _sqlite_date_trunc)
|
||||||
|
self.connection.create_function("regexp", 2, _sqlite_regexp)
|
||||||
cursor = self.connection.cursor(factory=SQLiteCursorWrapper)
|
cursor = self.connection.cursor(factory=SQLiteCursorWrapper)
|
||||||
cursor.row_factory = utf8rowFactory
|
cursor.row_factory = utf8rowFactory
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
@ -107,7 +108,14 @@ class SQLiteCursorWrapper(Database.Cursor):
|
|||||||
def convert_query(self, query, num_params):
|
def convert_query(self, query, num_params):
|
||||||
return query % tuple("?" * num_params)
|
return query % tuple("?" * num_params)
|
||||||
|
|
||||||
|
allows_group_by_ordinal = True
|
||||||
|
allows_unique_and_pk = True
|
||||||
|
autoindexes_primary_keys = True
|
||||||
|
needs_datetime_string_cast = True
|
||||||
|
needs_upper_for_iops = False
|
||||||
supports_constraints = False
|
supports_constraints = False
|
||||||
|
supports_tablespaces = False
|
||||||
|
uses_case_insensitive_names = False
|
||||||
|
|
||||||
def quote_name(name):
|
def quote_name(name):
|
||||||
if name.startswith('"') and name.endswith('"'):
|
if name.startswith('"') and name.endswith('"'):
|
||||||
@ -139,6 +147,9 @@ def get_date_trunc_sql(lookup_type, field_name):
|
|||||||
# sqlite doesn't support DATE_TRUNC, so we fake it as above.
|
# sqlite doesn't support DATE_TRUNC, so we fake it as above.
|
||||||
return 'django_date_trunc("%s", %s)' % (lookup_type.lower(), field_name)
|
return 'django_date_trunc("%s", %s)' % (lookup_type.lower(), field_name)
|
||||||
|
|
||||||
|
def get_datetime_cast_sql():
|
||||||
|
return None
|
||||||
|
|
||||||
def get_limit_offset_sql(limit, offset=None):
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
sql = "LIMIT %s" % limit
|
sql = "LIMIT %s" % limit
|
||||||
if offset and offset != 0:
|
if offset and offset != 0:
|
||||||
@ -160,6 +171,15 @@ def get_drop_foreignkey_sql():
|
|||||||
def get_pk_default_value():
|
def get_pk_default_value():
|
||||||
return "NULL"
|
return "NULL"
|
||||||
|
|
||||||
|
def get_max_name_length():
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_start_transaction_sql():
|
||||||
|
return "BEGIN;"
|
||||||
|
|
||||||
|
def get_autoinc_sql(table):
|
||||||
|
return None
|
||||||
|
|
||||||
def get_sql_flush(style, tables, sequences):
|
def get_sql_flush(style, tables, sequences):
|
||||||
"""Return a list of SQL statements required to remove all data from
|
"""Return a list of SQL statements required to remove all data from
|
||||||
all tables in the database (without actually removing the tables
|
all tables in the database (without actually removing the tables
|
||||||
@ -195,6 +215,13 @@ def _sqlite_date_trunc(lookup_type, dt):
|
|||||||
elif lookup_type == 'day':
|
elif lookup_type == 'day':
|
||||||
return "%i-%02i-%02i 00:00:00" % (dt.year, dt.month, dt.day)
|
return "%i-%02i-%02i 00:00:00" % (dt.year, dt.month, dt.day)
|
||||||
|
|
||||||
|
def _sqlite_regexp(re_pattern, re_string):
|
||||||
|
import re
|
||||||
|
try:
|
||||||
|
return bool(re.search(re_pattern, re_string))
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
# SQLite requires LIKE statements to include an ESCAPE clause if the value
|
# SQLite requires LIKE statements to include an ESCAPE clause if the value
|
||||||
# being escaped has a percent or underscore in it.
|
# being escaped has a percent or underscore in it.
|
||||||
# See http://www.sqlite.org/lang_expr.html for an explanation.
|
# See http://www.sqlite.org/lang_expr.html for an explanation.
|
||||||
@ -203,6 +230,8 @@ OPERATOR_MAPPING = {
|
|||||||
'iexact': "LIKE %s ESCAPE '\\'",
|
'iexact': "LIKE %s ESCAPE '\\'",
|
||||||
'contains': "LIKE %s ESCAPE '\\'",
|
'contains': "LIKE %s ESCAPE '\\'",
|
||||||
'icontains': "LIKE %s ESCAPE '\\'",
|
'icontains': "LIKE %s ESCAPE '\\'",
|
||||||
|
'regex': 'REGEXP %s',
|
||||||
|
'iregex': "REGEXP '(?i)' || %s",
|
||||||
'gt': '> %s',
|
'gt': '> %s',
|
||||||
'gte': '>= %s',
|
'gte': '>= %s',
|
||||||
'lt': '< %s',
|
'lt': '< %s',
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
import md5
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -107,6 +108,16 @@ def rev_typecast_decimal(d):
|
|||||||
return None
|
return None
|
||||||
return str(d)
|
return str(d)
|
||||||
|
|
||||||
|
def truncate_name(name, length=None):
|
||||||
|
"""Shortens a string to a repeatable mangled version with the given length.
|
||||||
|
"""
|
||||||
|
if length is None or len(name) <= length:
|
||||||
|
return name
|
||||||
|
|
||||||
|
hash = md5.md5(name).hexdigest()[:4]
|
||||||
|
|
||||||
|
return '%s%s' % (name[:length-4], hash)
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
# Helper functions for dictfetch* for databases that don't natively support them #
|
# Helper functions for dictfetch* for databases that don't natively support them #
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
@ -215,17 +215,18 @@ class Model(object):
|
|||||||
record_exists = True
|
record_exists = True
|
||||||
if pk_set:
|
if pk_set:
|
||||||
# Determine whether a record with the primary key already exists.
|
# Determine whether a record with the primary key already exists.
|
||||||
cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \
|
cursor.execute("SELECT COUNT(*) FROM %s WHERE %s=%%s" % \
|
||||||
(backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val])
|
(backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)),
|
||||||
|
self._meta.pk.get_db_prep_lookup('exact', pk_val))
|
||||||
# If it does already exist, do an UPDATE.
|
# If it does already exist, do an UPDATE.
|
||||||
if cursor.fetchone():
|
if cursor.fetchone()[0] > 0:
|
||||||
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
|
db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks]
|
||||||
if db_values:
|
if db_values:
|
||||||
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
|
||||||
(backend.quote_name(self._meta.db_table),
|
(backend.quote_name(self._meta.db_table),
|
||||||
','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
|
','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
|
||||||
backend.quote_name(self._meta.pk.column)),
|
backend.quote_name(self._meta.pk.column)),
|
||||||
db_values + [pk_val])
|
db_values + self._meta.pk.get_db_prep_lookup('exact', pk_val))
|
||||||
else:
|
else:
|
||||||
record_exists = False
|
record_exists = False
|
||||||
if not pk_set or not record_exists:
|
if not pk_set or not record_exists:
|
||||||
|
@ -72,12 +72,17 @@ class Field(object):
|
|||||||
maxlength=None, unique=False, blank=False, null=False, db_index=False,
|
maxlength=None, unique=False, blank=False, null=False, db_index=False,
|
||||||
core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True,
|
core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True,
|
||||||
unique_for_date=None, unique_for_month=None, unique_for_year=None,
|
unique_for_date=None, unique_for_month=None, unique_for_year=None,
|
||||||
validator_list=None, choices=None, radio_admin=None, help_text='', db_column=None):
|
validator_list=None, choices=None, radio_admin=None, help_text='', db_column=None,
|
||||||
|
db_tablespace=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.verbose_name = verbose_name
|
self.verbose_name = verbose_name
|
||||||
self.primary_key = primary_key
|
self.primary_key = primary_key
|
||||||
self.maxlength, self.unique = maxlength, unique
|
self.maxlength, self.unique = maxlength, unique
|
||||||
self.blank, self.null = blank, null
|
self.blank, self.null = blank, null
|
||||||
|
# Oracle treats the empty string ('') as null, so coerce the null
|
||||||
|
# option whenever '' is a possible value.
|
||||||
|
if self.empty_strings_allowed and settings.DATABASE_ENGINE == 'oracle':
|
||||||
|
self.null = True
|
||||||
self.core, self.rel, self.default = core, rel, default
|
self.core, self.rel, self.default = core, rel, default
|
||||||
self.editable = editable
|
self.editable = editable
|
||||||
self.serialize = serialize
|
self.serialize = serialize
|
||||||
@ -88,6 +93,7 @@ class Field(object):
|
|||||||
self.radio_admin = radio_admin
|
self.radio_admin = radio_admin
|
||||||
self.help_text = help_text
|
self.help_text = help_text
|
||||||
self.db_column = db_column
|
self.db_column = db_column
|
||||||
|
self.db_tablespace = db_tablespace
|
||||||
|
|
||||||
# Set db_index to True if the field has a relationship and doesn't explicitly set db_index.
|
# Set db_index to True if the field has a relationship and doesn't explicitly set db_index.
|
||||||
self.db_index = db_index
|
self.db_index = db_index
|
||||||
@ -166,7 +172,7 @@ class Field(object):
|
|||||||
|
|
||||||
def get_db_prep_lookup(self, lookup_type, value):
|
def get_db_prep_lookup(self, lookup_type, value):
|
||||||
"Returns field's value prepared for database lookup."
|
"Returns field's value prepared for database lookup."
|
||||||
if lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'):
|
if lookup_type in ('exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'):
|
||||||
return [value]
|
return [value]
|
||||||
elif lookup_type in ('range', 'in'):
|
elif lookup_type in ('range', 'in'):
|
||||||
return value
|
return value
|
||||||
@ -198,7 +204,7 @@ class Field(object):
|
|||||||
if callable(self.default):
|
if callable(self.default):
|
||||||
return self.default()
|
return self.default()
|
||||||
return self.default
|
return self.default
|
||||||
if not self.empty_strings_allowed or self.null:
|
if not self.empty_strings_allowed or (self.null and settings.DATABASE_ENGINE != 'oracle'):
|
||||||
return None
|
return None
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@ -792,6 +798,7 @@ class IntegerField(Field):
|
|||||||
return super(IntegerField, self).formfield(**defaults)
|
return super(IntegerField, self).formfield(**defaults)
|
||||||
|
|
||||||
class IPAddressField(Field):
|
class IPAddressField(Field):
|
||||||
|
empty_strings_allowed = False
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs['maxlength'] = 15
|
kwargs['maxlength'] = 15
|
||||||
Field.__init__(self, *args, **kwargs)
|
Field.__init__(self, *args, **kwargs)
|
||||||
@ -803,6 +810,7 @@ class IPAddressField(Field):
|
|||||||
validators.isValidIPAddress4(field_data, None)
|
validators.isValidIPAddress4(field_data, None)
|
||||||
|
|
||||||
class NullBooleanField(Field):
|
class NullBooleanField(Field):
|
||||||
|
empty_strings_allowed = False
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs['null'] = True
|
kwargs['null'] = True
|
||||||
Field.__init__(self, *args, **kwargs)
|
Field.__init__(self, *args, **kwargs)
|
||||||
@ -877,10 +885,18 @@ class TimeField(Field):
|
|||||||
Field.__init__(self, verbose_name, name, **kwargs)
|
Field.__init__(self, verbose_name, name, **kwargs)
|
||||||
|
|
||||||
def get_db_prep_lookup(self, lookup_type, value):
|
def get_db_prep_lookup(self, lookup_type, value):
|
||||||
if lookup_type == 'range':
|
if settings.DATABASE_ENGINE == 'oracle':
|
||||||
value = [str(v) for v in value]
|
# Oracle requires a date in order to parse.
|
||||||
|
def prep(value):
|
||||||
|
if isinstance(value, datetime.time):
|
||||||
|
value = datetime.datetime.combine(datetime.date(1900, 1, 1), value)
|
||||||
|
return str(value)
|
||||||
else:
|
else:
|
||||||
value = str(value)
|
prep = str
|
||||||
|
if lookup_type == 'range':
|
||||||
|
value = [prep(v) for v in value]
|
||||||
|
else:
|
||||||
|
value = prep(value)
|
||||||
return Field.get_db_prep_lookup(self, lookup_type, value)
|
return Field.get_db_prep_lookup(self, lookup_type, value)
|
||||||
|
|
||||||
def pre_save(self, model_instance, add):
|
def pre_save(self, model_instance, add):
|
||||||
@ -898,7 +914,15 @@ class TimeField(Field):
|
|||||||
# doesn't support microseconds.
|
# doesn't support microseconds.
|
||||||
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
|
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
|
||||||
value = value.replace(microsecond=0)
|
value = value.replace(microsecond=0)
|
||||||
value = str(value)
|
if settings.DATABASE_ENGINE == 'oracle':
|
||||||
|
# cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field.
|
||||||
|
if isinstance(value, datetime.time):
|
||||||
|
value = datetime.datetime(1900, 1, 1, value.hour, value.minute,
|
||||||
|
value.second, value.microsecond)
|
||||||
|
elif isinstance(value, basestring):
|
||||||
|
value = datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6]))
|
||||||
|
else:
|
||||||
|
value = str(value)
|
||||||
return Field.get_db_prep_save(self, value)
|
return Field.get_db_prep_save(self, value)
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
|
@ -10,9 +10,10 @@ from django import oldforms
|
|||||||
from django import newforms as forms
|
from django import newforms as forms
|
||||||
from django.dispatch import dispatcher
|
from django.dispatch import dispatcher
|
||||||
|
|
||||||
# For Python 2.3
|
try:
|
||||||
if not hasattr(__builtins__, 'set'):
|
set
|
||||||
from sets import Set as set
|
except NameError:
|
||||||
|
from sets import Set as set # Python 2.3 fallback
|
||||||
|
|
||||||
# Values for Relation.edit_inline.
|
# Values for Relation.edit_inline.
|
||||||
TABULAR, STACKED = 1, 2
|
TABULAR, STACKED = 1, 2
|
||||||
@ -335,10 +336,7 @@ def create_many_related_manager(superclass):
|
|||||||
(target_col_name, self.join_table, source_col_name,
|
(target_col_name, self.join_table, source_col_name,
|
||||||
target_col_name, ",".join(['%s'] * len(new_ids))),
|
target_col_name, ",".join(['%s'] * len(new_ids))),
|
||||||
[self._pk_val] + list(new_ids))
|
[self._pk_val] + list(new_ids))
|
||||||
if cursor.rowcount is not None and cursor.rowcount != 0:
|
existing_ids = set([row[0] for row in cursor.fetchall()])
|
||||||
existing_ids = set([row[0] for row in cursor.fetchmany(cursor.rowcount)])
|
|
||||||
else:
|
|
||||||
existing_ids = set()
|
|
||||||
|
|
||||||
# Add the ones that aren't there already
|
# Add the ones that aren't there already
|
||||||
for obj_id in (new_ids - existing_ids):
|
for obj_id in (new_ids - existing_ids):
|
||||||
|
@ -12,7 +12,7 @@ get_verbose_name = lambda class_name: re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|
|
|||||||
|
|
||||||
DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering',
|
DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering',
|
||||||
'unique_together', 'permissions', 'get_latest_by',
|
'unique_together', 'permissions', 'get_latest_by',
|
||||||
'order_with_respect_to', 'app_label')
|
'order_with_respect_to', 'app_label', 'db_tablespace')
|
||||||
|
|
||||||
class Options(object):
|
class Options(object):
|
||||||
def __init__(self, meta):
|
def __init__(self, meta):
|
||||||
@ -26,6 +26,7 @@ class Options(object):
|
|||||||
self.object_name, self.app_label = None, None
|
self.object_name, self.app_label = None, None
|
||||||
self.get_latest_by = None
|
self.get_latest_by = None
|
||||||
self.order_with_respect_to = None
|
self.order_with_respect_to = None
|
||||||
|
self.db_tablespace = None
|
||||||
self.admin = None
|
self.admin = None
|
||||||
self.meta = meta
|
self.meta = meta
|
||||||
self.pk = None
|
self.pk = None
|
||||||
@ -58,6 +59,8 @@ class Options(object):
|
|||||||
del self.meta
|
del self.meta
|
||||||
|
|
||||||
def _prepare(self, model):
|
def _prepare(self, model):
|
||||||
|
from django.db import backend
|
||||||
|
from django.db.backends.util import truncate_name
|
||||||
if self.order_with_respect_to:
|
if self.order_with_respect_to:
|
||||||
self.order_with_respect_to = self.get_field(self.order_with_respect_to)
|
self.order_with_respect_to = self.get_field(self.order_with_respect_to)
|
||||||
self.ordering = ('_order',)
|
self.ordering = ('_order',)
|
||||||
@ -72,6 +75,8 @@ class Options(object):
|
|||||||
# If the db_table wasn't provided, use the app_label + module_name.
|
# If the db_table wasn't provided, use the app_label + module_name.
|
||||||
if not self.db_table:
|
if not self.db_table:
|
||||||
self.db_table = "%s_%s" % (self.app_label, self.module_name)
|
self.db_table = "%s_%s" % (self.app_label, self.module_name)
|
||||||
|
self.db_table = truncate_name(self.db_table,
|
||||||
|
backend.get_max_name_length())
|
||||||
|
|
||||||
def add_field(self, field):
|
def add_field(self, field):
|
||||||
# Insert the given field in the order in which it was created, using
|
# Insert the given field in the order in which it was created, using
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
|
from django.conf import settings
|
||||||
from django.db import backend, connection, transaction
|
from django.db import backend, connection, transaction
|
||||||
from django.db.models.fields import DateField, FieldDoesNotExist
|
from django.db.models.fields import DateField, FieldDoesNotExist
|
||||||
from django.db.models import signals, loading
|
from django.db.models import signals, loading
|
||||||
from django.dispatch import dispatcher
|
from django.dispatch import dispatcher
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
from django.contrib.contenttypes import generic
|
from django.contrib.contenttypes import generic
|
||||||
|
import datetime
|
||||||
import operator
|
import operator
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# For Python 2.3
|
try:
|
||||||
if not hasattr(__builtins__, 'set'):
|
set
|
||||||
from sets import Set as set
|
except NameError:
|
||||||
|
from sets import Set as set # Python 2.3 fallback
|
||||||
|
|
||||||
# The string constant used to separate query parts
|
# The string constant used to separate query parts
|
||||||
LOOKUP_SEPARATOR = '__'
|
LOOKUP_SEPARATOR = '__'
|
||||||
@ -20,6 +23,7 @@ QUERY_TERMS = (
|
|||||||
'gt', 'gte', 'lt', 'lte', 'in',
|
'gt', 'gte', 'lt', 'lte', 'in',
|
||||||
'startswith', 'istartswith', 'endswith', 'iendswith',
|
'startswith', 'istartswith', 'endswith', 'iendswith',
|
||||||
'range', 'year', 'month', 'day', 'isnull', 'search',
|
'range', 'year', 'month', 'day', 'isnull', 'search',
|
||||||
|
'regex', 'iregex',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Size of each "chunk" for get_iterator calls.
|
# Size of each "chunk" for get_iterator calls.
|
||||||
@ -77,7 +81,7 @@ def quote_only_if_word(word):
|
|||||||
else:
|
else:
|
||||||
return backend.quote_name(word)
|
return backend.quote_name(word)
|
||||||
|
|
||||||
class QuerySet(object):
|
class _QuerySet(object):
|
||||||
"Represents a lazy database lookup for a set of objects"
|
"Represents a lazy database lookup for a set of objects"
|
||||||
def __init__(self, model=None):
|
def __init__(self, model=None):
|
||||||
self.model = model
|
self.model = model
|
||||||
@ -181,13 +185,18 @@ class QuerySet(object):
|
|||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
|
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
|
||||||
|
|
||||||
fill_cache = self._select_related
|
fill_cache = self._select_related
|
||||||
index_end = len(self.model._meta.fields)
|
fields = self.model._meta.fields
|
||||||
|
index_end = len(fields)
|
||||||
|
has_resolve_columns = hasattr(self, 'resolve_columns')
|
||||||
while 1:
|
while 1:
|
||||||
rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
|
rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
|
||||||
if not rows:
|
if not rows:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
if has_resolve_columns:
|
||||||
|
row = self.resolve_columns(row, fields)
|
||||||
if fill_cache:
|
if fill_cache:
|
||||||
obj, index_end = get_cached_row(klass=self.model, row=row,
|
obj, index_end = get_cached_row(klass=self.model, row=row,
|
||||||
index_start=0, max_depth=self._max_related_depth)
|
index_start=0, max_depth=self._max_related_depth)
|
||||||
@ -551,6 +560,12 @@ class QuerySet(object):
|
|||||||
|
|
||||||
return select, " ".join(sql), params
|
return select, " ".join(sql), params
|
||||||
|
|
||||||
|
# Use the backend's QuerySet class if it defines one, otherwise use _QuerySet.
|
||||||
|
if hasattr(backend, 'get_query_set_class'):
|
||||||
|
QuerySet = backend.get_query_set_class(_QuerySet)
|
||||||
|
else:
|
||||||
|
QuerySet = _QuerySet
|
||||||
|
|
||||||
class ValuesQuerySet(QuerySet):
|
class ValuesQuerySet(QuerySet):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(ValuesQuerySet, self).__init__(*args, **kwargs)
|
super(ValuesQuerySet, self).__init__(*args, **kwargs)
|
||||||
@ -565,35 +580,38 @@ class ValuesQuerySet(QuerySet):
|
|||||||
|
|
||||||
# self._fields is a list of field names to fetch.
|
# self._fields is a list of field names to fetch.
|
||||||
if self._fields:
|
if self._fields:
|
||||||
#columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
|
|
||||||
if not self._select:
|
if not self._select:
|
||||||
columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]
|
fields = [self.model._meta.get_field(f, many_to_many=False) for f in self._fields]
|
||||||
else:
|
else:
|
||||||
columns = []
|
fields = []
|
||||||
for f in self._fields:
|
for f in self._fields:
|
||||||
if f in [field.name for field in self.model._meta.fields]:
|
if f in [field.name for field in self.model._meta.fields]:
|
||||||
columns.append( self.model._meta.get_field(f, many_to_many=False).column )
|
fields.append(self.model._meta.get_field(f, many_to_many=False))
|
||||||
elif not self._select.has_key( f ):
|
elif not self._select.has_key( f ):
|
||||||
raise FieldDoesNotExist, '%s has no field named %r' % ( self.model._meta.object_name, f )
|
raise FieldDoesNotExist, '%s has no field named %r' % ( self.model._meta.object_name, f )
|
||||||
|
|
||||||
field_names = self._fields
|
field_names = self._fields
|
||||||
else: # Default to all fields.
|
else: # Default to all fields.
|
||||||
columns = [f.column for f in self.model._meta.fields]
|
fields = self.model._meta.fields
|
||||||
field_names = [f.attname for f in self.model._meta.fields]
|
field_names = [f.attname for f in fields]
|
||||||
|
|
||||||
|
columns = [f.column for f in fields]
|
||||||
select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
|
select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns]
|
||||||
|
|
||||||
# Add any additional SELECTs.
|
# Add any additional SELECTs.
|
||||||
if self._select:
|
if self._select:
|
||||||
select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
|
select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in self._select.items()])
|
||||||
|
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
|
cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params)
|
||||||
|
|
||||||
|
has_resolve_columns = hasattr(self, 'resolve_columns')
|
||||||
while 1:
|
while 1:
|
||||||
rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
|
rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
|
||||||
if not rows:
|
if not rows:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
if has_resolve_columns:
|
||||||
|
row = self.resolve_columns(row, fields)
|
||||||
yield dict(zip(field_names, row))
|
yield dict(zip(field_names, row))
|
||||||
|
|
||||||
def _clone(self, klass=None, **kwargs):
|
def _clone(self, klass=None, **kwargs):
|
||||||
@ -604,25 +622,49 @@ class ValuesQuerySet(QuerySet):
|
|||||||
class DateQuerySet(QuerySet):
|
class DateQuerySet(QuerySet):
|
||||||
def iterator(self):
|
def iterator(self):
|
||||||
from django.db.backends.util import typecast_timestamp
|
from django.db.backends.util import typecast_timestamp
|
||||||
|
from django.db.models.fields import DateTimeField
|
||||||
self._order_by = () # Clear this because it'll mess things up otherwise.
|
self._order_by = () # Clear this because it'll mess things up otherwise.
|
||||||
if self._field.null:
|
if self._field.null:
|
||||||
self._where.append('%s.%s IS NOT NULL' % \
|
self._where.append('%s.%s IS NOT NULL' % \
|
||||||
(backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column)))
|
(backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column)))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
select, sql, params = self._get_sql_clause()
|
select, sql, params = self._get_sql_clause()
|
||||||
except EmptyResultSet:
|
except EmptyResultSet:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|
||||||
sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \
|
table_name = backend.quote_name(self.model._meta.db_table)
|
||||||
|
field_name = backend.quote_name(self._field.column)
|
||||||
|
|
||||||
|
if backend.allows_group_by_ordinal:
|
||||||
|
group_by = '1'
|
||||||
|
else:
|
||||||
|
group_by = backend.get_date_trunc_sql(self._kind,
|
||||||
|
'%s.%s' % (table_name, field_name))
|
||||||
|
|
||||||
|
sql = 'SELECT %s %s GROUP BY %s ORDER BY 1 %s' % \
|
||||||
(backend.get_date_trunc_sql(self._kind, '%s.%s' % (backend.quote_name(self.model._meta.db_table),
|
(backend.get_date_trunc_sql(self._kind, '%s.%s' % (backend.quote_name(self.model._meta.db_table),
|
||||||
backend.quote_name(self._field.column))), sql, self._order)
|
backend.quote_name(self._field.column))), sql, group_by, self._order)
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute(sql, params)
|
cursor.execute(sql, params)
|
||||||
# We have to manually run typecast_timestamp(str()) on the results, because
|
|
||||||
# MySQL doesn't automatically cast the result of date functions as datetime
|
has_resolve_columns = hasattr(self, 'resolve_columns')
|
||||||
# objects -- MySQL returns the values as strings, instead.
|
needs_datetime_string_cast = backend.needs_datetime_string_cast
|
||||||
return [typecast_timestamp(str(row[0])) for row in cursor.fetchall()]
|
dates = []
|
||||||
|
# It would be better to use self._field here instead of DateTimeField(),
|
||||||
|
# but in Oracle that will result in a list of datetime.date instead of
|
||||||
|
# datetime.datetime.
|
||||||
|
fields = [DateTimeField()]
|
||||||
|
while 1:
|
||||||
|
rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
|
||||||
|
if not rows:
|
||||||
|
return dates
|
||||||
|
for row in rows:
|
||||||
|
date = row[0]
|
||||||
|
if has_resolve_columns:
|
||||||
|
date = self.resolve_columns([date], fields)[0]
|
||||||
|
elif needs_datetime_string_cast:
|
||||||
|
date = typecast_timestamp(str(date))
|
||||||
|
dates.append(date)
|
||||||
|
|
||||||
def _clone(self, klass=None, **kwargs):
|
def _clone(self, klass=None, **kwargs):
|
||||||
c = super(DateQuerySet, self)._clone(klass, **kwargs)
|
c = super(DateQuerySet, self)._clone(klass, **kwargs)
|
||||||
@ -730,8 +772,17 @@ def get_where_clause(lookup_type, table_prefix, field_name, value):
|
|||||||
if table_prefix.endswith('.'):
|
if table_prefix.endswith('.'):
|
||||||
table_prefix = backend.quote_name(table_prefix[:-1])+'.'
|
table_prefix = backend.quote_name(table_prefix[:-1])+'.'
|
||||||
field_name = backend.quote_name(field_name)
|
field_name = backend.quote_name(field_name)
|
||||||
|
if type(value) == datetime.datetime and backend.get_datetime_cast_sql():
|
||||||
|
cast_sql = backend.get_datetime_cast_sql()
|
||||||
|
else:
|
||||||
|
cast_sql = '%s'
|
||||||
|
if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith') and backend.needs_upper_for_iops:
|
||||||
|
format = 'UPPER(%s%s) %s'
|
||||||
|
else:
|
||||||
|
format = '%s%s %s'
|
||||||
try:
|
try:
|
||||||
return '%s%s %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s'))
|
return format % (table_prefix, field_name,
|
||||||
|
backend.OPERATOR_MAPPING[lookup_type] % cast_sql)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
if lookup_type == 'in':
|
if lookup_type == 'in':
|
||||||
@ -748,6 +799,15 @@ def get_where_clause(lookup_type, table_prefix, field_name, value):
|
|||||||
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))
|
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))
|
||||||
elif lookup_type == 'search':
|
elif lookup_type == 'search':
|
||||||
return backend.get_fulltext_search_sql(table_prefix + field_name)
|
return backend.get_fulltext_search_sql(table_prefix + field_name)
|
||||||
|
elif lookup_type in ('regex', 'iregex'):
|
||||||
|
if settings.DATABASE_ENGINE == 'oracle':
|
||||||
|
if lookup_type == 'regex':
|
||||||
|
match_option = 'c'
|
||||||
|
else:
|
||||||
|
match_option = 'i'
|
||||||
|
return "REGEXP_LIKE(%s%s, %s, '%s')" % (table_prefix, field_name, cast_sql, match_option)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type)
|
raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type)
|
||||||
|
|
||||||
def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0):
|
def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0):
|
||||||
|
@ -162,7 +162,7 @@ class HttpResponse(object):
|
|||||||
|
|
||||||
status_code = 200
|
status_code = 200
|
||||||
|
|
||||||
def __init__(self, content='', mimetype=None):
|
def __init__(self, content='', mimetype=None, status=None):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
self._charset = settings.DEFAULT_CHARSET
|
self._charset = settings.DEFAULT_CHARSET
|
||||||
if not mimetype:
|
if not mimetype:
|
||||||
@ -175,6 +175,8 @@ class HttpResponse(object):
|
|||||||
self._is_string = True
|
self._is_string = True
|
||||||
self.headers = {'Content-Type': mimetype}
|
self.headers = {'Content-Type': mimetype}
|
||||||
self.cookies = SimpleCookie()
|
self.cookies = SimpleCookie()
|
||||||
|
if status:
|
||||||
|
self.status_code = status
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"Full HTTP message, including headers"
|
"Full HTTP message, including headers"
|
||||||
|
@ -11,7 +11,8 @@ class CommonMiddleware(object):
|
|||||||
- Forbids access to User-Agents in settings.DISALLOWED_USER_AGENTS
|
- Forbids access to User-Agents in settings.DISALLOWED_USER_AGENTS
|
||||||
|
|
||||||
- URL rewriting: Based on the APPEND_SLASH and PREPEND_WWW settings,
|
- URL rewriting: Based on the APPEND_SLASH and PREPEND_WWW settings,
|
||||||
this middleware appends missing slashes and/or prepends missing "www."s.
|
this middleware appends missing slashes and/or prepends missing
|
||||||
|
"www."s.
|
||||||
|
|
||||||
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
- ETags: If the USE_ETAGS setting is set, ETags will be calculated from
|
||||||
the entire page content and Not Modified responses will be returned
|
the entire page content and Not Modified responses will be returned
|
||||||
@ -74,7 +75,10 @@ class CommonMiddleware(object):
|
|||||||
|
|
||||||
# Use ETags, if requested.
|
# Use ETags, if requested.
|
||||||
if settings.USE_ETAGS:
|
if settings.USE_ETAGS:
|
||||||
etag = md5.new(response.content).hexdigest()
|
if response.has_header('ETag'):
|
||||||
|
etag = response['ETag']
|
||||||
|
else:
|
||||||
|
etag = md5.new(response.content).hexdigest()
|
||||||
if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
|
if response.status_code >= 200 and response.status_code < 300 and request.META.get('HTTP_IF_NONE_MATCH') == etag:
|
||||||
response = http.HttpResponseNotModified()
|
response = http.HttpResponseNotModified()
|
||||||
else:
|
else:
|
||||||
|
@ -27,9 +27,9 @@ __all__ = (
|
|||||||
EMPTY_VALUES = (None, '')
|
EMPTY_VALUES = (None, '')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
set # Only available in Python 2.4+
|
set
|
||||||
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:
|
try:
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
@ -516,11 +516,13 @@ class MultiValueField(Field):
|
|||||||
"""
|
"""
|
||||||
clean_data = []
|
clean_data = []
|
||||||
errors = ErrorList()
|
errors = ErrorList()
|
||||||
if self.required and not value:
|
if not value or isinstance(value, (list, tuple)):
|
||||||
raise ValidationError(gettext(u'This field is required.'))
|
if not value or not [v for v in value if v not in EMPTY_VALUES]:
|
||||||
elif not self.required and not value:
|
if self.required:
|
||||||
return self.compress([])
|
raise ValidationError(gettext(u'This field is required.'))
|
||||||
if not isinstance(value, (list, tuple)):
|
else:
|
||||||
|
return self.compress([])
|
||||||
|
else:
|
||||||
raise ValidationError(gettext(u'Enter a list of values.'))
|
raise ValidationError(gettext(u'Enter a list of values.'))
|
||||||
for i, field in enumerate(self.fields):
|
for i, field in enumerate(self.fields):
|
||||||
try:
|
try:
|
||||||
@ -558,5 +560,11 @@ class SplitDateTimeField(MultiValueField):
|
|||||||
|
|
||||||
def compress(self, data_list):
|
def compress(self, data_list):
|
||||||
if data_list:
|
if data_list:
|
||||||
|
# Raise a validation error if time or date is empty
|
||||||
|
# (possible if SplitDateTimeField has required=False).
|
||||||
|
if data_list[0] in EMPTY_VALUES:
|
||||||
|
raise ValidationError(gettext(u'Enter a valid date.'))
|
||||||
|
if data_list[1] in EMPTY_VALUES:
|
||||||
|
raise ValidationError(gettext(u'Enter a valid time.'))
|
||||||
return datetime.datetime.combine(*data_list)
|
return datetime.datetime.combine(*data_list)
|
||||||
return None
|
return None
|
||||||
|
@ -159,7 +159,7 @@ class BaseForm(StrAndUnicode):
|
|||||||
|
|
||||||
def as_p(self):
|
def as_p(self):
|
||||||
"Returns this form rendered as HTML <p>s."
|
"Returns this form rendered as HTML <p>s."
|
||||||
return self._html_output(u'<p>%(label)s %(field)s%(help_text)s</p>', u'<p>%s</p>', '</p>', u' %s', True)
|
return self._html_output(u'<p>%(label)s %(field)s%(help_text)s</p>', u'%s', '</p>', u' %s', True)
|
||||||
|
|
||||||
def non_field_errors(self):
|
def non_field_errors(self):
|
||||||
"""
|
"""
|
||||||
|
@ -3,16 +3,15 @@ HTML Widget classes
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
set # Only available in Python 2.4+
|
set
|
||||||
except NameError:
|
except NameError:
|
||||||
from sets import Set as set # Python 2.3 fallback
|
from sets import Set as set # Python 2.3 fallback
|
||||||
from itertools import chain
|
|
||||||
|
|
||||||
|
from itertools import chain
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.translation import gettext
|
from django.utils.translation import gettext
|
||||||
from django.utils.encoding import StrAndUnicode, smart_unicode
|
from django.utils.encoding import StrAndUnicode, smart_unicode
|
||||||
|
|
||||||
from util import flatatt
|
from util import flatatt
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
|
@ -488,9 +488,6 @@ class TokenParser(object):
|
|||||||
self.pointer = i
|
self.pointer = i
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
filter_raw_string = r"""
|
filter_raw_string = r"""
|
||||||
^%(i18n_open)s"(?P<i18n_constant>%(str)s)"%(i18n_close)s|
|
^%(i18n_open)s"(?P<i18n_constant>%(str)s)"%(i18n_close)s|
|
||||||
^"(?P<constant>%(str)s)"|
|
^"(?P<constant>%(str)s)"|
|
||||||
|
@ -4,16 +4,14 @@ from django.template import Node, NodeList, Template, Context, resolve_variable
|
|||||||
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END
|
from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END
|
||||||
from django.template import get_library, Library, InvalidTemplateLibrary
|
from django.template import get_library, Library, InvalidTemplateLibrary
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.utils.itercompat import groupby
|
||||||
import sys
|
import sys
|
||||||
import re
|
import re
|
||||||
|
|
||||||
if not hasattr(__builtins__, 'reversed'):
|
try:
|
||||||
# For Python 2.3.
|
reversed
|
||||||
# From http://www.python.org/doc/current/tut/node11.html
|
except NameError:
|
||||||
def reversed(data):
|
from django.utils.itercompat import reversed # Python 2.3 fallback
|
||||||
for index in xrange(len(data)-1, -1, -1):
|
|
||||||
yield data[index]
|
|
||||||
|
|
||||||
|
|
||||||
register = Library()
|
register = Library()
|
||||||
|
|
||||||
@ -252,15 +250,10 @@ class RegroupNode(Node):
|
|||||||
if obj_list == None: # target_var wasn't found in context; fail silently
|
if obj_list == None: # target_var wasn't found in context; fail silently
|
||||||
context[self.var_name] = []
|
context[self.var_name] = []
|
||||||
return ''
|
return ''
|
||||||
output = [] # list of dictionaries in the format {'grouper': 'key', 'list': [list of contents]}
|
# List of dictionaries in the format
|
||||||
for obj in obj_list:
|
# {'grouper': 'key', 'list': [list of contents]}.
|
||||||
grouper = self.expression.resolve(obj, True)
|
context[self.var_name] = [{'grouper':key, 'list':list(val)} for key, val in
|
||||||
# TODO: Is this a sensible way to determine equality?
|
groupby(obj_list, lambda v, f=self.expression.resolve: f(v, True))]
|
||||||
if output and repr(output[-1]['grouper']) == repr(grouper):
|
|
||||||
output[-1]['list'].append(obj)
|
|
||||||
else:
|
|
||||||
output.append({'grouper': grouper, 'list': [obj]})
|
|
||||||
context[self.var_name] = output
|
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def include_is_allowed(filepath):
|
def include_is_allowed(filepath):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import sys, time
|
import sys, time
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import connection, transaction, backend
|
from django.db import connection, backend, get_creation_module
|
||||||
|
from django.core import management, mail
|
||||||
from django.core import management, mail
|
from django.core import management, mail
|
||||||
from django.dispatch import dispatcher
|
from django.dispatch import dispatcher
|
||||||
from django.test import signals
|
from django.test import signals
|
||||||
@ -88,6 +89,12 @@ def get_postgresql_create_suffix():
|
|||||||
return ''
|
return ''
|
||||||
|
|
||||||
def create_test_db(verbosity=1, autoclobber=False):
|
def create_test_db(verbosity=1, autoclobber=False):
|
||||||
|
# If the database backend wants to create the test DB itself, let it
|
||||||
|
creation_module = get_creation_module()
|
||||||
|
if hasattr(creation_module, "create_test_db"):
|
||||||
|
creation_module.create_test_db(settings, connection, backend, verbosity, autoclobber)
|
||||||
|
return
|
||||||
|
|
||||||
if verbosity >= 1:
|
if verbosity >= 1:
|
||||||
print "Creating test database..."
|
print "Creating test database..."
|
||||||
# If we're using SQLite, it's more convenient to test against an
|
# If we're using SQLite, it's more convenient to test against an
|
||||||
@ -142,6 +149,12 @@ def create_test_db(verbosity=1, autoclobber=False):
|
|||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
def destroy_test_db(old_database_name, verbosity=1):
|
def destroy_test_db(old_database_name, verbosity=1):
|
||||||
|
# If the database wants to drop the test DB itself, let it
|
||||||
|
creation_module = get_creation_module()
|
||||||
|
if hasattr(creation_module, "destroy_test_db"):
|
||||||
|
creation_module.destroy_test_db(settings, connection, backend, old_database_name, verbosity)
|
||||||
|
return
|
||||||
|
|
||||||
# Unless we're using SQLite, remove the test database to clean up after
|
# Unless we're using SQLite, remove the test database to clean up after
|
||||||
# ourselves. Connect to the previous database (not the test database)
|
# ourselves. Connect to the previous database (not the test database)
|
||||||
# to do so, because it's not allowed to delete a database while being
|
# to do so, because it's not allowed to delete a database while being
|
||||||
|
@ -3,6 +3,21 @@ def curry(_curried_func, *args, **kwargs):
|
|||||||
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
|
return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs))
|
||||||
return _curried
|
return _curried
|
||||||
|
|
||||||
|
def memoize(func, cache):
|
||||||
|
"""
|
||||||
|
Wrap a function so that results for any argument tuple are stored in
|
||||||
|
'cache'. Note that the args to the function must be usable as dictionary
|
||||||
|
keys.
|
||||||
|
"""
|
||||||
|
def wrapper(*args):
|
||||||
|
if args in cache:
|
||||||
|
return cache[args]
|
||||||
|
|
||||||
|
result = func(*args)
|
||||||
|
cache[args] = result
|
||||||
|
return result
|
||||||
|
return wrapper
|
||||||
|
|
||||||
class Promise:
|
class Promise:
|
||||||
"""
|
"""
|
||||||
This is just a base class for the proxy class created in
|
This is just a base class for the proxy class created in
|
||||||
|
@ -53,16 +53,18 @@ def fix_ampersands(value):
|
|||||||
|
|
||||||
def urlize(text, trim_url_limit=None, nofollow=False):
|
def urlize(text, trim_url_limit=None, nofollow=False):
|
||||||
"""
|
"""
|
||||||
Converts any URLs in text into clickable links. Works on http://, https:// and
|
Converts any URLs in text into clickable links. Works on http://, https://
|
||||||
www. links. Links can have trailing punctuation (periods, commas, close-parens)
|
and www. links. Links can have trailing punctuation (periods, commas,
|
||||||
and leading punctuation (opening parens) and it'll still do the right thing.
|
close-parens) and leading punctuation (opening parens) and it'll still do
|
||||||
|
the right thing.
|
||||||
|
|
||||||
If trim_url_limit is not None, the URLs in link text will be limited to
|
If trim_url_limit is not None, the URLs in link text longer than this limit
|
||||||
trim_url_limit characters.
|
will truncated to trim_url_limit-3 characters and appended with an elipsis.
|
||||||
|
|
||||||
If nofollow is True, the URLs in link text will get a rel="nofollow" attribute.
|
If nofollow is True, the URLs in link text will get a rel="nofollow"
|
||||||
|
attribute.
|
||||||
"""
|
"""
|
||||||
trim_url = lambda x, limit=trim_url_limit: limit is not None and (x[:limit] + (len(x) >=limit and '...' or '')) or x
|
trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
|
||||||
words = word_split_re.split(text)
|
words = word_split_re.split(text)
|
||||||
nofollow_attr = nofollow and ' rel="nofollow"' or ''
|
nofollow_attr = nofollow and ' rel="nofollow"' or ''
|
||||||
for i, word in enumerate(words):
|
for i, word in enumerate(words):
|
||||||
|
@ -7,7 +7,8 @@ these implementations if necessary.
|
|||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
def compat_tee(iterable):
|
def compat_tee(iterable):
|
||||||
"""Return two independent iterators from a single iterable.
|
"""
|
||||||
|
Return two independent iterators from a single iterable.
|
||||||
|
|
||||||
Based on http://www.python.org/doc/2.3.5/lib/itertools-example.html
|
Based on http://www.python.org/doc/2.3.5/lib/itertools-example.html
|
||||||
"""
|
"""
|
||||||
@ -25,7 +26,34 @@ def compat_tee(iterable):
|
|||||||
next = iter(iterable).next
|
next = iter(iterable).next
|
||||||
return gen(next), gen(next)
|
return gen(next), gen(next)
|
||||||
|
|
||||||
|
def groupby(iterable, keyfunc=None):
|
||||||
|
"""
|
||||||
|
Taken from http://docs.python.org/lib/itertools-functions.html
|
||||||
|
"""
|
||||||
|
if keyfunc is None:
|
||||||
|
keyfunc = lambda x:x
|
||||||
|
iterable = iter(iterable)
|
||||||
|
l = [iterable.next()]
|
||||||
|
lastkey = keyfunc(l[0])
|
||||||
|
for item in iterable:
|
||||||
|
key = keyfunc(item)
|
||||||
|
if key != lastkey:
|
||||||
|
yield lastkey, l
|
||||||
|
lastkey = key
|
||||||
|
l = [item]
|
||||||
|
else:
|
||||||
|
l.append(item)
|
||||||
|
yield lastkey, l
|
||||||
|
|
||||||
|
# Not really in itertools, since it's a builtin in Python 2.4 and later, but it
|
||||||
|
# does operate as an iterator.
|
||||||
|
def reversed(data):
|
||||||
|
for index in xrange(len(data)-1, -1, -1):
|
||||||
|
yield data[index]
|
||||||
|
|
||||||
if hasattr(itertools, 'tee'):
|
if hasattr(itertools, 'tee'):
|
||||||
tee = itertools.tee
|
tee = itertools.tee
|
||||||
else:
|
else:
|
||||||
tee = compat_tee
|
tee = compat_tee
|
||||||
|
if hasattr(itertools, 'groupby'):
|
||||||
|
groupby = itertools.groupby
|
||||||
|
@ -161,8 +161,8 @@ The ``User`` model has a custom manager that has the following helper functions:
|
|||||||
* ``make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')``
|
* ``make_random_password(length=10, allowed_chars='abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789')``
|
||||||
Returns a random password with the given length and given string of
|
Returns a random password with the given length and given string of
|
||||||
allowed characters. (Note that the default value of ``allowed_chars``
|
allowed characters. (Note that the default value of ``allowed_chars``
|
||||||
doesn't contain ``"I"`` or letters that look like it, to avoid user
|
doesn't contain letters that can cause user confusion, including
|
||||||
confusion.
|
``1``, ``I`` and ``0``).
|
||||||
|
|
||||||
Basic usage
|
Basic usage
|
||||||
-----------
|
-----------
|
||||||
@ -325,7 +325,7 @@ Manually checking a user's password
|
|||||||
|
|
||||||
If you'd like to manually authenticate a user by comparing a
|
If you'd like to manually authenticate a user by comparing a
|
||||||
plain-text password to the hashed password in the database, use the
|
plain-text password to the hashed password in the database, use the
|
||||||
convenience function `django.contrib.auth.models.check_password`. It
|
convenience function ``django.contrib.auth.models.check_password``. It
|
||||||
takes two arguments: the plain-text password to check, and the full
|
takes two arguments: the plain-text password to check, and the full
|
||||||
value of a user's ``password`` field in the database to check against,
|
value of a user's ``password`` field in the database to check against,
|
||||||
and returns ``True`` if they match, ``False`` otherwise.
|
and returns ``True`` if they match, ``False`` otherwise.
|
||||||
@ -461,7 +461,7 @@ block::
|
|||||||
Other built-in views
|
Other built-in views
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
In addition to the `login` view, the authentication system includes a
|
In addition to the ``login`` view, the authentication system includes a
|
||||||
few other useful built-in views:
|
few other useful built-in views:
|
||||||
|
|
||||||
``django.contrib.auth.views.logout``
|
``django.contrib.auth.views.logout``
|
||||||
|
@ -382,6 +382,65 @@ Model style
|
|||||||
('F', 'Female'),
|
('F', 'Female'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Documentation style
|
||||||
|
===================
|
||||||
|
|
||||||
|
We place a high importance on consistency and readability of documentation.
|
||||||
|
(After all, Django was created in a journalism environment!)
|
||||||
|
|
||||||
|
Guidelines for ReST files
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
These guidelines regulate the format of our ReST documentation:
|
||||||
|
|
||||||
|
* In section titles, capitalize only initial words and proper nouns.
|
||||||
|
|
||||||
|
* Wrap the documentation at 80 characters wide, unless a code example
|
||||||
|
is significantly less readable when split over two lines, or for another
|
||||||
|
good reason.
|
||||||
|
|
||||||
|
Commonly used terms
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Here are some style guidelines on commonly used terms throughout the
|
||||||
|
documentation:
|
||||||
|
|
||||||
|
* **Django** -- when referring to the framework, capitalize Django. It is
|
||||||
|
lowercase only in Python code and in the djangoproject.com logo.
|
||||||
|
|
||||||
|
* **e-mail** -- it has a hyphen.
|
||||||
|
|
||||||
|
* **MySQL**
|
||||||
|
|
||||||
|
* **PostgreSQL**
|
||||||
|
|
||||||
|
* **Python** -- when referring to the language, capitalize Python.
|
||||||
|
|
||||||
|
* **realize**, **customize**, **initialize**, etc. -- use the American
|
||||||
|
"ize" suffix, not "ise."
|
||||||
|
|
||||||
|
* **SQLite**
|
||||||
|
|
||||||
|
* **subclass** -- it's a single word without a hyphen, both as a verb
|
||||||
|
("subclass that model") and as a noun ("create a subclass").
|
||||||
|
|
||||||
|
* **Web**, **World Wide Web**, **the Web** -- note Web is always
|
||||||
|
capitalized when referring to the World Wide Web.
|
||||||
|
|
||||||
|
* **Web site** -- use two words, with Web capitalized.
|
||||||
|
|
||||||
|
Django-specific terminology
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
* **model** -- it's not capitalized.
|
||||||
|
|
||||||
|
* **template** -- it's not capitalized.
|
||||||
|
|
||||||
|
* **URLconf** -- use three capitalized letters, with no space before
|
||||||
|
"conf."
|
||||||
|
|
||||||
|
* **view** -- it's not capitalized.
|
||||||
|
|
||||||
Committing code
|
Committing code
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
@ -1173,6 +1173,58 @@ like ``contains`` but is significantly faster due to full-text indexing.
|
|||||||
Note this is only available in MySQL and requires direct manipulation of the
|
Note this is only available in MySQL and requires direct manipulation of the
|
||||||
database to add the full-text index.
|
database to add the full-text index.
|
||||||
|
|
||||||
|
regex
|
||||||
|
~~~~~
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
Case-sensitive regular expression match.
|
||||||
|
|
||||||
|
The regular expression syntax is that of the database backend in use. In the
|
||||||
|
case of SQLite, which doesn't natively support regular-expression lookups, the
|
||||||
|
syntax is that of Python's ``re`` module.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
Entry.objects.get(title__regex=r'^(An?|The) +')
|
||||||
|
|
||||||
|
SQL equivalents::
|
||||||
|
|
||||||
|
SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL
|
||||||
|
|
||||||
|
SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'c'); -- Oracle
|
||||||
|
|
||||||
|
SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL
|
||||||
|
|
||||||
|
SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite
|
||||||
|
|
||||||
|
Using raw strings (e.g., ``r'foo'`` instead of ``'foo'``) for passing in the
|
||||||
|
regular expression syntax is recommended.
|
||||||
|
|
||||||
|
Regular expression matching is not supported on the ``ado_mssql`` backend.
|
||||||
|
It will raise a ``NotImplementedError`` at runtime.
|
||||||
|
|
||||||
|
iregex
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
Case-insensitive regular expression match.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
Entry.objects.get(title__iregex=r'^(an?|the) +')
|
||||||
|
|
||||||
|
SQL equivalents::
|
||||||
|
|
||||||
|
SELECT ... WHERE title REGEXP '^(an?|the) +'; -- MySQL
|
||||||
|
|
||||||
|
SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'i'); -- Oracle
|
||||||
|
|
||||||
|
SELECT ... WHERE title ~* '^(an?|the) +'; -- PostgreSQL
|
||||||
|
|
||||||
|
SELECT ... WHERE title REGEXP '(?i)^(an?|the) +'; -- SQLite
|
||||||
|
|
||||||
Default lookups are exact
|
Default lookups are exact
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
@ -1779,7 +1831,7 @@ use the default manager, or if you want to search a list of related objects,
|
|||||||
you can provide ``get_object_or_404()`` with a manager object instead.
|
you can provide ``get_object_or_404()`` with a manager object instead.
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
# Get the author of blog instance `e` with a name of 'Fred'
|
# Get the author of blog instance e with a name of 'Fred'
|
||||||
a = get_object_or_404(e.authors, name='Fred')
|
a = get_object_or_404(e.authors, name='Fred')
|
||||||
|
|
||||||
# Use a custom manager 'recent_entries' in the search for an
|
# Use a custom manager 'recent_entries' in the search for an
|
||||||
|
@ -513,7 +513,7 @@ Example usage::
|
|||||||
|
|
||||||
Verbosity determines the amount of notification and debug information that
|
Verbosity determines the amount of notification and debug information that
|
||||||
will be printed to the console. '0' is no output, '1' is normal output,
|
will be printed to the console. '0' is no output, '1' is normal output,
|
||||||
and `2` is verbose output.
|
and ``2`` is verbose output.
|
||||||
|
|
||||||
--adminmedia
|
--adminmedia
|
||||||
------------
|
------------
|
||||||
|
126
docs/email.txt
126
docs/email.txt
@ -28,9 +28,9 @@ settings, if set, are used to authenticate to the SMTP server, and the
|
|||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
The character set of e-mail sent with ``django.core.mail`` will be set to
|
The character set of e-mail sent with ``django.core.mail`` will be set to
|
||||||
the value of your `DEFAULT_CHARSET setting`_.
|
the value of your `DEFAULT_CHARSET`_ setting.
|
||||||
|
|
||||||
.. _DEFAULT_CHARSET setting: ../settings/#default-charset
|
.. _DEFAULT_CHARSET: ../settings/#default-charset
|
||||||
.. _EMAIL_HOST: ../settings/#email-host
|
.. _EMAIL_HOST: ../settings/#email-host
|
||||||
.. _EMAIL_PORT: ../settings/#email-port
|
.. _EMAIL_PORT: ../settings/#email-port
|
||||||
.. _EMAIL_HOST_USER: ../settings/#email-host-user
|
.. _EMAIL_HOST_USER: ../settings/#email-host-user
|
||||||
@ -198,27 +198,58 @@ e-mail, you can subclass these two classes to suit your needs.
|
|||||||
.. note::
|
.. note::
|
||||||
Not all features of the ``EmailMessage`` class are available through the
|
Not all features of the ``EmailMessage`` class are available through the
|
||||||
``send_mail()`` and related wrapper functions. If you wish to use advanced
|
``send_mail()`` and related wrapper functions. If you wish to use advanced
|
||||||
features, such as BCC'ed recipients or multi-part e-mail, you'll need to
|
features, such as BCC'ed recipients, file attachments, or multi-part
|
||||||
create ``EmailMessage`` instances directly.
|
e-mail, you'll need to create ``EmailMessage`` instances directly.
|
||||||
|
|
||||||
|
This is a design feature. ``send_mail()`` and related functions were
|
||||||
|
originally the only interface Django provided. However, the list of
|
||||||
|
parameters they accepted was slowly growing over time. It made sense to
|
||||||
|
move to a more object-oriented design for e-mail messages and retain the
|
||||||
|
original functions only for backwards compatibility.
|
||||||
|
|
||||||
In general, ``EmailMessage`` is responsible for creating the e-mail message
|
In general, ``EmailMessage`` is responsible for creating the e-mail message
|
||||||
itself. ``SMTPConnection`` is responsible for the network connection side of
|
itself. ``SMTPConnection`` is responsible for the network connection side of
|
||||||
the operation. This means you can reuse the same connection (an
|
the operation. This means you can reuse the same connection (an
|
||||||
``SMTPConnection`` instance) for multiple messages.
|
``SMTPConnection`` instance) for multiple messages.
|
||||||
|
|
||||||
The ``EmailMessage`` class is initialized as follows::
|
E-mail messages
|
||||||
|
---------------
|
||||||
|
|
||||||
email = EmailMessage(subject, body, from_email, to, bcc, connection)
|
The ``EmailMessage`` class is initialized with the following parameters (in
|
||||||
|
the given order, if positional arguments are used). All parameters are
|
||||||
|
optional and can be set at any time prior to calling the ``send()`` method.
|
||||||
|
|
||||||
All of these parameters are optional. If ``from_email`` is omitted, the value
|
* ``subject``: The subject line of the e-mail.
|
||||||
from ``settings.DEFAULT_FROM_EMAIL`` is used. Both the ``to`` and ``bcc``
|
|
||||||
parameters are lists of addresses, as strings.
|
* ``body``: The body text. This should be a plain text message.
|
||||||
|
|
||||||
|
* ``from_email``: The sender's address. Both ``fred@example.com`` and
|
||||||
|
``Fred <fred@example.com>`` forms are legal. If omitted, the
|
||||||
|
``DEFAULT_FROM_EMAIL`` setting is used.
|
||||||
|
|
||||||
|
* ``to``: A list or tuple of recipient addresses.
|
||||||
|
|
||||||
|
* ``bcc``: A list or tuple of addresses used in the "Bcc" header when
|
||||||
|
sending the e-mail.
|
||||||
|
|
||||||
|
* ``connection``: An ``SMTPConnection`` instance. Use this parameter if
|
||||||
|
you want to use the same conneciton for multiple messages. If omitted, a
|
||||||
|
new connection is created when ``send()`` is called.
|
||||||
|
|
||||||
|
* ``attachments``: A list of attachments to put on the message. These can
|
||||||
|
be either ``email.MIMEBase.MIMEBase`` instances, or ``(filename,
|
||||||
|
content, mimetype)`` triples.
|
||||||
|
|
||||||
|
* ``headers``: A dictionary of extra headers to put on the message. The
|
||||||
|
keys are the header name, values are the header values. It's up to the
|
||||||
|
caller to ensure header names and values are in the correct format for
|
||||||
|
an e-mail message.
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
email = EmailMessage('Hello', 'Body goes here', 'from@example.com',
|
email = EmailMessage('Hello', 'Body goes here', 'from@example.com',
|
||||||
['to1@example.com', 'to2@example.com'],
|
['to1@example.com', 'to2@example.com'], ['bcc@example.com'],
|
||||||
['bcc@example.com'])
|
headers = {'Reply-To': 'another@example.com'})
|
||||||
|
|
||||||
The class has the following methods:
|
The class has the following methods:
|
||||||
|
|
||||||
@ -227,18 +258,83 @@ The class has the following methods:
|
|||||||
if none already exists.
|
if none already exists.
|
||||||
|
|
||||||
* ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a
|
* ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a
|
||||||
sub-class of Python's ``email.MIMEText.MIMEText`` class) holding the
|
subclass of Python's ``email.MIMEText.MIMEText`` class) or a
|
||||||
message to be sent. If you ever need to extend the `EmailMessage` class,
|
``django.core.mail.SafeMIMEMultipart`` object holding the
|
||||||
you'll probably want to override this method to put the content you wish
|
message to be sent. If you ever need to extend the ``EmailMessage`` class,
|
||||||
|
you'll probably want to override this method to put the content you want
|
||||||
into the MIME object.
|
into the MIME object.
|
||||||
|
|
||||||
* ``recipients()`` returns a list of all the recipients of the message,
|
* ``recipients()`` returns a list of all the recipients of the message,
|
||||||
whether they're recorded in the ``to`` or ``bcc`` attributes. This is
|
whether they're recorded in the ``to`` or ``bcc`` attributes. This is
|
||||||
another method you might need to override when sub-classing, because the
|
another method you might need to override when subclassing, because the
|
||||||
SMTP server needs to be told the full list of recipients when the message
|
SMTP server needs to be told the full list of recipients when the message
|
||||||
is sent. If you add another way to specify recipients in your class, they
|
is sent. If you add another way to specify recipients in your class, they
|
||||||
need to be returned from this method as well.
|
need to be returned from this method as well.
|
||||||
|
|
||||||
|
* ``attach()`` creates a new file attachment and adds it to the message.
|
||||||
|
There are two ways to call ``attach()``:
|
||||||
|
|
||||||
|
* You can pass it a single argument that is an
|
||||||
|
``email.MIMBase.MIMEBase`` instance. This will be inserted directly
|
||||||
|
into the resulting message.
|
||||||
|
|
||||||
|
* Alternatively, you can pass ``attach()`` three arguments:
|
||||||
|
``filename``, ``content`` and ``mimetype``. ``filename`` is the name
|
||||||
|
of the file attachment as it will appear in the e-mail, ``content`` is
|
||||||
|
the data that will be contained inside the attachment and
|
||||||
|
``mimetype`` is the optional MIME type for the attachment. If you
|
||||||
|
omit ``mimetype``, the MIME content type will be guessed from the
|
||||||
|
filename of the attachment.
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
message.attach('design.png', img_data, 'image/png')
|
||||||
|
|
||||||
|
* ``attach_file()`` creates a new attachment using a file from your
|
||||||
|
filesystem. Call it with the path of the file to attach and, optionally,
|
||||||
|
the MIME type to use for the attachment. If the MIME type is omitted, it
|
||||||
|
will be guessed from the filename. The simplest use would be::
|
||||||
|
|
||||||
|
message.attach_file('/images/weather_map.png')
|
||||||
|
|
||||||
|
Sending alternative content types
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
It can be useful to include multiple versions of the content in an e-mail;
|
||||||
|
the classic example is to send both text and HTML versions of a message. With
|
||||||
|
Django's e-mail library, you can do this using the ``EmailMultiAlternatives``
|
||||||
|
class. This subclass of ``EmailMessage`` has an ``attach_alternative()`` method
|
||||||
|
for including extra versions of the message body in the e-mail. All the other
|
||||||
|
methods (including the class initialization) are inherited directly from
|
||||||
|
``EmailMessage``.
|
||||||
|
|
||||||
|
To send a text and HTML combination, you could write::
|
||||||
|
|
||||||
|
from django.core.mail import EmailMultiAlternatives
|
||||||
|
|
||||||
|
subject, from_email, to = 'hello', 'from@example.com', 'to@example.com'
|
||||||
|
text_content = 'This is an important message.'
|
||||||
|
html_content = '<p>This is an <strong>important</strong> message.'
|
||||||
|
msg = EmailMultiAlternatives(subject, text_content, from_email, to)
|
||||||
|
msg.attach_alternative(html_content, "text/html")
|
||||||
|
msg.send()
|
||||||
|
|
||||||
|
By default, the MIME type of the ``body`` parameter in an ``EmailMessage`` is
|
||||||
|
``"text/plain"``. It is good practice to leave this alone, because it
|
||||||
|
guarantees that any recipient will be able to read the e-mail, regardless of
|
||||||
|
their mail client. However, if you are confident that your recipients can
|
||||||
|
handle an alternative content type, you can use the ``content_subtype``
|
||||||
|
attribute on the ``EmailMessage`` class to change the main content type. The
|
||||||
|
major type will always be ``"text"``, but you can change it to the subtype. For
|
||||||
|
example::
|
||||||
|
|
||||||
|
msg = EmailMessage(subject, html_content, from_email, to)
|
||||||
|
msg.content_subtype = "html" # Main content is now text/html
|
||||||
|
msg.send()
|
||||||
|
|
||||||
|
SMTP network connections
|
||||||
|
------------------------
|
||||||
|
|
||||||
The ``SMTPConnection`` class is initialized with the host, port, username and
|
The ``SMTPConnection`` class is initialized with the host, port, username and
|
||||||
password for the SMTP server. If you don't specify one or more of those
|
password for the SMTP server. If you don't specify one or more of those
|
||||||
options, they are read from your settings file.
|
options, they are read from your settings file.
|
||||||
|
@ -104,7 +104,7 @@ Lawrence, Kansas, USA.
|
|||||||
|
|
||||||
`Wilson Miner`_
|
`Wilson Miner`_
|
||||||
Wilson's design-fu makes us all look like rock stars. By day, he's an
|
Wilson's design-fu makes us all look like rock stars. By day, he's an
|
||||||
interactive designer for `Apple`. Don't ask him what he's working on, or
|
interactive designer for `Apple`_. Don't ask him what he's working on, or
|
||||||
he'll have to kill you. He lives in San Francisco.
|
he'll have to kill you. He lives in San Francisco.
|
||||||
|
|
||||||
On IRC, Wilson goes by ``wilsonian``.
|
On IRC, Wilson goes by ``wilsonian``.
|
||||||
@ -301,7 +301,7 @@ means it can run on a variety of server platforms.
|
|||||||
|
|
||||||
If you want to use Django with a database, which is probably the case, you'll
|
If you want to use Django with a database, which is probably the case, you'll
|
||||||
also need a database engine. PostgreSQL_ is recommended, because we're
|
also need a database engine. PostgreSQL_ is recommended, because we're
|
||||||
PostgreSQL fans, and MySQL_ and `SQLite 3`_ are also supported.
|
PostgreSQL fans, and MySQL_, `SQLite 3`_, and Oracle_ are also supported.
|
||||||
|
|
||||||
.. _Python: http://www.python.org/
|
.. _Python: http://www.python.org/
|
||||||
.. _Apache 2: http://httpd.apache.org/
|
.. _Apache 2: http://httpd.apache.org/
|
||||||
@ -310,6 +310,7 @@ PostgreSQL fans, and MySQL_ and `SQLite 3`_ are also supported.
|
|||||||
.. _PostgreSQL: http://www.postgresql.org/
|
.. _PostgreSQL: http://www.postgresql.org/
|
||||||
.. _MySQL: http://www.mysql.com/
|
.. _MySQL: http://www.mysql.com/
|
||||||
.. _`SQLite 3`: http://www.sqlite.org/
|
.. _`SQLite 3`: http://www.sqlite.org/
|
||||||
|
.. _Oracle: http://www.oracle.com/
|
||||||
|
|
||||||
Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5?
|
Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5?
|
||||||
----------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------
|
||||||
|
@ -754,10 +754,10 @@ If the results are paginated, the context will contain these extra variables:
|
|||||||
|
|
||||||
* ``previous``: The previous page number, as an integer. This is 1-based.
|
* ``previous``: The previous page number, as an integer. This is 1-based.
|
||||||
|
|
||||||
* `last_on_page`: The number of the
|
* ``last_on_page``: The number of the
|
||||||
last result on the current page. This is 1-based.
|
last result on the current page. This is 1-based.
|
||||||
|
|
||||||
* `first_on_page`: The number of the
|
* ``first_on_page``: The number of the
|
||||||
first result on the current page. This is 1-based.
|
first result on the current page. This is 1-based.
|
||||||
|
|
||||||
* ``pages``: The total number of pages, as an integer.
|
* ``pages``: The total number of pages, as an integer.
|
||||||
|
@ -17,8 +17,10 @@ probably already have it installed.
|
|||||||
Install Apache and mod_python
|
Install Apache and mod_python
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
If you just want to experiment with Django, skip this step. Django comes with
|
If you just want to experiment with Django, skip ahead to the next
|
||||||
its own Web server for development purposes.
|
section; Django includes a lightweight web server you can use for
|
||||||
|
testing, so you won't need to set up Apache until you're ready to
|
||||||
|
deploy Django in production.
|
||||||
|
|
||||||
If you want to use Django on a production site, use Apache with `mod_python`_.
|
If you want to use Django on a production site, use Apache with `mod_python`_.
|
||||||
mod_python is similar to mod_perl -- it embeds Python within Apache and loads
|
mod_python is similar to mod_perl -- it embeds Python within Apache and loads
|
||||||
@ -46,7 +48,8 @@ Get your database running
|
|||||||
|
|
||||||
If you plan to use Django's database API functionality, you'll need to
|
If you plan to use Django's database API functionality, you'll need to
|
||||||
make sure a database server is running. Django works with PostgreSQL_,
|
make sure a database server is running. Django works with PostgreSQL_,
|
||||||
MySQL_ and SQLite_.
|
MySQL_, Oracle_ and SQLite_ (the latter doesn't require a separate server to
|
||||||
|
be running).
|
||||||
|
|
||||||
Additionally, you'll need to make sure your Python database bindings are
|
Additionally, you'll need to make sure your Python database bindings are
|
||||||
installed.
|
installed.
|
||||||
@ -62,6 +65,8 @@ installed.
|
|||||||
|
|
||||||
* If you're using SQLite, you'll need pysqlite_. Use version 2.0.3 or higher.
|
* If you're using SQLite, you'll need pysqlite_. Use version 2.0.3 or higher.
|
||||||
|
|
||||||
|
* If you're using Oracle, you'll need cx_Oracle_, version 4.3.1 or higher.
|
||||||
|
|
||||||
.. _PostgreSQL: http://www.postgresql.org/
|
.. _PostgreSQL: http://www.postgresql.org/
|
||||||
.. _MySQL: http://www.mysql.com/
|
.. _MySQL: http://www.mysql.com/
|
||||||
.. _Django's ticket system: http://code.djangoproject.com/report/1
|
.. _Django's ticket system: http://code.djangoproject.com/report/1
|
||||||
@ -71,6 +76,8 @@ installed.
|
|||||||
.. _SQLite: http://www.sqlite.org/
|
.. _SQLite: http://www.sqlite.org/
|
||||||
.. _pysqlite: http://initd.org/tracker/pysqlite
|
.. _pysqlite: http://initd.org/tracker/pysqlite
|
||||||
.. _MySQL backend: ../databases/
|
.. _MySQL backend: ../databases/
|
||||||
|
.. _cx_Oracle: http://www.python.net/crew/atuining/cx_Oracle/
|
||||||
|
.. _Oracle: http://www.oracle.com/
|
||||||
|
|
||||||
Remove any old versions of Django
|
Remove any old versions of Django
|
||||||
=================================
|
=================================
|
||||||
@ -83,23 +90,20 @@ If you installed Django using ``setup.py install``, uninstalling
|
|||||||
is as simple as deleting the ``django`` directory from your Python
|
is as simple as deleting the ``django`` directory from your Python
|
||||||
``site-packages``.
|
``site-packages``.
|
||||||
|
|
||||||
If you installed Django from a Python Egg, remove the Django ``.egg`` file,
|
If you installed Django from a Python egg, remove the Django ``.egg`` file,
|
||||||
and remove the reference to the egg in the file named ``easy-install.pth``.
|
and remove the reference to the egg in the file named ``easy-install.pth``.
|
||||||
This file should also be located in your ``site-packages`` directory.
|
This file should also be located in your ``site-packages`` directory.
|
||||||
|
|
||||||
.. admonition:: Where are my ``site-packages`` stored?
|
.. admonition:: Where are my ``site-packages`` stored?
|
||||||
|
|
||||||
The location of the ``site-packages`` directory depends on the operating
|
The location of the ``site-packages`` directory depends on the operating
|
||||||
system, and the location in which Python was installed. However, the
|
system, and the location in which Python was installed. To find out your
|
||||||
following locations are common:
|
system's ``site-packages`` location, execute the following::
|
||||||
|
|
||||||
* If you're using Linux: ``/usr/lib/python2.X/site-packages``
|
python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"
|
||||||
|
|
||||||
* If you're using Windows: ``C:\Python2.X\lib\site-packages``
|
(Note that this should be run from a shell prompt, not a Python interactive
|
||||||
|
prompt.)
|
||||||
* If you're using MacOSX: ``/Library/Python2.X/site-packages`` or
|
|
||||||
``/Library/Frameworks/Python.framework/Versions/2.X/lib/python2.X/site-packages/``
|
|
||||||
(in later releases).
|
|
||||||
|
|
||||||
Install the Django code
|
Install the Django code
|
||||||
=======================
|
=======================
|
||||||
@ -138,12 +142,15 @@ latest bug fixes and improvements, follow these instructions:
|
|||||||
|
|
||||||
1. Make sure you have Subversion_ installed.
|
1. Make sure you have Subversion_ installed.
|
||||||
2. Check out the Django code into your Python ``site-packages`` directory.
|
2. Check out the Django code into your Python ``site-packages`` directory.
|
||||||
|
|
||||||
On Linux / Mac OSX / Unix, do this::
|
On Linux / Mac OSX / Unix, do this::
|
||||||
|
|
||||||
svn co http://code.djangoproject.com/svn/django/trunk/ django_src
|
svn co http://code.djangoproject.com/svn/django/trunk/ django_src
|
||||||
ln -s `pwd`/django_src/django /usr/lib/python2.3/site-packages/django
|
ln -s `pwd`/django_src/django SITE-PACKAGES-DIR/django
|
||||||
|
|
||||||
(In the above line, change ``python2.3`` to match your current Python version.)
|
(In the above line, change ``SITE-PACKAGES-DIR`` to match the location of
|
||||||
|
your system's ``site-packages`` directory, as explained in the
|
||||||
|
"Where are my ``site-packages`` stored?" section above.)
|
||||||
|
|
||||||
On Windows, do this::
|
On Windows, do this::
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ You'll need to tell Django what your database connection parameters are, and
|
|||||||
what the name of the database is. Do that by editing these settings in your
|
what the name of the database is. Do that by editing these settings in your
|
||||||
`settings file`_:
|
`settings file`_:
|
||||||
|
|
||||||
* `DATABASE_NAME`
|
* `DATABASE_NAME`_
|
||||||
* `DATABASE_ENGINE`_
|
* `DATABASE_ENGINE`_
|
||||||
* `DATABASE_USER`_
|
* `DATABASE_USER`_
|
||||||
* `DATABASE_PASSWORD`_
|
* `DATABASE_PASSWORD`_
|
||||||
|
@ -492,6 +492,11 @@ has ``null=True``, that means it has two possible values for "no data":
|
|||||||
possible values for "no data;" Django convention is to use the empty
|
possible values for "no data;" Django convention is to use the empty
|
||||||
string, not ``NULL``.
|
string, not ``NULL``.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
When using the Oracle database backend, the ``null=True`` option will
|
||||||
|
be coerced for string-based fields that can blank, and the value
|
||||||
|
``NULL`` will be stored to denote the empty string.
|
||||||
|
|
||||||
``blank``
|
``blank``
|
||||||
~~~~~~~~~
|
~~~~~~~~~
|
||||||
|
|
||||||
@ -586,6 +591,16 @@ scenes.
|
|||||||
If ``True``, ``django-admin.py sqlindexes`` will output a ``CREATE INDEX``
|
If ``True``, ``django-admin.py sqlindexes`` will output a ``CREATE INDEX``
|
||||||
statement for this field.
|
statement for this field.
|
||||||
|
|
||||||
|
``db_tablespace``
|
||||||
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
The name of the database tablespace to use for this field's index, if
|
||||||
|
indeed this field is indexed. The default is the ``db_tablespace`` of
|
||||||
|
the model, if any. If the backend doesn't support tablespaces, this
|
||||||
|
option is ignored.
|
||||||
|
|
||||||
``default``
|
``default``
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
@ -996,6 +1011,14 @@ If your database table name is an SQL reserved word, or contains characters
|
|||||||
that aren't allowed in Python variable names -- notably, the hyphen --
|
that aren't allowed in Python variable names -- notably, the hyphen --
|
||||||
that's OK. Django quotes column and table names behind the scenes.
|
that's OK. Django quotes column and table names behind the scenes.
|
||||||
|
|
||||||
|
``db_tablespace``
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
**New in Django development version**
|
||||||
|
|
||||||
|
The name of the database tablespace to use for the model. If the backend
|
||||||
|
doesn't support tablespaces, this option is ignored.
|
||||||
|
|
||||||
``get_latest_by``
|
``get_latest_by``
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -1876,11 +1899,11 @@ used by the SQLite Python bindings. This is for the sake of consistency and
|
|||||||
sanity.)
|
sanity.)
|
||||||
|
|
||||||
A final note: If all you want to do is a custom ``WHERE`` clause, you can just
|
A final note: If all you want to do is a custom ``WHERE`` clause, you can just
|
||||||
just the ``where``, ``tables`` and ``params`` arguments to the standard lookup
|
use the ``where``, ``tables`` and ``params`` arguments to the standard lookup
|
||||||
API. See `Other lookup options`_.
|
API. See `Other lookup options`_.
|
||||||
|
|
||||||
.. _Python DB-API: http://www.python.org/peps/pep-0249.html
|
.. _Python DB-API: http://www.python.org/peps/pep-0249.html
|
||||||
.. _Other lookup options: ../db-api/#extra-params-select-where-tables
|
.. _Other lookup options: ../db-api/#extra-select-none-where-none-params-none-tables-none
|
||||||
.. _transaction handling: ../transactions/
|
.. _transaction handling: ../transactions/
|
||||||
|
|
||||||
Overriding default model methods
|
Overriding default model methods
|
||||||
|
@ -110,7 +110,7 @@ shortly.
|
|||||||
Creating ``Form`` instances
|
Creating ``Form`` instances
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
A ``Form`` instance is either **bound** or **unbound** to a set of data.
|
A ``Form`` instance is either **bound** to a set of data, or **unbound**.
|
||||||
|
|
||||||
* If it's **bound** to a set of data, it's capable of validating that data
|
* If it's **bound** to a set of data, it's capable of validating that data
|
||||||
and rendering the form as HTML with the data displayed in the HTML.
|
and rendering the form as HTML with the data displayed in the HTML.
|
||||||
|
@ -28,7 +28,7 @@ The following changes may require you to update your code when you switch from
|
|||||||
|
|
||||||
Due to a bug in older versions of the ``MySQLdb`` Python module (which
|
Due to a bug in older versions of the ``MySQLdb`` Python module (which
|
||||||
Django uses to connect to MySQL databases), Django's MySQL backend now
|
Django uses to connect to MySQL databases), Django's MySQL backend now
|
||||||
requires version 1.2.1p2 or higher of `MySQLdb`, and will raise
|
requires version 1.2.1p2 or higher of ``MySQLdb``, and will raise
|
||||||
exceptions if you attempt to use an older version.
|
exceptions if you attempt to use an older version.
|
||||||
|
|
||||||
If you're currently unable to upgrade your copy of ``MySQLdb`` to meet
|
If you're currently unable to upgrade your copy of ``MySQLdb`` to meet
|
||||||
|
@ -48,12 +48,12 @@ Subset of fields
|
|||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
If you only want a subset of fields to be serialized, you can
|
If you only want a subset of fields to be serialized, you can
|
||||||
specify a `fields` argument to the serializer::
|
specify a ``fields`` argument to the serializer::
|
||||||
|
|
||||||
from django.core import serializers
|
from django.core import serializers
|
||||||
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))
|
data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))
|
||||||
|
|
||||||
In this example, only the `name` and `size` attributes of each model will
|
In this example, only the ``name`` and ``size`` attributes of each model will
|
||||||
be serialized.
|
be serialized.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -244,9 +244,9 @@ DATABASE_ENGINE
|
|||||||
|
|
||||||
Default: ``''`` (Empty string)
|
Default: ``''`` (Empty string)
|
||||||
|
|
||||||
Which database backend to use. Either ``'postgresql_psycopg2'``,
|
The database backend to use. Either ``'postgresql_psycopg2'``,
|
||||||
``'postgresql'``, ``'mysql'``, ``'mysql_old'``, ``'sqlite3'`` or
|
``'postgresql'``, ``'mysql'``, ``'mysql_old'``, ``'sqlite3'``,
|
||||||
``'ado_mssql'``.
|
``'oracle'``, or ``'ado_mssql'``.
|
||||||
|
|
||||||
DATABASE_HOST
|
DATABASE_HOST
|
||||||
-------------
|
-------------
|
||||||
|
@ -1266,7 +1266,8 @@ Converts URLs in plain text into clickable links.
|
|||||||
urlizetrunc
|
urlizetrunc
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
Converts URLs into clickable links, truncating URLs to the given character limit.
|
Converts URLs into clickable links, truncating URLs longer than the given
|
||||||
|
character limit.
|
||||||
|
|
||||||
**Argument:** Length to truncate URLs to
|
**Argument:** Length to truncate URLs to
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
|
|||||||
|
|
||||||
* ``user`` -- An ``auth.User`` instance representing the currently
|
* ``user`` -- An ``auth.User`` instance representing the currently
|
||||||
logged-in user (or an ``AnonymousUser`` instance, if the client isn't
|
logged-in user (or an ``AnonymousUser`` instance, if the client isn't
|
||||||
logged in). See the `user authentication docs`.
|
logged in). See the `user authentication docs`_.
|
||||||
|
|
||||||
* ``messages`` -- A list of messages (as strings) for the currently
|
* ``messages`` -- A list of messages (as strings) for the currently
|
||||||
logged-in user. Behind the scenes, this calls
|
logged-in user. Behind the scenes, this calls
|
||||||
|
@ -253,8 +253,8 @@ can be invoked on the ``Client`` instance.
|
|||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
will result in the evaluation of a POST request on ``/customers/wishes/``,
|
will result in the evaluation of a POST request on ``/customers/wishes/``,
|
||||||
with a POST dictionary that contains `name`, `attachment` (containing the
|
with a POST dictionary that contains ``name``, ``attachment`` (containing the
|
||||||
file name), and `attachment_file` (containing the file data). Note that you
|
file name), and ``attachment_file`` (containing the file data). Note that you
|
||||||
need to manually close the file after it has been provided to the POST.
|
need to manually close the file after it has been provided to the POST.
|
||||||
|
|
||||||
``login(**credentials)``
|
``login(**credentials)``
|
||||||
@ -660,8 +660,8 @@ arguments:
|
|||||||
tested. This is the same format returned by ``django.db.models.get_apps()``
|
tested. This is the same format returned by ``django.db.models.get_apps()``
|
||||||
|
|
||||||
Verbosity determines the amount of notification and debug information that
|
Verbosity determines the amount of notification and debug information that
|
||||||
will be printed to the console; `0` is no output, `1` is normal output,
|
will be printed to the console; ``0`` is no output, ``1`` is normal output,
|
||||||
and `2` is verbose output.
|
and ``2`` is verbose output.
|
||||||
|
|
||||||
This method should return the number of tests that failed.
|
This method should return the number of tests that failed.
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ poll application.
|
|||||||
It'll consist of two parts:
|
It'll consist of two parts:
|
||||||
|
|
||||||
* A public site that lets people view polls and vote in them.
|
* A public site that lets people view polls and vote in them.
|
||||||
* An admin site that lets you add, change and delete poll.
|
* An admin site that lets you add, change and delete polls.
|
||||||
|
|
||||||
We'll assume you have `Django installed`_ already. You can tell Django is
|
We'll assume you have `Django installed`_ already. You can tell Django is
|
||||||
installed by running the Python interactive interpreter and typing
|
installed by running the Python interactive interpreter and typing
|
||||||
@ -360,7 +360,7 @@ Note the following:
|
|||||||
quotes. The author of this tutorial runs PostgreSQL, so the example
|
quotes. The author of this tutorial runs PostgreSQL, so the example
|
||||||
output is in PostgreSQL syntax.
|
output is in PostgreSQL syntax.
|
||||||
|
|
||||||
* The `sql` command doesn't actually run the SQL in your database - it just
|
* The ``sql`` command doesn't actually run the SQL in your database - it just
|
||||||
prints it to the screen so that you can see what SQL Django thinks is required.
|
prints it to the screen so that you can see what SQL Django thinks is required.
|
||||||
If you wanted to, you could copy and paste this SQL into your database prompt.
|
If you wanted to, you could copy and paste this SQL into your database prompt.
|
||||||
However, as we will see shortly, Django provides an easier way of committing
|
However, as we will see shortly, Django provides an easier way of committing
|
||||||
|
@ -251,4 +251,98 @@ Traceback (most recent call last):
|
|||||||
...
|
...
|
||||||
TypeError: Cannot resolve keyword 'headline__starts' into field. Choices are: id, headline, pub_date
|
TypeError: Cannot resolve keyword 'headline__starts' into field. Choices are: id, headline, pub_date
|
||||||
|
|
||||||
|
# Create some articles with a bit more interesting headlines for testing field lookups:
|
||||||
|
>>> now = datetime.now()
|
||||||
|
>>> for a in Article.objects.all():
|
||||||
|
... a.delete()
|
||||||
|
>>> a1 = Article(pub_date=now, headline='f')
|
||||||
|
>>> a1.save()
|
||||||
|
>>> a2 = Article(pub_date=now, headline='fo')
|
||||||
|
>>> a2.save()
|
||||||
|
>>> a3 = Article(pub_date=now, headline='foo')
|
||||||
|
>>> a3.save()
|
||||||
|
>>> a4 = Article(pub_date=now, headline='fooo')
|
||||||
|
>>> a4.save()
|
||||||
|
>>> a5 = Article(pub_date=now, headline='Foo')
|
||||||
|
>>> a5.save()
|
||||||
|
|
||||||
|
# zero-or-more
|
||||||
|
>>> Article.objects.filter(headline__regex=r'fo*')
|
||||||
|
[<Article: f>, <Article: fo>, <Article: foo>, <Article: fooo>]
|
||||||
|
>>> Article.objects.filter(headline__iregex=r'fo*')
|
||||||
|
[<Article: Foo>, <Article: f>, <Article: fo>, <Article: foo>, <Article: fooo>]
|
||||||
|
|
||||||
|
# one-or-more
|
||||||
|
>>> Article.objects.filter(headline__regex=r'fo+')
|
||||||
|
[<Article: fo>, <Article: foo>, <Article: fooo>]
|
||||||
|
|
||||||
|
# wildcard
|
||||||
|
>>> Article.objects.filter(headline__regex=r'fooo?')
|
||||||
|
[<Article: foo>, <Article: fooo>]
|
||||||
|
|
||||||
|
# and some more:
|
||||||
|
>>> a6 = Article(pub_date=now, headline='bar')
|
||||||
|
>>> a6.save()
|
||||||
|
>>> a7 = Article(pub_date=now, headline='Bar')
|
||||||
|
>>> a7.save()
|
||||||
|
>>> a8 = Article(pub_date=now, headline='baz')
|
||||||
|
>>> a8.save()
|
||||||
|
>>> a9 = Article(pub_date=now, headline='baZ')
|
||||||
|
>>> a9.save()
|
||||||
|
|
||||||
|
# leading anchor
|
||||||
|
>>> Article.objects.filter(headline__regex=r'^b')
|
||||||
|
[<Article: baZ>, <Article: bar>, <Article: baz>]
|
||||||
|
>>> Article.objects.filter(headline__iregex=r'^b')
|
||||||
|
[<Article: Bar>, <Article: baZ>, <Article: bar>, <Article: baz>]
|
||||||
|
|
||||||
|
# trailing anchor
|
||||||
|
>>> Article.objects.filter(headline__regex=r'z$')
|
||||||
|
[<Article: baz>]
|
||||||
|
>>> Article.objects.filter(headline__iregex=r'z$')
|
||||||
|
[<Article: baZ>, <Article: baz>]
|
||||||
|
|
||||||
|
# character sets
|
||||||
|
>>> Article.objects.filter(headline__regex=r'ba[rz]')
|
||||||
|
[<Article: bar>, <Article: baz>]
|
||||||
|
>>> Article.objects.filter(headline__regex=r'ba[RZ]')
|
||||||
|
[<Article: baZ>]
|
||||||
|
>>> Article.objects.filter(headline__iregex=r'ba[RZ]')
|
||||||
|
[<Article: Bar>, <Article: baZ>, <Article: bar>, <Article: baz>]
|
||||||
|
|
||||||
|
# and yet more:
|
||||||
|
>>> a10 = Article(pub_date=now, headline='foobar')
|
||||||
|
>>> a10.save()
|
||||||
|
>>> a11 = Article(pub_date=now, headline='foobaz')
|
||||||
|
>>> a11.save()
|
||||||
|
>>> a12 = Article(pub_date=now, headline='FooBarBaz')
|
||||||
|
>>> a12.save()
|
||||||
|
>>> a13 = Article(pub_date=now, headline='foobarbaz')
|
||||||
|
>>> a13.save()
|
||||||
|
>>> a14 = Article(pub_date=now, headline='zoocarfaz')
|
||||||
|
>>> a14.save()
|
||||||
|
>>> a15 = Article(pub_date=now, headline='barfoobaz')
|
||||||
|
>>> a15.save()
|
||||||
|
>>> a16 = Article(pub_date=now, headline='BAZBARFOO')
|
||||||
|
>>> a16.save()
|
||||||
|
|
||||||
|
# alternation
|
||||||
|
>>> Article.objects.filter(headline__regex=r'foo(bar|baz)')
|
||||||
|
[<Article: barfoobaz>, <Article: foobar>, <Article: foobarbaz>, <Article: foobaz>]
|
||||||
|
>>> Article.objects.filter(headline__iregex=r'foo(bar|baz)')
|
||||||
|
[<Article: FooBarBaz>, <Article: barfoobaz>, <Article: foobar>, <Article: foobarbaz>, <Article: foobaz>]
|
||||||
|
>>> Article.objects.filter(headline__regex=r'^foo(bar|baz)')
|
||||||
|
[<Article: foobar>, <Article: foobarbaz>, <Article: foobaz>]
|
||||||
|
|
||||||
|
# greedy matching
|
||||||
|
>>> Article.objects.filter(headline__regex=r'f.*z')
|
||||||
|
[<Article: barfoobaz>, <Article: foobarbaz>, <Article: foobaz>, <Article: zoocarfaz>]
|
||||||
|
>>> Article.objects.filter(headline__iregex=r'f.*z')
|
||||||
|
[<Article: FooBarBaz>, <Article: barfoobaz>, <Article: foobarbaz>, <Article: foobaz>, <Article: zoocarfaz>]
|
||||||
|
|
||||||
|
# grouping and backreferences
|
||||||
|
>>> Article.objects.filter(headline__regex=r'b(.).*b\1')
|
||||||
|
[<Article: barfoobaz>, <Article: foobarbaz>]
|
||||||
|
>>> Article.objects.filter(headline__iregex=r'b(.).*b\1')
|
||||||
|
[<Article: BAZBARFOO>, <Article: FooBarBaz>, <Article: barfoobaz>, <Article: foobarbaz>]
|
||||||
"""}
|
"""}
|
||||||
|
0
tests/regressiontests/datatypes/__init__.py
Normal file
0
tests/regressiontests/datatypes/__init__.py
Normal file
59
tests/regressiontests/datatypes/models.py
Normal file
59
tests/regressiontests/datatypes/models.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
This is a basic model to test saving and loading boolean and date-related
|
||||||
|
types, which in the past were problematic for some database backends.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
class Donut(models.Model):
|
||||||
|
name = models.CharField(maxlength=100)
|
||||||
|
is_frosted = models.BooleanField(default=False)
|
||||||
|
has_sprinkles = models.NullBooleanField()
|
||||||
|
baked_date = models.DateField(null=True)
|
||||||
|
baked_time = models.TimeField(null=True)
|
||||||
|
consumed_at = models.DateTimeField(null=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ('consumed_at',)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
__test__ = {'API_TESTS': """
|
||||||
|
# No donuts are in the system yet.
|
||||||
|
>>> Donut.objects.all()
|
||||||
|
[]
|
||||||
|
|
||||||
|
>>> d = Donut(name='Apple Fritter')
|
||||||
|
|
||||||
|
# Ensure we're getting True and False, not 0 and 1
|
||||||
|
>>> d.is_frosted
|
||||||
|
False
|
||||||
|
>>> d.has_sprinkles
|
||||||
|
>>> d.has_sprinkles = True
|
||||||
|
>>> d.has_sprinkles == True
|
||||||
|
True
|
||||||
|
>>> d.save()
|
||||||
|
>>> d2 = Donut.objects.all()[0]
|
||||||
|
>>> d2
|
||||||
|
<Donut: Apple Fritter>
|
||||||
|
>>> d2.is_frosted == False
|
||||||
|
True
|
||||||
|
>>> d2.has_sprinkles == True
|
||||||
|
True
|
||||||
|
|
||||||
|
>>> import datetime
|
||||||
|
>>> d2.baked_date = datetime.date(year=1938, month=6, day=4)
|
||||||
|
>>> d2.baked_time = datetime.time(hour=5, minute=30)
|
||||||
|
>>> d2.consumed_at = datetime.datetime(year=2007, month=4, day=20, hour=16, minute=19, second=59)
|
||||||
|
>>> d2.save()
|
||||||
|
|
||||||
|
>>> d3 = Donut.objects.all()[0]
|
||||||
|
>>> d3.baked_date
|
||||||
|
datetime.date(1938, 6, 4)
|
||||||
|
>>> d3.baked_time
|
||||||
|
datetime.time(5, 30)
|
||||||
|
>>> d3.consumed_at
|
||||||
|
datetime.datetime(2007, 4, 20, 16, 19, 59)
|
||||||
|
"""}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user