mirror of
https://github.com/django/django.git
synced 2025-07-04 01:39:20 +00:00
gis: Merged revisions 4669-4785 via svnmerge from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@4786 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
8b279b63be
commit
fa3ed6e134
7
AUTHORS
7
AUTHORS
@ -42,7 +42,6 @@ people who have submitted patches, reported bugs, added translations, helped
|
|||||||
answer newbie questions, and generally made Django that much better:
|
answer newbie questions, and generally made Django that much better:
|
||||||
|
|
||||||
adurdin@gmail.com
|
adurdin@gmail.com
|
||||||
akaihola
|
|
||||||
Andreas
|
Andreas
|
||||||
andy@jadedplanet.net
|
andy@jadedplanet.net
|
||||||
ant9000@netwise.it
|
ant9000@netwise.it
|
||||||
@ -86,10 +85,12 @@ 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
|
||||||
Eric Floehr <eric@intellovations.com>
|
Eric Floehr <eric@intellovations.com>
|
||||||
|
Jorge Gajon <gajon@gajon.org>
|
||||||
gandalf@owca.info
|
gandalf@owca.info
|
||||||
Baishampayan Ghose
|
Baishampayan Ghose
|
||||||
martin.glueck@gmail.com
|
martin.glueck@gmail.com
|
||||||
Simon Greenhill <dev@simon.net.nz>
|
Simon Greenhill <dev@simon.net.nz>
|
||||||
|
Owen Griffiths
|
||||||
Espen Grindhaug <http://grindhaug.org/>
|
Espen Grindhaug <http://grindhaug.org/>
|
||||||
Brian Harring <ferringb@gmail.com>
|
Brian Harring <ferringb@gmail.com>
|
||||||
Brant Harris
|
Brant Harris
|
||||||
@ -107,10 +108,12 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Michael Josephson <http://www.sdjournal.com/>
|
Michael Josephson <http://www.sdjournal.com/>
|
||||||
jpellerin@gmail.com
|
jpellerin@gmail.com
|
||||||
junzhang.jn@gmail.com
|
junzhang.jn@gmail.com
|
||||||
|
Antti Kaihola <http://akaihola.blogspot.com/>
|
||||||
Ben Dean Kawamura <ben.dean.kawamura@gmail.com>
|
Ben Dean Kawamura <ben.dean.kawamura@gmail.com>
|
||||||
Garth Kidd <http://www.deadlybloodyserious.com/>
|
Garth Kidd <http://www.deadlybloodyserious.com/>
|
||||||
kilian <kilian.cavalotti@lip6.fr>
|
kilian <kilian.cavalotti@lip6.fr>
|
||||||
Sune Kirkeby <http://ibofobi.dk/>
|
Sune Kirkeby <http://ibofobi.dk/>
|
||||||
|
Bastian Kleineidam <calvin@debian.org>
|
||||||
Cameron Knight (ckknight)
|
Cameron Knight (ckknight)
|
||||||
Meir Kriheli <http://mksoft.co.il/>
|
Meir Kriheli <http://mksoft.co.il/>
|
||||||
Bruce Kroeze <http://coderseye.com/>
|
Bruce Kroeze <http://coderseye.com/>
|
||||||
@ -130,6 +133,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
masonsimon+django@gmail.com
|
masonsimon+django@gmail.com
|
||||||
Manuzhai
|
Manuzhai
|
||||||
Petar Marić <http://www.petarmaric.com/>
|
Petar Marić <http://www.petarmaric.com/>
|
||||||
|
Nuno Mariz <nmariz@gmail.com>
|
||||||
mark@junklight.com
|
mark@junklight.com
|
||||||
Yasushi Masuda <whosaysni@gmail.com>
|
Yasushi Masuda <whosaysni@gmail.com>
|
||||||
mattycakes@gmail.com
|
mattycakes@gmail.com
|
||||||
@ -148,6 +152,7 @@ answer newbie questions, and generally made Django that much better:
|
|||||||
Neal Norwitz <nnorwitz@google.com>
|
Neal Norwitz <nnorwitz@google.com>
|
||||||
oggie rob <oz.robharvey@gmail.com>
|
oggie rob <oz.robharvey@gmail.com>
|
||||||
Jay Parlar <parlar@gmail.com>
|
Jay Parlar <parlar@gmail.com>
|
||||||
|
pavithran s <pavithran.s@gmail.com>
|
||||||
pgross@thoughtworks.com
|
pgross@thoughtworks.com
|
||||||
phaedo <http://phaedo.cx/>
|
phaedo <http://phaedo.cx/>
|
||||||
phil@produxion.net
|
phil@produxion.net
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import optparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
def compile_messages():
|
def compile_messages(locale=None):
|
||||||
basedir = None
|
basedir = None
|
||||||
|
|
||||||
if os.path.isdir(os.path.join('conf', 'locale')):
|
if os.path.isdir(os.path.join('conf', 'locale')):
|
||||||
@ -14,6 +15,9 @@ def compile_messages():
|
|||||||
print "This script should be run from the Django SVN tree or your project or app tree."
|
print "This script should be run from the Django SVN tree or your project or app tree."
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
if locale is not None:
|
||||||
|
basedir = os.path.join(basedir, locale, 'LC_MESSAGES')
|
||||||
|
|
||||||
for dirpath, dirnames, filenames in os.walk(basedir):
|
for dirpath, dirnames, filenames in os.walk(basedir):
|
||||||
for f in filenames:
|
for f in filenames:
|
||||||
if f.endswith('.po'):
|
if f.endswith('.po'):
|
||||||
@ -32,5 +36,14 @@ def compile_messages():
|
|||||||
cmd = 'msgfmt -o "$djangocompilemo" "$djangocompilepo"'
|
cmd = 'msgfmt -o "$djangocompilemo" "$djangocompilepo"'
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = optparse.OptionParser()
|
||||||
|
parser.add_option('-l', '--locale', dest='locale',
|
||||||
|
help="The locale to process. Default is to process all.")
|
||||||
|
options, args = parser.parse_args()
|
||||||
|
if len(args):
|
||||||
|
parser.error("This program takes no arguments")
|
||||||
|
compile_messages(options.locale)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
compile_messages()
|
main()
|
||||||
|
@ -81,7 +81,7 @@ def make_messages():
|
|||||||
src = pythonize_re.sub('\n#', src)
|
src = pythonize_re.sub('\n#', src)
|
||||||
open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
|
open(os.path.join(dirpath, '%s.py' % file), "wb").write(src)
|
||||||
thefile = '%s.py' % file
|
thefile = '%s.py' % file
|
||||||
cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy -o - "%s"' % (
|
cmd = 'xgettext %s -d %s -L Perl --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy --from-code UTF-8 -o - "%s"' % (
|
||||||
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
|
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
|
||||||
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
|
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
|
||||||
msgs = stdout.read()
|
msgs = stdout.read()
|
||||||
@ -103,7 +103,7 @@ def make_messages():
|
|||||||
open(os.path.join(dirpath, '%s.py' % file), "wb").write(templatize(src))
|
open(os.path.join(dirpath, '%s.py' % file), "wb").write(templatize(src))
|
||||||
thefile = '%s.py' % file
|
thefile = '%s.py' % file
|
||||||
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
|
if verbose: sys.stdout.write('processing file %s in %s\n' % (file, dirpath))
|
||||||
cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy -o - "%s"' % (
|
cmd = 'xgettext %s -d %s -L Python --keyword=gettext_noop --keyword=gettext_lazy --keyword=ngettext_lazy --from-code UTF-8 -o - "%s"' % (
|
||||||
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
|
os.path.exists(potfile) and '--omit-header' or '', domain, os.path.join(dirpath, thefile))
|
||||||
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
|
(stdin, stdout, stderr) = os.popen3(cmd, 'b')
|
||||||
msgs = stdout.read()
|
msgs = stdout.read()
|
||||||
|
@ -61,6 +61,7 @@ LANGUAGES = (
|
|||||||
('nl', gettext_noop('Dutch')),
|
('nl', gettext_noop('Dutch')),
|
||||||
('no', gettext_noop('Norwegian')),
|
('no', gettext_noop('Norwegian')),
|
||||||
('pl', gettext_noop('Polish')),
|
('pl', gettext_noop('Polish')),
|
||||||
|
('pt', gettext_noop('Portugese')),
|
||||||
('pt-br', gettext_noop('Brazilian')),
|
('pt-br', gettext_noop('Brazilian')),
|
||||||
('ro', gettext_noop('Romanian')),
|
('ro', gettext_noop('Romanian')),
|
||||||
('ru', gettext_noop('Russian')),
|
('ru', gettext_noop('Russian')),
|
||||||
@ -69,6 +70,7 @@ LANGUAGES = (
|
|||||||
('sr', gettext_noop('Serbian')),
|
('sr', gettext_noop('Serbian')),
|
||||||
('sv', gettext_noop('Swedish')),
|
('sv', gettext_noop('Swedish')),
|
||||||
('ta', gettext_noop('Tamil')),
|
('ta', gettext_noop('Tamil')),
|
||||||
|
('te', gettext_noop('Telugu')),
|
||||||
('tr', gettext_noop('Turkish')),
|
('tr', gettext_noop('Turkish')),
|
||||||
('uk', gettext_noop('Ukrainian')),
|
('uk', gettext_noop('Ukrainian')),
|
||||||
('zh-cn', gettext_noop('Simplified Chinese')),
|
('zh-cn', gettext_noop('Simplified Chinese')),
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -11,7 +11,7 @@ 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-02-26 20:44+0100\n"
|
"POT-Creation-Date: 2007-02-26 20:44+0100\n"
|
||||||
"PO-Revision-Date: 2007-02-27 20:06+0100\n"
|
"PO-Revision-Date: 2007-03-14 19:29+0100\n"
|
||||||
"Last-Translator: Nicola Larosa <nico@tekNico.net>\n"
|
"Last-Translator: Nicola Larosa <nico@tekNico.net>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@ -523,7 +523,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/auth/forms.py:17 contrib/auth/forms.py:138
|
#: contrib/auth/forms.py:17 contrib/auth/forms.py:138
|
||||||
msgid "The two password fields didn't match."
|
msgid "The two password fields didn't match."
|
||||||
msgstr "I due campi parola chiave non corrispondono."
|
msgstr "I due campi password non corrispondono."
|
||||||
|
|
||||||
#: contrib/auth/forms.py:25
|
#: contrib/auth/forms.py:25
|
||||||
msgid "A user with that username already exists."
|
msgid "A user with that username already exists."
|
||||||
@ -555,7 +555,7 @@ msgstr "Questo indirizzo email non è associato ad alcun account utente. Sei sic
|
|||||||
|
|
||||||
#: contrib/auth/forms.py:117
|
#: contrib/auth/forms.py:117
|
||||||
msgid "The two 'new password' fields didn't match."
|
msgid "The two 'new password' fields didn't match."
|
||||||
msgstr "I due campi 'nuova parola chiave' non corrispondono."
|
msgstr "I due campi 'nuova password' non corrispondono."
|
||||||
|
|
||||||
#: contrib/auth/forms.py:124
|
#: contrib/auth/forms.py:124
|
||||||
msgid "Your old password was entered incorrectly. Please enter it again."
|
msgid "Your old password was entered incorrectly. Please enter it again."
|
||||||
@ -609,13 +609,13 @@ msgstr "indirizzo e-mail"
|
|||||||
|
|
||||||
#: contrib/auth/models.py:94
|
#: contrib/auth/models.py:94
|
||||||
msgid "password"
|
msgid "password"
|
||||||
msgstr "parola chiave"
|
msgstr "password"
|
||||||
|
|
||||||
#: contrib/auth/models.py:94
|
#: contrib/auth/models.py:94
|
||||||
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>."
|
||||||
msgstr "Usare '[algo]$[salt]$[hexdigest]' oppure la maschera di <a href=\"password/\">cambio parola chiave</a>."
|
msgstr "Usare '[algo]$[salt]$[hexdigest]' oppure la maschera di <a href=\"password/\">cambio password</a>."
|
||||||
|
|
||||||
#: contrib/auth/models.py:95
|
#: contrib/auth/models.py:95
|
||||||
msgid "staff status"
|
msgid "staff status"
|
||||||
@ -1040,12 +1040,12 @@ msgstr "Aggiungi utente"
|
|||||||
|
|
||||||
#: contrib/admin/views/auth.py:57
|
#: contrib/admin/views/auth.py:57
|
||||||
msgid "Password changed successfully."
|
msgid "Password changed successfully."
|
||||||
msgstr "La parola chiave è stata cambiata correttamente."
|
msgstr "La password è stata cambiata correttamente."
|
||||||
|
|
||||||
#: contrib/admin/views/auth.py:64
|
#: contrib/admin/views/auth.py:64
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Change password: %s"
|
msgid "Change password: %s"
|
||||||
msgstr "Cambia la parola chiave: %s"
|
msgstr "Cambia la password: %s"
|
||||||
|
|
||||||
#: contrib/admin/templatetags/admin_list.py:247
|
#: contrib/admin/templatetags/admin_list.py:247
|
||||||
msgid "All dates"
|
msgid "All dates"
|
||||||
@ -1088,7 +1088,7 @@ msgstr "Documentazione"
|
|||||||
#: contrib/admin/templates/registration/password_change_form.html:3
|
#: contrib/admin/templates/registration/password_change_form.html:3
|
||||||
#: contrib/admin/templates/registration/password_change_done.html:3
|
#: contrib/admin/templates/registration/password_change_done.html:3
|
||||||
msgid "Change password"
|
msgid "Change password"
|
||||||
msgstr "Cambia la parola chiave"
|
msgstr "Cambia la password"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/delete_confirmation.html:3
|
#: contrib/admin/templates/admin/delete_confirmation.html:3
|
||||||
#: contrib/admin/templates/admin/change_form.html:10
|
#: contrib/admin/templates/admin/change_form.html:10
|
||||||
@ -1335,11 +1335,11 @@ msgstr "Nome utente:"
|
|||||||
#: contrib/admin/templates/admin/login.html:20
|
#: contrib/admin/templates/admin/login.html:20
|
||||||
#: contrib/comments/templates/comments/form.html:8
|
#: contrib/comments/templates/comments/form.html:8
|
||||||
msgid "Password:"
|
msgid "Password:"
|
||||||
msgstr "Parola chiave:"
|
msgstr "Password:"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/login.html:22
|
#: contrib/admin/templates/admin/login.html:22
|
||||||
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
|
msgid "Have you <a href=\"/password_reset/\">forgotten your password</a>?"
|
||||||
msgstr "Hai <a href=\"/password_reset/\">dimenticato la parola chiave</a>?"
|
msgstr "Hai <a href=\"/password_reset/\">dimenticato la password</a>?"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/base.html:25
|
#: contrib/admin/templates/admin/base.html:25
|
||||||
msgid "Welcome,"
|
msgid "Welcome,"
|
||||||
@ -1349,7 +1349,7 @@ msgstr "Benvenuto,"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"First, enter a username and password. Then, you'll be able to edit more user "
|
"First, enter a username and password. Then, you'll be able to edit more user "
|
||||||
"options."
|
"options."
|
||||||
msgstr "Inserire innanzitutto nome utente e parola chiave. Si potrà quindi modificare le altre impostazioni dell'utente."
|
msgstr "Inserire innanzitutto nome utente e password. Si potrà quindi modificare le altre impostazioni dell'utente."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/auth/user/add_form.html:12
|
#: contrib/admin/templates/admin/auth/user/add_form.html:12
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
@ -1358,22 +1358,22 @@ msgstr "Nome utente"
|
|||||||
#: contrib/admin/templates/admin/auth/user/add_form.html:18
|
#: contrib/admin/templates/admin/auth/user/add_form.html:18
|
||||||
#: contrib/admin/templates/admin/auth/user/change_password.html:34
|
#: contrib/admin/templates/admin/auth/user/change_password.html:34
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Parola chiave"
|
msgstr "Password"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/auth/user/add_form.html:23
|
#: contrib/admin/templates/admin/auth/user/add_form.html:23
|
||||||
#: contrib/admin/templates/admin/auth/user/change_password.html:39
|
#: contrib/admin/templates/admin/auth/user/change_password.html:39
|
||||||
msgid "Password (again)"
|
msgid "Password (again)"
|
||||||
msgstr "Parola chiave (di nuovo)"
|
msgstr "Password (di nuovo)"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/auth/user/add_form.html:24
|
#: contrib/admin/templates/admin/auth/user/add_form.html:24
|
||||||
#: contrib/admin/templates/admin/auth/user/change_password.html:40
|
#: contrib/admin/templates/admin/auth/user/change_password.html:40
|
||||||
msgid "Enter the same password as above, for verification."
|
msgid "Enter the same password as above, for verification."
|
||||||
msgstr "Inserire la stessa parola chiave inserita sopra, come verifica."
|
msgstr "Inserire la stessa password inserita sopra, come verifica."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/auth/user/change_password.html:28
|
#: contrib/admin/templates/admin/auth/user/change_password.html:28
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Enter a new password for the user <strong>%(username)s</strong>."
|
msgid "Enter a new password for the user <strong>%(username)s</strong>."
|
||||||
msgstr "Inserire una nuova parola chiave per l'utente <strong>%(username)s</strong>."
|
msgstr "Inserire una nuova password per l'utente <strong>%(username)s</strong>."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
|
#: contrib/admin/templates/admin_doc/bookmarklets.html:3
|
||||||
msgid "Bookmarklets"
|
msgid "Bookmarklets"
|
||||||
@ -1460,13 +1460,13 @@ msgstr "Modifica:"
|
|||||||
#: contrib/admin/templates/registration/password_reset_form.html:10
|
#: contrib/admin/templates/registration/password_reset_form.html:10
|
||||||
#: contrib/admin/templates/registration/password_reset_done.html:4
|
#: contrib/admin/templates/registration/password_reset_done.html:4
|
||||||
msgid "Password reset"
|
msgid "Password reset"
|
||||||
msgstr "Reimposta la parola chiave"
|
msgstr "Reimposta la password"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_form.html:12
|
#: contrib/admin/templates/registration/password_reset_form.html:12
|
||||||
msgid ""
|
msgid ""
|
||||||
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
||||||
"your password and e-mail the new one to you."
|
"your password and e-mail the new one to you."
|
||||||
msgstr "Dimenticata la parola chiave? Inserire il proprio indirizzo e-mail qui sotto: la parola chiave sarà reimpostata, e la nuova ti verrà inviata per e-mail."
|
msgstr "Dimenticata la password? Inserire il proprio indirizzo e-mail qui sotto: la password sarà reimpostata, e la nuova ti verrà inviata per e-mail."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_form.html:16
|
#: contrib/admin/templates/registration/password_reset_form.html:16
|
||||||
msgid "E-mail address:"
|
msgid "E-mail address:"
|
||||||
@ -1474,11 +1474,11 @@ msgstr "Indirizzo e-mail:"
|
|||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_form.html:16
|
#: contrib/admin/templates/registration/password_reset_form.html:16
|
||||||
msgid "Reset my password"
|
msgid "Reset my password"
|
||||||
msgstr "Reimposta la mia parola chiave"
|
msgstr "Reimposta la mia password"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:2
|
#: contrib/admin/templates/registration/password_reset_email.html:2
|
||||||
msgid "You're receiving this e-mail because you requested a password reset"
|
msgid "You're receiving this e-mail because you requested a password reset"
|
||||||
msgstr "Hai ricevuto questa e-mail perché hai chiesto di reimpostare la parola chiave"
|
msgstr "Hai ricevuto questa e-mail perché hai chiesto di reimpostare la password"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:3
|
#: contrib/admin/templates/registration/password_reset_email.html:3
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1488,11 +1488,11 @@ msgstr "per il tuo account utente su %(site_name)s"
|
|||||||
#: contrib/admin/templates/registration/password_reset_email.html:5
|
#: contrib/admin/templates/registration/password_reset_email.html:5
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your new password is: %(new_password)s"
|
msgid "Your new password is: %(new_password)s"
|
||||||
msgstr "La tua nuova parola chiave è: %(new_password)s"
|
msgstr "La tua nuova password è: %(new_password)s"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:7
|
#: contrib/admin/templates/registration/password_reset_email.html:7
|
||||||
msgid "Feel free to change this password by going to this page:"
|
msgid "Feel free to change this password by going to this page:"
|
||||||
msgstr "Puoi liberamente cambiare la tua parola chiave tramite questa pagina:"
|
msgstr "Puoi liberamente cambiare la tua password tramite questa pagina:"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:11
|
#: contrib/admin/templates/registration/password_reset_email.html:11
|
||||||
msgid "Your username, in case you've forgotten:"
|
msgid "Your username, in case you've forgotten:"
|
||||||
@ -1518,51 +1518,51 @@ msgstr "Accedi di nuovo"
|
|||||||
#: contrib/admin/templates/registration/password_reset_done.html:6
|
#: contrib/admin/templates/registration/password_reset_done.html:6
|
||||||
#: contrib/admin/templates/registration/password_reset_done.html:10
|
#: contrib/admin/templates/registration/password_reset_done.html:10
|
||||||
msgid "Password reset successful"
|
msgid "Password reset successful"
|
||||||
msgstr "Parola chiave reimpostata correttamente"
|
msgstr "Password reimpostata correttamente"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_done.html:12
|
#: contrib/admin/templates/registration/password_reset_done.html:12
|
||||||
msgid ""
|
msgid ""
|
||||||
"We've e-mailed a new password to the e-mail address you submitted. You "
|
"We've e-mailed a new password to the e-mail address you submitted. You "
|
||||||
"should be receiving it shortly."
|
"should be receiving it shortly."
|
||||||
msgstr "La nuova parola chiave è stata inviata all'indirizzo e-mail inserito. Arriverà a breve."
|
msgstr "La nuova password è stata inviata all'indirizzo e-mail inserito. Arriverà a breve."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:4
|
#: contrib/admin/templates/registration/password_change_form.html:4
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:6
|
#: contrib/admin/templates/registration/password_change_form.html:6
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:10
|
#: contrib/admin/templates/registration/password_change_form.html:10
|
||||||
#: contrib/admin/templates/registration/password_change_done.html:4
|
#: contrib/admin/templates/registration/password_change_done.html:4
|
||||||
msgid "Password change"
|
msgid "Password change"
|
||||||
msgstr "Cambio di parola chiave"
|
msgstr "Cambio password"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:12
|
#: contrib/admin/templates/registration/password_change_form.html:12
|
||||||
msgid ""
|
msgid ""
|
||||||
"Please enter your old password, for security's sake, and then enter your new "
|
"Please enter your old password, for security's sake, and then enter your new "
|
||||||
"password twice so we can verify you typed it in correctly."
|
"password twice so we can verify you typed it in correctly."
|
||||||
msgstr "Inserire l'attuale parola chiave, per ragioni di sicurezza, e poi la nuova parola chiave due volte, per verificare di averla scritta correttamente."
|
msgstr "Inserire l'attuale password, per ragioni di sicurezza, e poi la nuova password due volte, per verificare di averla scritta correttamente."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:17
|
#: contrib/admin/templates/registration/password_change_form.html:17
|
||||||
msgid "Old password:"
|
msgid "Old password:"
|
||||||
msgstr "Parola chiave attuale:"
|
msgstr "Password attuale:"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:19
|
#: contrib/admin/templates/registration/password_change_form.html:19
|
||||||
msgid "New password:"
|
msgid "New password:"
|
||||||
msgstr "Nuova parola chiave:"
|
msgstr "Nuova password:"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:21
|
#: contrib/admin/templates/registration/password_change_form.html:21
|
||||||
msgid "Confirm password:"
|
msgid "Confirm password:"
|
||||||
msgstr "Confermare la parola chiave:"
|
msgstr "Confermare la password:"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:23
|
#: contrib/admin/templates/registration/password_change_form.html:23
|
||||||
msgid "Change my password"
|
msgid "Change my password"
|
||||||
msgstr "Modifica la mia parola chiave"
|
msgstr "Modifica la mia password"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_done.html:6
|
#: contrib/admin/templates/registration/password_change_done.html:6
|
||||||
#: contrib/admin/templates/registration/password_change_done.html:10
|
#: contrib/admin/templates/registration/password_change_done.html:10
|
||||||
msgid "Password change successful"
|
msgid "Password change successful"
|
||||||
msgstr "Cambio di parola chiave avvenuto correttamente"
|
msgstr "Cambio di password avvenuto correttamente"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_done.html:12
|
#: contrib/admin/templates/registration/password_change_done.html:12
|
||||||
msgid "Your password was changed."
|
msgid "Your password was changed."
|
||||||
msgstr "La parola chiave è stata cambiata."
|
msgstr "La password è stata cambiata."
|
||||||
|
|
||||||
#: contrib/sites/models.py:10
|
#: contrib/sites/models.py:10
|
||||||
msgid "domain name"
|
msgid "domain name"
|
||||||
@ -1905,7 +1905,7 @@ msgstr "Il modulo di commento non fornisce né 'anteprima' né 'invia'"
|
|||||||
|
|
||||||
#: contrib/comments/templates/comments/form.html:8
|
#: contrib/comments/templates/comments/form.html:8
|
||||||
msgid "Forgotten your password?"
|
msgid "Forgotten your password?"
|
||||||
msgstr "Hai dimenticato la parola chiave?"
|
msgstr "Hai dimenticato la password?"
|
||||||
|
|
||||||
#: contrib/comments/templates/comments/form.html:12
|
#: contrib/comments/templates/comments/form.html:12
|
||||||
msgid "Ratings"
|
msgid "Ratings"
|
||||||
|
BIN
django/conf/locale/pl/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/pl/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
112
django/conf/locale/pl/LC_MESSAGES/djangojs.po
Normal file
112
django/conf/locale/pl/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
# translation of djangojs.po to Polish
|
||||||
|
# Copyright (C) 2007 Michal Chruszcz
|
||||||
|
# This file is distributed under the same license as the django package.
|
||||||
|
#
|
||||||
|
# Michal Chruszcz <troll@pld-linux.org>, 2007.
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: 0.1\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
|
||||||
|
"PO-Revision-Date: 2007-03-12 11:42+0100\n"
|
||||||
|
"Last-Translator: Michal Chruszcz <troll@pld-linux.org>\n"
|
||||||
|
"Language-Team: Polish <pl@li.org>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: KBabel 1.11.4\n"
|
||||||
|
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr "Dostępne %s"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr "Wybierz wszystko"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr "Dodaj"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr "Usuń"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr "Wybrano %s"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
#, fuzzy
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr "Zaznacz swój wybór i kliknij "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr "Wyczyść wszystko"
|
||||||
|
|
||||||
|
#: 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 "Styczeń Luty Marzec Kwiecień Maj Czerwiec Lipiec Sierpień Wrzesień Październik Listopad Grudzień"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:27
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr "Niedziela Poniedziałek Wtorek Środa Czwartek Piątek Sobota"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr "N Pn Wt Śr Cz Pt So"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||||
|
msgid "Now"
|
||||||
|
msgstr "Teraz"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr "Zegar"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr "Wybierz czas"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr "Północ"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr "6 rano"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr "Południe"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Anuluj"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Dzisiaj"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr "Kalendarz"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "Wczoraj"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr "Jutro"
|
||||||
|
|
BIN
django/conf/locale/pt/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/pt/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2125
django/conf/locale/pt/LC_MESSAGES/django.po
Normal file
2125
django/conf/locale/pt/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/pt/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/pt/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
108
django/conf/locale/pt/LC_MESSAGES/djangojs.po
Normal file
108
django/conf/locale/pt/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# Portuguese translation of Django.
|
||||||
|
# Copyright (C) 2007 the Lawrence Journal-World
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# Nuno Mariz <nmariz@gmail.com>, 2007.
|
||||||
|
#
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: Django 0.96pre\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-03-15 11:51+0100\n"
|
||||||
|
"PO-Revision-Date: 2007-03-16 10:01+0000\n"
|
||||||
|
"Last-Translator: Nuno Mariz <nmariz@gmail.com>\n"
|
||||||
|
"Language-Team: pt_PT <nmariz@gmail.com>\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 "Disponível %s"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
|
msgid "Choose all"
|
||||||
|
msgstr "Escolher todos"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
|
msgid "Add"
|
||||||
|
msgstr "Adicionar"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
|
msgid "Remove"
|
||||||
|
msgstr "Remover"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:53
|
||||||
|
#, perl-format
|
||||||
|
msgid "Chosen %s"
|
||||||
|
msgstr "Escolhido %s"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:54
|
||||||
|
msgid "Select your choice(s) and click "
|
||||||
|
msgstr "Seleccione a(s) sua(s) escolha(s) e clique "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
|
msgid "Clear all"
|
||||||
|
msgstr "Limpar tudo"
|
||||||
|
|
||||||
|
#: 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 "Janeiro Fevereiro Março Abril Maio Junho Julho Agosto Setembro Outubro Novembro Dezembro"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/dateparse.js:27
|
||||||
|
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
|
||||||
|
msgstr "Domingo Segunda Terça Quarta Quinta Sexta Sábado"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/calendar.js:25
|
||||||
|
msgid "S M T W T F S"
|
||||||
|
msgstr "D S T Q Q S S"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||||
|
msgid "Now"
|
||||||
|
msgstr "Agora"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr "Relógio"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr "Escolha a hora"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr "Meia-noite"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr "6 a.m."
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr "Meio-dia"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "Cancelar"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "Hoje"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr "Calendário"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "Ontem"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr "Amanhã"
|
Binary file not shown.
@ -11,9 +11,9 @@ 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-03-06 00:17+0100\n"
|
"POT-Creation-Date: 2007-03-06 00:17+0100\n"
|
||||||
"PO-Revision-Date: 2007-03-06 01:46+0100\n"
|
"PO-Revision-Date: 2007-03-06 10:30+0100\n"
|
||||||
"Last-Translator: Mikko Hellsing <mikko@sorl.net>\n"
|
"Last-Translator: Mikko Hellsing <mikko@sorl.net>\n"
|
||||||
"Language-Team: Django translators <djangoi18n@googlegroups.com>\n"
|
"Language-Team: Django I18N <Django-I18N@googlegroups.com>\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"
|
||||||
@ -27,7 +27,7 @@ msgstr ""
|
|||||||
#: newforms/fields.py:78 newforms/fields.py:374 newforms/fields.py:450
|
#: newforms/fields.py:78 newforms/fields.py:374 newforms/fields.py:450
|
||||||
#: newforms/fields.py:461
|
#: newforms/fields.py:461
|
||||||
msgid "This field is required."
|
msgid "This field is required."
|
||||||
msgstr "Det här fältet är obligatoriskt."
|
msgstr "Detta fältet är obligatoriskt."
|
||||||
|
|
||||||
#: oldforms/__init__.py:387
|
#: oldforms/__init__.py:387
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -122,7 +122,7 @@ msgstr "Fyll i ett giltigt filnamn."
|
|||||||
#: db/models/fields/related.py:53
|
#: db/models/fields/related.py:53
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Please enter a valid %s."
|
msgid "Please enter a valid %s."
|
||||||
msgstr "Var god fyll i ett giltigt %s."
|
msgstr "Var god fyll i giltigt %s."
|
||||||
|
|
||||||
#: db/models/fields/related.py:642
|
#: db/models/fields/related.py:642
|
||||||
msgid "Separate multiple IDs with commas."
|
msgid "Separate multiple IDs with commas."
|
||||||
@ -317,7 +317,7 @@ msgstr "Fyll enbart i siffror avskilda med kommatecken."
|
|||||||
|
|
||||||
#: core/validators.py:99
|
#: core/validators.py:99
|
||||||
msgid "Enter valid e-mail addresses separated by commas."
|
msgid "Enter valid e-mail addresses separated by commas."
|
||||||
msgstr "Fyll i giltiga e-postadresser avskilda med kommatecken."
|
msgstr "Fyll i giltiga e-mailadresser avskilda med kommatecken."
|
||||||
|
|
||||||
#: core/validators.py:103
|
#: core/validators.py:103
|
||||||
msgid "Please enter a valid IP address."
|
msgid "Please enter a valid IP address."
|
||||||
@ -358,7 +358,7 @@ msgstr "Fyll i en giltig tid i formatet HH:MM"
|
|||||||
|
|
||||||
#: core/validators.py:161 newforms/fields.py:269
|
#: core/validators.py:161 newforms/fields.py:269
|
||||||
msgid "Enter a valid e-mail address."
|
msgid "Enter a valid e-mail address."
|
||||||
msgstr "Fyll i en giltig e-postadress."
|
msgstr "Fyll i en giltig e-mailadress."
|
||||||
|
|
||||||
#: core/validators.py:177
|
#: core/validators.py:177
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -652,7 +652,7 @@ msgstr "Detta URL verkar vara en trasig länk."
|
|||||||
|
|
||||||
#: contrib/contenttypes/models.py:26
|
#: contrib/contenttypes/models.py:26
|
||||||
msgid "python model class name"
|
msgid "python model class name"
|
||||||
msgstr "python model class namn"
|
msgstr "python modell klass namn"
|
||||||
|
|
||||||
#: contrib/contenttypes/models.py:29
|
#: contrib/contenttypes/models.py:29
|
||||||
msgid "content type"
|
msgid "content type"
|
||||||
@ -710,7 +710,7 @@ msgstr "efternamn"
|
|||||||
|
|
||||||
#: contrib/auth/models.py:93
|
#: contrib/auth/models.py:93
|
||||||
msgid "e-mail address"
|
msgid "e-mail address"
|
||||||
msgstr "e-postadress"
|
msgstr "e-mailadress"
|
||||||
|
|
||||||
#: contrib/auth/models.py:94
|
#: contrib/auth/models.py:94
|
||||||
msgid "password"
|
msgid "password"
|
||||||
@ -728,7 +728,7 @@ msgstr "personalstatus"
|
|||||||
|
|
||||||
#: contrib/auth/models.py:95
|
#: contrib/auth/models.py:95
|
||||||
msgid "Designates whether the user can log into this admin site."
|
msgid "Designates whether the user can log into this admin site."
|
||||||
msgstr "Avgör om användaren kan logga in till den här administrationssidan."
|
msgstr "Avgör om användaren kan logga in på den här admin-siten."
|
||||||
|
|
||||||
#: contrib/auth/models.py:96
|
#: contrib/auth/models.py:96
|
||||||
msgid "active"
|
msgid "active"
|
||||||
@ -823,8 +823,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 ""
|
||||||
"V.G. ange ett korrekt användarnamn och lösenord. Notera att båda fält är "
|
"V.G. ange ett korrekt användarnamn och lösenord. Observera att båda fälten gör "
|
||||||
"skiftlägeskänsliga."
|
"skillnad på versaler och gemener."
|
||||||
|
|
||||||
#: contrib/auth/forms.py:62
|
#: contrib/auth/forms.py:62
|
||||||
msgid "This account is inactive."
|
msgid "This account is inactive."
|
||||||
@ -835,7 +835,7 @@ 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?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Den e-postadressen har inte något konto associerat med sig. Är du säker på "
|
"Den e-mailadressen har inte något konto associerat med sig. Är du säker på "
|
||||||
"att du har registrerat dig?"
|
"att du har registrerat dig?"
|
||||||
|
|
||||||
#: contrib/auth/forms.py:117
|
#: contrib/auth/forms.py:117
|
||||||
@ -848,7 +848,7 @@ msgstr "Ditt gamla lösenord var felaktigt ifyllt. Var vänlig fyll i det igen"
|
|||||||
|
|
||||||
#: contrib/redirects/models.py:7
|
#: contrib/redirects/models.py:7
|
||||||
msgid "redirect from"
|
msgid "redirect from"
|
||||||
msgstr "vidarebefordra från"
|
msgstr "omdirigera från"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:8
|
#: contrib/redirects/models.py:8
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -860,7 +860,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/redirects/models.py:9
|
#: contrib/redirects/models.py:9
|
||||||
msgid "redirect to"
|
msgid "redirect to"
|
||||||
msgstr "vidarebefordra till"
|
msgstr "omdirigera till"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:10
|
#: contrib/redirects/models.py:10
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -872,11 +872,11 @@ msgstr ""
|
|||||||
|
|
||||||
#: contrib/redirects/models.py:13
|
#: contrib/redirects/models.py:13
|
||||||
msgid "redirect"
|
msgid "redirect"
|
||||||
msgstr "vidarebefordra"
|
msgstr "omdirigera"
|
||||||
|
|
||||||
#: contrib/redirects/models.py:14
|
#: contrib/redirects/models.py:14
|
||||||
msgid "redirects"
|
msgid "redirects"
|
||||||
msgstr "vidarebefordringar"
|
msgstr "omdirigeringar"
|
||||||
|
|
||||||
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
#: contrib/comments/models.py:67 contrib/comments/models.py:166
|
||||||
msgid "object ID"
|
msgid "object ID"
|
||||||
@ -1113,7 +1113,7 @@ msgstr ""
|
|||||||
#: contrib/comments/views/comments.py:188
|
#: contrib/comments/views/comments.py:188
|
||||||
#: contrib/comments/views/comments.py:280
|
#: contrib/comments/views/comments.py:280
|
||||||
msgid "Only POSTs are allowed"
|
msgid "Only POSTs are allowed"
|
||||||
msgstr "Endast POSTningar är tillåtna"
|
msgstr "Endast POST tillåtet"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:192
|
#: contrib/comments/views/comments.py:192
|
||||||
#: contrib/comments/views/comments.py:284
|
#: contrib/comments/views/comments.py:284
|
||||||
@ -1131,7 +1131,7 @@ msgid ""
|
|||||||
"The comment form had an invalid 'target' parameter -- the object ID was "
|
"The comment form had an invalid 'target' parameter -- the object ID was "
|
||||||
"invalid"
|
"invalid"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Kommentars-formuläret har en ogiltig 'target'-parameter -- objektets ID är "
|
"Kommentars-formuläret hade en ogiltig 'mål'-parameter -- objektets ID var "
|
||||||
"ogiltigt"
|
"ogiltigt"
|
||||||
|
|
||||||
#: contrib/comments/views/comments.py:257
|
#: contrib/comments/views/comments.py:257
|
||||||
@ -1286,11 +1286,11 @@ msgstr "visat namn"
|
|||||||
|
|
||||||
#: contrib/sites/models.py:15
|
#: contrib/sites/models.py:15
|
||||||
msgid "site"
|
msgid "site"
|
||||||
msgstr "sida"
|
msgstr "site"
|
||||||
|
|
||||||
#: contrib/sites/models.py:16
|
#: contrib/sites/models.py:16
|
||||||
msgid "sites"
|
msgid "sites"
|
||||||
msgstr "sidor"
|
msgstr "siter"
|
||||||
|
|
||||||
#: contrib/admin/filterspecs.py:40
|
#: contrib/admin/filterspecs.py:40
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1386,7 +1386,7 @@ msgstr "Användarnamn kan inte innehålla tecknet '@'."
|
|||||||
#: contrib/admin/views/decorators.py:85
|
#: contrib/admin/views/decorators.py:85
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Your e-mail address is not your username. Try '%s' instead."
|
msgid "Your e-mail address is not your username. Try '%s' instead."
|
||||||
msgstr "Din e-postadress är inte ditt användarnamn. Försök med '%s' istället."
|
msgstr "Din e-mailadress är inte ditt användarnamn. Försök med '%s' istället."
|
||||||
|
|
||||||
#: contrib/admin/views/auth.py:19 contrib/admin/views/main.py:257
|
#: contrib/admin/views/auth.py:19 contrib/admin/views/main.py:257
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1594,11 +1594,11 @@ msgstr "Decimaltal"
|
|||||||
|
|
||||||
#: contrib/admin/views/doc.py:306
|
#: contrib/admin/views/doc.py:306
|
||||||
msgid "Boolean (Either True, False or None)"
|
msgid "Boolean (Either True, False or None)"
|
||||||
msgstr "Boolesk (antingen Sann, Falsk eller Inget)"
|
msgstr "Boolesk (antingen True, False eller None)"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:307
|
#: contrib/admin/views/doc.py:307
|
||||||
msgid "Relation to parent model"
|
msgid "Relation to parent model"
|
||||||
msgstr "Relation till förälder modell"
|
msgstr "Relation till förälder-modell"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:308
|
#: contrib/admin/views/doc.py:308
|
||||||
msgid "Phone number"
|
msgid "Phone number"
|
||||||
@ -1614,7 +1614,7 @@ msgstr "Tid"
|
|||||||
|
|
||||||
#: contrib/admin/views/doc.py:316
|
#: contrib/admin/views/doc.py:316
|
||||||
msgid "U.S. state (two uppercase letters)"
|
msgid "U.S. state (two uppercase letters)"
|
||||||
msgstr "Stat i USA (två stora bokstäver)"
|
msgstr "Stat i USA (två versaler)"
|
||||||
|
|
||||||
#: contrib/admin/views/doc.py:317
|
#: contrib/admin/views/doc.py:317
|
||||||
msgid "XML text"
|
msgid "XML text"
|
||||||
@ -1720,7 +1720,7 @@ msgid ""
|
|||||||
"admin site."
|
"admin site."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Det här objektet har ingen ändringshistorik. Det lades antagligen inte till "
|
"Det här objektet har ingen ändringshistorik. Det lades antagligen inte till "
|
||||||
"i den här admin-sidan"
|
"i den här admin-siten"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_list.html:12
|
#: contrib/admin/templates/admin/change_list.html:12
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -1749,7 +1749,7 @@ msgid ""
|
|||||||
"There's been an error. It's been reported to the site administrators via e-"
|
"There's been an error. It's been reported to the site administrators via e-"
|
||||||
"mail and should be fixed shortly. Thanks for your patience."
|
"mail and should be fixed shortly. Thanks for your patience."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ett fel har uppstått. Administratören har meddelats via e-post och "
|
"Ett fel har uppstått. Administratören har meddelats via e-mail och "
|
||||||
"felet bör åtgärdas snart. Tack för ditt tålamod."
|
"felet bör åtgärdas snart. Tack för ditt tålamod."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/invalid_setup.html:8
|
#: contrib/admin/templates/admin/invalid_setup.html:8
|
||||||
@ -1783,7 +1783,7 @@ msgstr "Visa alla"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/base_site.html:4
|
#: contrib/admin/templates/admin/base_site.html:4
|
||||||
msgid "Django site admin"
|
msgid "Django site admin"
|
||||||
msgstr "Django sidadministration"
|
msgstr "Django site-administration"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/base_site.html:7
|
#: contrib/admin/templates/admin/base_site.html:7
|
||||||
msgid "Django administration"
|
msgid "Django administration"
|
||||||
@ -1827,11 +1827,11 @@ msgstr "Du har inte rättigheter att ändra något."
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:52
|
#: contrib/admin/templates/admin/index.html:52
|
||||||
msgid "Recent Actions"
|
msgid "Recent Actions"
|
||||||
msgstr "Senaste händelserna"
|
msgstr "Senaste Händelserna"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:53
|
#: contrib/admin/templates/admin/index.html:53
|
||||||
msgid "My Actions"
|
msgid "My Actions"
|
||||||
msgstr "Mina händelser"
|
msgstr "Mina Händelser"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/index.html:57
|
#: contrib/admin/templates/admin/index.html:57
|
||||||
msgid "None available"
|
msgid "None available"
|
||||||
@ -1839,7 +1839,7 @@ msgstr "Inga tillgängliga"
|
|||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:22
|
#: contrib/admin/templates/admin/change_form.html:22
|
||||||
msgid "View on site"
|
msgid "View on site"
|
||||||
msgstr "Visa på hemsidan"
|
msgstr "Visa på siten"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/change_form.html:32
|
#: contrib/admin/templates/admin/change_form.html:32
|
||||||
#: contrib/admin/templates/admin/auth/user/change_password.html:24
|
#: contrib/admin/templates/admin/auth/user/change_password.html:24
|
||||||
@ -1918,7 +1918,7 @@ msgstr "Lösenord"
|
|||||||
#: contrib/admin/templates/admin/auth/user/change_password.html:39
|
#: contrib/admin/templates/admin/auth/user/change_password.html:39
|
||||||
#: contrib/admin/templates/admin/auth/user/add_form.html:23
|
#: contrib/admin/templates/admin/auth/user/add_form.html:23
|
||||||
msgid "Password (again)"
|
msgid "Password (again)"
|
||||||
msgstr "lösenord (igen)"
|
msgstr "Lösenord (igen)"
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/auth/user/change_password.html:40
|
#: contrib/admin/templates/admin/auth/user/change_password.html:40
|
||||||
#: contrib/admin/templates/admin/auth/user/add_form.html:24
|
#: contrib/admin/templates/admin/auth/user/add_form.html:24
|
||||||
@ -1930,8 +1930,8 @@ msgid ""
|
|||||||
"First, enter a username and password. Then, you'll be able to edit more user "
|
"First, enter a username and password. Then, you'll be able to edit more user "
|
||||||
"options."
|
"options."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ange först ett användarnamn och ett lösenord sedan kommer du att kunna "
|
"Ange först ett användarnamn och ett lösenord. Sedan kommer du att kunna ändra "
|
||||||
"ändra fler användaralternativ."
|
"fler användaralternativ."
|
||||||
|
|
||||||
#: contrib/admin/templates/admin/auth/user/add_form.html:12
|
#: contrib/admin/templates/admin/auth/user/add_form.html:12
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
@ -1965,7 +1965,7 @@ msgid ""
|
|||||||
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
"Forgotten your password? Enter your e-mail address below, and we'll reset "
|
||||||
"your password and e-mail the new one to you."
|
"your password and e-mail the new one to you."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Har du glömt ditt lösenord? Fyll i din e-postadress nedan, så nollställer vi "
|
"Har du glömt ditt lösenord? Fyll i din e-mailadress nedan, så nollställer vi "
|
||||||
"ditt lösenord och mailar det nya till dig."
|
"ditt lösenord och mailar det nya till dig."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_form.html:16
|
#: contrib/admin/templates/registration/password_reset_form.html:16
|
||||||
@ -1978,7 +1978,7 @@ msgstr "Nollställ mitt lösenord"
|
|||||||
|
|
||||||
#: contrib/admin/templates/registration/logged_out.html:8
|
#: contrib/admin/templates/registration/logged_out.html:8
|
||||||
msgid "Thanks for spending some quality time with the Web site today."
|
msgid "Thanks for spending some quality time with the Web site today."
|
||||||
msgstr "Tack för att du spenderade kvalitetstid med websidan idag."
|
msgstr "Tack för att du spenderade kvalitetstid med web-siten idag."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/logged_out.html:10
|
#: contrib/admin/templates/registration/logged_out.html:10
|
||||||
msgid "Log in again"
|
msgid "Log in again"
|
||||||
@ -1994,7 +1994,7 @@ msgid ""
|
|||||||
"We've e-mailed a new password to the e-mail address you submitted. You "
|
"We've e-mailed a new password to the e-mail address you submitted. You "
|
||||||
"should be receiving it shortly."
|
"should be receiving it shortly."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Vi har skickat ett nytt lösenord till e-postadressen du fyllde i. Det bör "
|
"Vi har skickat ett nytt lösenord till e-mailadressen du fyllde i. Det bör "
|
||||||
"anlända snarast."
|
"anlända snarast."
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_change_form.html:12
|
#: contrib/admin/templates/registration/password_change_form.html:12
|
||||||
@ -2047,7 +2047,7 @@ msgstr "Ditt användarnamn, om du har glömt:"
|
|||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:13
|
#: contrib/admin/templates/registration/password_reset_email.html:13
|
||||||
msgid "Thanks for using our site!"
|
msgid "Thanks for using our site!"
|
||||||
msgstr "Tack för att du använder vår sida!"
|
msgstr "Tack för att du använder vår site!"
|
||||||
|
|
||||||
#: contrib/admin/templates/registration/password_reset_email.html:15
|
#: contrib/admin/templates/registration/password_reset_email.html:15
|
||||||
#, python-format
|
#, python-format
|
||||||
@ -2076,7 +2076,7 @@ msgstr ""
|
|||||||
"<p class=\"help\">För att installera smarta bokmärken, dra länken till din\n"
|
"<p class=\"help\">För att installera smarta bokmärken, dra länken till din\n"
|
||||||
"verktygsrad med bokmärken, eller högerklicka på länken och lägg till den\n"
|
"verktygsrad med bokmärken, eller högerklicka på länken och lägg till den\n"
|
||||||
"till dina bokmärken. Nu kan du välja det smarta bokmärket från alla sidor\n"
|
"till dina bokmärken. Nu kan du välja det smarta bokmärket från alla sidor\n"
|
||||||
"på hemsidan. Observera att några av dessa smarta bokmärken kräver att du besöker\n"
|
"på siten. Observera att några av dessa smarta bokmärken kräver att du besöker\n"
|
||||||
"sidan från en dator som är \"intern\" (tala med din systemadministratör\n"
|
"sidan från en dator som är \"intern\" (tala med din systemadministratör\n"
|
||||||
"om du inte är säker på om din dator är \"intern\").</p>\n"
|
"om du inte är säker på om din dator är \"intern\").</p>\n"
|
||||||
|
|
||||||
|
Binary file not shown.
@ -10,9 +10,9 @@ 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-03-06 02:29+0100\n"
|
"POT-Creation-Date: 2007-03-06 02:29+0100\n"
|
||||||
"PO-Revision-Date: 2007-03-06 02:30+0100\n"
|
"PO-Revision-Date: 2007-03-06 10:30+0100\n"
|
||||||
"Last-Translator: Mikko Hellsing <mikko@sorl.net>\n"
|
"Last-Translator: Mikko Hellsing <mikko@sorl.net>\n"
|
||||||
"Language-Team: Django translators <djangoi18n@googlegroups.com>\n"
|
"Language-Team: Django I18N <Django-I18N@googlegroups.com>\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"
|
||||||
@ -27,7 +27,7 @@ msgstr "Tillgänglig %s"
|
|||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:41
|
#: contrib/admin/media/js/SelectFilter2.js:41
|
||||||
msgid "Choose all"
|
msgid "Choose all"
|
||||||
msgstr "Visa alla"
|
msgstr "Välj alla"
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:46
|
#: contrib/admin/media/js/SelectFilter2.js:46
|
||||||
msgid "Add"
|
msgid "Add"
|
||||||
@ -35,20 +35,20 @@ msgstr "Lägg till"
|
|||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:48
|
#: contrib/admin/media/js/SelectFilter2.js:48
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr "Tag bort"
|
msgstr "Ta bort"
|
||||||
|
|
||||||
#: 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 "Valde %s"
|
msgstr "Vald %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 "Välj ditt/dina val och klicka "
|
msgstr "Gör dina val och klicka på "
|
||||||
|
|
||||||
#: contrib/admin/media/js/SelectFilter2.js:59
|
#: contrib/admin/media/js/SelectFilter2.js:59
|
||||||
msgid "Clear all"
|
msgid "Clear all"
|
||||||
msgstr "Avmarkera alla"
|
msgstr "Ta bort alla"
|
||||||
|
|
||||||
#: contrib/admin/media/js/dateparse.js:32
|
#: contrib/admin/media/js/dateparse.js:32
|
||||||
#: contrib/admin/media/js/calendar.js:24
|
#: contrib/admin/media/js/calendar.js:24
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ta/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/ta/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
112
django/conf/locale/ta/LC_MESSAGES/djangojs.po
Normal file
112
django/conf/locale/ta/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
# translation of djangojs.po to tamil
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
#
|
||||||
|
# PONNUSAMY.A <ponnusamy.simpleman@gmail.com>, 2007.
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: djangojs\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-12-09 11:51+0100\n"
|
||||||
|
"PO-Revision-Date: 2007-03-14 16:40+0530\n"
|
||||||
|
"Last-Translator: PONNUSAMY <ponnusamy.simpleman@gmail.com>\n"
|
||||||
|
"Language-Team: tamil <tamilinix@yahoogroups.com>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: KBabel 1.11.4\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr "%s இருக்கிறதா "
|
||||||
|
|
||||||
|
#: 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 "%s தேர்ந்த்தெடுக்கப்பட்ட"
|
||||||
|
|
||||||
|
#: 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:26
|
||||||
|
#: 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:27
|
||||||
|
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:45
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||||
|
msgid "Now"
|
||||||
|
msgstr "இப்பொழுது "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr "கடிகாரம் "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr "ஒரு நேரத்தை தேர்ந்த்தெடுக்க "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr "நடு இரவு "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr "காலை 6 மணி "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr "மதியம் "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "வேண்டாம் "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "இன்று "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr "நாள்காட்டி "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "நேற்று "
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr "நாளை"
|
||||||
|
|
BIN
django/conf/locale/te/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/te/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2106
django/conf/locale/te/LC_MESSAGES/django.po
Normal file
2106
django/conf/locale/te/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/te/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/te/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
110
django/conf/locale/te/LC_MESSAGES/djangojs.po
Normal file
110
django/conf/locale/te/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
# translation of djangojs.po to Telugu
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
#
|
||||||
|
# pavithran <pavithran.s@gmail.com>, 2007.
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: djangojs\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
|
||||||
|
"PO-Revision-Date: 2007-03-06 16:08+0530\n"
|
||||||
|
"Last-Translator: pavithran <pavithran.s@gmail.com>\n"
|
||||||
|
"Language-Team: Telugu <indlinux-telugu@lists.sourceforge.net>\n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: KBabel 1.11.4\n"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/SelectFilter2.js:33
|
||||||
|
#, perl-format
|
||||||
|
msgid "Available %s"
|
||||||
|
msgstr "ఆందుబాతులోఉన్న %s "
|
||||||
|
|
||||||
|
#: 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 "ఎన్నుకున్న %s"
|
||||||
|
|
||||||
|
#: 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:26
|
||||||
|
#: 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:27
|
||||||
|
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:45
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
|
||||||
|
msgid "Now"
|
||||||
|
msgstr "ఇప్పుడు"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
|
||||||
|
msgid "Clock"
|
||||||
|
msgstr "గడియారము"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
|
||||||
|
msgid "Choose a time"
|
||||||
|
msgstr "ఒక సమయము ఎన్నుకోండి"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
|
||||||
|
msgid "Midnight"
|
||||||
|
msgstr "ఆర్ధరాత్రి"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
|
||||||
|
msgid "6 a.m."
|
||||||
|
msgstr "6"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
|
||||||
|
msgid "Noon"
|
||||||
|
msgstr "మధ్యాహ్నము"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
|
||||||
|
msgid "Cancel"
|
||||||
|
msgstr "రద్దు చేయు"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
|
||||||
|
msgid "Today"
|
||||||
|
msgstr "ఈనాడు"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
|
||||||
|
msgid "Calendar"
|
||||||
|
msgstr "కాలెండర్"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
|
||||||
|
msgid "Yesterday"
|
||||||
|
msgstr "నిన్న"
|
||||||
|
|
||||||
|
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
|
||||||
|
msgid "Tomorrow"
|
||||||
|
msgstr "రేపు"
|
||||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -16,8 +16,9 @@ DATABASE_PASSWORD = '' # Not used with sqlite3.
|
|||||||
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
|
DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
|
||||||
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
|
||||||
|
|
||||||
# Local time zone for this installation. All choices can be found here:
|
# Local time zone for this installation. Choices can be found here:
|
||||||
# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
|
# http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
|
||||||
|
# although not all variations may be possible on all operating systems.
|
||||||
# If running in a Windows environment this must be set to the same as your
|
# If running in a Windows environment this must be set to the same as your
|
||||||
# system time zone.
|
# system time zone.
|
||||||
TIME_ZONE = 'America/Chicago'
|
TIME_ZONE = 'America/Chicago'
|
||||||
|
@ -11,6 +11,7 @@ import re
|
|||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
word_re = re.compile('[A-Z][a-z]+')
|
word_re = re.compile('[A-Z][a-z]+')
|
||||||
|
absolute_url_re = re.compile(r'^(?:http(?:s)?:/)?/', re.IGNORECASE)
|
||||||
|
|
||||||
def class_name_to_underscored(name):
|
def class_name_to_underscored(name):
|
||||||
return '_'.join([s.lower() for s in word_re.findall(name)[:-1]])
|
return '_'.join([s.lower() for s in word_re.findall(name)[:-1]])
|
||||||
@ -18,18 +19,19 @@ def class_name_to_underscored(name):
|
|||||||
def include_admin_script(script_path):
|
def include_admin_script(script_path):
|
||||||
"""
|
"""
|
||||||
Returns an HTML script element for including a script from the admin
|
Returns an HTML script element for including a script from the admin
|
||||||
media url.
|
media url (or other location if an absolute url is given).
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
{% include_admin_script js/calendar.js %}
|
{% include_admin_script "js/calendar.js" %}
|
||||||
|
|
||||||
could return::
|
could return::
|
||||||
|
|
||||||
<script type="text/javascript" src="/media/admin/js/calendar.js">
|
<script type="text/javascript" src="/media/admin/js/calendar.js">
|
||||||
"""
|
"""
|
||||||
|
if not absolute_url_re.match(script_path):
|
||||||
return '<script type="text/javascript" src="%s%s"></script>' % (settings.ADMIN_MEDIA_PREFIX, script_path)
|
script_path = '%s%s' % (settings.ADMIN_MEDIA_PREFIX, script_path)
|
||||||
|
return '<script type="text/javascript" src="%s"></script>' % script_path
|
||||||
include_admin_script = register.simple_tag(include_admin_script)
|
include_admin_script = register.simple_tag(include_admin_script)
|
||||||
|
|
||||||
def submit_row(context):
|
def submit_row(context):
|
||||||
|
@ -168,7 +168,7 @@ def model_detail(request, app_label, model_name):
|
|||||||
model = m
|
model = m
|
||||||
break
|
break
|
||||||
if model is None:
|
if model is None:
|
||||||
raise Http404, _("Model %r not found in app %r") % (model_name, app_label)
|
raise Http404, _("Model %(name)r not found in app %(label)r") % {'name': model_name, 'label': app_label}
|
||||||
|
|
||||||
opts = model._meta
|
opts = model._meta
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ def model_detail(request, app_label, model_name):
|
|||||||
if isinstance(field, models.ForeignKey):
|
if isinstance(field, models.ForeignKey):
|
||||||
data_type = related_object_name = field.rel.to.__name__
|
data_type = related_object_name = field.rel.to.__name__
|
||||||
app_label = field.rel.to._meta.app_label
|
app_label = field.rel.to._meta.app_label
|
||||||
verbose = utils.parse_rst((_("the related `%s.%s` object") % (app_label, data_type)), 'model', _('model:') + data_type)
|
verbose = utils.parse_rst((_("the related `%(label)s.%(type)s` object") % {'label': app_label, 'type': data_type}), 'model', _('model:') + data_type)
|
||||||
else:
|
else:
|
||||||
data_type = get_readable_field_data_type(field)
|
data_type = get_readable_field_data_type(field)
|
||||||
verbose = field.verbose_name
|
verbose = field.verbose_name
|
||||||
@ -211,7 +211,7 @@ def model_detail(request, app_label, model_name):
|
|||||||
|
|
||||||
# Gather related objects
|
# Gather related objects
|
||||||
for rel in opts.get_all_related_objects():
|
for rel in opts.get_all_related_objects():
|
||||||
verbose = _("related `%s.%s` objects") % (rel.opts.app_label, rel.opts.object_name)
|
verbose = _("related `%(label)s.%(name)s` objects") % {'label': rel.opts.app_label, 'name': rel.opts.object_name}
|
||||||
accessor = rel.get_accessor_name()
|
accessor = rel.get_accessor_name()
|
||||||
fields.append({
|
fields.append({
|
||||||
'name' : "%s.all" % accessor,
|
'name' : "%s.all" % accessor,
|
||||||
|
@ -7,6 +7,7 @@ from django.db.models import get_apps, get_models, signals
|
|||||||
|
|
||||||
def create_contenttypes(app, created_models, verbosity=2):
|
def create_contenttypes(app, created_models, verbosity=2):
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
ContentType.objects.clear_cache()
|
||||||
app_models = get_models(app)
|
app_models = get_models(app)
|
||||||
if not app_models:
|
if not app_models:
|
||||||
return
|
return
|
||||||
|
@ -19,6 +19,16 @@ class ContentTypeManager(models.Manager):
|
|||||||
model=key[1], defaults={'name': str(opts.verbose_name)})
|
model=key[1], defaults={'name': str(opts.verbose_name)})
|
||||||
CONTENT_TYPE_CACHE[key] = ct
|
CONTENT_TYPE_CACHE[key] = ct
|
||||||
return ct
|
return ct
|
||||||
|
|
||||||
|
def clear_cache(self):
|
||||||
|
"""
|
||||||
|
Clear out the content-type cache. This needs to happen during database
|
||||||
|
flushes to prevent caching of "stale" content type IDs (see
|
||||||
|
django.contrib.contenttypes.management.create_contenttypes for where
|
||||||
|
this gets called).
|
||||||
|
"""
|
||||||
|
global CONTENT_TYPE_CACHE
|
||||||
|
CONTENT_TYPE_CACHE = {}
|
||||||
|
|
||||||
class ContentType(models.Model):
|
class ContentType(models.Model):
|
||||||
name = models.CharField(maxlength=100)
|
name = models.CharField(maxlength=100)
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
{{ form }}
|
{{ form }}
|
||||||
</table>
|
</table>
|
||||||
<input type="hidden" name="{{ stage_field }}" value="1" />
|
<input type="hidden" name="{{ stage_field }}" value="1" />
|
||||||
<p><input type="submit" value="Submit" /></p>
|
<p><input type="submit" value="Preview" /></p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<table>
|
<table>
|
||||||
{% for field in form %}
|
{% for field in form %}
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{ field.verbose_name }}:</th>
|
<th>{{ field.label }}:</th>
|
||||||
<td>{{ field.data|escape }}</td>
|
<td>{{ field.data|escape }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@ -30,7 +30,7 @@
|
|||||||
{{ form }}
|
{{ form }}
|
||||||
</table>
|
</table>
|
||||||
<input type="hidden" name="{{ stage_field }}" value="1" />
|
<input type="hidden" name="{{ stage_field }}" value="1" />
|
||||||
<p><input type="submit" value="Submit changes" /></p>
|
<p><input type="submit" value="Preview" /></p>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from django.utils.translation import ngettext
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
from django import template
|
from django import template
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -12,9 +14,9 @@ def ordinal(value):
|
|||||||
value = int(value)
|
value = int(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return value
|
return value
|
||||||
t = ('th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th')
|
t = (_('th'), _('st'), _('nd'), _('rd'), _('th'), _('th'), _('th'), _('th'), _('th'), _('th'))
|
||||||
if value % 100 in (11, 12, 13): # special case
|
if value % 100 in (11, 12, 13): # special case
|
||||||
return '%dth' % value
|
return "%d%s" % (value, t[0])
|
||||||
return '%d%s' % (value, t[value % 10])
|
return '%d%s' % (value, t[value % 10])
|
||||||
register.filter(ordinal)
|
register.filter(ordinal)
|
||||||
|
|
||||||
@ -41,11 +43,14 @@ def intword(value):
|
|||||||
if value < 1000000:
|
if value < 1000000:
|
||||||
return value
|
return value
|
||||||
if value < 1000000000:
|
if value < 1000000000:
|
||||||
return '%.1f million' % (value / 1000000.0)
|
new_value = value / 1000000.0
|
||||||
|
return ngettext('%(value).1f million', '%(value).1f million', new_value) % {'value': new_value}
|
||||||
if value < 1000000000000:
|
if value < 1000000000000:
|
||||||
return '%.1f billion' % (value / 1000000000.0)
|
new_value = value / 1000000000.0
|
||||||
|
return ngettext('%(value).1f billion', '%(value).1f billion', new_value) % {'value': new_value}
|
||||||
if value < 1000000000000000:
|
if value < 1000000000000000:
|
||||||
return '%.1f trillion' % (value / 1000000000000.0)
|
new_value = value / 1000000000000.0
|
||||||
|
return ngettext('%(value).1f trillion', '%(value).1f trillion', new_value) % {'value': new_value}
|
||||||
return value
|
return value
|
||||||
register.filter(intword)
|
register.filter(intword)
|
||||||
|
|
||||||
@ -60,5 +65,5 @@ def apnumber(value):
|
|||||||
return value
|
return value
|
||||||
if not 0 < value < 10:
|
if not 0 < value < 10:
|
||||||
return value
|
return value
|
||||||
return ('one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine')[value-1]
|
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
|
||||||
register.filter(apnumber)
|
register.filter(apnumber)
|
||||||
|
@ -10,6 +10,7 @@ TEST_COOKIE_VALUE = 'worked'
|
|||||||
class SessionWrapper(object):
|
class SessionWrapper(object):
|
||||||
def __init__(self, session_key):
|
def __init__(self, session_key):
|
||||||
self.session_key = session_key
|
self.session_key = session_key
|
||||||
|
self.accessed = False
|
||||||
self.modified = False
|
self.modified = False
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
@ -46,6 +47,7 @@ class SessionWrapper(object):
|
|||||||
|
|
||||||
def _get_session(self):
|
def _get_session(self):
|
||||||
# Lazily loads session from storage.
|
# Lazily loads session from storage.
|
||||||
|
self.accessed = True
|
||||||
try:
|
try:
|
||||||
return self._session_cache
|
return self._session_cache
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@ -72,14 +74,21 @@ class SessionMiddleware(object):
|
|||||||
def process_response(self, request, response):
|
def process_response(self, request, response):
|
||||||
# If request.session was modified, or if response.session was set, save
|
# If request.session was modified, or if response.session was set, save
|
||||||
# those changes and set a session cookie.
|
# those changes and set a session cookie.
|
||||||
patch_vary_headers(response, ('Cookie',))
|
|
||||||
try:
|
try:
|
||||||
|
accessed = request.session.accessed
|
||||||
modified = request.session.modified
|
modified = request.session.modified
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
|
if accessed:
|
||||||
|
patch_vary_headers(response, ('Cookie',))
|
||||||
if modified or settings.SESSION_SAVE_EVERY_REQUEST:
|
if modified or settings.SESSION_SAVE_EVERY_REQUEST:
|
||||||
session_key = request.session.session_key or Session.objects.get_new_session_key()
|
if request.session.session_key:
|
||||||
|
session_key = request.session.session_key
|
||||||
|
else:
|
||||||
|
obj = Session.objects.get_new_session_object()
|
||||||
|
session_key = obj.session_key
|
||||||
|
|
||||||
if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
|
if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
|
||||||
max_age = None
|
max_age = None
|
||||||
expires = None
|
expires = None
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import base64, md5, random, sys
|
import base64, md5, random, sys, datetime
|
||||||
import cPickle as pickle
|
import cPickle as pickle
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
@ -23,6 +23,23 @@ class SessionManager(models.Manager):
|
|||||||
break
|
break
|
||||||
return session_key
|
return session_key
|
||||||
|
|
||||||
|
def get_new_session_object(self):
|
||||||
|
"""
|
||||||
|
Returns a new session object.
|
||||||
|
"""
|
||||||
|
# FIXME: There is a *small* chance of collision here, meaning we will
|
||||||
|
# return an existing object. That can be fixed when we add a way to
|
||||||
|
# validate (and guarantee) that non-auto primary keys are unique. For
|
||||||
|
# now, we save immediately in order to reduce the "window of
|
||||||
|
# misfortune" as much as possible.
|
||||||
|
created = False
|
||||||
|
while not created:
|
||||||
|
obj, created = self.get_or_create(session_key=self.get_new_session_key(),
|
||||||
|
expire_date = datetime.datetime.now())
|
||||||
|
# Collision in key generation, so re-seed the generator
|
||||||
|
random.seed()
|
||||||
|
return obj
|
||||||
|
|
||||||
def save(self, session_key, session_dict, expire_date):
|
def save(self, session_key, session_dict, expire_date):
|
||||||
s = self.model(session_key, self.encode(session_dict), expire_date)
|
s = self.model(session_key, self.encode(session_dict), expire_date)
|
||||||
if session_dict:
|
if session_dict:
|
||||||
|
@ -280,7 +280,7 @@ def get_sql_delete(app):
|
|||||||
from django.db import backend, connection, models, get_introspection_module
|
from django.db import backend, connection, models, get_introspection_module
|
||||||
introspection = get_introspection_module()
|
introspection = get_introspection_module()
|
||||||
|
|
||||||
# This should work even if a connecton isn't available
|
# This should work even if a connection isn't available
|
||||||
try:
|
try:
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
except:
|
except:
|
||||||
@ -516,6 +516,7 @@ def syncdb(verbosity=1, interactive=True):
|
|||||||
created_models = set()
|
created_models = set()
|
||||||
pending_references = {}
|
pending_references = {}
|
||||||
|
|
||||||
|
# Create the tables for each model
|
||||||
for app in models.get_apps():
|
for app in models.get_apps():
|
||||||
app_name = app.__name__.split('.')[-2]
|
app_name = app.__name__.split('.')[-2]
|
||||||
model_list = models.get_models(app)
|
model_list = models.get_models(app)
|
||||||
@ -537,6 +538,11 @@ def syncdb(verbosity=1, interactive=True):
|
|||||||
cursor.execute(statement)
|
cursor.execute(statement)
|
||||||
table_list.append(model._meta.db_table)
|
table_list.append(model._meta.db_table)
|
||||||
|
|
||||||
|
# Create the m2m tables. This must be done after all tables have been created
|
||||||
|
# to ensure that all referred tables will exist.
|
||||||
|
for app in models.get_apps():
|
||||||
|
app_name = app.__name__.split('.')[-2]
|
||||||
|
model_list = models.get_models(app)
|
||||||
for model in model_list:
|
for model in model_list:
|
||||||
if model in created_models:
|
if model in created_models:
|
||||||
sql = _get_many_to_many_sql_for_model(model)
|
sql = _get_many_to_many_sql_for_model(model)
|
||||||
@ -546,7 +552,7 @@ def syncdb(verbosity=1, interactive=True):
|
|||||||
for statement in sql:
|
for statement in sql:
|
||||||
cursor.execute(statement)
|
cursor.execute(statement)
|
||||||
|
|
||||||
transaction.commit_unless_managed()
|
transaction.commit_unless_managed()
|
||||||
|
|
||||||
# Send the post_syncdb signal, so individual apps can do whatever they need
|
# Send the post_syncdb signal, so individual apps can do whatever they need
|
||||||
# to do at this point.
|
# to do at this point.
|
||||||
@ -1358,13 +1364,14 @@ def load_data(fixture_labels, verbosity=1):
|
|||||||
for fixture_dir in app_fixtures + list(settings.FIXTURE_DIRS) + ['']:
|
for fixture_dir in app_fixtures + list(settings.FIXTURE_DIRS) + ['']:
|
||||||
if verbosity > 1:
|
if verbosity > 1:
|
||||||
print "Checking %s for fixtures..." % humanize(fixture_dir)
|
print "Checking %s for fixtures..." % humanize(fixture_dir)
|
||||||
try:
|
parts = fixture_label.split('.')
|
||||||
fixture_name, format = fixture_label.rsplit('.', 1)
|
if len(parts) == 1:
|
||||||
formats = [format]
|
|
||||||
except ValueError:
|
|
||||||
fixture_name = fixture_label
|
fixture_name = fixture_label
|
||||||
formats = serializers.get_serializer_formats()
|
formats = serializers.get_serializer_formats()
|
||||||
|
else:
|
||||||
|
fixture_name, format = '.'.join(parts[:-1]), parts[-1]
|
||||||
|
formats = [format]
|
||||||
|
|
||||||
label_found = False
|
label_found = False
|
||||||
for format in formats:
|
for format in formats:
|
||||||
serializer = serializers.get_serializer(format)
|
serializer = serializers.get_serializer(format)
|
||||||
@ -1439,7 +1446,7 @@ def dump_data(app_labels, format='json', indent=None):
|
|||||||
for model in get_models(app):
|
for model in get_models(app):
|
||||||
objects.extend(model.objects.all())
|
objects.extend(model.objects.all())
|
||||||
try:
|
try:
|
||||||
print serializers.serialize(format, objects, indent=indent)
|
return serializers.serialize(format, objects, indent=indent)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e))
|
sys.stderr.write(style.ERROR("Unable to serialize database: %s\n" % e))
|
||||||
dump_data.help_doc = 'Output the contents of the database as a fixture of the given format'
|
dump_data.help_doc = 'Output the contents of the database as a fixture of the given format'
|
||||||
@ -1585,7 +1592,7 @@ def execute_from_command_line(action_mapping=DEFAULT_ACTION_MAPPING, argv=None):
|
|||||||
parser.print_usage_and_exit()
|
parser.print_usage_and_exit()
|
||||||
elif action == 'dumpdata':
|
elif action == 'dumpdata':
|
||||||
try:
|
try:
|
||||||
action_mapping[action](args[1:], options.format, options.indent)
|
print action_mapping[action](args[1:], options.format, options.indent)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
parser.print_usage_and_exit()
|
parser.print_usage_and_exit()
|
||||||
elif action in ('startapp', 'startproject'):
|
elif action in ('startapp', 'startproject'):
|
||||||
|
@ -25,6 +25,13 @@ BUILTIN_SERIALIZERS = {
|
|||||||
"json" : "django.core.serializers.json",
|
"json" : "django.core.serializers.json",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check for PyYaml and register the serializer if it's available.
|
||||||
|
try:
|
||||||
|
import yaml
|
||||||
|
BUILTIN_SERIALIZERS["yaml"] = "django.core.serializers.pyyaml"
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
_serializers = {}
|
_serializers = {}
|
||||||
|
|
||||||
def register_serializer(format, serializer_module):
|
def register_serializer(format, serializer_module):
|
||||||
|
@ -34,17 +34,17 @@ class Serializer(object):
|
|||||||
for obj in queryset:
|
for obj in queryset:
|
||||||
self.start_object(obj)
|
self.start_object(obj)
|
||||||
for field in obj._meta.fields:
|
for field in obj._meta.fields:
|
||||||
if field is obj._meta.pk:
|
if field.serialize:
|
||||||
continue
|
if field.rel is None:
|
||||||
elif field.rel is None:
|
if self.selected_fields is None or field.attname in self.selected_fields:
|
||||||
if self.selected_fields is None or field.attname in self.selected_fields:
|
self.handle_field(obj, field)
|
||||||
self.handle_field(obj, field)
|
else:
|
||||||
else:
|
if self.selected_fields is None or field.attname[:-3] in self.selected_fields:
|
||||||
if self.selected_fields is None or field.attname[:-3] in self.selected_fields:
|
self.handle_fk_field(obj, field)
|
||||||
self.handle_fk_field(obj, field)
|
|
||||||
for field in obj._meta.many_to_many:
|
for field in obj._meta.many_to_many:
|
||||||
if self.selected_fields is None or field.attname in self.selected_fields:
|
if field.serialize:
|
||||||
self.handle_m2m_field(obj, field)
|
if self.selected_fields is None or field.attname in self.selected_fields:
|
||||||
|
self.handle_m2m_field(obj, field)
|
||||||
self.end_object(obj)
|
self.end_object(obj)
|
||||||
self.end_serialization()
|
self.end_serialization()
|
||||||
return self.getvalue()
|
return self.getvalue()
|
||||||
@ -54,11 +54,7 @@ class Serializer(object):
|
|||||||
Convert a field's value to a string.
|
Convert a field's value to a string.
|
||||||
"""
|
"""
|
||||||
if isinstance(field, models.DateTimeField):
|
if isinstance(field, models.DateTimeField):
|
||||||
value = getattr(obj, field.name)
|
value = getattr(obj, field.name).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
if value is None:
|
|
||||||
value = ''
|
|
||||||
else:
|
|
||||||
value = value.strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
elif isinstance(field, models.FileField):
|
elif isinstance(field, models.FileField):
|
||||||
value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
|
value = getattr(obj, "get_%s_url" % field.name, lambda: None)()
|
||||||
else:
|
else:
|
||||||
|
@ -57,7 +57,7 @@ def Deserializer(object_list, **options):
|
|||||||
for d in object_list:
|
for d in object_list:
|
||||||
# Look up the model and starting build a dict of data for it.
|
# Look up the model and starting build a dict of data for it.
|
||||||
Model = _get_model(d["model"])
|
Model = _get_model(d["model"])
|
||||||
data = {Model._meta.pk.attname : d["pk"]}
|
data = {Model._meta.pk.attname : Model._meta.pk.to_python(d["pk"])}
|
||||||
m2m_data = {}
|
m2m_data = {}
|
||||||
|
|
||||||
# Handle each field
|
# Handle each field
|
||||||
@ -70,16 +70,17 @@ def Deserializer(object_list, **options):
|
|||||||
# Handle M2M relations
|
# Handle M2M relations
|
||||||
if field.rel and isinstance(field.rel, models.ManyToManyRel):
|
if field.rel and isinstance(field.rel, models.ManyToManyRel):
|
||||||
pks = []
|
pks = []
|
||||||
|
m2m_convert = field.rel.to._meta.pk.to_python
|
||||||
for pk in field_value:
|
for pk in field_value:
|
||||||
if isinstance(pk, unicode):
|
if isinstance(pk, unicode):
|
||||||
pks.append(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET)))
|
pks.append(m2m_convert(pk.encode(options.get("encoding", settings.DEFAULT_CHARSET))))
|
||||||
else:
|
else:
|
||||||
pks.append(pk)
|
pks.append(m2m_convert(pk))
|
||||||
m2m_data[field.name] = pks
|
m2m_data[field.name] = pks
|
||||||
|
|
||||||
# Handle FK fields
|
# Handle FK fields
|
||||||
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
||||||
data[field.attname] = field_value
|
data[field.attname] = field.rel.to._meta.pk.to_python(field_value)
|
||||||
|
|
||||||
# Handle all other fields
|
# Handle all other fields
|
||||||
else:
|
else:
|
||||||
|
36
django/core/serializers/pyyaml.py
Normal file
36
django/core/serializers/pyyaml.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"""
|
||||||
|
YAML serializer.
|
||||||
|
|
||||||
|
Requires PyYaml (http://pyyaml.org/), but that's checked for in __init__.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from django.core.serializers.python import Serializer as PythonSerializer
|
||||||
|
from django.core.serializers.python import Deserializer as PythonDeserializer
|
||||||
|
try:
|
||||||
|
from cStringIO import StringIO
|
||||||
|
except ImportError:
|
||||||
|
from StringIO import StringIO
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
class Serializer(PythonSerializer):
|
||||||
|
"""
|
||||||
|
Convert a queryset to YAML.
|
||||||
|
"""
|
||||||
|
def end_serialization(self):
|
||||||
|
yaml.dump(self.objects, self.stream, **self.options)
|
||||||
|
|
||||||
|
def getvalue(self):
|
||||||
|
return self.stream.getvalue()
|
||||||
|
|
||||||
|
def Deserializer(stream_or_string, **options):
|
||||||
|
"""
|
||||||
|
Deserialize a stream or string of YAML data.
|
||||||
|
"""
|
||||||
|
if isinstance(stream_or_string, basestring):
|
||||||
|
stream = StringIO(stream_or_string)
|
||||||
|
else:
|
||||||
|
stream = stream_or_string
|
||||||
|
for obj in PythonDeserializer(yaml.load(stream)):
|
||||||
|
yield obj
|
||||||
|
|
@ -13,6 +13,10 @@ class Serializer(base.Serializer):
|
|||||||
Serializes a QuerySet to XML.
|
Serializes a QuerySet to XML.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def indent(self, level):
|
||||||
|
if self.options.get('indent', None) is not None:
|
||||||
|
self.xml.ignorableWhitespace('\n' + ' ' * self.options.get('indent', None) * level)
|
||||||
|
|
||||||
def start_serialization(self):
|
def start_serialization(self):
|
||||||
"""
|
"""
|
||||||
Start serialization -- open the XML document and the root element.
|
Start serialization -- open the XML document and the root element.
|
||||||
@ -25,6 +29,7 @@ class Serializer(base.Serializer):
|
|||||||
"""
|
"""
|
||||||
End serialization -- end the document.
|
End serialization -- end the document.
|
||||||
"""
|
"""
|
||||||
|
self.indent(0)
|
||||||
self.xml.endElement("django-objects")
|
self.xml.endElement("django-objects")
|
||||||
self.xml.endDocument()
|
self.xml.endDocument()
|
||||||
|
|
||||||
@ -35,6 +40,7 @@ class Serializer(base.Serializer):
|
|||||||
if not hasattr(obj, "_meta"):
|
if not hasattr(obj, "_meta"):
|
||||||
raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj))
|
raise base.SerializationError("Non-model object (%s) encountered during serialization" % type(obj))
|
||||||
|
|
||||||
|
self.indent(1)
|
||||||
self.xml.startElement("object", {
|
self.xml.startElement("object", {
|
||||||
"pk" : str(obj._get_pk_val()),
|
"pk" : str(obj._get_pk_val()),
|
||||||
"model" : str(obj._meta),
|
"model" : str(obj._meta),
|
||||||
@ -44,6 +50,7 @@ class Serializer(base.Serializer):
|
|||||||
"""
|
"""
|
||||||
Called after handling all fields for an object.
|
Called after handling all fields for an object.
|
||||||
"""
|
"""
|
||||||
|
self.indent(1)
|
||||||
self.xml.endElement("object")
|
self.xml.endElement("object")
|
||||||
|
|
||||||
def handle_field(self, obj, field):
|
def handle_field(self, obj, field):
|
||||||
@ -51,16 +58,19 @@ class Serializer(base.Serializer):
|
|||||||
Called to handle each field on an object (except for ForeignKeys and
|
Called to handle each field on an object (except for ForeignKeys and
|
||||||
ManyToManyFields)
|
ManyToManyFields)
|
||||||
"""
|
"""
|
||||||
|
self.indent(2)
|
||||||
self.xml.startElement("field", {
|
self.xml.startElement("field", {
|
||||||
"name" : field.name,
|
"name" : field.name,
|
||||||
"type" : field.get_internal_type()
|
"type" : field.get_internal_type()
|
||||||
})
|
})
|
||||||
|
|
||||||
# Get a "string version" of the object's data (this is handled by the
|
# Get a "string version" of the object's data (this is handled by the
|
||||||
# serializer base class). None is handled specially.
|
# serializer base class).
|
||||||
value = self.get_string_value(obj, field)
|
if getattr(obj, field.name) is not None:
|
||||||
if value is not None:
|
value = self.get_string_value(obj, field)
|
||||||
self.xml.characters(str(value))
|
self.xml.characters(str(value))
|
||||||
|
else:
|
||||||
|
self.xml.addQuickElement("None")
|
||||||
|
|
||||||
self.xml.endElement("field")
|
self.xml.endElement("field")
|
||||||
|
|
||||||
@ -92,6 +102,7 @@ class Serializer(base.Serializer):
|
|||||||
"""
|
"""
|
||||||
Helper to output the <field> element for relational fields
|
Helper to output the <field> element for relational fields
|
||||||
"""
|
"""
|
||||||
|
self.indent(2)
|
||||||
self.xml.startElement("field", {
|
self.xml.startElement("field", {
|
||||||
"name" : field.name,
|
"name" : field.name,
|
||||||
"rel" : field.rel.__class__.__name__,
|
"rel" : field.rel.__class__.__name__,
|
||||||
@ -127,7 +138,8 @@ class Deserializer(base.Deserializer):
|
|||||||
pk = node.getAttribute("pk")
|
pk = node.getAttribute("pk")
|
||||||
if not pk:
|
if not pk:
|
||||||
raise base.DeserializationError("<object> node is missing the 'pk' attribute")
|
raise base.DeserializationError("<object> node is missing the 'pk' attribute")
|
||||||
data = {Model._meta.pk.name : pk}
|
|
||||||
|
data = {Model._meta.pk.attname : Model._meta.pk.to_python(pk)}
|
||||||
|
|
||||||
# Also start building a dict of m2m data (this is saved as
|
# Also start building a dict of m2m data (this is saved as
|
||||||
# {m2m_accessor_attribute : [list_of_related_objects]})
|
# {m2m_accessor_attribute : [list_of_related_objects]})
|
||||||
@ -148,17 +160,20 @@ class Deserializer(base.Deserializer):
|
|||||||
|
|
||||||
# As is usually the case, relation fields get the special treatment.
|
# As is usually the case, relation fields get the special treatment.
|
||||||
if field.rel and isinstance(field.rel, models.ManyToManyRel):
|
if field.rel and isinstance(field.rel, models.ManyToManyRel):
|
||||||
m2m_data[field.name] = self._handle_m2m_field_node(field_node)
|
m2m_data[field.name] = self._handle_m2m_field_node(field_node, field)
|
||||||
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
elif field.rel and isinstance(field.rel, models.ManyToOneRel):
|
||||||
data[field.attname] = self._handle_fk_field_node(field_node)
|
data[field.attname] = self._handle_fk_field_node(field_node, field)
|
||||||
else:
|
else:
|
||||||
value = field.to_python(getInnerText(field_node).strip().encode(self.encoding))
|
if len(field_node.childNodes) == 1 and field_node.childNodes[0].nodeName == 'None':
|
||||||
|
value = None
|
||||||
|
else:
|
||||||
|
value = field.to_python(getInnerText(field_node).strip().encode(self.encoding))
|
||||||
data[field.name] = value
|
data[field.name] = value
|
||||||
|
|
||||||
# Return a DeserializedObject so that the m2m data has a place to live.
|
# Return a DeserializedObject so that the m2m data has a place to live.
|
||||||
return base.DeserializedObject(Model(**data), m2m_data)
|
return base.DeserializedObject(Model(**data), m2m_data)
|
||||||
|
|
||||||
def _handle_fk_field_node(self, node):
|
def _handle_fk_field_node(self, node, field):
|
||||||
"""
|
"""
|
||||||
Handle a <field> node for a ForeignKey
|
Handle a <field> node for a ForeignKey
|
||||||
"""
|
"""
|
||||||
@ -166,13 +181,16 @@ class Deserializer(base.Deserializer):
|
|||||||
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
|
if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None':
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return getInnerText(node).strip().encode(self.encoding)
|
return field.rel.to._meta.pk.to_python(
|
||||||
|
getInnerText(node).strip().encode(self.encoding))
|
||||||
|
|
||||||
def _handle_m2m_field_node(self, node):
|
def _handle_m2m_field_node(self, node, field):
|
||||||
"""
|
"""
|
||||||
Handle a <field> node for a ManyToManyField
|
Handle a <field> node for a ManyToManyField
|
||||||
"""
|
"""
|
||||||
return [c.getAttribute("pk").encode(self.encoding) for c in node.getElementsByTagName("object")]
|
return [field.rel.to._meta.pk.to_python(
|
||||||
|
c.getAttribute("pk").encode(self.encoding))
|
||||||
|
for c in node.getElementsByTagName("object")]
|
||||||
|
|
||||||
def _get_model_from_node(self, node, attr):
|
def _get_model_from_node(self, node, attr):
|
||||||
"""
|
"""
|
||||||
|
@ -140,7 +140,8 @@ def _isValidDate(date_string):
|
|||||||
try:
|
try:
|
||||||
date(year, month, day)
|
date(year, month, day)
|
||||||
except ValueError, e:
|
except ValueError, e:
|
||||||
raise ValidationError, gettext('Invalid date: %s.' % e)
|
msg = gettext('Invalid date: %s') % gettext(str(e))
|
||||||
|
raise ValidationError, msg
|
||||||
|
|
||||||
def isValidANSIDate(field_data, all_data):
|
def isValidANSIDate(field_data, all_data):
|
||||||
if not ansi_date_re.search(field_data):
|
if not ansi_date_re.search(field_data):
|
||||||
@ -363,7 +364,7 @@ class NumberIsInRange(object):
|
|||||||
self.lower, self.upper = lower, upper
|
self.lower, self.upper = lower, upper
|
||||||
if not error_message:
|
if not error_message:
|
||||||
if lower and upper:
|
if lower and upper:
|
||||||
self.error_message = gettext("This value must be between %s and %s.") % (lower, upper)
|
self.error_message = gettext("This value must be between %(lower)s and %(upper)s.") % {'lower': lower, 'upper': upper}
|
||||||
elif lower:
|
elif lower:
|
||||||
self.error_message = gettext("This value must be at least %s.") % lower
|
self.error_message = gettext("This value must be at least %s.") % lower
|
||||||
elif upper:
|
elif upper:
|
||||||
|
@ -76,10 +76,11 @@ class DatabaseWrapper(local):
|
|||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
def _commit(self):
|
def _commit(self):
|
||||||
return self.connection.commit()
|
if self.connection is not None:
|
||||||
|
return self.connection.commit()
|
||||||
|
|
||||||
def _rollback(self):
|
def _rollback(self):
|
||||||
if self.connection:
|
if self.connection is not None:
|
||||||
return self.connection.rollback()
|
return self.connection.rollback()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
@ -10,6 +10,15 @@ try:
|
|||||||
except ImportError, e:
|
except ImportError, e:
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e
|
raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e
|
||||||
|
|
||||||
|
# We want version (1, 2, 1, 'final', 2) or later. We can't just use
|
||||||
|
# lexicographic ordering in this check because then (1, 2, 1, 'gamma')
|
||||||
|
# inadvertently passes the version test.
|
||||||
|
version = Database.version_info
|
||||||
|
if (version < (1,2,1) or (version[:3] == (1, 2, 1) and
|
||||||
|
(len(version) < 5 or version[3] != 'final' or version[4] < 2))):
|
||||||
|
raise ImportError, "MySQLdb-1.2.1p2 or newer is required; you have %s" % Database.__version__
|
||||||
|
|
||||||
from MySQLdb.converters import conversions
|
from MySQLdb.converters import conversions
|
||||||
from MySQLdb.constants import FIELD_TYPE
|
from MySQLdb.constants import FIELD_TYPE
|
||||||
import types
|
import types
|
||||||
@ -17,11 +26,14 @@ import re
|
|||||||
|
|
||||||
DatabaseError = Database.DatabaseError
|
DatabaseError = Database.DatabaseError
|
||||||
|
|
||||||
|
# MySQLdb-1.2.1 supports the Python boolean type, and only uses datetime
|
||||||
|
# module for time-related columns; older versions could have used mx.DateTime
|
||||||
|
# or strings if there were no datetime module. However, MySQLdb still returns
|
||||||
|
# TIME columns as timedelta -- they are more like timedelta in terms of actual
|
||||||
|
# behavior as they are signed and include days -- and Django expects time, so
|
||||||
|
# we still need to override that.
|
||||||
django_conversions = conversions.copy()
|
django_conversions = conversions.copy()
|
||||||
django_conversions.update({
|
django_conversions.update({
|
||||||
types.BooleanType: util.rev_typecast_boolean,
|
|
||||||
FIELD_TYPE.DATETIME: util.typecast_timestamp,
|
|
||||||
FIELD_TYPE.DATE: util.typecast_date,
|
|
||||||
FIELD_TYPE.TIME: util.typecast_time,
|
FIELD_TYPE.TIME: util.typecast_time,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -31,31 +43,12 @@ django_conversions.update({
|
|||||||
# http://dev.mysql.com/doc/refman/5.0/en/news.html .
|
# http://dev.mysql.com/doc/refman/5.0/en/news.html .
|
||||||
server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
|
server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
|
||||||
|
|
||||||
# This is an extra debug layer over MySQL queries, to display warnings.
|
# MySQLdb-1.2.1 and newer automatically makes use of SHOW WARNINGS on
|
||||||
# It's only used when DEBUG=True.
|
# MySQL-4.1 and newer, so the MysqlDebugWrapper is unnecessary. Since the
|
||||||
class MysqlDebugWrapper:
|
# point is to raise Warnings as exceptions, this can be done with the Python
|
||||||
def __init__(self, cursor):
|
# warning module, and this is setup when the connection is created, and the
|
||||||
self.cursor = cursor
|
# standard util.CursorDebugWrapper can be used. Also, using sql_mode
|
||||||
|
# TRADITIONAL will automatically cause most warnings to be treated as errors.
|
||||||
def execute(self, sql, params=()):
|
|
||||||
try:
|
|
||||||
return self.cursor.execute(sql, params)
|
|
||||||
except Database.Warning, w:
|
|
||||||
self.cursor.execute("SHOW WARNINGS")
|
|
||||||
raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
|
|
||||||
|
|
||||||
def executemany(self, sql, param_list):
|
|
||||||
try:
|
|
||||||
return self.cursor.executemany(sql, param_list)
|
|
||||||
except Database.Warning, w:
|
|
||||||
self.cursor.execute("SHOW WARNINGS")
|
|
||||||
raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
|
|
||||||
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
if self.__dict__.has_key(attr):
|
|
||||||
return self.__dict__[attr]
|
|
||||||
else:
|
|
||||||
return getattr(self.cursor, attr)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Only exists in Python 2.4+
|
# Only exists in Python 2.4+
|
||||||
@ -83,35 +76,41 @@ class DatabaseWrapper(local):
|
|||||||
|
|
||||||
def cursor(self):
|
def cursor(self):
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from warnings import filterwarnings
|
||||||
if not self._valid_connection():
|
if not self._valid_connection():
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'user': settings.DATABASE_USER,
|
|
||||||
'db': settings.DATABASE_NAME,
|
|
||||||
'passwd': settings.DATABASE_PASSWORD,
|
|
||||||
'conv': django_conversions,
|
'conv': django_conversions,
|
||||||
|
'charset': 'utf8',
|
||||||
|
'use_unicode': False,
|
||||||
}
|
}
|
||||||
|
if settings.DATABASE_USER:
|
||||||
|
kwargs['user'] = settings.DATABASE_USER
|
||||||
|
if settings.DATABASE_NAME:
|
||||||
|
kwargs['db'] = settings.DATABASE_NAME
|
||||||
|
if settings.DATABASE_PASSWORD:
|
||||||
|
kwargs['passwd'] = settings.DATABASE_PASSWORD
|
||||||
if settings.DATABASE_HOST.startswith('/'):
|
if settings.DATABASE_HOST.startswith('/'):
|
||||||
kwargs['unix_socket'] = settings.DATABASE_HOST
|
kwargs['unix_socket'] = settings.DATABASE_HOST
|
||||||
else:
|
elif settings.DATABASE_HOST:
|
||||||
kwargs['host'] = settings.DATABASE_HOST
|
kwargs['host'] = settings.DATABASE_HOST
|
||||||
if settings.DATABASE_PORT:
|
if settings.DATABASE_PORT:
|
||||||
kwargs['port'] = int(settings.DATABASE_PORT)
|
kwargs['port'] = int(settings.DATABASE_PORT)
|
||||||
kwargs.update(self.options)
|
kwargs.update(self.options)
|
||||||
self.connection = Database.connect(**kwargs)
|
self.connection = Database.connect(**kwargs)
|
||||||
cursor = self.connection.cursor()
|
cursor = self.connection.cursor()
|
||||||
if self.connection.get_server_info() >= '4.1':
|
|
||||||
cursor.execute("SET NAMES 'utf8'")
|
|
||||||
else:
|
else:
|
||||||
cursor = self.connection.cursor()
|
cursor = self.connection.cursor()
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
return util.CursorDebugWrapper(MysqlDebugWrapper(cursor), self)
|
filterwarnings("error", category=Database.Warning)
|
||||||
|
return util.CursorDebugWrapper(cursor, self)
|
||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
def _commit(self):
|
def _commit(self):
|
||||||
self.connection.commit()
|
if self.connection is not None:
|
||||||
|
self.connection.commit()
|
||||||
|
|
||||||
def _rollback(self):
|
def _rollback(self):
|
||||||
if self.connection:
|
if self.connection is not None:
|
||||||
try:
|
try:
|
||||||
self.connection.rollback()
|
self.connection.rollback()
|
||||||
except Database.NotSupportedError:
|
except Database.NotSupportedError:
|
||||||
|
@ -3,12 +3,25 @@ import os
|
|||||||
|
|
||||||
def runshell():
|
def runshell():
|
||||||
args = ['']
|
args = ['']
|
||||||
args += ["--user=%s" % settings.DATABASE_USER]
|
db = settings.DATABASE_OPTIONS.get('db', settings.DATABASE_NAME)
|
||||||
if settings.DATABASE_PASSWORD:
|
user = settings.DATABASE_OPTIONS.get('user', settings.DATABASE_USER)
|
||||||
args += ["--password=%s" % settings.DATABASE_PASSWORD]
|
passwd = settings.DATABASE_OPTIONS.get('passwd', settings.DATABASE_PASSWORD)
|
||||||
if settings.DATABASE_HOST:
|
host = settings.DATABASE_OPTIONS.get('host', settings.DATABASE_HOST)
|
||||||
args += ["--host=%s" % settings.DATABASE_HOST]
|
port = settings.DATABASE_OPTIONS.get('port', settings.DATABASE_PORT)
|
||||||
if settings.DATABASE_PORT:
|
defaults_file = settings.DATABASE_OPTIONS.get('read_default_file')
|
||||||
args += ["--port=%s" % settings.DATABASE_PORT]
|
# Seems to be no good way to set sql_mode with CLI
|
||||||
args += [settings.DATABASE_NAME]
|
|
||||||
|
if defaults_file:
|
||||||
|
args += ["--defaults-file=%s" % defaults_file]
|
||||||
|
if user:
|
||||||
|
args += ["--user=%s" % user]
|
||||||
|
if passwd:
|
||||||
|
args += ["--password=%s" % passwd]
|
||||||
|
if host:
|
||||||
|
args += ["--host=%s" % host]
|
||||||
|
if port:
|
||||||
|
args += ["--port=%s" % port]
|
||||||
|
if db:
|
||||||
|
args += [db]
|
||||||
|
|
||||||
os.execvp('mysql', args)
|
os.execvp('mysql', args)
|
||||||
|
0
django/db/backends/mysql_old/__init__.py
Normal file
0
django/db/backends/mysql_old/__init__.py
Normal file
233
django/db/backends/mysql_old/base.py
Normal file
233
django/db/backends/mysql_old/base.py
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
"""
|
||||||
|
MySQL database backend for Django.
|
||||||
|
|
||||||
|
Requires MySQLdb: http://sourceforge.net/projects/mysql-python
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.db.backends import util
|
||||||
|
try:
|
||||||
|
import MySQLdb as Database
|
||||||
|
except ImportError, e:
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
raise ImproperlyConfigured, "Error loading MySQLdb module: %s" % e
|
||||||
|
from MySQLdb.converters import conversions
|
||||||
|
from MySQLdb.constants import FIELD_TYPE
|
||||||
|
import types
|
||||||
|
import re
|
||||||
|
|
||||||
|
DatabaseError = Database.DatabaseError
|
||||||
|
|
||||||
|
django_conversions = conversions.copy()
|
||||||
|
django_conversions.update({
|
||||||
|
types.BooleanType: util.rev_typecast_boolean,
|
||||||
|
FIELD_TYPE.DATETIME: util.typecast_timestamp,
|
||||||
|
FIELD_TYPE.DATE: util.typecast_date,
|
||||||
|
FIELD_TYPE.TIME: util.typecast_time,
|
||||||
|
})
|
||||||
|
|
||||||
|
# This should match the numerical portion of the version numbers (we can treat
|
||||||
|
# versions like 5.0.24 and 5.0.24a as the same). Based on the list of version
|
||||||
|
# at http://dev.mysql.com/doc/refman/4.1/en/news.html and
|
||||||
|
# http://dev.mysql.com/doc/refman/5.0/en/news.html .
|
||||||
|
server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})')
|
||||||
|
|
||||||
|
# This is an extra debug layer over MySQL queries, to display warnings.
|
||||||
|
# It's only used when DEBUG=True.
|
||||||
|
class MysqlDebugWrapper:
|
||||||
|
def __init__(self, cursor):
|
||||||
|
self.cursor = cursor
|
||||||
|
|
||||||
|
def execute(self, sql, params=()):
|
||||||
|
try:
|
||||||
|
return self.cursor.execute(sql, params)
|
||||||
|
except Database.Warning, w:
|
||||||
|
self.cursor.execute("SHOW WARNINGS")
|
||||||
|
raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
|
||||||
|
|
||||||
|
def executemany(self, sql, param_list):
|
||||||
|
try:
|
||||||
|
return self.cursor.executemany(sql, param_list)
|
||||||
|
except Database.Warning, w:
|
||||||
|
self.cursor.execute("SHOW WARNINGS")
|
||||||
|
raise Database.Warning, "%s: %s" % (w, self.cursor.fetchall())
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
if self.__dict__.has_key(attr):
|
||||||
|
return self.__dict__[attr]
|
||||||
|
else:
|
||||||
|
return getattr(self.cursor, attr)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Only exists in Python 2.4+
|
||||||
|
from threading import local
|
||||||
|
except ImportError:
|
||||||
|
# Import copy of _thread_local.py from Python 2.4
|
||||||
|
from django.utils._threading_local import local
|
||||||
|
|
||||||
|
class DatabaseWrapper(local):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
self.connection = None
|
||||||
|
self.queries = []
|
||||||
|
self.server_version = None
|
||||||
|
self.options = kwargs
|
||||||
|
|
||||||
|
def _valid_connection(self):
|
||||||
|
if self.connection is not None:
|
||||||
|
try:
|
||||||
|
self.connection.ping()
|
||||||
|
return True
|
||||||
|
except DatabaseError:
|
||||||
|
self.connection.close()
|
||||||
|
self.connection = None
|
||||||
|
return False
|
||||||
|
|
||||||
|
def cursor(self):
|
||||||
|
from django.conf import settings
|
||||||
|
if not self._valid_connection():
|
||||||
|
kwargs = {
|
||||||
|
'user': settings.DATABASE_USER,
|
||||||
|
'db': settings.DATABASE_NAME,
|
||||||
|
'passwd': settings.DATABASE_PASSWORD,
|
||||||
|
'conv': django_conversions,
|
||||||
|
}
|
||||||
|
if settings.DATABASE_HOST.startswith('/'):
|
||||||
|
kwargs['unix_socket'] = settings.DATABASE_HOST
|
||||||
|
else:
|
||||||
|
kwargs['host'] = settings.DATABASE_HOST
|
||||||
|
if settings.DATABASE_PORT:
|
||||||
|
kwargs['port'] = int(settings.DATABASE_PORT)
|
||||||
|
kwargs.update(self.options)
|
||||||
|
self.connection = Database.connect(**kwargs)
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
if self.connection.get_server_info() >= '4.1':
|
||||||
|
cursor.execute("SET NAMES 'utf8'")
|
||||||
|
else:
|
||||||
|
cursor = self.connection.cursor()
|
||||||
|
if settings.DEBUG:
|
||||||
|
return util.CursorDebugWrapper(MysqlDebugWrapper(cursor), self)
|
||||||
|
return cursor
|
||||||
|
|
||||||
|
def _commit(self):
|
||||||
|
if self.connection is not None:
|
||||||
|
self.connection.commit()
|
||||||
|
|
||||||
|
def _rollback(self):
|
||||||
|
if self.connection is not None:
|
||||||
|
try:
|
||||||
|
self.connection.rollback()
|
||||||
|
except Database.NotSupportedError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
if self.connection is not None:
|
||||||
|
self.connection.close()
|
||||||
|
self.connection = None
|
||||||
|
|
||||||
|
def get_server_version(self):
|
||||||
|
if not self.server_version:
|
||||||
|
if not self._valid_connection():
|
||||||
|
self.cursor()
|
||||||
|
m = server_version_re.match(self.connection.get_server_info())
|
||||||
|
if not m:
|
||||||
|
raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info())
|
||||||
|
self.server_version = tuple([int(x) for x in m.groups()])
|
||||||
|
return self.server_version
|
||||||
|
|
||||||
|
supports_constraints = True
|
||||||
|
|
||||||
|
def quote_name(name):
|
||||||
|
if name.startswith("`") and name.endswith("`"):
|
||||||
|
return name # Quoting once is enough.
|
||||||
|
return "`%s`" % name
|
||||||
|
|
||||||
|
dictfetchone = util.dictfetchone
|
||||||
|
dictfetchmany = util.dictfetchmany
|
||||||
|
dictfetchall = util.dictfetchall
|
||||||
|
|
||||||
|
def get_last_insert_id(cursor, table_name, pk_name):
|
||||||
|
return cursor.lastrowid
|
||||||
|
|
||||||
|
def get_date_extract_sql(lookup_type, table_name):
|
||||||
|
# lookup_type is 'year', 'month', 'day'
|
||||||
|
# http://dev.mysql.com/doc/mysql/en/date-and-time-functions.html
|
||||||
|
return "EXTRACT(%s FROM %s)" % (lookup_type.upper(), table_name)
|
||||||
|
|
||||||
|
def get_date_trunc_sql(lookup_type, field_name):
|
||||||
|
# lookup_type is 'year', 'month', 'day'
|
||||||
|
fields = ['year', 'month', 'day', 'hour', 'minute', 'second']
|
||||||
|
format = ('%%Y-', '%%m', '-%%d', ' %%H:', '%%i', ':%%s') # Use double percents to escape.
|
||||||
|
format_def = ('0000-', '01', '-01', ' 00:', '00', ':00')
|
||||||
|
try:
|
||||||
|
i = fields.index(lookup_type) + 1
|
||||||
|
except ValueError:
|
||||||
|
sql = field_name
|
||||||
|
else:
|
||||||
|
format_str = ''.join([f for f in format[:i]] + [f for f in format_def[i:]])
|
||||||
|
sql = "CAST(DATE_FORMAT(%s, '%s') AS DATETIME)" % (field_name, format_str)
|
||||||
|
return sql
|
||||||
|
|
||||||
|
def get_limit_offset_sql(limit, offset=None):
|
||||||
|
sql = "LIMIT "
|
||||||
|
if offset and offset != 0:
|
||||||
|
sql += "%s," % offset
|
||||||
|
return sql + str(limit)
|
||||||
|
|
||||||
|
def get_random_function_sql():
|
||||||
|
return "RAND()"
|
||||||
|
|
||||||
|
def get_deferrable_sql():
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def get_fulltext_search_sql(field_name):
|
||||||
|
return 'MATCH (%s) AGAINST (%%s IN BOOLEAN MODE)' % field_name
|
||||||
|
|
||||||
|
def get_drop_foreignkey_sql():
|
||||||
|
return "DROP FOREIGN KEY"
|
||||||
|
|
||||||
|
def get_pk_default_value():
|
||||||
|
return "DEFAULT"
|
||||||
|
|
||||||
|
def get_sql_flush(style, tables, sequences):
|
||||||
|
"""Return a list of SQL statements required to remove all data from
|
||||||
|
all tables in the database (without actually removing the tables
|
||||||
|
themselves) and put the database in an empty 'initial' state
|
||||||
|
|
||||||
|
"""
|
||||||
|
# NB: The generated SQL below is specific to MySQL
|
||||||
|
# 'TRUNCATE x;', 'TRUNCATE y;', 'TRUNCATE z;'... style SQL statements
|
||||||
|
# to clear all tables of all data
|
||||||
|
if tables:
|
||||||
|
sql = ['SET FOREIGN_KEY_CHECKS = 0;'] + \
|
||||||
|
['%s %s;' % \
|
||||||
|
(style.SQL_KEYWORD('TRUNCATE'),
|
||||||
|
style.SQL_FIELD(quote_name(table))
|
||||||
|
) for table in tables] + \
|
||||||
|
['SET FOREIGN_KEY_CHECKS = 1;']
|
||||||
|
|
||||||
|
# 'ALTER TABLE table AUTO_INCREMENT = 1;'... style SQL statements
|
||||||
|
# to reset sequence indices
|
||||||
|
sql.extend(["%s %s %s %s %s;" % \
|
||||||
|
(style.SQL_KEYWORD('ALTER'),
|
||||||
|
style.SQL_KEYWORD('TABLE'),
|
||||||
|
style.SQL_TABLE(quote_name(sequence['table'])),
|
||||||
|
style.SQL_KEYWORD('AUTO_INCREMENT'),
|
||||||
|
style.SQL_FIELD('= 1'),
|
||||||
|
) for sequence in sequences])
|
||||||
|
return sql
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
OPERATOR_MAPPING = {
|
||||||
|
'exact': '= %s',
|
||||||
|
'iexact': 'LIKE %s',
|
||||||
|
'contains': 'LIKE BINARY %s',
|
||||||
|
'icontains': 'LIKE %s',
|
||||||
|
'gt': '> %s',
|
||||||
|
'gte': '>= %s',
|
||||||
|
'lt': '< %s',
|
||||||
|
'lte': '<= %s',
|
||||||
|
'startswith': 'LIKE BINARY %s',
|
||||||
|
'endswith': 'LIKE BINARY %s',
|
||||||
|
'istartswith': 'LIKE %s',
|
||||||
|
'iendswith': 'LIKE %s',
|
||||||
|
}
|
14
django/db/backends/mysql_old/client.py
Normal file
14
django/db/backends/mysql_old/client.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from django.conf import settings
|
||||||
|
import os
|
||||||
|
|
||||||
|
def runshell():
|
||||||
|
args = ['']
|
||||||
|
args += ["--user=%s" % settings.DATABASE_USER]
|
||||||
|
if settings.DATABASE_PASSWORD:
|
||||||
|
args += ["--password=%s" % settings.DATABASE_PASSWORD]
|
||||||
|
if settings.DATABASE_HOST:
|
||||||
|
args += ["--host=%s" % settings.DATABASE_HOST]
|
||||||
|
if settings.DATABASE_PORT:
|
||||||
|
args += ["--port=%s" % settings.DATABASE_PORT]
|
||||||
|
args += [settings.DATABASE_NAME]
|
||||||
|
os.execvp('mysql', args)
|
29
django/db/backends/mysql_old/creation.py
Normal file
29
django/db/backends/mysql_old/creation.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# This dictionary maps Field objects to their associated MySQL 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 = {
|
||||||
|
'AutoField': 'integer AUTO_INCREMENT',
|
||||||
|
'BooleanField': 'bool',
|
||||||
|
'CharField': 'varchar(%(maxlength)s)',
|
||||||
|
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
|
||||||
|
'DateField': 'date',
|
||||||
|
'DateTimeField': 'datetime',
|
||||||
|
'FileField': 'varchar(100)',
|
||||||
|
'FilePathField': 'varchar(100)',
|
||||||
|
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
|
||||||
|
'ImageField': 'varchar(100)',
|
||||||
|
'IntegerField': 'integer',
|
||||||
|
'IPAddressField': 'char(15)',
|
||||||
|
'ManyToManyField': None,
|
||||||
|
'NullBooleanField': 'bool',
|
||||||
|
'OneToOneField': 'integer',
|
||||||
|
'PhoneNumberField': 'varchar(20)',
|
||||||
|
'PositiveIntegerField': 'integer UNSIGNED',
|
||||||
|
'PositiveSmallIntegerField': 'smallint UNSIGNED',
|
||||||
|
'SlugField': 'varchar(%(maxlength)s)',
|
||||||
|
'SmallIntegerField': 'smallint',
|
||||||
|
'TextField': 'longtext',
|
||||||
|
'TimeField': 'time',
|
||||||
|
'USStateField': 'varchar(2)',
|
||||||
|
}
|
95
django/db/backends/mysql_old/introspection.py
Normal file
95
django/db/backends/mysql_old/introspection.py
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
from django.db.backends.mysql_old.base import quote_name
|
||||||
|
from MySQLdb import ProgrammingError, OperationalError
|
||||||
|
from MySQLdb.constants import FIELD_TYPE
|
||||||
|
import re
|
||||||
|
|
||||||
|
foreign_key_re = re.compile(r"\sCONSTRAINT `[^`]*` FOREIGN KEY \(`([^`]*)`\) REFERENCES `([^`]*)` \(`([^`]*)`\)")
|
||||||
|
|
||||||
|
def get_table_list(cursor):
|
||||||
|
"Returns a list of table names in the current database."
|
||||||
|
cursor.execute("SHOW TABLES")
|
||||||
|
return [row[0] for row in cursor.fetchall()]
|
||||||
|
|
||||||
|
def get_table_description(cursor, table_name):
|
||||||
|
"Returns a description of the table, with the DB-API cursor.description interface."
|
||||||
|
cursor.execute("SELECT * FROM %s LIMIT 1" % quote_name(table_name))
|
||||||
|
return cursor.description
|
||||||
|
|
||||||
|
def _name_to_index(cursor, table_name):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of {field_name: field_index} for the given table.
|
||||||
|
Indexes are 0-based.
|
||||||
|
"""
|
||||||
|
return dict([(d[0], i) for i, d in enumerate(get_table_description(cursor, table_name))])
|
||||||
|
|
||||||
|
def get_relations(cursor, table_name):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of {field_index: (field_index_other_table, other_table)}
|
||||||
|
representing all relationships to the given table. Indexes are 0-based.
|
||||||
|
"""
|
||||||
|
my_field_dict = _name_to_index(cursor, table_name)
|
||||||
|
constraints = []
|
||||||
|
relations = {}
|
||||||
|
try:
|
||||||
|
# This should work for MySQL 5.0.
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT column_name, referenced_table_name, referenced_column_name
|
||||||
|
FROM information_schema.key_column_usage
|
||||||
|
WHERE table_name = %s
|
||||||
|
AND table_schema = DATABASE()
|
||||||
|
AND referenced_table_name IS NOT NULL
|
||||||
|
AND referenced_column_name IS NOT NULL""", [table_name])
|
||||||
|
constraints.extend(cursor.fetchall())
|
||||||
|
except (ProgrammingError, OperationalError):
|
||||||
|
# Fall back to "SHOW CREATE TABLE", for previous MySQL versions.
|
||||||
|
# Go through all constraints and save the equal matches.
|
||||||
|
cursor.execute("SHOW CREATE TABLE %s" % quote_name(table_name))
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
pos = 0
|
||||||
|
while True:
|
||||||
|
match = foreign_key_re.search(row[1], pos)
|
||||||
|
if match == None:
|
||||||
|
break
|
||||||
|
pos = match.end()
|
||||||
|
constraints.append(match.groups())
|
||||||
|
|
||||||
|
for my_fieldname, other_table, other_field in constraints:
|
||||||
|
other_field_index = _name_to_index(cursor, other_table)[other_field]
|
||||||
|
my_field_index = my_field_dict[my_fieldname]
|
||||||
|
relations[my_field_index] = (other_field_index, other_table)
|
||||||
|
|
||||||
|
return relations
|
||||||
|
|
||||||
|
def get_indexes(cursor, table_name):
|
||||||
|
"""
|
||||||
|
Returns a dictionary of fieldname -> infodict for the given table,
|
||||||
|
where each infodict is in the format:
|
||||||
|
{'primary_key': boolean representing whether it's the primary key,
|
||||||
|
'unique': boolean representing whether it's a unique index}
|
||||||
|
"""
|
||||||
|
cursor.execute("SHOW INDEX FROM %s" % quote_name(table_name))
|
||||||
|
indexes = {}
|
||||||
|
for row in cursor.fetchall():
|
||||||
|
indexes[row[4]] = {'primary_key': (row[2] == 'PRIMARY'), 'unique': not bool(row[1])}
|
||||||
|
return indexes
|
||||||
|
|
||||||
|
DATA_TYPES_REVERSE = {
|
||||||
|
FIELD_TYPE.BLOB: 'TextField',
|
||||||
|
FIELD_TYPE.CHAR: 'CharField',
|
||||||
|
FIELD_TYPE.DECIMAL: 'FloatField',
|
||||||
|
FIELD_TYPE.DATE: 'DateField',
|
||||||
|
FIELD_TYPE.DATETIME: 'DateTimeField',
|
||||||
|
FIELD_TYPE.DOUBLE: 'FloatField',
|
||||||
|
FIELD_TYPE.FLOAT: 'FloatField',
|
||||||
|
FIELD_TYPE.INT24: 'IntegerField',
|
||||||
|
FIELD_TYPE.LONG: 'IntegerField',
|
||||||
|
FIELD_TYPE.LONGLONG: 'IntegerField',
|
||||||
|
FIELD_TYPE.SHORT: 'IntegerField',
|
||||||
|
FIELD_TYPE.STRING: 'TextField',
|
||||||
|
FIELD_TYPE.TIMESTAMP: 'DateTimeField',
|
||||||
|
FIELD_TYPE.TINY: 'IntegerField',
|
||||||
|
FIELD_TYPE.TINY_BLOB: 'TextField',
|
||||||
|
FIELD_TYPE.MEDIUM_BLOB: 'TextField',
|
||||||
|
FIELD_TYPE.LONG_BLOB: 'TextField',
|
||||||
|
FIELD_TYPE.VAR_STRING: 'CharField',
|
||||||
|
}
|
@ -43,10 +43,11 @@ class DatabaseWrapper(local):
|
|||||||
return FormatStylePlaceholderCursor(self.connection)
|
return FormatStylePlaceholderCursor(self.connection)
|
||||||
|
|
||||||
def _commit(self):
|
def _commit(self):
|
||||||
self.connection.commit()
|
if self.connection is not None:
|
||||||
|
self.connection.commit()
|
||||||
|
|
||||||
def _rollback(self):
|
def _rollback(self):
|
||||||
if self.connection:
|
if self.connection is not None:
|
||||||
try:
|
try:
|
||||||
self.connection.rollback()
|
self.connection.rollback()
|
||||||
except Database.NotSupportedError:
|
except Database.NotSupportedError:
|
||||||
|
@ -92,10 +92,11 @@ class DatabaseWrapper(local):
|
|||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
def _commit(self):
|
def _commit(self):
|
||||||
return self.connection.commit()
|
if self.connection is not None:
|
||||||
|
return self.connection.commit()
|
||||||
|
|
||||||
def _rollback(self):
|
def _rollback(self):
|
||||||
if self.connection:
|
if self.connection is not None:
|
||||||
return self.connection.rollback()
|
return self.connection.rollback()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
@ -60,10 +60,11 @@ class DatabaseWrapper(local):
|
|||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
def _commit(self):
|
def _commit(self):
|
||||||
return self.connection.commit()
|
if self.connection is not None:
|
||||||
|
return self.connection.commit()
|
||||||
|
|
||||||
def _rollback(self):
|
def _rollback(self):
|
||||||
if self.connection:
|
if self.connection is not None:
|
||||||
return self.connection.rollback()
|
return self.connection.rollback()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
@ -67,10 +67,11 @@ class DatabaseWrapper(local):
|
|||||||
return cursor
|
return cursor
|
||||||
|
|
||||||
def _commit(self):
|
def _commit(self):
|
||||||
self.connection.commit()
|
if self.connection is not None:
|
||||||
|
self.connection.commit()
|
||||||
|
|
||||||
def _rollback(self):
|
def _rollback(self):
|
||||||
if self.connection:
|
if self.connection is not None:
|
||||||
self.connection.rollback()
|
self.connection.rollback()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
|
@ -67,7 +67,7 @@ class Field(object):
|
|||||||
|
|
||||||
def __init__(self, verbose_name=None, name=None, primary_key=False,
|
def __init__(self, verbose_name=None, name=None, primary_key=False,
|
||||||
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,
|
core=False, rel=None, default=NOT_PROVIDED, editable=True, serialize=True,
|
||||||
prepopulate_from=None, unique_for_date=None, unique_for_month=None,
|
prepopulate_from=None, unique_for_date=None, unique_for_month=None,
|
||||||
unique_for_year=None, validator_list=None, choices=None, radio_admin=None,
|
unique_for_year=None, validator_list=None, choices=None, radio_admin=None,
|
||||||
help_text='', db_column=None):
|
help_text='', db_column=None):
|
||||||
@ -78,6 +78,7 @@ class Field(object):
|
|||||||
self.blank, self.null = blank, null
|
self.blank, self.null = blank, null
|
||||||
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.validator_list = validator_list or []
|
self.validator_list = validator_list or []
|
||||||
self.prepopulate_from = prepopulate_from
|
self.prepopulate_from = prepopulate_from
|
||||||
self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month
|
self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month
|
||||||
@ -742,6 +743,13 @@ class NullBooleanField(Field):
|
|||||||
kwargs['null'] = True
|
kwargs['null'] = True
|
||||||
Field.__init__(self, *args, **kwargs)
|
Field.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
def to_python(self, value):
|
||||||
|
if value in (None, True, False): return value
|
||||||
|
if value in ('None'): return None
|
||||||
|
if value in ('t', 'True', '1'): return True
|
||||||
|
if value in ('f', 'False', '0'): return False
|
||||||
|
raise validators.ValidationError, gettext("This value must be either None, True or False.")
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
return [oldforms.NullBooleanField]
|
return [oldforms.NullBooleanField]
|
||||||
|
|
||||||
@ -819,7 +827,7 @@ class TimeField(Field):
|
|||||||
if value is not None:
|
if value is not None:
|
||||||
# MySQL will throw a warning if microseconds are given, because it
|
# MySQL will throw a warning if microseconds are given, because it
|
||||||
# doesn't support microseconds.
|
# doesn't support microseconds.
|
||||||
if settings.DATABASE_ENGINE == 'mysql':
|
if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'):
|
||||||
value = value.replace(microsecond=0)
|
value = value.replace(microsecond=0)
|
||||||
value = str(value)
|
value = str(value)
|
||||||
return Field.get_db_prep_save(self, value)
|
return Field.get_db_prep_save(self, value)
|
||||||
|
@ -94,6 +94,7 @@ class GenericRelation(RelatedField, Field):
|
|||||||
|
|
||||||
kwargs['blank'] = True
|
kwargs['blank'] = True
|
||||||
kwargs['editable'] = False
|
kwargs['editable'] = False
|
||||||
|
kwargs['serialize'] = False
|
||||||
Field.__init__(self, **kwargs)
|
Field.__init__(self, **kwargs)
|
||||||
|
|
||||||
def get_manipulator_field_objs(self):
|
def get_manipulator_field_objs(self):
|
||||||
|
@ -84,6 +84,7 @@ class Options(object):
|
|||||||
self.fields.insert(bisect(self.fields, field), field)
|
self.fields.insert(bisect(self.fields, field), field)
|
||||||
if not self.pk and field.primary_key:
|
if not self.pk and field.primary_key:
|
||||||
self.pk = field
|
self.pk = field
|
||||||
|
field.serialize = False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<Options for %s>' % self.object_name
|
return '<Options for %s>' % self.object_name
|
||||||
|
@ -109,6 +109,8 @@ class QuerySet(object):
|
|||||||
|
|
||||||
def __getitem__(self, k):
|
def __getitem__(self, k):
|
||||||
"Retrieve an item or slice from the set of results."
|
"Retrieve an item or slice from the set of results."
|
||||||
|
if not isinstance(k, (slice, int)):
|
||||||
|
raise TypeError
|
||||||
assert (not isinstance(k, slice) and (k >= 0)) \
|
assert (not isinstance(k, slice) and (k >= 0)) \
|
||||||
or (isinstance(k, slice) and (k.start is None or k.start >= 0) and (k.stop is None or k.stop >= 0)), \
|
or (isinstance(k, slice) and (k.start is None or k.start >= 0) and (k.stop is None or k.stop >= 0)), \
|
||||||
"Negative indexing is not supported."
|
"Negative indexing is not supported."
|
||||||
@ -780,7 +782,7 @@ def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen,
|
|||||||
def parse_lookup(kwarg_items, opts):
|
def parse_lookup(kwarg_items, opts):
|
||||||
# Helper function that handles converting API kwargs
|
# Helper function that handles converting API kwargs
|
||||||
# (e.g. "name__exact": "tom") to SQL.
|
# (e.g. "name__exact": "tom") to SQL.
|
||||||
# Returns a tuple of (tables, joins, where, params).
|
# Returns a tuple of (joins, where, params).
|
||||||
|
|
||||||
# 'joins' is a sorted dictionary describing the tables that must be joined
|
# 'joins' is a sorted dictionary describing the tables that must be joined
|
||||||
# to complete the query. The dictionary is sorted because creation order
|
# to complete the query. The dictionary is sorted because creation order
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
class BoundRelatedObject(object):
|
class BoundRelatedObject(object):
|
||||||
def __init__(self, related_object, field_mapping, original):
|
def __init__(self, related_object, field_mapping, original):
|
||||||
self.relation = related_object
|
self.relation = related_object
|
||||||
self.field_mappings = field_mapping[related_object.opts.module_name]
|
self.field_mappings = field_mapping[related_object.name]
|
||||||
|
|
||||||
def template_name(self):
|
def template_name(self):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
@ -16,7 +16,7 @@ class RelatedObject(object):
|
|||||||
self.opts = model._meta
|
self.opts = model._meta
|
||||||
self.field = field
|
self.field = field
|
||||||
self.edit_inline = field.rel.edit_inline
|
self.edit_inline = field.rel.edit_inline
|
||||||
self.name = self.opts.module_name
|
self.name = '%s:%s' % (self.opts.app_label, self.opts.module_name)
|
||||||
self.var_name = self.opts.object_name.lower()
|
self.var_name = self.opts.object_name.lower()
|
||||||
|
|
||||||
def flatten_data(self, follow, obj=None):
|
def flatten_data(self, follow, obj=None):
|
||||||
|
@ -130,7 +130,9 @@ class FormWrapper(object):
|
|||||||
if self.edit_inline:
|
if self.edit_inline:
|
||||||
self.fill_inline_collections()
|
self.fill_inline_collections()
|
||||||
for inline_collection in self._inline_collections:
|
for inline_collection in self._inline_collections:
|
||||||
if inline_collection.name == key:
|
# The 'orig_name' comparison is for backwards compatibility
|
||||||
|
# with hand-crafted forms.
|
||||||
|
if inline_collection.name == key or (':' not in key and inline_collection.orig_name == key):
|
||||||
return inline_collection
|
return inline_collection
|
||||||
raise KeyError, "Could not find Formfield or InlineObjectCollection named %r" % key
|
raise KeyError, "Could not find Formfield or InlineObjectCollection named %r" % key
|
||||||
|
|
||||||
@ -226,6 +228,9 @@ class InlineObjectCollection(object):
|
|||||||
self.errors = errors
|
self.errors = errors
|
||||||
self._collections = None
|
self._collections = None
|
||||||
self.name = rel_obj.name
|
self.name = rel_obj.name
|
||||||
|
# This is the name used prior to fixing #1839. Needs for backwards
|
||||||
|
# compatibility.
|
||||||
|
self.orig_name = rel_obj.opts.module_name
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
self.fill()
|
self.fill()
|
||||||
|
@ -19,7 +19,7 @@ def get_object_or_404(klass, *args, **kwargs):
|
|||||||
try:
|
try:
|
||||||
return manager.get(*args, **kwargs)
|
return manager.get(*args, **kwargs)
|
||||||
except klass.DoesNotExist:
|
except klass.DoesNotExist:
|
||||||
raise Http404
|
raise Http404('No %s matches the given query.' % klass._meta.object_name)
|
||||||
|
|
||||||
def get_list_or_404(klass, *args, **kwargs):
|
def get_list_or_404(klass, *args, **kwargs):
|
||||||
if isinstance(klass, Manager):
|
if isinstance(klass, Manager):
|
||||||
@ -28,5 +28,5 @@ def get_list_or_404(klass, *args, **kwargs):
|
|||||||
manager = klass._default_manager
|
manager = klass._default_manager
|
||||||
obj_list = list(manager.filter(*args, **kwargs))
|
obj_list = list(manager.filter(*args, **kwargs))
|
||||||
if not obj_list:
|
if not obj_list:
|
||||||
raise Http404
|
raise Http404('No %s matches the given query.' % manager.model._meta.object_name)
|
||||||
return obj_list
|
return obj_list
|
||||||
|
@ -91,6 +91,8 @@ UNKNOWN_SOURCE="<unknown source>"
|
|||||||
tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
|
tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
|
||||||
re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
|
re.escape(VARIABLE_TAG_START), re.escape(VARIABLE_TAG_END),
|
||||||
re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END)))
|
re.escape(COMMENT_TAG_START), re.escape(COMMENT_TAG_END)))
|
||||||
|
# matches if the string is valid number
|
||||||
|
number_re = re.compile(r'[-+]?(\d+|\d*\.\d+)$')
|
||||||
|
|
||||||
# global dictionary of libraries that have been loaded using get_library
|
# global dictionary of libraries that have been loaded using get_library
|
||||||
libraries = {}
|
libraries = {}
|
||||||
@ -632,12 +634,9 @@ def resolve_variable(path, context):
|
|||||||
|
|
||||||
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
|
(The example assumes VARIABLE_ATTRIBUTE_SEPARATOR is '.')
|
||||||
"""
|
"""
|
||||||
if path[0].isdigit():
|
if number_re.match(path):
|
||||||
number_type = '.' in path and float or int
|
number_type = '.' in path and float or int
|
||||||
try:
|
current = number_type(path)
|
||||||
current = number_type(path)
|
|
||||||
except ValueError:
|
|
||||||
current = settings.TEMPLATE_STRING_IF_INVALID
|
|
||||||
elif path[0] in ('"', "'") and path[0] == path[-1]:
|
elif path[0] in ('"', "'") and path[0] == path[-1]:
|
||||||
current = path[1:-1]
|
current = path[1:-1]
|
||||||
else:
|
else:
|
||||||
|
@ -70,14 +70,15 @@ def floatformat(text, arg=-1):
|
|||||||
With a negative numeric argument, it will display that many decimal
|
With a negative numeric argument, it will display that many decimal
|
||||||
places -- but only if there's places to be displayed.
|
places -- but only if there's places to be displayed.
|
||||||
Examples:
|
Examples:
|
||||||
num1 = 34.23234
|
|
||||||
num2 = 34.00000
|
* num1 = 34.23234
|
||||||
num1|floatformat results in 34.2
|
* num2 = 34.00000
|
||||||
num2|floatformat is 34
|
* num1|floatformat results in 34.2
|
||||||
num1|floatformat:3 is 34.232
|
* num2|floatformat is 34
|
||||||
num2|floatformat:3 is 34.000
|
* num1|floatformat:3 is 34.232
|
||||||
num1|floatformat:-3 is 34.232
|
* num2|floatformat:3 is 34.000
|
||||||
num2|floatformat:-3 is 34
|
* num1|floatformat:-3 is 34.232
|
||||||
|
* num2|floatformat:-3 is 34
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
f = float(text)
|
f = float(text)
|
||||||
|
@ -435,6 +435,15 @@ def cycle(parser, token):
|
|||||||
cycle = register.tag(cycle)
|
cycle = register.tag(cycle)
|
||||||
|
|
||||||
def debug(parser, token):
|
def debug(parser, token):
|
||||||
|
"""
|
||||||
|
Output a whole load of debugging information, including the current context and imported modules.
|
||||||
|
|
||||||
|
Sample usage::
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
{% debug %}
|
||||||
|
</pre>
|
||||||
|
"""
|
||||||
return DebugNode()
|
return DebugNode()
|
||||||
debug = register.tag(debug)
|
debug = register.tag(debug)
|
||||||
|
|
||||||
@ -538,21 +547,6 @@ def do_for(parser, token):
|
|||||||
do_for = register.tag("for", do_for)
|
do_for = register.tag("for", do_for)
|
||||||
|
|
||||||
def do_ifequal(parser, token, negate):
|
def do_ifequal(parser, token, negate):
|
||||||
"""
|
|
||||||
Output the contents of the block if the two arguments equal/don't equal each other.
|
|
||||||
|
|
||||||
Examples::
|
|
||||||
|
|
||||||
{% ifequal user.id comment.user_id %}
|
|
||||||
...
|
|
||||||
{% endifequal %}
|
|
||||||
|
|
||||||
{% ifnotequal user.id comment.user_id %}
|
|
||||||
...
|
|
||||||
{% else %}
|
|
||||||
...
|
|
||||||
{% endifnotequal %}
|
|
||||||
"""
|
|
||||||
bits = list(token.split_contents())
|
bits = list(token.split_contents())
|
||||||
if len(bits) != 3:
|
if len(bits) != 3:
|
||||||
raise TemplateSyntaxError, "%r takes two arguments" % bits[0]
|
raise TemplateSyntaxError, "%r takes two arguments" % bits[0]
|
||||||
@ -568,11 +562,27 @@ def do_ifequal(parser, token, negate):
|
|||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def ifequal(parser, token):
|
def ifequal(parser, token):
|
||||||
|
"""
|
||||||
|
Output the contents of the block if the two arguments equal each other.
|
||||||
|
|
||||||
|
Examples::
|
||||||
|
|
||||||
|
{% ifequal user.id comment.user_id %}
|
||||||
|
...
|
||||||
|
{% endifequal %}
|
||||||
|
|
||||||
|
{% ifnotequal user.id comment.user_id %}
|
||||||
|
...
|
||||||
|
{% else %}
|
||||||
|
...
|
||||||
|
{% endifnotequal %}
|
||||||
|
"""
|
||||||
return do_ifequal(parser, token, False)
|
return do_ifequal(parser, token, False)
|
||||||
ifequal = register.tag(ifequal)
|
ifequal = register.tag(ifequal)
|
||||||
|
|
||||||
#@register.tag
|
#@register.tag
|
||||||
def ifnotequal(parser, token):
|
def ifnotequal(parser, token):
|
||||||
|
"""Output the contents of the block if the two arguments are not equal. See ifequal."""
|
||||||
return do_ifequal(parser, token, True)
|
return do_ifequal(parser, token, True)
|
||||||
ifnotequal = register.tag(ifnotequal)
|
ifnotequal = register.tag(ifnotequal)
|
||||||
|
|
||||||
@ -889,8 +899,9 @@ templatetag = register.tag(templatetag)
|
|||||||
|
|
||||||
def url(parser, token):
|
def url(parser, token):
|
||||||
"""
|
"""
|
||||||
Returns an absolute URL matching given view with its parameters. This is a
|
Returns an absolute URL matching given view with its parameters.
|
||||||
way to define links that aren't tied to a particular url configuration:
|
|
||||||
|
This is a way to define links that aren't tied to a particular URL configuration::
|
||||||
|
|
||||||
{% url path.to.some_view arg1,arg2,name1=value1 %}
|
{% url path.to.some_view arg1,arg2,name1=value1 %}
|
||||||
|
|
||||||
@ -901,16 +912,16 @@ def url(parser, token):
|
|||||||
URL. All arguments for the URL should be present.
|
URL. All arguments for the URL should be present.
|
||||||
|
|
||||||
For example if you have a view ``app_name.client`` taking client's id and
|
For example if you have a view ``app_name.client`` taking client's id and
|
||||||
the corresponding line in a urlconf looks like this:
|
the corresponding line in a URLconf looks like this::
|
||||||
|
|
||||||
('^client/(\d+)/$', 'app_name.client')
|
('^client/(\d+)/$', 'app_name.client')
|
||||||
|
|
||||||
and this app's urlconf is included into the project's urlconf under some
|
and this app's URLconf is included into the project's URLconf under some
|
||||||
path:
|
path::
|
||||||
|
|
||||||
('^clients/', include('project_name.app_name.urls'))
|
('^clients/', include('project_name.app_name.urls'))
|
||||||
|
|
||||||
then in a template you can create a link for a certain client like this:
|
then in a template you can create a link for a certain client like this::
|
||||||
|
|
||||||
{% url app_name.client client.id %}
|
{% url app_name.client client.id %}
|
||||||
|
|
||||||
|
@ -69,6 +69,14 @@ def encode_multipart(boundary, data):
|
|||||||
'',
|
'',
|
||||||
value.read()
|
value.read()
|
||||||
])
|
])
|
||||||
|
elif hasattr(value, '__iter__'):
|
||||||
|
for item in value:
|
||||||
|
lines.extend([
|
||||||
|
'--' + boundary,
|
||||||
|
'Content-Disposition: form-data; name="%s"' % key,
|
||||||
|
'',
|
||||||
|
str(item)
|
||||||
|
])
|
||||||
else:
|
else:
|
||||||
lines.extend([
|
lines.extend([
|
||||||
'--' + boundary,
|
'--' + boundary,
|
||||||
|
@ -92,6 +92,13 @@ class SortedDict(dict):
|
|||||||
"Returns the value of the item at the given zero-based index."
|
"Returns the value of the item at the given zero-based index."
|
||||||
return self[self.keyOrder[index]]
|
return self[self.keyOrder[index]]
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
"Returns a copy of this object."
|
||||||
|
# This way of initializing the copy means it works for subclasses, too.
|
||||||
|
obj = self.__class__(self)
|
||||||
|
obj.keyOrder = self.keyOrder
|
||||||
|
return obj
|
||||||
|
|
||||||
class MultiValueDictKeyError(KeyError):
|
class MultiValueDictKeyError(KeyError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ Usage:
|
|||||||
|
|
||||||
from django.utils.dates import MONTHS, MONTHS_3, MONTHS_AP, WEEKDAYS
|
from django.utils.dates import MONTHS, MONTHS_3, MONTHS_AP, WEEKDAYS
|
||||||
from django.utils.tzinfo import LocalTimezone
|
from django.utils.tzinfo import LocalTimezone
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
from calendar import isleap, monthrange
|
from calendar import isleap, monthrange
|
||||||
import re, time
|
import re, time
|
||||||
|
|
||||||
@ -36,14 +37,14 @@ class TimeFormat(Formatter):
|
|||||||
def a(self):
|
def a(self):
|
||||||
"'a.m.' or 'p.m.'"
|
"'a.m.' or 'p.m.'"
|
||||||
if self.data.hour > 11:
|
if self.data.hour > 11:
|
||||||
return 'p.m.'
|
return _('p.m.')
|
||||||
return 'a.m.'
|
return _('a.m.')
|
||||||
|
|
||||||
def A(self):
|
def A(self):
|
||||||
"'AM' or 'PM'"
|
"'AM' or 'PM'"
|
||||||
if self.data.hour > 11:
|
if self.data.hour > 11:
|
||||||
return 'PM'
|
return _('PM')
|
||||||
return 'AM'
|
return _('AM')
|
||||||
|
|
||||||
def B(self):
|
def B(self):
|
||||||
"Swatch Internet time"
|
"Swatch Internet time"
|
||||||
@ -91,9 +92,9 @@ class TimeFormat(Formatter):
|
|||||||
Proprietary extension.
|
Proprietary extension.
|
||||||
"""
|
"""
|
||||||
if self.data.minute == 0 and self.data.hour == 0:
|
if self.data.minute == 0 and self.data.hour == 0:
|
||||||
return 'midnight'
|
return _('midnight')
|
||||||
if self.data.minute == 0 and self.data.hour == 12:
|
if self.data.minute == 0 and self.data.hour == 12:
|
||||||
return 'noon'
|
return _('noon')
|
||||||
return '%s %s' % (self.f(), self.a())
|
return '%s %s' % (self.f(), self.a())
|
||||||
|
|
||||||
def s(self):
|
def s(self):
|
||||||
|
@ -17,7 +17,7 @@ def wrap(text, width):
|
|||||||
pos = len(word) - word.rfind('\n') - 1
|
pos = len(word) - word.rfind('\n') - 1
|
||||||
for word in it:
|
for word in it:
|
||||||
if "\n" in word:
|
if "\n" in word:
|
||||||
lines = word.splitlines()
|
lines = word.split('\n')
|
||||||
else:
|
else:
|
||||||
lines = (word,)
|
lines = (word,)
|
||||||
pos += len(lines[0]) + 1
|
pos += len(lines[0]) + 1
|
||||||
|
@ -9,16 +9,16 @@ def set_language(request):
|
|||||||
"""
|
"""
|
||||||
Redirect to a given url while setting the chosen language in the
|
Redirect to a given url while setting the chosen language in the
|
||||||
session or cookie. The url and the language code need to be
|
session or cookie. The url and the language code need to be
|
||||||
specified in the GET paramters.
|
specified in the GET parameters.
|
||||||
"""
|
"""
|
||||||
lang_code = request.GET['language']
|
lang_code = request.GET.get('language', None)
|
||||||
next = request.GET.get('next', None)
|
next = request.GET.get('next', None)
|
||||||
if not next:
|
if not next:
|
||||||
next = request.META.get('HTTP_REFERER', None)
|
next = request.META.get('HTTP_REFERER', None)
|
||||||
if not next:
|
if not next:
|
||||||
next = '/'
|
next = '/'
|
||||||
response = http.HttpResponseRedirect(next)
|
response = http.HttpResponseRedirect(next)
|
||||||
if check_for_language(lang_code):
|
if lang_code and check_for_language(lang_code):
|
||||||
if hasattr(request, 'session'):
|
if hasattr(request, 'session'):
|
||||||
request.session['django_language'] = lang_code
|
request.session['django_language'] = lang_code
|
||||||
else:
|
else:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
=====================
|
============================
|
||||||
The "contrib" add-ons
|
The "django.contrib" add-ons
|
||||||
=====================
|
============================
|
||||||
|
|
||||||
Django aims to follow Python's `"batteries included" philosophy`_. It ships
|
Django aims to follow Python's `"batteries included" philosophy`_. It ships
|
||||||
with a variety of extra, optional tools that solve common Web-development
|
with a variety of extra, optional tools that solve common Web-development
|
||||||
@ -153,12 +153,16 @@ markup
|
|||||||
|
|
||||||
A collection of template filters that implement these common markup languages:
|
A collection of template filters that implement these common markup languages:
|
||||||
|
|
||||||
* Textile
|
* `Textile`_
|
||||||
* Markdown
|
* `Markdown`_
|
||||||
* ReST (ReStructured Text)
|
* `ReST (ReStructured Text)`_
|
||||||
|
|
||||||
For documentation, read the source code in django/contrib/markup/templatetags/markup.py.
|
For documentation, read the source code in django/contrib/markup/templatetags/markup.py.
|
||||||
|
|
||||||
|
.. _Textile: http://en.wikipedia.org/wiki/Textile_%28markup_language%29
|
||||||
|
.. _Markdown: http://en.wikipedia.org/wiki/Markdown
|
||||||
|
.. _ReST (ReStructured Text): http://en.wikipedia.org/wiki/ReStructuredText
|
||||||
|
|
||||||
redirects
|
redirects
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ The second part of this workflow involves a set of flags the describe what the
|
|||||||
ticket has or needs in order to be "ready for checkin":
|
ticket has or needs in order to be "ready for checkin":
|
||||||
|
|
||||||
"Has patch"
|
"Has patch"
|
||||||
The means the ticket has an associated patch_. These will be
|
This means the ticket has an associated patch_. These will be
|
||||||
reviewed to see if the patch is "good".
|
reviewed to see if the patch is "good".
|
||||||
|
|
||||||
"Needs documentation"
|
"Needs documentation"
|
||||||
@ -212,6 +212,33 @@ ticket has or needs in order to be "ready for checkin":
|
|||||||
ready for checkin. This could mean the patch no longer applies
|
ready for checkin. This could mean the patch no longer applies
|
||||||
cleanly, or that the code doesn't live up to our standards.
|
cleanly, or that the code doesn't live up to our standards.
|
||||||
|
|
||||||
|
A ticket can be resolved in a number of ways:
|
||||||
|
|
||||||
|
"fixed"
|
||||||
|
Used by one of the core developers once a patch has been rolled into
|
||||||
|
Django and the issue is fixed.
|
||||||
|
|
||||||
|
"invalid"
|
||||||
|
Used if the ticket is found to be incorrect or a user error.
|
||||||
|
|
||||||
|
"wontfix"
|
||||||
|
Used when a core developer decides that this request is not
|
||||||
|
appropriate for consideration in Django. This is usually chosen after
|
||||||
|
discussion in the ``django-developers`` mailing list, and you should
|
||||||
|
feel free to join in when it's something you care about.
|
||||||
|
|
||||||
|
"duplicate"
|
||||||
|
Used when another ticket covers the same issue. By closing duplicate
|
||||||
|
tickets, we keep all the discussion in one place, which helps everyone.
|
||||||
|
|
||||||
|
"worksforme"
|
||||||
|
Used when the triage team is unable to replicate the original bug.
|
||||||
|
|
||||||
|
If you believe that the ticket was closed in error -- because you're
|
||||||
|
still having the issue, or it's popped up somewhere else, or the triagers have
|
||||||
|
-- made a mistake, please reopen the ticket and tell us why. Please do not
|
||||||
|
reopen tickets that have been marked as "wontfix" by core developers.
|
||||||
|
|
||||||
.. _required details: `Reporting bugs`_
|
.. _required details: `Reporting bugs`_
|
||||||
.. _good patch: `Patch style`_
|
.. _good patch: `Patch style`_
|
||||||
.. _patch: `Submitting patches`_
|
.. _patch: `Submitting patches`_
|
||||||
@ -276,9 +303,11 @@ Please follow these coding standards when writing code for inclusion in Django:
|
|||||||
def my_view(req, foo):
|
def my_view(req, foo):
|
||||||
# ...
|
# ...
|
||||||
|
|
||||||
* Please don't put your name in the code. While we appreciate all
|
* Please don't put your name in the code you contribute. Our policy is to
|
||||||
contributions to Django, our policy is not to publish individual
|
keep contributors' names in the ``AUTHORS`` file distributed with Django
|
||||||
developer names in code -- for instance, at the top of Python modules.
|
-- not scattered throughout the codebase itself. Feel free to include a
|
||||||
|
change to the ``AUTHORS`` file in your patch if you make more than a
|
||||||
|
single trivial change.
|
||||||
|
|
||||||
Committing code
|
Committing code
|
||||||
===============
|
===============
|
||||||
@ -498,12 +527,12 @@ sure all other lines are commented::
|
|||||||
# http://code.djangoproject.com/svn/django/trunk/
|
# http://code.djangoproject.com/svn/django/trunk/
|
||||||
#
|
#
|
||||||
/path/to/trunk
|
/path/to/trunk
|
||||||
|
|
||||||
# <branch> is a svn checkout of:
|
# <branch> is a svn checkout of:
|
||||||
# http://code.djangoproject.com/svn/django/branches/<branch>/
|
# http://code.djangoproject.com/svn/django/branches/<branch>/
|
||||||
#
|
#
|
||||||
#/path/to/<branch>
|
#/path/to/<branch>
|
||||||
|
|
||||||
# On windows a path may look like this:
|
# On windows a path may look like this:
|
||||||
# C:/path/to/<branch>
|
# C:/path/to/<branch>
|
||||||
|
|
||||||
|
162
docs/databases.txt
Normal file
162
docs/databases.txt
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
===============================
|
||||||
|
Notes about supported databases
|
||||||
|
===============================
|
||||||
|
|
||||||
|
Django attempts to support as many features as possible on all database
|
||||||
|
backends. However, not all database backends are alike, and we've had to make
|
||||||
|
design decisions on which features to support and which assumptions we can make
|
||||||
|
safely.
|
||||||
|
|
||||||
|
This file describes some of the features that might be relevant to Django
|
||||||
|
usage. Of course, it is not intended as a replacement for server-specific
|
||||||
|
documentation or reference manuals.
|
||||||
|
|
||||||
|
MySQL notes
|
||||||
|
===========
|
||||||
|
|
||||||
|
Django expects the database to support transactions, referential integrity,
|
||||||
|
and Unicode support (UTF-8 encoding). Fortunately, MySQL_ has all these
|
||||||
|
features as available as far back as 3.23. While it may be possible to use
|
||||||
|
3.23 or 4.0, you'll probably have less trouble if you use 4.1 or 5.0.
|
||||||
|
|
||||||
|
MySQL 4.1
|
||||||
|
---------
|
||||||
|
|
||||||
|
`MySQL 4.1`_ has greatly improved support for character sets. It is possible to
|
||||||
|
set different default character sets on the database, table, and column.
|
||||||
|
Previous versions have only a server-wide character set setting. It's also the
|
||||||
|
first version where the character set can be changed on the fly. 4.1 also has
|
||||||
|
support for views, but Django currently doesn't use views.
|
||||||
|
|
||||||
|
MySQL 5.0
|
||||||
|
---------
|
||||||
|
|
||||||
|
`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed
|
||||||
|
data on all database schema. Django's ``inspectdb`` feature uses this
|
||||||
|
``information_schema`` if it's available. 5.0 also has support for stored
|
||||||
|
procedures, but Django currently doesn't use stored procedures.
|
||||||
|
|
||||||
|
.. _MySQL: http://www.mysql.com/
|
||||||
|
.. _MySQL 4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html
|
||||||
|
.. _MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html
|
||||||
|
|
||||||
|
Storage engines
|
||||||
|
---------------
|
||||||
|
|
||||||
|
MySQL has several `storage engines`_ (previously called table types). You can
|
||||||
|
change the default storage engine in the server configuration.
|
||||||
|
|
||||||
|
The default engine is MyISAM_. The main drawback of MyISAM is that it doesn't
|
||||||
|
currently support transactions or foreign keys. On the plus side, it's
|
||||||
|
currently the only engine that supports full-text indexing and searching.
|
||||||
|
|
||||||
|
The InnoDB_ engine is fully transactional and supports foreign key references.
|
||||||
|
|
||||||
|
The BDB_ engine, like InnoDB, is also fully transactional and supports foreign
|
||||||
|
key references. However, its use seems to be deprecated.
|
||||||
|
|
||||||
|
`Other storage engines`_, including SolidDB_ and Falcon_, are on the horizon.
|
||||||
|
For now, InnoDB is probably your best choice.
|
||||||
|
|
||||||
|
.. _storage engines: http://dev.mysql.com/doc/refman/5.0/en/storage-engines.html
|
||||||
|
.. _MyISAM: http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html
|
||||||
|
.. _BDB: http://dev.mysql.com/doc/refman/5.0/en/bdb-storage-engine.html
|
||||||
|
.. _InnoDB: http://dev.mysql.com/doc/refman/5.0/en/innodb.html
|
||||||
|
.. _Other storage engines: http://dev.mysql.com/doc/refman/5.1/en/storage-engines-other.html
|
||||||
|
.. _SolidDB: http://forge.mysql.com/projects/view.php?id=139
|
||||||
|
.. _Falcon: http://dev.mysql.com/doc/falcon/en/index.html
|
||||||
|
|
||||||
|
MySQLdb
|
||||||
|
-------
|
||||||
|
|
||||||
|
`MySQLdb`_ is the Python interface to MySQL. 1.2.1 is the first version that
|
||||||
|
has support for MySQL 4.1 and newer. If you are trying to use an older version
|
||||||
|
of MySQL, then 1.2.0 *might* work for you.
|
||||||
|
|
||||||
|
.. _MySQLdb: http://sourceforge.net/projects/mysql-python
|
||||||
|
|
||||||
|
Creating your database
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
You can `create your database`_ using the command-line tools and this SQL::
|
||||||
|
|
||||||
|
CREATE DATABASE <dbname> CHARACTER SET utf8;
|
||||||
|
|
||||||
|
This ensures all tables and columns will use UTF-8 by default.
|
||||||
|
|
||||||
|
.. _create your database: http://dev.mysql.com/doc/refman/5.0/en/create-database.html
|
||||||
|
|
||||||
|
Connecting to the database
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
Refer to the `settings documentation`_.
|
||||||
|
|
||||||
|
Connection settings are used in this order:
|
||||||
|
|
||||||
|
1. ``DATABASE_OPTIONS``
|
||||||
|
2. ``DATABASE_NAME``, ``DATABASE_USER``, ``DATABASE_PASSWORD``, ``DATABASE_HOST``,
|
||||||
|
``DATABASE_PORT``
|
||||||
|
3. MySQL option files.
|
||||||
|
|
||||||
|
In other words, if you set the name of the database in ``DATABASE_OPTIONS``,
|
||||||
|
this will take precedence over ``DATABASE_NAME``, which would override
|
||||||
|
anything in a `MySQL option file`_.
|
||||||
|
|
||||||
|
Here's a sample configuration which uses a MySQL option file::
|
||||||
|
|
||||||
|
# settings.py
|
||||||
|
DATABASE_ENGINE = "mysql"
|
||||||
|
DATABASE_OPTIONS = {
|
||||||
|
'read_default_file': '/path/to/my.cnf',
|
||||||
|
}
|
||||||
|
|
||||||
|
# my.cnf
|
||||||
|
[client]
|
||||||
|
database = DATABASE_NAME
|
||||||
|
user = DATABASE_USER
|
||||||
|
passwd = DATABASE_PASSWORD
|
||||||
|
default-character-set = utf8
|
||||||
|
|
||||||
|
Several other MySQLdb connection options may be useful, such as ``ssl``,
|
||||||
|
``use_unicode``, ``init_command``, and ``sql_mode``. Consult the
|
||||||
|
`MySQLdb documentation`_ for more details.
|
||||||
|
|
||||||
|
.. _settings documentation: http://www.djangoproject.com/documentation/settings/#database-engine
|
||||||
|
.. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html
|
||||||
|
.. _MySQLdb documentation: http://mysql-python.sourceforge.net/
|
||||||
|
|
||||||
|
Creating your tables
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
When Django generates the schema, it doesn't specify a storage engine, so
|
||||||
|
tables will be created with whatever default storage engine your database
|
||||||
|
server is configured for. The easiest solution is to set your database server's
|
||||||
|
default storage engine to the desired engine.
|
||||||
|
|
||||||
|
If you're using a hosting service and can't change your server's default
|
||||||
|
storage engine, you have a couple of options.
|
||||||
|
|
||||||
|
* After the tables are created, execute an ``ALTER TABLE`` statement to
|
||||||
|
convert a table to a new storage engine (such as InnoDB)::
|
||||||
|
|
||||||
|
ALTER TABLE <tablename> ENGINE=INNODB;
|
||||||
|
|
||||||
|
This can be tedious if you have a lot of tables.
|
||||||
|
|
||||||
|
* Another option is to use the ``init_command`` option for MySQLdb prior to
|
||||||
|
creating your tables::
|
||||||
|
|
||||||
|
DATABASE_OPTIONS = {
|
||||||
|
# ...
|
||||||
|
"init_command": "SET storage_engine=INNODB",
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
|
||||||
|
This sets the default storage engine upon connecting to the database.
|
||||||
|
After your tables have been created, you should remove this option.
|
||||||
|
|
||||||
|
* Another method for changing the storage engine is described in
|
||||||
|
AlterModelOnSyncDB_.
|
||||||
|
|
||||||
|
.. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB
|
||||||
|
|
@ -6,7 +6,7 @@ Once you've created your `data models`_, Django automatically gives you a
|
|||||||
database-abstraction API that lets you create, retrieve, update and delete
|
database-abstraction API that lets you create, retrieve, update and delete
|
||||||
objects. This document explains that API.
|
objects. This document explains that API.
|
||||||
|
|
||||||
.. _`data models`: http://www.djangoproject.com/documentation/model_api/
|
.. _`data models`: ../model_api/
|
||||||
|
|
||||||
Throughout this reference, we'll refer to the following models, which comprise
|
Throughout this reference, we'll refer to the following models, which comprise
|
||||||
a weblog application::
|
a weblog application::
|
||||||
@ -85,7 +85,7 @@ There's no way to tell what the value of an ID will be before you call
|
|||||||
unless you explicitly specify ``primary_key=True`` on a field. See the
|
unless you explicitly specify ``primary_key=True`` on a field. See the
|
||||||
`AutoField documentation`_.)
|
`AutoField documentation`_.)
|
||||||
|
|
||||||
.. _AutoField documentation: http://www.djangoproject.com/documentation/model_api/#autofield
|
.. _AutoField documentation: ../model_api/#autofield
|
||||||
|
|
||||||
Explicitly specifying auto-primary-key values
|
Explicitly specifying auto-primary-key values
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -1801,4 +1801,4 @@ interface to your database. You can access your database via other tools,
|
|||||||
programming languages or database frameworks; there's nothing Django-specific
|
programming languages or database frameworks; there's nothing Django-specific
|
||||||
about your database.
|
about your database.
|
||||||
|
|
||||||
.. _Executing custom SQL: http://www.djangoproject.com/documentation/model_api/#executing-custom-sql
|
.. _Executing custom SQL: ../model_api/#executing-custom-sql
|
||||||
|
@ -57,7 +57,7 @@ Gentoo
|
|||||||
------
|
------
|
||||||
|
|
||||||
A Django build is available for `Gentoo Linux`_, and is based on Django 0.95.1.
|
A Django build is available for `Gentoo Linux`_, and is based on Django 0.95.1.
|
||||||
The `current Gentoo build`_ can be installed by typing ``emerge Django``.
|
The `current Gentoo build`_ can be installed by typing ``emerge django``.
|
||||||
|
|
||||||
.. _Gentoo Linux: http://www.gentoo.org/
|
.. _Gentoo Linux: http://www.gentoo.org/
|
||||||
.. _current Gentoo build: http://packages.gentoo.org/packages/?category=dev-python;name=django
|
.. _current Gentoo build: http://packages.gentoo.org/packages/?category=dev-python;name=django
|
||||||
|
@ -216,7 +216,7 @@ installation will be aborted, and any data installed in the call to
|
|||||||
``loaddata`` will be removed from the database.
|
``loaddata`` will be removed from the database.
|
||||||
|
|
||||||
The fixtures that are named can include directory components. These
|
The fixtures that are named can include directory components. These
|
||||||
directories will be inluded in the search path. For example::
|
directories will be included in the search path. For example::
|
||||||
|
|
||||||
django-admin.py loaddata foo/bar/mydata.json
|
django-admin.py loaddata foo/bar/mydata.json
|
||||||
|
|
||||||
|
@ -304,3 +304,14 @@ If you have access to a command shell on a Unix system, you can accomplish this
|
|||||||
easily by using the ``touch`` command::
|
easily by using the ``touch`` command::
|
||||||
|
|
||||||
touch mysite.fcgi
|
touch mysite.fcgi
|
||||||
|
|
||||||
|
Serving admin media files
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Regardless of the server and configuration you eventually decide to use, you will
|
||||||
|
also need to give some thought to how to serve the admin media files. The
|
||||||
|
advice given in the modpython_ documentation is also applicable in the setups
|
||||||
|
detailed above.
|
||||||
|
|
||||||
|
.. _modpython: ../modpython/#serving-the-admin-files
|
||||||
|
|
||||||
|
@ -417,6 +417,27 @@ Here's a simple function that might drive the above form::
|
|||||||
form = forms.FormWrapper(manipulator, new_data, errors)
|
form = forms.FormWrapper(manipulator, new_data, errors)
|
||||||
return render_to_response('contact_form.html', {'form': form})
|
return render_to_response('contact_form.html', {'form': form})
|
||||||
|
|
||||||
|
Implementing ``flatten_data`` for custom manipulators
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
It is possible (although rarely needed) to replace the default automatically
|
||||||
|
created manipulators on a model with your own custom manipulators. If you do
|
||||||
|
this and you are intending to use those models in generic views, you should
|
||||||
|
also define a ``flatten_data`` method in any ``ChangeManipulator`` replacement.
|
||||||
|
This should act like the default ``flatten_data`` and return a dictionary
|
||||||
|
mapping field names to their values, like so::
|
||||||
|
|
||||||
|
def flatten_data(self):
|
||||||
|
obj = self.original_object
|
||||||
|
return dict(
|
||||||
|
from = obj.from,
|
||||||
|
subject = obj.subject,
|
||||||
|
...
|
||||||
|
)
|
||||||
|
|
||||||
|
In this way, your new change manipulator will act exactly like the default
|
||||||
|
version.
|
||||||
|
|
||||||
``FileField`` and ``ImageField`` special cases
|
``FileField`` and ``ImageField`` special cases
|
||||||
==============================================
|
==============================================
|
||||||
|
|
||||||
|
@ -282,6 +282,17 @@ How to create language files
|
|||||||
Once you've tagged your strings for later translation, you need to write (or
|
Once you've tagged your strings for later translation, you need to write (or
|
||||||
obtain) the language translations themselves. Here's how that works.
|
obtain) the language translations themselves. Here's how that works.
|
||||||
|
|
||||||
|
.. admonition:: Locale restrictions
|
||||||
|
|
||||||
|
Django does not support localizing your application into a locale for
|
||||||
|
which Django itself has not been translated. In this case, it will ignore
|
||||||
|
your translation files. If you were to try this and Django supported it,
|
||||||
|
you would inevitably see a mixture of translated strings (from your
|
||||||
|
application) and English strings (from Django itself). If you want to
|
||||||
|
support a locale for your application that is not already part of
|
||||||
|
Django, you'll need to make at least a minimal translation of the Django
|
||||||
|
core.
|
||||||
|
|
||||||
Message files
|
Message files
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@ -1216,6 +1216,10 @@ screen via ``<script src="">`` tags. This can be used to tweak a given type of
|
|||||||
admin page in JavaScript or to provide "quick links" to fill in default values
|
admin page in JavaScript or to provide "quick links" to fill in default values
|
||||||
for certain fields.
|
for certain fields.
|
||||||
|
|
||||||
|
If you use relative URLs -- URLs that don't start with ``http://`` or ``/`` --
|
||||||
|
then the admin site will automatically prefix these links with
|
||||||
|
``settings.ADMIN_MEDIA_PREFIX``.
|
||||||
|
|
||||||
``list_display``
|
``list_display``
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
264
docs/release_notes_0.96.txt
Normal file
264
docs/release_notes_0.96.txt
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
=================================
|
||||||
|
Django version 0.96 release notes
|
||||||
|
=================================
|
||||||
|
|
||||||
|
Welcome to Django 0.96!
|
||||||
|
|
||||||
|
The primary goal for 0.96 is a cleanup and stabilization of the features
|
||||||
|
introduced in 0.95. There have been a few small `backwards-incompatible
|
||||||
|
changes`_ since 0.95, but the upgrade process should be fairly simple
|
||||||
|
and should not require major changes to existing applications.
|
||||||
|
|
||||||
|
However, we're also releasing 0.96 now because we have a set of
|
||||||
|
backwards-incompatible changes scheduled for the near future. Once
|
||||||
|
completed, they will involve some code changes for application
|
||||||
|
developers, so we recommend that you stick with Django 0.96 until the
|
||||||
|
next official release; then you'll be able to upgrade in one step
|
||||||
|
instead of needing to make incremental changes to keep up with the
|
||||||
|
development version of Django.
|
||||||
|
|
||||||
|
What's new in 0.96?
|
||||||
|
===================
|
||||||
|
|
||||||
|
This revision represents over a thousand source commits and over four hundred
|
||||||
|
bug fixes, so we can't possibly catalog all the changes. Here, we describe the
|
||||||
|
most notable changes in this release.
|
||||||
|
|
||||||
|
New forms library
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
``django.newforms`` is Django's new form-handling library. It's a
|
||||||
|
replacement for ``django.forms``, the old form/manipulator/validation
|
||||||
|
framework. Both APIs are available in 0.96, but over the next two
|
||||||
|
releases we plan to switch completely to the new forms system, and
|
||||||
|
deprecate and remove the old system.
|
||||||
|
|
||||||
|
There are three elements to this transition:
|
||||||
|
|
||||||
|
* We've copied the current ``django.forms`` to
|
||||||
|
``django.oldforms``. This allows you to upgrade your code *now*
|
||||||
|
rather than waiting for the backwards-incompatible change and
|
||||||
|
rushing to fix your code after the fact. Just change your
|
||||||
|
import statements like this::
|
||||||
|
|
||||||
|
from django import forms # 0.95-style
|
||||||
|
from django import oldforms as forms # 0.96-style
|
||||||
|
|
||||||
|
* The next official release of Django will move the current
|
||||||
|
``django.newforms`` to ``django.forms``. This will be a
|
||||||
|
backwards-incompatible change, and anyone still using the old
|
||||||
|
version of ``django.forms`` at that time will need to change
|
||||||
|
their import statements as described above.
|
||||||
|
|
||||||
|
* The next release after that will completely remove
|
||||||
|
``django.oldforms``.
|
||||||
|
|
||||||
|
Although the ``newforms`` library will continue to evolve, it's ready for use
|
||||||
|
for most common cases. We recommend that anyone new to form handling skip the
|
||||||
|
old forms system and start with the new.
|
||||||
|
|
||||||
|
For more information about ``django.newforms``, read the `newforms
|
||||||
|
documentation`_.
|
||||||
|
|
||||||
|
.. _newforms documentation: ../newforms/
|
||||||
|
|
||||||
|
URLconf improvements
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
You can now use any callable as the callback in URLconfs (previously, only
|
||||||
|
strings that referred to callables were allowed). This allows a much more
|
||||||
|
natural use of URLconfs. For example, this URLconf::
|
||||||
|
|
||||||
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
('^myview/$', 'mysite.myapp.views.myview')
|
||||||
|
)
|
||||||
|
|
||||||
|
can now be rewritten as::
|
||||||
|
|
||||||
|
from django.conf.urls.defaults import *
|
||||||
|
from mysite.myapp.views import myview
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
('^myview/$', myview)
|
||||||
|
)
|
||||||
|
|
||||||
|
One useful application of this can be seen when using decorators; this
|
||||||
|
change allows you to apply decorators to views *in your
|
||||||
|
URLconf*. Thus, you can make a generic view require login very
|
||||||
|
easily::
|
||||||
|
|
||||||
|
from django.conf.urls.defaults import *
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.views.generic.list_detail import object_list
|
||||||
|
from mysite.myapp.models import MyModel
|
||||||
|
|
||||||
|
info = {
|
||||||
|
"queryset" : MyModel.objects.all(),
|
||||||
|
}
|
||||||
|
|
||||||
|
urlpatterns = patterns('',
|
||||||
|
('^myview/$', login_required(object_list), info)
|
||||||
|
)
|
||||||
|
|
||||||
|
Note that both syntaxes (strings and callables) are valid, and will continue to
|
||||||
|
be valid for the foreseeable future.
|
||||||
|
|
||||||
|
The test framework
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Django now includes a test framework so you can start transmuting fear into
|
||||||
|
boredom (with apologies to Kent Beck). You can write tests based on doctest_
|
||||||
|
or unittest_ and test your views with a simple test client.
|
||||||
|
|
||||||
|
There is also new support for "fixtures" -- initial data, stored in any of the
|
||||||
|
supported `serialization formats`_, that will be loaded into your database at the
|
||||||
|
start of your tests. This makes testing with real data much easier.
|
||||||
|
|
||||||
|
See `the testing documentation`_ for the full details.
|
||||||
|
|
||||||
|
.. _doctest: http://docs.python.org/lib/module-doctest.html
|
||||||
|
.. _unittest: http://docs.python.org/lib/module-unittest.html
|
||||||
|
.. _the testing documentation: ../testing/
|
||||||
|
.. _serialization formats: ../serialization/
|
||||||
|
|
||||||
|
Improvements to the admin interface
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
A small change, but a very nice one: dedicated views for adding and
|
||||||
|
updating users have been added to the admin interface, so you no
|
||||||
|
longer need to worry about working with hashed passwords in the admin.
|
||||||
|
|
||||||
|
Backwards-incompatible changes
|
||||||
|
==============================
|
||||||
|
|
||||||
|
The following changes may require you to update your code when you switch from
|
||||||
|
0.95 to 0.96:
|
||||||
|
|
||||||
|
`MySQLdb` version requirement
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
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
|
||||||
|
requires version 1.2.1p2 or higher of `MySQLdb`, and will raise
|
||||||
|
exceptions if you attempt to use an older version.
|
||||||
|
|
||||||
|
If you're currently unable to upgrade your copy of `MySQLdb` to meet
|
||||||
|
this requirement, a separate, backwards-compatible backend, called
|
||||||
|
"mysql_old", has been added to Django. To use this backend, change
|
||||||
|
the ``DATABASE_ENGINE`` setting in your Django settings file from
|
||||||
|
this::
|
||||||
|
|
||||||
|
DATABASE_ENGINE = "mysql"
|
||||||
|
|
||||||
|
to this::
|
||||||
|
|
||||||
|
DATABASE_ENGINE = "mysql_old"
|
||||||
|
|
||||||
|
However, we strongly encourage MySQL users to upgrade to a more recent
|
||||||
|
version of `MySQLdb` as soon as possible, The "mysql_old" backend is
|
||||||
|
provided only to ease this transition, and is considered deprecated;
|
||||||
|
aside from any necessary security fixes, it will not be actively
|
||||||
|
maintained, and it will be removed in a future release of Django.
|
||||||
|
|
||||||
|
Also, note that some features, like the new ``DATABASE_OPTIONS``
|
||||||
|
setting (see the `databases documentation`_ for details), are only
|
||||||
|
available on the "mysql" backend, and will not be made available for
|
||||||
|
"mysql_old".
|
||||||
|
|
||||||
|
.. _databases: ../databases/
|
||||||
|
|
||||||
|
Database constraint names changed
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
The format of the constraint names Django generates for foreign key
|
||||||
|
references have changed slightly. These names are generally only used
|
||||||
|
when it is not possible to put the reference directly on the affected
|
||||||
|
column, so they is not always visible.
|
||||||
|
|
||||||
|
The effect of this change is that running ``manage.py reset`` and
|
||||||
|
similar commands against an existing database may generate SQL with
|
||||||
|
the new form of constraint name, while the database itself contains
|
||||||
|
constraints named in the old form; this will cause the database server
|
||||||
|
to raise an error message about modifying non-existent constraints.
|
||||||
|
|
||||||
|
If you need to work around this, there are two methods available:
|
||||||
|
|
||||||
|
1. Redirect the output of ``manage.py`` to a file, and edit the
|
||||||
|
generated SQL to use the correct constraint names before
|
||||||
|
executing it.
|
||||||
|
|
||||||
|
2. Examine the output of ``manage.py sqlall`` to see the new-style
|
||||||
|
constraint names, and use that as a guide to rename existing
|
||||||
|
constraints in your database.
|
||||||
|
|
||||||
|
Names changes in ``manage.py``
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
A few of the options to ``manage.py`` have changed with the addition of fixture
|
||||||
|
support:
|
||||||
|
|
||||||
|
* There are new ``dumpdata`` and ``loaddata`` commands which, as
|
||||||
|
you might expect, will dump and load data to/from the
|
||||||
|
database. These commands can operate against any of Django's
|
||||||
|
supported serialization formats.
|
||||||
|
|
||||||
|
* The ``sqlinitialdata`` command has been renamed to ``sqlcustom`` to
|
||||||
|
emphasize that ``loaddata`` should be used for data (and ``sqlcustom`` for
|
||||||
|
other custom SQL -- views, stored procedures, etc.).
|
||||||
|
|
||||||
|
* The vestigial ``install`` command has been removed. Use ``syncdb``.
|
||||||
|
|
||||||
|
Backslash escaping changed
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
The Django database API now escapes backslashes given as query parameters. If
|
||||||
|
you have any database API code that matches backslashes, and it was working before
|
||||||
|
(despite the lack of escaping), you'll have to change your code to "unescape" the
|
||||||
|
slashes one level.
|
||||||
|
|
||||||
|
For example, this used to work::
|
||||||
|
|
||||||
|
# Find text containing a single backslash
|
||||||
|
MyModel.objects.filter(text__contains='\\\\')
|
||||||
|
|
||||||
|
The above is now incorrect, and should be rewritten as::
|
||||||
|
|
||||||
|
# Find text containing a single backslash
|
||||||
|
MyModel.objects.filter(text__contains='\\')
|
||||||
|
|
||||||
|
Removed ENABLE_PSYCO setting
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
The ``ENABLE_PSYCO`` setting no longer exists. If your settings file includes
|
||||||
|
``ENABLE_PSYCO`` it will have no effect; to use Psyco, we recommend
|
||||||
|
writing a middleware class to activate it.
|
||||||
|
|
||||||
|
.. _psyco: http://psyco.sourceforge.net/
|
||||||
|
|
||||||
|
Thanks
|
||||||
|
======
|
||||||
|
|
||||||
|
Since 0.95, a number of people have stepped forward and taken a major
|
||||||
|
new role in Django's development. We'd like to thank these people for
|
||||||
|
all their hard work:
|
||||||
|
|
||||||
|
* Russell Keith-Magee and Malcolm Tredinnick for their major code
|
||||||
|
contributions. This release wouldn't have been possible without them.
|
||||||
|
|
||||||
|
* Our new release manager, James Bennett, for his work in getting out
|
||||||
|
0.95.1, 0.96, and (hopefully) future release.
|
||||||
|
|
||||||
|
* Our ticket managers Chris Beaven (aka SmileyChris), Simon Greenhill,
|
||||||
|
Michael Radziej, and Gary Wilson. They agreed to take on the monumental
|
||||||
|
task of wrangling our tickets into nicely cataloged submission. Figuring
|
||||||
|
out what to work on is now about a million times easier; thanks again,
|
||||||
|
guys.
|
||||||
|
|
||||||
|
* Everyone who submitted a bug report, patch or ticket comment. We can't
|
||||||
|
possibly thank everyone by name -- over 200 developers submitted patches
|
||||||
|
that went into 0.96 -- but everyone who's contributed to Django is listed
|
||||||
|
in AUTHORS_.
|
||||||
|
|
||||||
|
.. _AUTHORS: http://code.djangoproject.com/browser/django/trunk/AUTHORS
|
@ -31,7 +31,8 @@ but it'll almost always be a QuerySet).
|
|||||||
|
|
||||||
You can also use a serializer object directly::
|
You can also use a serializer object directly::
|
||||||
|
|
||||||
xml_serializer = serializers.get_serializer("xml")
|
XMLSerializer = serializers.get_serializer("xml")
|
||||||
|
xml_serializer = XMLSerializer()
|
||||||
xml_serializer.serialize(queryset)
|
xml_serializer.serialize(queryset)
|
||||||
data = xml_serializer.getvalue()
|
data = xml_serializer.getvalue()
|
||||||
|
|
||||||
|
@ -162,10 +162,13 @@ a model object and return its URL. This is a way of overriding
|
|||||||
``get_absolute_url()`` methods on a per-installation basis. Example::
|
``get_absolute_url()`` methods on a per-installation basis. Example::
|
||||||
|
|
||||||
ABSOLUTE_URL_OVERRIDES = {
|
ABSOLUTE_URL_OVERRIDES = {
|
||||||
'blogs.Weblog': lambda o: "/blogs/%s/" % o.slug,
|
'blogs.weblog': lambda o: "/blogs/%s/" % o.slug,
|
||||||
'news.Story': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug),
|
'news.story': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Note that the model name used in this setting should be all lower-case, regardless
|
||||||
|
of the case of the actual model class name.
|
||||||
|
|
||||||
ADMIN_FOR
|
ADMIN_FOR
|
||||||
---------
|
---------
|
||||||
|
|
||||||
@ -242,7 +245,8 @@ DATABASE_ENGINE
|
|||||||
Default: ``''`` (Empty string)
|
Default: ``''`` (Empty string)
|
||||||
|
|
||||||
Which database backend to use. Either ``'postgresql_psycopg2'``,
|
Which database backend to use. Either ``'postgresql_psycopg2'``,
|
||||||
``'postgresql'``, ``'mysql'``, ``'sqlite3'`` or ``'ado_mssql'``.
|
``'postgresql'``, ``'mysql'``, ``'mysql_old'``, ``'sqlite3'`` or
|
||||||
|
``'ado_mssql'``.
|
||||||
|
|
||||||
DATABASE_HOST
|
DATABASE_HOST
|
||||||
-------------
|
-------------
|
||||||
|
@ -227,6 +227,12 @@ can be invoked on the ``Client`` instance.
|
|||||||
The key-value pairs in the data dictionary will be encoded as a multipart
|
The key-value pairs in the data dictionary will be encoded as a multipart
|
||||||
message and used to create the POST data payload.
|
message and used to create the POST data payload.
|
||||||
|
|
||||||
|
To submit multiple values for a given key (for example, to specify
|
||||||
|
the selections for a multiple selection list), provide the values as a
|
||||||
|
list or tuple for the required key. For example, a data dictionary of
|
||||||
|
``{'choices': ('a','b','d')}`` would submit three selected rows for the
|
||||||
|
field named ``choices``.
|
||||||
|
|
||||||
Submitting files is a special case. To POST a file, you need only
|
Submitting files is a special case. To POST a file, you need only
|
||||||
provide the file field name as a key, and a file handle to the file you wish to
|
provide the file field name as a key, and a file handle to the file you wish to
|
||||||
upload as a value. The Test Client will populate the two POST fields (i.e.,
|
upload as a value. The Test Client will populate the two POST fields (i.e.,
|
||||||
|
@ -147,7 +147,7 @@ complete -F _django_completion django-admin.py manage.py
|
|||||||
# Support for multiple interpreters.
|
# Support for multiple interpreters.
|
||||||
unset pythons
|
unset pythons
|
||||||
if command -v whereis &>/dev/null; then
|
if command -v whereis &>/dev/null; then
|
||||||
python_interpreters=$(whereis -b python | cut -d " " -f 2-)
|
python_interpreters=$(whereis python | cut -d " " -f 2-)
|
||||||
for python in $python_interpreters; do
|
for python in $python_interpreters; do
|
||||||
pythons="${pythons} $(basename $python)"
|
pythons="${pythons} $(basename $python)"
|
||||||
done
|
done
|
||||||
|
@ -67,13 +67,13 @@ __test__ = {'API_TESTS': """
|
|||||||
# Try to load fixture 2 using format discovery; this will fail
|
# Try to load fixture 2 using format discovery; this will fail
|
||||||
# because there are two fixture2's in the fixtures directory
|
# because there are two fixture2's in the fixtures directory
|
||||||
>>> management.load_data(['fixture2'], verbosity=0) # doctest: +ELLIPSIS
|
>>> management.load_data(['fixture2'], verbosity=0) # doctest: +ELLIPSIS
|
||||||
Multiple fixtures named 'fixture2' in '.../fixtures'. Aborting.
|
Multiple fixtures named 'fixture2' in '...fixtures'. Aborting.
|
||||||
|
|
||||||
>>> Article.objects.all()
|
>>> Article.objects.all()
|
||||||
[<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>]
|
[<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>]
|
||||||
|
|
||||||
# Dump the current contents of the database as a JSON fixture
|
# Dump the current contents of the database as a JSON fixture
|
||||||
>>> management.dump_data(['fixtures'], format='json')
|
>>> print management.dump_data(['fixtures'], format='json')
|
||||||
[{"pk": "3", "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "2", "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": "1", "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]
|
[{"pk": "3", "model": "fixtures.article", "fields": {"headline": "Time to reform copyright", "pub_date": "2006-06-16 13:00:00"}}, {"pk": "2", "model": "fixtures.article", "fields": {"headline": "Poker has no place on ESPN", "pub_date": "2006-06-16 12:00:00"}}, {"pk": "1", "model": "fixtures.article", "fields": {"headline": "Python program becomes self aware", "pub_date": "2006-06-16 11:00:00"}}]
|
||||||
"""}
|
"""}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ __test__ = {'API_TESTS':"""
|
|||||||
>>> get_object_or_404(Article, title="Foo")
|
>>> get_object_or_404(Article, title="Foo")
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
Http404
|
Http404: No Article matches the given query.
|
||||||
|
|
||||||
# Create an Article.
|
# Create an Article.
|
||||||
>>> article = Article.objects.create(title="Run away!")
|
>>> article = Article.objects.create(title="Run away!")
|
||||||
@ -63,7 +63,7 @@ Http404
|
|||||||
>>> get_object_or_404(a.article_set, title__contains="Camelot")
|
>>> get_object_or_404(a.article_set, title__contains="Camelot")
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
Http404
|
Http404: No Article matches the given query.
|
||||||
|
|
||||||
# Custom managers can be used too.
|
# Custom managers can be used too.
|
||||||
>>> get_object_or_404(Article.by_a_sir, title="Run away!")
|
>>> get_object_or_404(Article.by_a_sir, title="Run away!")
|
||||||
@ -77,7 +77,7 @@ Http404
|
|||||||
>>> get_list_or_404(a.article_set, title__icontains='Shrubbery')
|
>>> get_list_or_404(a.article_set, title__icontains='Shrubbery')
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
Http404
|
Http404: No Article matches the given query.
|
||||||
|
|
||||||
# Custom managers can be used too.
|
# Custom managers can be used too.
|
||||||
>>> get_list_or_404(Article.by_a_sir, title__icontains="Run")
|
>>> get_list_or_404(Article.by_a_sir, title__icontains="Run")
|
||||||
|
@ -81,7 +81,43 @@ class ClientTest(TestCase):
|
|||||||
|
|
||||||
# Check that the response was a 302 (redirect)
|
# Check that the response was a 302 (redirect)
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
|
|
||||||
|
def test_valid_form(self):
|
||||||
|
"POST valid data to a form"
|
||||||
|
post_data = {
|
||||||
|
'text': 'Hello World',
|
||||||
|
'email': 'foo@example.com',
|
||||||
|
'value': 37,
|
||||||
|
'single': 'b',
|
||||||
|
'multi': ('b','c','e')
|
||||||
|
}
|
||||||
|
response = self.client.post('/test_client/form_view/', post_data)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(response.template.name, "Valid POST Template")
|
||||||
|
|
||||||
|
def test_incomplete_data_form(self):
|
||||||
|
"POST incomplete data to a form"
|
||||||
|
post_data = {
|
||||||
|
'text': 'Hello World',
|
||||||
|
'value': 37
|
||||||
|
}
|
||||||
|
response = self.client.post('/test_client/form_view/', post_data)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(response.template.name, "Invalid POST Template")
|
||||||
|
|
||||||
|
def test_form_error(self):
|
||||||
|
"POST erroneous data to a form"
|
||||||
|
post_data = {
|
||||||
|
'text': 'Hello World',
|
||||||
|
'email': 'not an email address',
|
||||||
|
'value': 37,
|
||||||
|
'single': 'b',
|
||||||
|
'multi': ('b','c','e')
|
||||||
|
}
|
||||||
|
response = self.client.post('/test_client/form_view/', post_data)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertEqual(response.template.name, "Invalid POST Template")
|
||||||
|
|
||||||
def test_unknown_page(self):
|
def test_unknown_page(self):
|
||||||
"GET an invalid URL"
|
"GET an invalid URL"
|
||||||
response = self.client.get('/test_client/unknown_view/')
|
response = self.client.get('/test_client/unknown_view/')
|
||||||
|
@ -6,6 +6,7 @@ urlpatterns = patterns('',
|
|||||||
(r'^post_view/$', views.post_view),
|
(r'^post_view/$', views.post_view),
|
||||||
(r'^raw_post_view/$', views.raw_post_view),
|
(r'^raw_post_view/$', views.raw_post_view),
|
||||||
(r'^redirect_view/$', views.redirect_view),
|
(r'^redirect_view/$', views.redirect_view),
|
||||||
|
(r'^form_view/$', views.form_view),
|
||||||
(r'^login_protected_view/$', views.login_protected_view),
|
(r'^login_protected_view/$', views.login_protected_view),
|
||||||
(r'^session_view/$', views.session_view),
|
(r'^session_view/$', views.session_view),
|
||||||
(r'^broken_view/$', views.broken_view)
|
(r'^broken_view/$', views.broken_view)
|
||||||
|
@ -2,6 +2,8 @@ from xml.dom.minidom import parseString
|
|||||||
from django.template import Context, Template
|
from django.template import Context, Template
|
||||||
from django.http import HttpResponse, HttpResponseRedirect
|
from django.http import HttpResponse, HttpResponseRedirect
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.newforms.forms import Form
|
||||||
|
from django.newforms import fields
|
||||||
|
|
||||||
def get_view(request):
|
def get_view(request):
|
||||||
"A simple view that expects a GET request, and returns a rendered template"
|
"A simple view that expects a GET request, and returns a rendered template"
|
||||||
@ -45,7 +47,39 @@ def raw_post_view(request):
|
|||||||
def redirect_view(request):
|
def redirect_view(request):
|
||||||
"A view that redirects all requests to the GET view"
|
"A view that redirects all requests to the GET view"
|
||||||
return HttpResponseRedirect('/test_client/get_view/')
|
return HttpResponseRedirect('/test_client/get_view/')
|
||||||
|
|
||||||
|
TestChoices = (
|
||||||
|
('a', 'First Choice'),
|
||||||
|
('b', 'Second Choice'),
|
||||||
|
('c', 'Third Choice'),
|
||||||
|
('d', 'Fourth Choice'),
|
||||||
|
('e', 'Fifth Choice')
|
||||||
|
)
|
||||||
|
|
||||||
|
class TestForm(Form):
|
||||||
|
text = fields.CharField()
|
||||||
|
email = fields.EmailField()
|
||||||
|
value = fields.IntegerField()
|
||||||
|
single = fields.ChoiceField(choices=TestChoices)
|
||||||
|
multi = fields.MultipleChoiceField(choices=TestChoices)
|
||||||
|
|
||||||
|
def form_view(request):
|
||||||
|
"A view that tests a simple form"
|
||||||
|
if request.method == 'POST':
|
||||||
|
form = TestForm(request.POST)
|
||||||
|
if form.is_valid():
|
||||||
|
t = Template('Valid POST data.', name='Valid POST Template')
|
||||||
|
c = Context()
|
||||||
|
else:
|
||||||
|
t = Template('Invalid POST data. {{ form.errors }}', name='Invalid POST Template')
|
||||||
|
c = Context({'form': form})
|
||||||
|
else:
|
||||||
|
form = TestForm()
|
||||||
|
t = Template('Viewing base form. {{ form }}.', name='Form GET Template')
|
||||||
|
c = Context({'form': form})
|
||||||
|
|
||||||
|
return HttpResponse(t.render(c))
|
||||||
|
|
||||||
def login_protected_view(request):
|
def login_protected_view(request):
|
||||||
"A simple view that is login protected."
|
"A simple view that is login protected."
|
||||||
t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
|
t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
|
||||||
|
@ -31,4 +31,35 @@
|
|||||||
'nonexistent'
|
'nonexistent'
|
||||||
>>> d.setlist('lastname', ['Holovaty', 'Willison'])
|
>>> d.setlist('lastname', ['Holovaty', 'Willison'])
|
||||||
|
|
||||||
"""
|
### SortedDict #################################################################
|
||||||
|
|
||||||
|
>>> d = SortedDict()
|
||||||
|
>>> d['one'] = 'one'
|
||||||
|
>>> d['two'] = 'two'
|
||||||
|
>>> d['three'] = 'three'
|
||||||
|
>>> d['one']
|
||||||
|
'one'
|
||||||
|
>>> d['two']
|
||||||
|
'two'
|
||||||
|
>>> d['three']
|
||||||
|
'three'
|
||||||
|
>>> d.keys()
|
||||||
|
['one', 'two', 'three']
|
||||||
|
>>> d.values()
|
||||||
|
['one', 'two', 'three']
|
||||||
|
>>> d['one'] = 'not one'
|
||||||
|
>>> d['one']
|
||||||
|
'not one'
|
||||||
|
>>> d.keys() == d.copy().keys()
|
||||||
|
True
|
||||||
|
|
||||||
|
### DotExpandedDict ############################################################
|
||||||
|
|
||||||
|
>>> d = DotExpandedDict({'person.1.firstname': ['Simon'], 'person.1.lastname': ['Willison'], 'person.2.firstname': ['Adrian'], 'person.2.lastname': ['Holovaty']})
|
||||||
|
>>> d['person']['1']['lastname']
|
||||||
|
['Willison']
|
||||||
|
>>> d['person']['2']['lastname']
|
||||||
|
['Holovaty']
|
||||||
|
>>> d['person']['2']['firstname']
|
||||||
|
['Adrian']
|
||||||
|
"""
|
||||||
|
@ -133,6 +133,12 @@ u'\xcb'
|
|||||||
>>> wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14)
|
>>> wordwrap('this is a long paragraph of text that really needs to be wrapped I\'m afraid', 14)
|
||||||
"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid"
|
"this is a long\nparagraph of\ntext that\nreally needs\nto be wrapped\nI'm afraid"
|
||||||
|
|
||||||
|
>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',14)
|
||||||
|
'this is a\nshort\nparagraph of\ntext.\n But this\nline should be\nindented'
|
||||||
|
|
||||||
|
>>> wordwrap('this is a short paragraph of text.\n But this line should be indented',15)
|
||||||
|
'this is a short\nparagraph of\ntext.\n But this line\nshould be\nindented'
|
||||||
|
|
||||||
>>> ljust('test', 10)
|
>>> ljust('test', 10)
|
||||||
'test '
|
'test '
|
||||||
|
|
||||||
|
@ -1,13 +1,34 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
# If ticket #1578 ever slips back in, these models will not be able to be
|
||||||
|
# created (the field names being lower-cased versions of their opposite
|
||||||
|
# classes is important here).
|
||||||
|
|
||||||
class First(models.Model):
|
class First(models.Model):
|
||||||
second = models.IntegerField()
|
second = models.IntegerField()
|
||||||
|
|
||||||
class Second(models.Model):
|
class Second(models.Model):
|
||||||
first = models.ForeignKey(First, related_name = 'the_first')
|
first = models.ForeignKey(First, related_name = 'the_first')
|
||||||
|
|
||||||
# If ticket #1578 ever slips back in, these models will not be able to be
|
# Protect against repetition of #1839, #2415 and #2536.
|
||||||
# created (the field names being lower-cased versions of their opposite
|
class Third(models.Model):
|
||||||
# classes is important here).
|
name = models.CharField(maxlength=20)
|
||||||
|
third = models.ForeignKey('self', null=True, related_name='child_set')
|
||||||
|
|
||||||
__test__ = {'API_TESTS':""}
|
class Parent(models.Model):
|
||||||
|
name = models.CharField(maxlength=20)
|
||||||
|
bestchild = models.ForeignKey('Child', null=True, related_name='favored_by')
|
||||||
|
|
||||||
|
class Child(models.Model):
|
||||||
|
name = models.CharField(maxlength=20)
|
||||||
|
parent = models.ForeignKey(Parent)
|
||||||
|
|
||||||
|
|
||||||
|
__test__ = {'API_TESTS':"""
|
||||||
|
>>> Third.AddManipulator().save(dict(id='3', name='An example', another=None))
|
||||||
|
<Third: Third object>
|
||||||
|
>>> parent = Parent(name = 'fred')
|
||||||
|
>>> parent.save()
|
||||||
|
>>> Child.AddManipulator().save(dict(name='bam-bam', parent=parent.id))
|
||||||
|
<Child: Child object>
|
||||||
|
"""}
|
||||||
|
187
tests/regressiontests/serializers_regress/models.py
Normal file
187
tests/regressiontests/serializers_regress/models.py
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
"""
|
||||||
|
A test spanning all the capabilities of all the serializers.
|
||||||
|
|
||||||
|
This class sets up a model for each model field type
|
||||||
|
(except for image types, because of the PIL dependency).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
|
||||||
|
# The following classes are for testing basic data
|
||||||
|
# marshalling, including NULL values.
|
||||||
|
|
||||||
|
class BooleanData(models.Model):
|
||||||
|
data = models.BooleanField(null=True)
|
||||||
|
|
||||||
|
class CharData(models.Model):
|
||||||
|
data = models.CharField(maxlength=30, null=True)
|
||||||
|
|
||||||
|
class DateData(models.Model):
|
||||||
|
data = models.DateField(null=True)
|
||||||
|
|
||||||
|
class DateTimeData(models.Model):
|
||||||
|
data = models.DateTimeField(null=True)
|
||||||
|
|
||||||
|
class EmailData(models.Model):
|
||||||
|
data = models.EmailField(null=True)
|
||||||
|
|
||||||
|
class FileData(models.Model):
|
||||||
|
data = models.FileField(null=True, upload_to='/foo/bar')
|
||||||
|
|
||||||
|
class FilePathData(models.Model):
|
||||||
|
data = models.FilePathField(null=True)
|
||||||
|
|
||||||
|
class FloatData(models.Model):
|
||||||
|
data = models.FloatField(null=True, decimal_places=3, max_digits=5)
|
||||||
|
|
||||||
|
class IntegerData(models.Model):
|
||||||
|
data = models.IntegerField(null=True)
|
||||||
|
|
||||||
|
# class ImageData(models.Model):
|
||||||
|
# data = models.ImageField(null=True)
|
||||||
|
|
||||||
|
class IPAddressData(models.Model):
|
||||||
|
data = models.IPAddressField(null=True)
|
||||||
|
|
||||||
|
class NullBooleanData(models.Model):
|
||||||
|
data = models.NullBooleanField(null=True)
|
||||||
|
|
||||||
|
class PhoneData(models.Model):
|
||||||
|
data = models.PhoneNumberField(null=True)
|
||||||
|
|
||||||
|
class PositiveIntegerData(models.Model):
|
||||||
|
data = models.PositiveIntegerField(null=True)
|
||||||
|
|
||||||
|
class PositiveSmallIntegerData(models.Model):
|
||||||
|
data = models.PositiveSmallIntegerField(null=True)
|
||||||
|
|
||||||
|
class SlugData(models.Model):
|
||||||
|
data = models.SlugField(null=True)
|
||||||
|
|
||||||
|
class SmallData(models.Model):
|
||||||
|
data = models.SmallIntegerField(null=True)
|
||||||
|
|
||||||
|
class TextData(models.Model):
|
||||||
|
data = models.TextField(null=True)
|
||||||
|
|
||||||
|
class TimeData(models.Model):
|
||||||
|
data = models.TimeField(null=True)
|
||||||
|
|
||||||
|
class USStateData(models.Model):
|
||||||
|
data = models.USStateField(null=True)
|
||||||
|
|
||||||
|
class XMLData(models.Model):
|
||||||
|
data = models.XMLField(null=True)
|
||||||
|
|
||||||
|
class Tag(models.Model):
|
||||||
|
"""A tag on an item."""
|
||||||
|
data = models.SlugField()
|
||||||
|
content_type = models.ForeignKey(ContentType)
|
||||||
|
object_id = models.PositiveIntegerField()
|
||||||
|
|
||||||
|
content_object = models.GenericForeignKey()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ["data"]
|
||||||
|
|
||||||
|
class GenericData(models.Model):
|
||||||
|
data = models.CharField(maxlength=30)
|
||||||
|
|
||||||
|
tags = models.GenericRelation(Tag)
|
||||||
|
|
||||||
|
# The following test classes are all for validation
|
||||||
|
# of related objects; in particular, forward, backward,
|
||||||
|
# and self references.
|
||||||
|
|
||||||
|
class Anchor(models.Model):
|
||||||
|
"""This is a model that can be used as
|
||||||
|
something for other models to point at"""
|
||||||
|
|
||||||
|
data = models.CharField(maxlength=30)
|
||||||
|
|
||||||
|
class FKData(models.Model):
|
||||||
|
data = models.ForeignKey(Anchor, null=True)
|
||||||
|
|
||||||
|
class M2MData(models.Model):
|
||||||
|
data = models.ManyToManyField(Anchor, null=True)
|
||||||
|
|
||||||
|
class O2OData(models.Model):
|
||||||
|
data = models.OneToOneField(Anchor, null=True)
|
||||||
|
|
||||||
|
class FKSelfData(models.Model):
|
||||||
|
data = models.ForeignKey('self', null=True)
|
||||||
|
|
||||||
|
class M2MSelfData(models.Model):
|
||||||
|
data = models.ManyToManyField('self', null=True, symmetrical=False)
|
||||||
|
|
||||||
|
# The following test classes are for validating the
|
||||||
|
# deserialization of objects that use a user-defined
|
||||||
|
# field as the primary key.
|
||||||
|
# Some of these data types have been commented out
|
||||||
|
# because they can't be used as a primary key on one
|
||||||
|
# or all database backends.
|
||||||
|
|
||||||
|
class BooleanPKData(models.Model):
|
||||||
|
data = models.BooleanField(primary_key=True)
|
||||||
|
|
||||||
|
class CharPKData(models.Model):
|
||||||
|
data = models.CharField(maxlength=30, primary_key=True)
|
||||||
|
|
||||||
|
# class DatePKData(models.Model):
|
||||||
|
# data = models.DateField(primary_key=True)
|
||||||
|
|
||||||
|
# class DateTimePKData(models.Model):
|
||||||
|
# data = models.DateTimeField(primary_key=True)
|
||||||
|
|
||||||
|
class EmailPKData(models.Model):
|
||||||
|
data = models.EmailField(primary_key=True)
|
||||||
|
|
||||||
|
class FilePKData(models.Model):
|
||||||
|
data = models.FileField(primary_key=True, upload_to='/foo/bar')
|
||||||
|
|
||||||
|
class FilePathPKData(models.Model):
|
||||||
|
data = models.FilePathField(primary_key=True)
|
||||||
|
|
||||||
|
class FloatPKData(models.Model):
|
||||||
|
data = models.FloatField(primary_key=True, decimal_places=3, max_digits=5)
|
||||||
|
|
||||||
|
class IntegerPKData(models.Model):
|
||||||
|
data = models.IntegerField(primary_key=True)
|
||||||
|
|
||||||
|
# class ImagePKData(models.Model):
|
||||||
|
# data = models.ImageField(primary_key=True)
|
||||||
|
|
||||||
|
class IPAddressPKData(models.Model):
|
||||||
|
data = models.IPAddressField(primary_key=True)
|
||||||
|
|
||||||
|
class NullBooleanPKData(models.Model):
|
||||||
|
data = models.NullBooleanField(primary_key=True)
|
||||||
|
|
||||||
|
class PhonePKData(models.Model):
|
||||||
|
data = models.PhoneNumberField(primary_key=True)
|
||||||
|
|
||||||
|
class PositiveIntegerPKData(models.Model):
|
||||||
|
data = models.PositiveIntegerField(primary_key=True)
|
||||||
|
|
||||||
|
class PositiveSmallIntegerPKData(models.Model):
|
||||||
|
data = models.PositiveSmallIntegerField(primary_key=True)
|
||||||
|
|
||||||
|
class SlugPKData(models.Model):
|
||||||
|
data = models.SlugField(primary_key=True)
|
||||||
|
|
||||||
|
class SmallPKData(models.Model):
|
||||||
|
data = models.SmallIntegerField(primary_key=True)
|
||||||
|
|
||||||
|
# class TextPKData(models.Model):
|
||||||
|
# data = models.TextField(primary_key=True)
|
||||||
|
|
||||||
|
# class TimePKData(models.Model):
|
||||||
|
# data = models.TimeField(primary_key=True)
|
||||||
|
|
||||||
|
class USStatePKData(models.Model):
|
||||||
|
data = models.USStateField(primary_key=True)
|
||||||
|
|
||||||
|
# class XMLPKData(models.Model):
|
||||||
|
# data = models.XMLField(primary_key=True)
|
||||||
|
|
263
tests/regressiontests/serializers_regress/tests.py
Normal file
263
tests/regressiontests/serializers_regress/tests.py
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
"""
|
||||||
|
A test spanning all the capabilities of all the serializers.
|
||||||
|
|
||||||
|
This class defines sample data and a dynamically generated
|
||||||
|
test case that is capable of testing the capabilities of
|
||||||
|
the serializers. This includes all valid data values, plus
|
||||||
|
forward, backwards and self references.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import unittest, datetime
|
||||||
|
|
||||||
|
from django.utils.functional import curry
|
||||||
|
from django.core import serializers
|
||||||
|
from django.db import transaction
|
||||||
|
from django.core import management
|
||||||
|
|
||||||
|
from models import *
|
||||||
|
|
||||||
|
# A set of functions that can be used to recreate
|
||||||
|
# test data objects of various kinds
|
||||||
|
def data_create(pk, klass, data):
|
||||||
|
instance = klass(id=pk)
|
||||||
|
instance.data = data
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def generic_create(pk, klass, data):
|
||||||
|
instance = klass(id=pk)
|
||||||
|
instance.data = data[0]
|
||||||
|
instance.save()
|
||||||
|
for tag in data[1:]:
|
||||||
|
instance.tags.create(data=tag)
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def fk_create(pk, klass, data):
|
||||||
|
instance = klass(id=pk)
|
||||||
|
setattr(instance, 'data_id', data)
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def m2m_create(pk, klass, data):
|
||||||
|
instance = klass(id=pk)
|
||||||
|
instance.save()
|
||||||
|
instance.data = data
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def o2o_create(pk, klass, data):
|
||||||
|
instance = klass()
|
||||||
|
instance.data_id = data
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def pk_create(pk, klass, data):
|
||||||
|
instance = klass()
|
||||||
|
instance.data = data
|
||||||
|
instance.save()
|
||||||
|
return instance
|
||||||
|
|
||||||
|
# A set of functions that can be used to compare
|
||||||
|
# test data objects of various kinds
|
||||||
|
def data_compare(testcase, pk, klass, data):
|
||||||
|
instance = klass.objects.get(id=pk)
|
||||||
|
testcase.assertEqual(data, instance.data,
|
||||||
|
"Objects with PK=%d not equal; expected '%s' (%s), got '%s' (%s)" % (pk,data, type(data), instance.data, type(instance.data)))
|
||||||
|
|
||||||
|
def generic_compare(testcase, pk, klass, data):
|
||||||
|
instance = klass.objects.get(id=pk)
|
||||||
|
testcase.assertEqual(data[0], instance.data)
|
||||||
|
testcase.assertEqual(data[1:], [t.data for t in instance.tags.all()])
|
||||||
|
|
||||||
|
def fk_compare(testcase, pk, klass, data):
|
||||||
|
instance = klass.objects.get(id=pk)
|
||||||
|
testcase.assertEqual(data, instance.data_id)
|
||||||
|
|
||||||
|
def m2m_compare(testcase, pk, klass, data):
|
||||||
|
instance = klass.objects.get(id=pk)
|
||||||
|
testcase.assertEqual(data, [obj.id for obj in instance.data.all()])
|
||||||
|
|
||||||
|
def o2o_compare(testcase, pk, klass, data):
|
||||||
|
instance = klass.objects.get(data=data)
|
||||||
|
testcase.assertEqual(data, instance.data_id)
|
||||||
|
|
||||||
|
def pk_compare(testcase, pk, klass, data):
|
||||||
|
instance = klass.objects.get(data=data)
|
||||||
|
testcase.assertEqual(data, instance.data)
|
||||||
|
|
||||||
|
# Define some data types. Each data type is
|
||||||
|
# actually a pair of functions; one to create
|
||||||
|
# and one to compare objects of that type
|
||||||
|
data_obj = (data_create, data_compare)
|
||||||
|
generic_obj = (generic_create, generic_compare)
|
||||||
|
fk_obj = (fk_create, fk_compare)
|
||||||
|
m2m_obj = (m2m_create, m2m_compare)
|
||||||
|
o2o_obj = (o2o_create, o2o_compare)
|
||||||
|
pk_obj = (pk_create, pk_compare)
|
||||||
|
|
||||||
|
test_data = [
|
||||||
|
# Format: (data type, PK value, Model Class, data)
|
||||||
|
(data_obj, 1, BooleanData, True),
|
||||||
|
(data_obj, 2, BooleanData, False),
|
||||||
|
(data_obj, 10, CharData, "Test Char Data"),
|
||||||
|
(data_obj, 11, CharData, ""),
|
||||||
|
(data_obj, 12, CharData, "None"),
|
||||||
|
(data_obj, 13, CharData, "null"),
|
||||||
|
(data_obj, 14, CharData, "NULL"),
|
||||||
|
(data_obj, 15, CharData, None),
|
||||||
|
(data_obj, 20, DateData, datetime.date(2006,6,16)),
|
||||||
|
(data_obj, 21, DateData, None),
|
||||||
|
(data_obj, 30, DateTimeData, datetime.datetime(2006,6,16,10,42,37)),
|
||||||
|
(data_obj, 31, DateTimeData, None),
|
||||||
|
(data_obj, 40, EmailData, "hovercraft@example.com"),
|
||||||
|
(data_obj, 41, EmailData, None),
|
||||||
|
(data_obj, 50, FileData, 'file:///foo/bar/whiz.txt'),
|
||||||
|
(data_obj, 51, FileData, None),
|
||||||
|
(data_obj, 60, FilePathData, "/foo/bar/whiz.txt"),
|
||||||
|
(data_obj, 61, FilePathData, None),
|
||||||
|
(data_obj, 70, FloatData, 12.345),
|
||||||
|
(data_obj, 71, FloatData, -12.345),
|
||||||
|
(data_obj, 72, FloatData, 0.0),
|
||||||
|
(data_obj, 73, FloatData, None),
|
||||||
|
(data_obj, 80, IntegerData, 123456789),
|
||||||
|
(data_obj, 81, IntegerData, -123456789),
|
||||||
|
(data_obj, 82, IntegerData, 0),
|
||||||
|
(data_obj, 83, IntegerData, None),
|
||||||
|
#(XX, ImageData
|
||||||
|
(data_obj, 90, IPAddressData, "127.0.0.1"),
|
||||||
|
(data_obj, 91, IPAddressData, None),
|
||||||
|
(data_obj, 100, NullBooleanData, True),
|
||||||
|
(data_obj, 101, NullBooleanData, False),
|
||||||
|
(data_obj, 102, NullBooleanData, None),
|
||||||
|
(data_obj, 110, PhoneData, "212-634-5789"),
|
||||||
|
(data_obj, 111, PhoneData, None),
|
||||||
|
(data_obj, 120, PositiveIntegerData, 123456789),
|
||||||
|
(data_obj, 121, PositiveIntegerData, None),
|
||||||
|
(data_obj, 130, PositiveSmallIntegerData, 12),
|
||||||
|
(data_obj, 131, PositiveSmallIntegerData, None),
|
||||||
|
(data_obj, 140, SlugData, "this-is-a-slug"),
|
||||||
|
(data_obj, 141, SlugData, None),
|
||||||
|
(data_obj, 150, SmallData, 12),
|
||||||
|
(data_obj, 151, SmallData, -12),
|
||||||
|
(data_obj, 152, SmallData, 0),
|
||||||
|
(data_obj, 153, SmallData, None),
|
||||||
|
(data_obj, 160, TextData, """This is a long piece of text.
|
||||||
|
It contains line breaks.
|
||||||
|
Several of them.
|
||||||
|
The end."""),
|
||||||
|
(data_obj, 161, TextData, ""),
|
||||||
|
(data_obj, 162, TextData, None),
|
||||||
|
(data_obj, 170, TimeData, datetime.time(10,42,37)),
|
||||||
|
(data_obj, 171, TimeData, None),
|
||||||
|
(data_obj, 180, USStateData, "MA"),
|
||||||
|
(data_obj, 181, USStateData, None),
|
||||||
|
(data_obj, 190, XMLData, "<foo></foo>"),
|
||||||
|
(data_obj, 191, XMLData, None),
|
||||||
|
|
||||||
|
(generic_obj, 200, GenericData, ['Generic Object 1', 'tag1', 'tag2']),
|
||||||
|
(generic_obj, 201, GenericData, ['Generic Object 2', 'tag2', 'tag3']),
|
||||||
|
|
||||||
|
(data_obj, 300, Anchor, "Anchor 1"),
|
||||||
|
(data_obj, 301, Anchor, "Anchor 2"),
|
||||||
|
|
||||||
|
(fk_obj, 400, FKData, 300), # Post reference
|
||||||
|
(fk_obj, 401, FKData, 500), # Pre reference
|
||||||
|
(fk_obj, 402, FKData, None), # Empty reference
|
||||||
|
|
||||||
|
(m2m_obj, 410, M2MData, []), # Empty set
|
||||||
|
(m2m_obj, 411, M2MData, [300,301]), # Post reference
|
||||||
|
(m2m_obj, 412, M2MData, [500,501]), # Pre reference
|
||||||
|
(m2m_obj, 413, M2MData, [300,301,500,501]), # Pre and Post reference
|
||||||
|
|
||||||
|
(o2o_obj, None, O2OData, 300), # Post reference
|
||||||
|
(o2o_obj, None, O2OData, 500), # Pre reference
|
||||||
|
|
||||||
|
(fk_obj, 430, FKSelfData, 431), # Pre reference
|
||||||
|
(fk_obj, 431, FKSelfData, 430), # Post reference
|
||||||
|
(fk_obj, 432, FKSelfData, None), # Empty reference
|
||||||
|
|
||||||
|
(m2m_obj, 440, M2MSelfData, []),
|
||||||
|
(m2m_obj, 441, M2MSelfData, []),
|
||||||
|
(m2m_obj, 442, M2MSelfData, [440, 441]),
|
||||||
|
(m2m_obj, 443, M2MSelfData, [445, 446]),
|
||||||
|
(m2m_obj, 444, M2MSelfData, [440, 441, 445, 446]),
|
||||||
|
(m2m_obj, 445, M2MSelfData, []),
|
||||||
|
(m2m_obj, 446, M2MSelfData, []),
|
||||||
|
|
||||||
|
(data_obj, 500, Anchor, "Anchor 3"),
|
||||||
|
(data_obj, 501, Anchor, "Anchor 4"),
|
||||||
|
|
||||||
|
(pk_obj, 601, BooleanPKData, True),
|
||||||
|
(pk_obj, 602, BooleanPKData, False),
|
||||||
|
(pk_obj, 610, CharPKData, "Test Char PKData"),
|
||||||
|
# (pk_obj, 620, DatePKData, datetime.date(2006,6,16)),
|
||||||
|
# (pk_obj, 630, DateTimePKData, datetime.datetime(2006,6,16,10,42,37)),
|
||||||
|
(pk_obj, 640, EmailPKData, "hovercraft@example.com"),
|
||||||
|
(pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'),
|
||||||
|
(pk_obj, 660, FilePathPKData, "/foo/bar/whiz.txt"),
|
||||||
|
(pk_obj, 670, FloatPKData, 12.345),
|
||||||
|
(pk_obj, 671, FloatPKData, -12.345),
|
||||||
|
(pk_obj, 672, FloatPKData, 0.0),
|
||||||
|
(pk_obj, 680, IntegerPKData, 123456789),
|
||||||
|
(pk_obj, 681, IntegerPKData, -123456789),
|
||||||
|
(pk_obj, 682, IntegerPKData, 0),
|
||||||
|
# (XX, ImagePKData
|
||||||
|
(pk_obj, 690, IPAddressPKData, "127.0.0.1"),
|
||||||
|
(pk_obj, 700, NullBooleanPKData, True),
|
||||||
|
(pk_obj, 701, NullBooleanPKData, False),
|
||||||
|
(pk_obj, 710, PhonePKData, "212-634-5789"),
|
||||||
|
(pk_obj, 720, PositiveIntegerPKData, 123456789),
|
||||||
|
(pk_obj, 730, PositiveSmallIntegerPKData, 12),
|
||||||
|
(pk_obj, 740, SlugPKData, "this-is-a-slug"),
|
||||||
|
(pk_obj, 750, SmallPKData, 12),
|
||||||
|
(pk_obj, 751, SmallPKData, -12),
|
||||||
|
(pk_obj, 752, SmallPKData, 0),
|
||||||
|
# (pk_obj, 760, TextPKData, """This is a long piece of text.
|
||||||
|
# It contains line breaks.
|
||||||
|
# Several of them.
|
||||||
|
# The end."""),
|
||||||
|
# (pk_obj, 770, TimePKData, datetime.time(10,42,37)),
|
||||||
|
(pk_obj, 780, USStatePKData, "MA"),
|
||||||
|
# (pk_obj, 790, XMLPKData, "<foo></foo>"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Dynamically create serializer tests to ensure that all
|
||||||
|
# registered serializers are automatically tested.
|
||||||
|
class SerializerTests(unittest.TestCase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def serializerTest(format, self):
|
||||||
|
# Clear the database first
|
||||||
|
management.flush(verbosity=0, interactive=False)
|
||||||
|
|
||||||
|
# Create all the objects defined in the test data
|
||||||
|
objects = []
|
||||||
|
transaction.enter_transaction_management()
|
||||||
|
transaction.managed(True)
|
||||||
|
for (func, pk, klass, datum) in test_data:
|
||||||
|
objects.append(func[0](pk, klass, datum))
|
||||||
|
transaction.commit()
|
||||||
|
transaction.leave_transaction_management()
|
||||||
|
|
||||||
|
# Add the generic tagged objects to the object list
|
||||||
|
objects.extend(Tag.objects.all())
|
||||||
|
|
||||||
|
# Serialize the test database
|
||||||
|
serialized_data = serializers.serialize(format, objects, indent=2)
|
||||||
|
|
||||||
|
# Flush the database and recreate from the serialized data
|
||||||
|
management.flush(verbosity=0, interactive=False)
|
||||||
|
transaction.enter_transaction_management()
|
||||||
|
transaction.managed(True)
|
||||||
|
for obj in serializers.deserialize(format, serialized_data):
|
||||||
|
obj.save()
|
||||||
|
transaction.commit()
|
||||||
|
transaction.leave_transaction_management()
|
||||||
|
|
||||||
|
# Assert that the deserialized data is the same
|
||||||
|
# as the original source
|
||||||
|
for (func, pk, klass, datum) in test_data:
|
||||||
|
func[1](self, pk, klass, datum)
|
||||||
|
|
||||||
|
for format in serializers.get_serializer_formats():
|
||||||
|
setattr(SerializerTests, 'test_'+format+'_serializer', curry(serializerTest, format))
|
@ -401,6 +401,20 @@ class Templates(unittest.TestCase):
|
|||||||
'ifequal-split09': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slash\man"}, "yes"),
|
'ifequal-split09': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slash\man"}, "yes"),
|
||||||
'ifequal-split10': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slashman"}, "no"),
|
'ifequal-split10': (r"{% ifequal a 'slash\man' %}yes{% else %}no{% endifequal %}", {'a': r"slashman"}, "no"),
|
||||||
|
|
||||||
|
# NUMERIC RESOLUTION
|
||||||
|
'ifequal-numeric01': ('{% ifequal x 5 %}yes{% endifequal %}', {'x': '5'}, ''),
|
||||||
|
'ifequal-numeric02': ('{% ifequal x 5 %}yes{% endifequal %}', {'x': 5}, 'yes'),
|
||||||
|
'ifequal-numeric03': ('{% ifequal x 5.2 %}yes{% endifequal %}', {'x': 5}, ''),
|
||||||
|
'ifequal-numeric04': ('{% ifequal x 5.2 %}yes{% endifequal %}', {'x': 5.2}, 'yes'),
|
||||||
|
'ifequal-numeric05': ('{% ifequal x 0.2 %}yes{% endifequal %}', {'x': .2}, 'yes'),
|
||||||
|
'ifequal-numeric06': ('{% ifequal x .2 %}yes{% endifequal %}', {'x': .2}, 'yes'),
|
||||||
|
'ifequal-numeric07': ('{% ifequal x 2. %}yes{% endifequal %}', {'x': 2}, ''),
|
||||||
|
'ifequal-numeric08': ('{% ifequal x "5" %}yes{% endifequal %}', {'x': 5}, ''),
|
||||||
|
'ifequal-numeric09': ('{% ifequal x "5" %}yes{% endifequal %}', {'x': '5'}, 'yes'),
|
||||||
|
'ifequal-numeric10': ('{% ifequal x -5 %}yes{% endifequal %}', {'x': -5}, 'yes'),
|
||||||
|
'ifequal-numeric11': ('{% ifequal x -5.2 %}yes{% endifequal %}', {'x': -5.2}, 'yes'),
|
||||||
|
'ifequal-numeric12': ('{% ifequal x +5 %}yes{% endifequal %}', {'x': 5}, 'yes'),
|
||||||
|
|
||||||
### IFNOTEQUAL TAG ########################################################
|
### IFNOTEQUAL TAG ########################################################
|
||||||
'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
|
'ifnotequal01': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 2}, "yes"),
|
||||||
'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
|
'ifnotequal02': ("{% ifnotequal a b %}yes{% endifnotequal %}", {"a": 1, "b": 1}, ""),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user