1
0
mirror of https://github.com/django/django.git synced 2025-07-03 17:29:12 +00:00

unicode: Merged up to [5053].

git-svn-id: http://code.djangoproject.com/svn/django/branches/unicode@5054 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2007-04-21 06:18:25 +00:00
parent 349bf5a355
commit 5860a5a4be
87 changed files with 10170 additions and 4557 deletions

View File

@ -78,6 +78,7 @@ answer newbie questions, and generally made Django that much better:
Jason Davies (Esaj) <http://www.jasondavies.com/> Jason Davies (Esaj) <http://www.jasondavies.com/>
Alex Dedul Alex Dedul
deric@monowerks.com deric@monowerks.com
Max Derkachev <mderk@yandex.ru>
dne@mayonnaise.net dne@mayonnaise.net
Maximillian Dornseif <md@hudora.de> Maximillian Dornseif <md@hudora.de>
Jeremy Dunck <http://dunck.us/> Jeremy Dunck <http://dunck.us/>
@ -88,12 +89,14 @@ answer newbie questions, and generally made Django that much better:
Dirk Eschler <dirk.eschler@gmx.net> Dirk Eschler <dirk.eschler@gmx.net>
Marc Fargas <telenieko@telenieko.com> Marc Fargas <telenieko@telenieko.com>
favo@exoweb.net favo@exoweb.net
Bill Fenner <fenner@gmail.com>
Matthew Flanagan <http://wadofstuff.blogspot.com> Matthew Flanagan <http://wadofstuff.blogspot.com>
Eric Floehr <eric@intellovations.com> Eric Floehr <eric@intellovations.com>
Jorge Gajon <gajon@gajon.org> Jorge Gajon <gajon@gajon.org>
gandalf@owca.info gandalf@owca.info
Baishampayan Ghose Baishampayan Ghose
martin.glueck@gmail.com martin.glueck@gmail.com
GomoX <gomo@datafull.com>
Simon Greenhill <dev@simon.net.nz> Simon Greenhill <dev@simon.net.nz>
Owen Griffiths Owen Griffiths
Espen Grindhaug <http://grindhaug.org/> Espen Grindhaug <http://grindhaug.org/>
@ -107,9 +110,11 @@ answer newbie questions, and generally made Django that much better:
Kieran Holland <http://www.kieranholland.com> Kieran Holland <http://www.kieranholland.com>
Robert Rock Howard <http://djangomojo.com/> Robert Rock Howard <http://djangomojo.com/>
Jason Huggins <http://www.jrandolph.com/blog/> Jason Huggins <http://www.jrandolph.com/blog/>
Hyun Mi Ae
Tom Insam Tom Insam
Baurzhan Ismagulov <ibr@radix50.net> Baurzhan Ismagulov <ibr@radix50.net>
jcrasta@gmail.com jcrasta@gmail.com
Zak Johnson <zakj@nox.cx>
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
@ -120,6 +125,8 @@ answer newbie questions, and generally made Django that much better:
Sune Kirkeby <http://ibofobi.dk/> Sune Kirkeby <http://ibofobi.dk/>
Bastian Kleineidam <calvin@debian.org> Bastian Kleineidam <calvin@debian.org>
Cameron Knight (ckknight) Cameron Knight (ckknight)
Gasper Koren
Martin Kosír <martin@martinkosir.net>
Meir Kriheli <http://mksoft.co.il/> Meir Kriheli <http://mksoft.co.il/>
Bruce Kroeze <http://coderseye.com/> Bruce Kroeze <http://coderseye.com/>
Joseph Kocherhans Joseph Kocherhans
@ -171,9 +178,11 @@ answer newbie questions, and generally made Django that much better:
J. Rademaker J. Rademaker
Michael Radziej <mir@noris.de> Michael Radziej <mir@noris.de>
ramiro ramiro
Massimiliano Ravelli <massimiliano.ravelli@gmail.com>
Brian Ray <http://brianray.chipy.org/> Brian Ray <http://brianray.chipy.org/>
remco@diji.biz remco@diji.biz
rhettg@gmail.com rhettg@gmail.com
Armin Ronacher
Oliver Rutherfurd <http://rutherfurd.net/> Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/> Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
David Schein David Schein

View File

@ -11,4 +11,5 @@ recursive-include django/conf/locale *
recursive-include django/contrib/admin/templates * recursive-include django/contrib/admin/templates *
recursive-include django/contrib/admin/media * recursive-include django/contrib/admin/media *
recursive-include django/contrib/comments/templates * recursive-include django/contrib/comments/templates *
recursive-include django/contrib/databrowse/templates *
recursive-include django/contrib/sitemaps/templates * recursive-include django/contrib/sitemaps/templates *

View File

@ -55,6 +55,7 @@ LANGUAGES = (
('is', gettext_noop('Icelandic')), ('is', gettext_noop('Icelandic')),
('it', gettext_noop('Italian')), ('it', gettext_noop('Italian')),
('ja', gettext_noop('Japanese')), ('ja', gettext_noop('Japanese')),
('ko', gettext_noop('Korean')),
('kn', gettext_noop('Kannada')), ('kn', gettext_noop('Kannada')),
('lv', gettext_noop('Latvian')), ('lv', gettext_noop('Latvian')),
('mk', gettext_noop('Macedonian')), ('mk', gettext_noop('Macedonian')),

View File

@ -305,7 +305,7 @@ msgstr "Japon
#: conf/global_settings.py:58 #: conf/global_settings.py:58
msgid "Latvian" msgid "Latvian"
msgstr "" msgstr "Latvio"
#: conf/global_settings.py:59 #: conf/global_settings.py:59
msgid "Macedonian" msgid "Macedonian"
@ -611,7 +611,7 @@ msgstr "La URL %s no apunta a una imagen v
#, python-format #, python-format
msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid." msgid "Phone numbers must be in XXX-XXX-XXXX format. \"%s\" is invalid."
msgstr "" msgstr ""
"Los números de teléfono deben guardar el formato XXX-XXX-XXXX format. \"%s\" " "Los números de teléfono deben guardar el formato XXX-XXX-XXXX. \"%s\" "
"no es válido." "no es válido."
#: core/validators.py:196 #: core/validators.py:196
@ -726,10 +726,10 @@ msgid "Please enter a valid decimal number with a whole part of at most %s digit
msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits." msgid_plural "Please enter a valid decimal number with a whole part of at most %s digits."
msgstr[0] "" msgstr[0] ""
"Por favor, introduzca un número decimal válido con a lo más %s dígito en " "Por favor, introduzca un número decimal válido con a lo más %s dígito en "
"total." "su parte entera."
msgstr[1] "" msgstr[1] ""
"Por favor, introduzca un número decimal válido con a lo más %s dígitos en " "Por favor, introduzca un número decimal válido con a lo más %s dígitos en "
"total." "su parte entera."
#: core/validators.py:426 #: core/validators.py:426
#, python-format #, python-format
@ -958,7 +958,7 @@ msgid ""
"digits and underscores)." "digits and underscores)."
msgstr "" msgstr ""
"Requerido. 30 caracteres o menos. Sólo caracteres alfanuméricos (letras, " "Requerido. 30 caracteres o menos. Sólo caracteres alfanuméricos (letras, "
"dígutos y guiones bajos)." "dígitos y guiones bajos)."
#: contrib/auth/models.py:91 #: contrib/auth/models.py:91
msgid "first name" msgid "first name"
@ -1107,7 +1107,7 @@ msgstr "Las contrase
#: 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."
msgstr "" msgstr ""
"Tu contraseña antígua es incorrecta. Por favor, vuelve a introducirla " "Tu contraseña antigua es incorrecta. Por favor, vuelve a introducirla "
"correctamente." "correctamente."
#: contrib/comments/models.py:67 contrib/comments/models.py:166 #: contrib/comments/models.py:67 contrib/comments/models.py:166
@ -1707,7 +1707,7 @@ msgid ""
msgstr "" msgstr ""
"Ha ocurrido un error. Se ha informado a los administradores del sitio " "Ha ocurrido un error. Se ha informado a los administradores del sitio "
"mediante correo electrónico y debería arreglarse en breve. Gracias por su " "mediante correo electrónico y debería arreglarse en breve. Gracias por su "
"paciencia" "paciencia."
#: contrib/admin/templates/admin/search_form.html:8 #: contrib/admin/templates/admin/search_form.html:8
msgid "Go" msgid "Go"
@ -1899,7 +1899,7 @@ msgid ""
"the appropriate user." "the appropriate user."
msgstr "" msgstr ""
"Algo va mal con la instalación de la base de datos. Asegúrate que las tablas " "Algo va mal con la instalación de la base de datos. Asegúrate que las tablas "
"necesarias han sido creadas, y que la base de datos puede ser leida por el " "necesarias han sido creadas, y que la base de datos puede ser leída por el "
"usuario apropiado." "usuario apropiado."
#: contrib/admin/templates/admin/filter.html:2 #: contrib/admin/templates/admin/filter.html:2
@ -1912,7 +1912,7 @@ 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 ""
"Primero, introduzca un nombre de usuario y una contraseña. Luego, podrá " "Primero introduzca un nombre de usuario y una contraseña. Luego podrá "
"editar el resto de opciones del usuario." "editar el resto de opciones del usuario."
#: contrib/admin/templates/admin/auth/user/add_form.html:12 #: contrib/admin/templates/admin/auth/user/add_form.html:12
@ -2105,7 +2105,7 @@ msgstr "vista:"
#: contrib/admin/views/doc.py:164 #: contrib/admin/views/doc.py:164
#, python-format #, python-format
msgid "App %r not found" msgid "App %r not found"
msgstr "Applicación %r no encontrada" msgstr "Aplicación %r no encontrada"
#: contrib/admin/views/doc.py:171 #: contrib/admin/views/doc.py:171
#, python-format #, python-format
@ -2326,12 +2326,12 @@ msgstr "Cambiar clave: %s"
#: contrib/localflavor/usa/forms.py:17 #: contrib/localflavor/usa/forms.py:17
msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX." msgid "Enter a zip code in the format XXXXX or XXXXX-XXXX."
msgstr "Introduzca un código zip en el formato XXXXX o XXXX-XXXX." msgstr "Introduzca un código postal en el formato XXXXX o XXXX-XXXX."
#: contrib/localflavor/uk/forms.py:18 #: contrib/localflavor/uk/forms.py:18
msgid "Enter a postcode. A space is required between the two postcode parts." msgid "Enter a postcode. A space is required between the two postcode parts."
msgstr "" msgstr ""
"Introduzca in código postal. Se necesita un espacio entre las dos partes del " "Introduzca un código postal. Se necesita un espacio entre las dos partes del "
"código." "código."
#: contrib/sessions/models.py:51 #: contrib/sessions/models.py:51

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -0,0 +1,118 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-04-06 11:10+0900\n"
"PO-Revision-Date: 2007-04-06 11:15+0900\n"
"Last-Translator: Hyun Mi Ae <happyhyun@gmail.com>\n"
"Language-Team: Korean\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: contrib/admin/media/js/calendar.js:24
#: contrib/admin/media/js/dateparse.js:32
msgid ""
"January February March April May June July August September October November "
"December"
msgstr "1월 2월 3월 4월 5월 6월 7월 8월 9월 10월 11월 12월"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "일 월 화 수 목 금 토"
#: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "일요일 월요일 화요일 수요일 목요일 금요일 토요일"
#: 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/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr "보기"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr "감추기"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now"
msgstr "현재"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock"
msgstr "시계"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time"
msgstr "시간 선택"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight"
msgstr "자정"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m."
msgstr "오전 6시"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon"
msgstr "정오"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel"
msgstr "취소"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today"
msgstr "오늘"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar"
msgstr "달력"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday"
msgstr "어제"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow"
msgstr "내일"

File diff suppressed because it is too large Load Diff

View File

@ -1732,7 +1732,7 @@ msgstr "Ikke godkjent URL: %s"
#: core/validators.py:206 core/validators.py:208 #: core/validators.py:206 core/validators.py:208
#, python-format #, python-format
msgid "The URL %s is a broken link." msgid "The URL %s is a broken link."
msgstr "Internettadresse fører til en side som ikke virker." msgstr "Internettadresse %s fører til en side som ikke virker."
#: core/validators.py:214 #: core/validators.py:214
msgid "Enter a valid U.S. state abbreviation." msgid "Enter a valid U.S. state abbreviation."
@ -1881,7 +1881,7 @@ msgid ""
"The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line " "The \"%(attr)s\" attribute on line %(line)s has an invalid value. (Line "
"starts with \"%(start)s\".)" "starts with \"%(start)s\".)"
msgstr "" msgstr ""
"\"%(attr)s\" tillegg på linje $(line)s har en ikke godkjent verdi. (Linjen " "\"%(attr)s\" tillegg på linje %(line)s har en ikke godkjent verdi. (Linjen "
"starter med \"%(start)s\".)" "starter med \"%(start)s\".)"
#: db/models/manipulators.py:302 #: db/models/manipulators.py:302
@ -1892,7 +1892,7 @@ msgstr "%(object)s med %(type)s finnes allerede for angitt %(field)s."
#: db/models/fields/__init__.py:40 #: db/models/fields/__init__.py:40
#, python-format #, python-format
msgid "%(optname)s with this %(fieldname)s already exists." msgid "%(optname)s with this %(fieldname)s already exists."
msgstr "$(optname)s med %(fieldname)s finnes allerede." msgstr "%(optname)s med %(fieldname)s finnes allerede."
#: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265 #: db/models/fields/__init__.py:114 db/models/fields/__init__.py:265
#: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553 #: db/models/fields/__init__.py:542 db/models/fields/__init__.py:553

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,15 @@
# SOME DESCRIPTIVE TITLE. #
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# VLADO LABATH <vlado@labath.org>, 2005.
#
#, fuzzy
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: Django 1.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-18 19:38-0500\n" "POT-Creation-Date: 2007-04-01 19:21+0200\n"
"PO-Revision-Date: 2005-12-18 19:26-0500\n" "PO-Revision-Date: 2007-04-03 21:48+0200\n"
"Last-Translator: VLADO LABATH <vlado@labath.org>\n" "Last-Translator: <>\n"
"Language-Team: LANGUAGE <sk@li.org>\n" "Language-Team: \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"
#: contrib/admin/media/js/SelectFilter2.js:33 #: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format #, perl-format
@ -23,15 +18,15 @@ msgstr "Možný %s"
#: contrib/admin/media/js/SelectFilter2.js:41 #: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all" msgid "Choose all"
msgstr "Vyber všetko" msgstr "Vybr všetko"
#: contrib/admin/media/js/SelectFilter2.js:46 #: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add" msgid "Add"
msgstr "Pridaj" msgstr "Pridať"
#: contrib/admin/media/js/SelectFilter2.js:48 #: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove" msgid "Remove"
msgstr "Vymaž" msgstr "Vymazať"
#: contrib/admin/media/js/SelectFilter2.js:53 #: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format #, perl-format
@ -40,13 +35,13 @@ msgstr "Vybrané %s"
#: contrib/admin/media/js/SelectFilter2.js:54 #: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click " msgid "Select your choice(s) and click "
msgstr "Vyber si svoju voľbu a klikni" msgstr "Vyberte položku a kliknite"
#: contrib/admin/media/js/SelectFilter2.js:59 #: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all" msgid "Clear all"
msgstr "Vyčisti všetko" msgstr "Odstrániť vybrané"
#: contrib/admin/media/js/dateparse.js:26 #: contrib/admin/media/js/dateparse.js:32
#: contrib/admin/media/js/calendar.js:24 #: contrib/admin/media/js/calendar.js:24
msgid "" msgid ""
"January February March April May June July August September October November " "January February March April May June July August September October November "
@ -55,7 +50,7 @@ msgstr ""
"Január Február Marec Apríl Máj Jún Júl August September Október November " "Január Február Marec Apríl Máj Jún Júl August September Október November "
"December" "December"
#: contrib/admin/media/js/dateparse.js:27 #: contrib/admin/media/js/dateparse.js:33
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday" msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Nedeľa Pondelok Utorok Streda Štvrtok Piatok Sobota" msgstr "Nedeľa Pondelok Utorok Streda Štvrtok Piatok Sobota"
@ -63,49 +58,59 @@ msgstr "Nedeľa Pondelok Utorok Streda Štvrtok Piatok Sobota"
msgid "S M T W T F S" msgid "S M T W T F S"
msgstr "N P U S Š P S" msgstr "N P U S Š P S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:34
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80 #: contrib/admin/media/js/admin/CollapsedFieldsets.js:72
msgid "Show"
msgstr "Zobraziť"
#: contrib/admin/media/js/admin/CollapsedFieldsets.js:63
msgid "Hide"
msgstr "Skryť"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:47
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Now" msgid "Now"
msgstr "Práve teraz" msgstr "Práve teraz"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:51
msgid "Clock" msgid "Clock"
msgstr "Hodiny" msgstr "Hodiny"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:78
msgid "Choose a time" msgid "Choose a time"
msgstr "Vyber čas" msgstr "Vybr čas"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "Midnight" msgid "Midnight"
msgstr "Polnoc" msgstr "Polnoc"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "6 a.m." msgid "6 a.m."
msgstr "6 ráno" msgstr "6 ráno"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:84
msgid "Noon" msgid "Noon"
msgstr "Poludnie" msgstr "Poludnie"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:88
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:183
msgid "Cancel" msgid "Cancel"
msgstr "Zruš" msgstr "Zruš"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:128
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:177
msgid "Today" msgid "Today"
msgstr "Dnes" msgstr "Dnes"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:132
msgid "Calendar" msgid "Calendar"
msgstr "Kalendár" msgstr "Kalendár"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:175
msgid "Yesterday" msgid "Yesterday"
msgstr "Včera" msgstr "Včera"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164 #: contrib/admin/media/js/admin/DateTimeShortcuts.js:179
msgid "Tomorrow" msgid "Tomorrow"
msgstr "Zajtra" msgstr "Zajtra"

Binary file not shown.

View File

@ -0,0 +1,107 @@
# Copyright (C) 2007
# This file is distributed under the same license as the PACKAGE package.
#
msgid ""
msgstr ""
"Project-Id-Version: DJANGO-JS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2005-12-09 11:51+0100\n"
"PO-Revision-Date: 2007-03-31 21:29+0100\n"
"Last-Translator: Gasper Koren <skrat@owca.info>\n"
"Language-Team: SLOVENIAN <lugos-slo@lugos.si>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-Language: Slovenian\n"
"X-Poedit-Country: SLOVENIA\n"
#: contrib/admin/media/js/SelectFilter2.js:33
#, perl-format
msgid "Available %s"
msgstr "Možne %s"
#: contrib/admin/media/js/SelectFilter2.js:41
msgid "Choose all"
msgstr "Izberi vse"
#: contrib/admin/media/js/SelectFilter2.js:46
msgid "Add"
msgstr "Dodaj"
#: contrib/admin/media/js/SelectFilter2.js:48
msgid "Remove"
msgstr "Odstrani"
#: contrib/admin/media/js/SelectFilter2.js:53
#, perl-format
msgid "Chosen %s"
msgstr "Izberite %s"
#: contrib/admin/media/js/SelectFilter2.js:54
msgid "Select your choice(s) and click "
msgstr "Izberite in kliknite"
#: contrib/admin/media/js/SelectFilter2.js:59
msgid "Clear all"
msgstr "Izbriši vse"
#: 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 "Januar Februar Marec April Maj Junij Julij Avgust September Oktober November December"
#: contrib/admin/media/js/dateparse.js:27
msgid "Sunday Monday Tuesday Wednesday Thursday Friday Saturday"
msgstr "Nedelja Ponedeljek Torek Sreda Četrtek Petek Sobota"
#: contrib/admin/media/js/calendar.js:25
msgid "S M T W T F S"
msgstr "N P T S Č P S"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:45
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:80
msgid "Now"
msgstr "Sedaj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:48
msgid "Clock"
msgstr "URA"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:77
msgid "Choose a time"
msgstr "Izberite čas"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:81
msgid "Midnight"
msgstr "Polnoč"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:82
msgid "6 a.m."
msgstr "Ob 6h"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:83
msgid "Noon"
msgstr "Opoldne"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:87
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:168
msgid "Cancel"
msgstr "Prekliči"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:111
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:162
msgid "Today"
msgstr "Danes"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:114
msgid "Calendar"
msgstr "Koledar"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:160
msgid "Yesterday"
msgstr "Včeraj"
#: contrib/admin/media/js/admin/DateTimeShortcuts.js:164
msgid "Tomorrow"
msgstr "Jutri"

View File

@ -26,7 +26,7 @@ form .aligned p, form .aligned ul { margin-left:7em; padding-left:30px; }
form .aligned table p { margin-left:0; padding-left:0; } form .aligned table p { margin-left:0; padding-left:0; }
form .aligned p.help { padding-left:38px; } form .aligned p.help { padding-left:38px; }
.aligned .vCheckboxLabel { float:none !important; display:inline; padding-left:4px; } .aligned .vCheckboxLabel { float:none !important; display:inline; padding-left:4px; }
.colM .aligned .vLargeTextField, colM .aligned .vXMLLargeTextField { width:610px; } .colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { width:610px; }
.checkbox-row p.help { margin-left:0; padding-left:0 !important; } .checkbox-row p.help { margin-left:0; padding-left:0 !important; }
/* WIDE FIELDSETS */ /* WIDE FIELDSETS */

View File

@ -98,8 +98,8 @@ class User(models.Model):
is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site.")) is_staff = models.BooleanField(_('staff status'), default=False, help_text=_("Designates whether the user can log into this admin site."))
is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts.")) is_active = models.BooleanField(_('active'), default=True, help_text=_("Designates whether this user can log into the Django admin. Unselect this instead of deleting accounts."))
is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them.")) is_superuser = models.BooleanField(_('superuser status'), default=False, help_text=_("Designates that this user has all permissions without explicitly assigning them."))
last_login = models.DateTimeField(_('last login'), default=models.LazyDate()) last_login = models.DateTimeField(_('last login'), default=datetime.datetime.now)
date_joined = models.DateTimeField(_('date joined'), default=models.LazyDate()) date_joined = models.DateTimeField(_('date joined'), default=datetime.datetime.now)
groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True, groups = models.ManyToManyField(Group, verbose_name=_('groups'), blank=True,
help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in.")) help_text=_("In addition to the permissions manually assigned, this user will also get all permissions granted to each group he/she is in."))
user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True, filter_interface=models.HORIZONTAL) user_permissions = models.ManyToManyField(Permission, verbose_name=_('user permissions'), blank=True, filter_interface=models.HORIZONTAL)

View File

@ -0,0 +1 @@
from django.contrib.databrowse.sites import DatabrowsePlugin, ModelDatabrowse, DatabrowseSite, site

View File

@ -0,0 +1,192 @@
"""
These classes are light wrappers around Django's database API that provide
convenience functionality and permalink functions for the databrowse app.
"""
from django.db import models
from django.utils import dateformat
from django.utils.text import capfirst
from django.utils.translation import get_date_formats
EMPTY_VALUE = '(None)'
class EasyModel(object):
def __init__(self, site, model):
self.site = site
self.model = model
self.model_list = site.registry.keys()
self.verbose_name = model._meta.verbose_name
self.verbose_name_plural = model._meta.verbose_name_plural
def __repr__(self):
return '<EasyModel for %s>' % self.model._meta.object_name
def model_databrowse(self):
"Returns the ModelDatabrowse class for this model."
return self.site.registry[self.model]
def url(self):
return '%s%s/%s/' % (self.site.root_url, self.model._meta.app_label, self.model._meta.module_name)
def objects(self, **kwargs):
for obj in self.model._default_manager.filter(**kwargs):
yield EasyInstance(self, obj)
def object_by_pk(self, pk):
return EasyInstance(self, self.model._default_manager.get(pk=pk))
def sample_objects(self):
for obj in self.model._default_manager.all()[:3]:
yield EasyInstance(self, obj)
def field(self, name):
try:
f = self.model._meta.get_field(name)
except models.FieldDoesNotExist:
return None
return EasyField(self, f)
def fields(self):
return [EasyField(self, f) for f in (self.model._meta.fields + self.model._meta.many_to_many)]
class EasyField(object):
def __init__(self, easy_model, field):
self.model, self.field = easy_model, field
def __repr__(self):
return '<EasyField for %s.%s>' % (self.model.model._meta.object_name, self.field.name)
def choices(self):
for value, label in self.field.choices:
yield EasyChoice(self.model, self, value, label)
def url(self):
if self.field.choices:
return '%s%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name)
elif self.field.rel:
return '%s%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name)
class EasyChoice(object):
def __init__(self, easy_model, field, value, label):
self.model, self.field = easy_model, field
self.value, self.label = value, label
def __repr__(self):
return '<EasyChoice for %s.%s>' % (self.model.model._meta.object_name, self.field.name)
def url(self):
return '%s%s/%s/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.field.name, self.value)
class EasyInstance(object):
def __init__(self, easy_model, instance):
self.model, self.instance = easy_model, instance
def __repr__(self):
return '<EasyInstance for %s (%s)>' % (self.model.model._meta.object_name, self.instance._get_pk_val())
def __str__(self):
val = str(self.instance)
if len(val) > 30:
return val[:30] + '...'
return val
def pk(self):
return self.instance._get_pk_val()
def url(self):
return '%s%s/%s/objects/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.pk())
def fields(self):
"""
Generator that yields EasyInstanceFields for each field in this
EasyInstance's model.
"""
for f in self.model.model._meta.fields + self.model.model._meta.many_to_many:
yield EasyInstanceField(self.model, self, f)
def related_objects(self):
"""
Generator that yields dictionaries of all models that have this
EasyInstance's model as a ForeignKey or ManyToManyField, along with
lists of related objects.
"""
for rel_object in self.model.model._meta.get_all_related_objects() + self.model.model._meta.get_all_related_many_to_many_objects():
if rel_object.model not in self.model.model_list:
continue # Skip models that aren't in the model_list
em = EasyModel(self.model.site, rel_object.model)
yield {
'model': em,
'related_field': rel_object.field.verbose_name,
'object_list': [EasyInstance(em, i) for i in getattr(self.instance, rel_object.get_accessor_name()).all()],
}
class EasyInstanceField(object):
def __init__(self, easy_model, instance, field):
self.model, self.field, self.instance = easy_model, field, instance
self.raw_value = getattr(instance.instance, field.name)
def __repr__(self):
return '<EasyInstanceField for %s.%s>' % (self.model.model._meta.object_name, self.field.name)
def values(self):
"""
Returns a list of values for this field for this instance. It's a list
so we can accomodate many-to-many fields.
"""
# This import is deliberately inside the function because it causes
# some settings to be imported, and we don't want to do that at the
# module level.
if self.field.rel:
if isinstance(self.field.rel, models.ManyToOneRel):
objs = getattr(self.instance.instance, self.field.name)
elif isinstance(self.field.rel, models.ManyToManyRel): # ManyToManyRel
return list(getattr(self.instance.instance, self.field.name).all())
elif self.field.choices:
objs = dict(self.field.choices).get(self.raw_value, EMPTY_VALUE)
elif isinstance(self.field, models.DateField) or isinstance(self.field, models.TimeField):
if self.raw_value:
date_format, datetime_format, time_format = get_date_formats()
if isinstance(self.field, models.DateTimeField):
objs = capfirst(dateformat.format(self.raw_value, datetime_format))
elif isinstance(self.field, models.TimeField):
objs = capfirst(dateformat.time_format(self.raw_value, time_format))
else:
objs = capfirst(dateformat.format(self.raw_value, date_format))
else:
objs = EMPTY_VALUE
elif isinstance(self.field, models.BooleanField) or isinstance(self.field, models.NullBooleanField):
objs = {True: 'Yes', False: 'No', None: 'Unknown'}[self.raw_value]
else:
objs = self.raw_value
return [objs]
def urls(self):
"Returns a list of (value, URL) tuples."
# First, check the urls() method for each plugin.
plugin_urls = []
for plugin_name, plugin in self.model.model_databrowse().plugins.items():
urls = plugin.urls(plugin_name, self)
if urls is not None:
#plugin_urls.append(urls)
values = self.values()
return zip(self.values(), urls)
if self.field.rel:
m = EasyModel(self.model.site, self.field.rel.to)
if self.field.rel.to in self.model.model_list:
lst = []
for value in self.values():
url = '%s%s/%s/objects/%s/' % (self.model.site.root_url, m.model._meta.app_label, m.model._meta.module_name, value._get_pk_val())
lst.append((str(value), url))
else:
lst = [(value, None) for value in self.values()]
elif self.field.choices:
lst = []
for value in self.values():
url = '%s%s/%s/fields/%s/%s/' % (self.model.site.root_url, self.model.model._meta.app_label, self.model.model._meta.module_name, self.field.name, self.raw_value)
lst.append((value, url))
elif isinstance(self.field, models.URLField):
val = self.values()[0]
lst = [(val, val)]
else:
lst = [(self.values()[0], None)]
return lst

View File

@ -0,0 +1,84 @@
from django import http
from django.db import models
from django.contrib.databrowse.datastructures import EasyModel
from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response
from django.utils.text import capfirst
from django.utils.translation import get_date_formats
from django.views.generic import date_based
import datetime
import time
class CalendarPlugin(DatabrowsePlugin):
def __init__(self, field_names=None):
self.field_names = field_names
def field_dict(self, model):
"""
Helper function that returns a dictionary of all DateFields or
DateTimeFields in the given model. If self.field_names is set, it takes
take that into account when building the dictionary.
"""
if self.field_names is None:
return dict([(f.name, f) for f in model._meta.fields if isinstance(f, models.DateField)])
else:
return dict([(f.name, f) for f in model._meta.fields if isinstance(f, models.DateField) and f.name in self.field_names])
def model_index_html(self, request, model, site):
fields = self.field_dict(model)
if not fields:
return ''
return '<p class="filter"><strong>View calendar by:</strong> %s</p>' % \
', '.join(['<a href="calendars/%s/">%s</a>' % (f.name, capfirst(f.verbose_name)) for f in fields.values()])
def urls(self, plugin_name, easy_instance_field):
if isinstance(easy_instance_field.field, models.DateField):
return ['%s%s/%s/%s/%s/%s/' % (easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name,
easy_instance_field.raw_value.year,
easy_instance_field.raw_value.strftime('%b').lower(),
easy_instance_field.raw_value.day)]
def model_view(self, request, model_databrowse, url):
self.model, self.site = model_databrowse.model, model_databrowse.site
self.fields = self.field_dict(self.model)
# If the model has no DateFields, there's no point in going further.
if not self.fields:
raise http.Http404('The requested model has no calendars.')
if url is None:
return self.homepage_view(request)
url_bits = url.split('/')
if self.fields.has_key(url_bits[0]):
return self.calendar_view(request, self.fields[url_bits[0]], *url_bits[1:])
raise http.Http404('The requested page does not exist.')
def homepage_view(self, request):
easy_model = EasyModel(self.site, self.model)
field_list = self.fields.values()
field_list.sort(lambda x, y: cmp(x.verbose_name, y.verbose_name))
return render_to_response('databrowse/calendar_homepage.html', {'root_url': self.site.root_url, 'model': easy_model, 'field_list': field_list})
def calendar_view(self, request, field, year=None, month=None, day=None):
easy_model = EasyModel(self.site, self.model)
extra_context = {'root_url': self.site.root_url, 'model': easy_model, 'field': field}
if day is not None:
# TODO: The objects in this template should be EasyInstances
return date_based.archive_day(request, year, month, day, self.model.objects.all(), field.name,
template_name='databrowse/calendar_day.html', allow_empty=False, allow_future=True,
extra_context=extra_context)
elif month is not None:
return date_based.archive_month(request, year, month, self.model.objects.all(), field.name,
template_name='databrowse/calendar_month.html', allow_empty=False, allow_future=True,
extra_context=extra_context)
elif year is not None:
return date_based.archive_year(request, year, self.model.objects.all(), field.name,
template_name='databrowse/calendar_year.html', allow_empty=False, allow_future=True,
extra_context=extra_context)
else:
return date_based.archive_index(request, self.model.objects.all(), field.name,
template_name='databrowse/calendar_main.html', allow_empty=True, allow_future=True,
extra_context=extra_context)
assert False, ('%s, %s, %s, %s' % (field, year, month, day))

View File

@ -0,0 +1,72 @@
from django import http
from django.db import models
from django.contrib.databrowse.datastructures import EasyModel
from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response
from django.utils.text import capfirst
from django.views.generic import date_based
import datetime
import time
class FieldChoicePlugin(DatabrowsePlugin):
def __init__(self, field_filter=None):
# If field_filter is given, it should be a callable that takes a
# Django database Field instance and returns True if that field should
# be included. If field_filter is None, that all fields will be used.
self.field_filter = field_filter
def field_dict(self, model):
"""
Helper function that returns a dictionary of all fields in the given
model. If self.field_filter is set, it only includes the fields that
match the filter.
"""
if self.field_filter:
return dict([(f.name, f) for f in model._meta.fields if self.field_filter(f)])
else:
return dict([(f.name, f) for f in model._meta.fields if not f.rel and not f.primary_key and not f.unique and not isinstance(f, (models.AutoField, models.TextField))])
def model_index_html(self, request, model, site):
fields = self.field_dict(model)
if not fields:
return ''
return '<p class="filter"><strong>View by:</strong> %s</p>' % \
', '.join(['<a href="fields/%s/">%s</a>' % (f.name, capfirst(f.verbose_name)) for f in fields.values()])
def urls(self, plugin_name, easy_instance_field):
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
return ['%s%s/%s/%s/' % (easy_instance_field.model.url(),
plugin_name, easy_instance_field.field.name,
easy_instance_field.raw_value)]
def model_view(self, request, model_databrowse, url):
self.model, self.site = model_databrowse.model, model_databrowse.site
self.fields = self.field_dict(self.model)
# If the model has no fields with choices, there's no point in going
# further.
if not self.fields:
raise http.Http404('The requested model has no fields.')
if url is None:
return self.homepage_view(request)
url_bits = url.split('/', 1)
if self.fields.has_key(url_bits[0]):
return self.field_view(request, self.fields[url_bits[0]], *url_bits[1:])
raise http.Http404('The requested page does not exist.')
def homepage_view(self, request):
easy_model = EasyModel(self.site, self.model)
field_list = self.fields.values()
field_list.sort(lambda x, y: cmp(x.verbose_name, y.verbose_name))
return render_to_response('databrowse/fieldchoice_homepage.html', {'root_url': self.site.root_url, 'model': easy_model, 'field_list': field_list})
def field_view(self, request, field, value=None):
easy_model = EasyModel(self.site, self.model)
easy_field = easy_model.field(field.name)
if value is not None:
obj_list = easy_model.objects(**{field.name: value})
return render_to_response('databrowse/fieldchoice_detail.html', {'root_url': self.site.root_url, 'model': easy_model, 'field': easy_field, 'value': value, 'object_list': obj_list})
obj_list = [v[field.name] for v in self.model._default_manager.distinct().order_by(field.name).values(field.name)]
return render_to_response('databrowse/fieldchoice_list.html', {'root_url': self.site.root_url, 'model': easy_model, 'field': easy_field, 'object_list': obj_list})

View File

@ -0,0 +1,14 @@
from django import http
from django.contrib.databrowse.datastructures import EasyModel
from django.contrib.databrowse.sites import DatabrowsePlugin
from django.shortcuts import render_to_response
import urlparse
class ObjectDetailPlugin(DatabrowsePlugin):
def model_view(self, request, model_databrowse, url):
# If the object ID wasn't provided, redirect to the model page, which is one level up.
if url is None:
return http.HttpResponseRedirect(urlparse.urljoin(request.path, '../'))
easy_model = EasyModel(model_databrowse.site, model_databrowse.model)
obj = easy_model.object_by_pk(url)
return render_to_response('databrowse/object_detail.html', {'object': obj, 'root_url': model_databrowse.site.root_url})

View File

@ -0,0 +1,148 @@
from django import http
from django.db import models
from django.contrib.databrowse.datastructures import EasyModel, EasyChoice
from django.shortcuts import render_to_response
class AlreadyRegistered(Exception):
pass
class NotRegistered(Exception):
pass
class DatabrowsePlugin(object):
def urls(self, plugin_name, easy_instance_field):
"""
Given an EasyInstanceField object, returns a list of URLs for this
plugin's views of this object. These URLs should be absolute.
Returns None if the EasyInstanceField object doesn't get a
list of plugin-specific URLs.
"""
return None
def model_index_html(self, request, model, site):
"""
Returns a snippet of HTML to include on the model index page.
"""
return ''
def model_view(self, request, model_databrowse, url):
"""
Handles main URL routing for a plugin's model-specific pages.
"""
raise NotImplementedError
class ModelDatabrowse(object):
plugins = {}
def __init__(self, model, site):
self.model = model
self.site = site
def root(self, request, url):
"""
Handles main URL routing for the databrowse app.
`url` is the remainder of the URL -- e.g. 'objects/3'.
"""
# Delegate to the appropriate method, based on the URL.
if url is None:
return self.main_view(request)
try:
plugin_name, rest_of_url = url.split('/', 1)
except ValueError: # need more than 1 value to unpack
plugin_name, rest_of_url = url, None
try:
plugin = self.plugins[plugin_name]
except KeyError:
raise http.Http404('A plugin with the requested name does not exist.')
return plugin.model_view(request, self, rest_of_url)
def main_view(self, request):
easy_model = EasyModel(self.site, self.model)
html_snippets = '\n'.join([p.model_index_html(request, self.model, self.site) for p in self.plugins.values()])
return render_to_response('databrowse/model_detail.html', {
'model': easy_model,
'root_url': self.site.root_url,
'plugin_html': html_snippets,
})
class DatabrowseSite(object):
def __init__(self):
self.registry = {} # model_class -> databrowse_class
self.root_url = None
def register(self, model_or_iterable, databrowse_class=None, **options):
"""
Registers the given model(s) with the given databrowse site.
The model(s) should be Model classes, not instances.
If a databrowse class isn't given, it will use DefaultModelDatabrowse
(the default databrowse options).
If a model is already registered, this will raise AlreadyRegistered.
"""
databrowse_class = databrowse_class or DefaultModelDatabrowse
if issubclass(model_or_iterable, models.Model):
model_or_iterable = [model_or_iterable]
for model in model_or_iterable:
if model in self.registry:
raise AlreadyRegistered('The model %s is already registered' % model.__class__.__name__)
self.registry[model] = databrowse_class
def unregister(self, model_or_iterable):
"""
Unregisters the given model(s).
If a model isn't already registered, this will raise NotRegistered.
"""
if issubclass(model_or_iterable, models.Model):
model_or_iterable = [model_or_iterable]
for model in model_or_iterable:
if model not in self.registry:
raise NotRegistered('The model %s is not registered' % model.__class__.__name__)
del self.registry[model]
def root(self, request, url):
"""
Handles main URL routing for the databrowse app.
`url` is the remainder of the URL -- e.g. 'comments/comment/'.
"""
self.root_url = request.path[:len(request.path) - len(url)]
url = url.rstrip('/') # Trim trailing slash, if it exists.
if url == '':
return self.index(request)
elif '/' in url:
return self.model_page(request, *url.split('/', 2))
raise http.Http404('The requested databrowse page does not exist.')
def index(self, request):
m_list = [EasyModel(self, m) for m in self.registry.keys()]
return render_to_response('databrowse/homepage.html', {'model_list': m_list, 'root_url': self.root_url})
def model_page(self, request, app_label, model_name, rest_of_url=None):
"""
Handles the model-specific functionality of the databrowse site, delegating
to the appropriate ModelDatabrowse class.
"""
model = models.get_model(app_label, model_name)
if model is None:
raise http.Http404("App %r, model %r, not found." % (app_label, model_name))
try:
databrowse_class = self.registry[model]
except KeyError:
raise http.Http404("This model exists but has not been registered with databrowse.")
return databrowse_class(model, self).root(request, rest_of_url)
site = DatabrowseSite()
from django.contrib.databrowse.plugins.calendars import CalendarPlugin
from django.contrib.databrowse.plugins.objects import ObjectDetailPlugin
from django.contrib.databrowse.plugins.fieldchoices import FieldChoicePlugin
class DefaultModelDatabrowse(ModelDatabrowse):
plugins = {'objects': ObjectDetailPlugin(), 'calendars': CalendarPlugin(), 'fields': FieldChoicePlugin()}

View File

@ -0,0 +1,58 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE }}" xml:lang="{{ LANGUAGE_CODE }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}>
<head>
<title>{% block title %}{% endblock %}</title>
<style type="text/css">
* { margin:0; padding:0; }
body { background:#eee; color:#333; font:76%/1.6 "Lucida Grande","Bitstream Vera Sans",Verdana,sans-serif; }
a { color: #5b80b2; text-decoration:none; }
a:hover { text-decoration:underline; }
a img { border:none; }
h1 { font-size:1.8em; color:#666; margin:0.4em 0 0.2em 0; }
h2 { font-size:1.5em; color:#666; margin:1em 0 0.2em 0; }
p { margin:0.5em 0 1em 0; }
.odd { background-color:#EDF3FE; }
.quiet { color:#666; }
/* FILTERS */
.filter { color:#999; font-size:0.9em; float:left; margin-bottom:10px; margin-right:20px; }
.filter strong { color:#666; }
/* OBJECT LISTS */
.objectlist { clear:both; margin:0 -20px; color:#666; }
.objectlist li a { display:block; padding:1em 20px; }
.objectlist li a:hover { background:#5b80b2; color:#3B5572; color:#fff; text-decoration:none; }
.related h2 { font-size: 1em; margin-bottom: 0.6em; }
.related .objectlist li a { padding: 0.6em 20px; }
.related .objectlist li.odd { background:#eee; }
/* OBJECT DETAIL */
.objectinfo { border-collapse:collapse; color:#666; margin:0 -20px; }
.objectinfo td, .objectinfo th { padding:1em 20px; vertical-align:top; }
.objectinfo td { width:100%; }
.objectinfo th { text-align:left; white-space:nowrap; }
/* MODEL GROUPS */
.modelgroup { color:#999; font-size:0.9em; margin:0 -20px; }
.modelgroup h2 { font-size:1.2em; margin:0; }
.modelgroup h2 a { display: block; padding: 0.83em 20px; }
.modelgroup h2 a:hover { text-decoration: none; color: #fff; }
.modelgroup p { float:left; margin:-2.65em 0 0 14em; position:relative; }
.modelgroup p a { white-space:nowrap; }
.modelgroup a.more { color:#999; }
.modelgroup:hover { background:#5b80b2; color:#becfe5; }
.modelgroup:hover p a { color:#becfe5; }
.modelgroup:hover a { color:#fff; }
.modelgroup:hover a.more { color:#fff; }
/* BREADCRUMBS */
#breadcrumbs { padding:10px 0; color:#999; font-size:0.9em; }
/* HEADER */
#header a { display:block; background:#eee; color:#676868; padding:10px 20px; font-weight:bold; font-size:1em; text-decoration:none; border-bottom:1px solid #ddd; }
#header a:hover { text-decoration:underline; }
/* CONTENT */
#content { background:#fff; border-bottom:1px solid #ddd; padding:0 20px; }
</style>
</head>
<body id="{% block bodyid %}page{% endblock %}">
<div id="header"><a href="{{ root_url }}">Databrowse</a></div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} {{ day|date:"F j, Y" }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../../../">Calendars</a> / <a href="../../../">By {{ field.verbose_name }}</a> / <a href="../../">{{ day.year }}</a> / <a href="../">{{ day|date:"F" }}</a> / {{ day.day }}</div>
<h1>{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} on {{ day|date:"F j, Y" }}</h1>
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}Calendars{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / Calendars</div>
<h1>Calendars</h1>
<ul class="objectlist">
{% for field in field_list %}
<li class="{% cycle odd,even %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ field.verbose_name|capfirst }} calendar{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../">Calendars</a> / By {{ field.verbose_name }}</div>
<h1>{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</h1>
<ul class="objectlist">
{% for year in date_list %}
<li class="{% cycle odd,even %}"><a href="{{ year.year }}/">{{ year.year }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ month|date:"F Y" }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../../">Calendars</a> / <a href="../../">By {{ field.verbose_name }}</a> / <a href="../">{{ month.year }}</a> / {{ month|date:"F" }}</div>
<h1>{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ month|date:"F Y" }}</h1>
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ year }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../">Calendars</a> / <a href="../">By {{ field.verbose_name }}</a> / {{ year }}</div>
<h1>{{ model.verbose_name_plural|capfirst }} with {{ field.verbose_name }} in {{ year }}</h1>
<ul class="objectlist">
{% for month in date_list %}
<li class="{% cycle odd,even %}"><a href="{{ month|date:"M"|lower }}/">{{ month|date:"F" }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}: {{ value|escape }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="{{ field.url }}">By {{ field.field.verbose_name }}</a> / {{ value|escape }}</div>
<h1>{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}: {{ value|escape }}</h1>
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / By {{ field.field.verbose_name }}</div>
<h1>{{ model.verbose_name_plural|capfirst }} by {{ field.field.verbose_name }}</h1>
<ul class="objectlist">
{% for choice in field.choices %}
<li class="{% cycle odd,even %}"><a href="{{ choice.url }}">{{ choice.label }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst|escape }} with {{ field.field.verbose_name|escape }} {{ value|escape }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../../">Fields</a> / <a href="../">By {{ field.field.verbose_name|escape }}</a> / {{ value|escape }}</div>
<h1>{{ model.verbose_name_plural|capfirst|escape }} with {{ field.field.verbose_name|escape }} {{ value|escape }}</h1>
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object|escape }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}Browsable fields in {{ model.verbose_name_plural|escape }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / Fields</div>
<h1>Browsable fields in {{ model.verbose_name_plural }}</h1>
<ul class="objectlist">
{% for field in field_list %}
<li class="{% cycle odd,even %}"><a href="{{ field.name }}/">{{ model.verbose_name_plural|capfirst }} by {{ field.verbose_name }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,17 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst|escape }} by {{ field.field.verbose_name|escape }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a> / <a href="../">Fields</a> / By {{ field.field.verbose_name|escape }}</div>
<h1>{{ model.verbose_name_plural|capfirst|escape }} by {{ field.field.verbose_name|escape }}</h1>
<ul class="objectlist">
{% for object in object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object }}/">{{ object|escape }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,21 @@
{% extends "databrowse/base.html" %}
{% block title %}Databrowse{% endblock %}
{% block bodyid %}homepage{% endblock %}
{% block content %}
{% for model in model_list %}
<div class="modelgroup {% cycle even,odd %}">
<h2><a href="{{ model.url }}">{{ model.verbose_name_plural|capfirst }}</a></h2>
<p>
{% for object in model.sample_objects %}
<a href="{{ object.url }}">{{ object }}</a>,
{% endfor %}
<a class="more" href="{{ model.url }}">More &rarr;</a>
</p>
</div>
{% endfor %}
{% endblock %}

View File

@ -0,0 +1,19 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ model.verbose_name_plural|capfirst }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / {{ model.verbose_name_plural|capfirst }}</div>
<h1>{{ model.verbose_name_plural|capfirst }}</h1>
{{ plugin_html }}
<ul class="objectlist">
{% for object in model.objects %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
{% endfor %}
</ul>
{% endblock %}

View File

@ -0,0 +1,41 @@
{% extends "databrowse/base.html" %}
{% block title %}{{ object.model.verbose_name|capfirst }}: {{ object }}{% endblock %}
{% block content %}
<div id="breadcrumbs"><a href="{{ root_url }}">Home</a> / <a href="{{ object.model.url }}">{{ object.model.verbose_name_plural|capfirst }}</a> / {{ object }}</div>
<h1>{{ object.model.verbose_name|capfirst }}: {{ object }}</h1>
<table class="objectinfo">
{% for field in object.fields %}
<tr class="{% cycle odd,even %}">
<th>{{ field.field.verbose_name|capfirst }}</th>
<td>
{% if field.urls %}
{% for urlvalue in field.urls %}
{% if urlvalue.1 %}<a href="{{ urlvalue.1 }}">{% endif %}{{ urlvalue.0 }}{% if urlvalue.1 %}</a>{% endif %}{% if not forloop.last %}, {% endif %}
{% endfor %}
{% else %}None{% endif %}
</td>
</tr>
{% endfor %}
</table>
{% for related_object in object.related_objects %}
<div class="related">
<h2>Appears in "{{ related_object.related_field }}" in the following {{ related_object.model.verbose_name_plural }}:</h2>
{% if related_object.object_list %}
<ul class="objectlist">
{% for object in related_object.object_list %}
<li class="{% cycle odd,even %}"><a href="{{ object.url }}">{{ object }}</a></li>
{% endfor %}
</ul>
</div>
{% else %}
<p class="quiet">(None)</p>
{% endif %}
{% endfor %}
{% endblock %}

View File

@ -0,0 +1,20 @@
from django.conf.urls.defaults import *
from django.contrib.databrowse import views
# Note: The views in this URLconf all require a 'models' argument,
# which is a list of model classes (*not* instances).
urlpatterns = patterns('',
#(r'^$', views.homepage),
#(r'^([^/]+)/([^/]+)/$', views.model_detail),
(r'^([^/]+)/([^/]+)/fields/(\w+)/$', views.choice_list),
(r'^([^/]+)/([^/]+)/fields/(\w+)/(.*)/$', views.choice_detail),
#(r'^([^/]+)/([^/]+)/calendars/(\w+)/$', views.calendar_main),
#(r'^([^/]+)/([^/]+)/calendars/(\w+)/(\d{4})/$', views.calendar_year),
#(r'^([^/]+)/([^/]+)/calendars/(\w+)/(\d{4})/(\w{3})/$', views.calendar_month),
#(r'^([^/]+)/([^/]+)/calendars/(\w+)/(\d{4})/(\w{3})/(\d{1,2})/$', views.calendar_day),
#(r'^([^/]+)/([^/]+)/objects/(.*)/$', views.object_detail),
)

View File

@ -0,0 +1,23 @@
from django.db.models import FieldDoesNotExist, DateTimeField
from django.http import Http404
from django.shortcuts import render_to_response
from django.contrib.databrowse.datastructures import EasyModel, EasyChoice
import datetime
import time
###########
# CHOICES #
###########
def choice_list(request, app_label, module_name, field_name, models):
m, f = lookup_field(app_label, module_name, field_name, models)
return render_to_response('databrowse/choice_list.html', {'model': m, 'field': f})
def choice_detail(request, app_label, module_name, field_name, field_val, models):
m, f = lookup_field(app_label, module_name, field_name, models)
try:
label = dict(f.field.choices)[field_val]
except KeyError:
raise Http404('Invalid choice value given')
obj_list = m.objects(**{f.field.name: field_val})
return render_to_response('databrowse/choice_detail.html', {'model': m, 'field': f, 'value': label, 'object_list': obj_list})

View File

@ -5,13 +5,15 @@ IT-specific Form helpers
from django.newforms import ValidationError from django.newforms import ValidationError
from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
from django.utils.translation import gettext from django.utils.translation import gettext
from django.utils.encoding import smart_unicode
from django.contrib.localflavor.it.util import ssn_check_digit, vat_number_check_digit
import re import re
class ITZipCodeField(RegexField): class ITZipCodeField(RegexField):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ITZipCodeField, self).__init__(r'^\d{5}$', super(ITZipCodeField, self).__init__(r'^\d{5}$',
max_length=None, min_length=None, max_length=None, min_length=None,
error_message=gettext(u'Enter a zip code in the format XXXXX.'), error_message=gettext(u'Enter a valid zip code.'),
*args, **kwargs) *args, **kwargs)
class ITRegionSelect(Select): class ITRegionSelect(Select):
@ -29,3 +31,47 @@ class ITProvinceSelect(Select):
def __init__(self, attrs=None): def __init__(self, attrs=None):
from it_province import PROVINCE_CHOICES # relative import from it_province import PROVINCE_CHOICES # relative import
super(ITProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES) super(ITProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
class ITSocialSecurityNumberField(RegexField):
"""
A form field that validates Italian Social Security numbers (codice fiscale).
For reference see http://www.agenziaentrate.it/ and search for
'Informazioni sulla codificazione delle persone fisiche'.
"""
err_msg = gettext(u'Enter a valid Social Security number.')
def __init__(self, *args, **kwargs):
super(ITSocialSecurityNumberField, self).__init__(r'^\w{3}\s*\w{3}\s*\w{5}\s*\w{5}$',
max_length=None, min_length=None, error_message=self.err_msg,
*args, **kwargs)
def clean(self, value):
value = super(ITSocialSecurityNumberField, self).clean(value)
if value == u'':
return value
value = re.sub('\s', u'', value).upper()
try:
check_digit = ssn_check_digit(value)
except ValueError:
raise ValidationError(self.err_msg)
if not value[15] == check_digit:
raise ValidationError(self.err_msg)
return value
class ITVatNumberField(Field):
"""
A form field that validates Italian VAT numbers (partita IVA).
"""
def clean(self, value):
value = super(ITVatNumberField, self).clean(value)
if value == u'':
return value
err_msg = gettext(u'Enter a valid VAT number.')
try:
vat_number = int(value)
except ValueError:
raise ValidationError(err_msg)
vat_number = str(vat_number).zfill(11)
check_digit = vat_number_check_digit(vat_number[0:10])
if not vat_number[10] == check_digit:
raise ValidationError(err_msg)
return smart_unicode(vat_number)

View File

@ -0,0 +1,40 @@
def ssn_check_digit(value):
"Calculate Italian social security number check digit."
ssn_even_chars = {
'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9,
'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9,
'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18,
'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25
}
ssn_odd_chars = {
'0': 1, '1': 0, '2': 5, '3': 7, '4': 9, '5': 13, '6': 15, '7': 17, '8': 19, '9': 21,
'A': 1, 'B': 0, 'C': 5, 'D': 7, 'E': 9, 'F': 13, 'G': 15, 'H': 17, 'I': 19, 'J': 21,
'K': 2, 'L': 4, 'M': 18, 'N': 20, 'O': 11, 'P': 3, 'Q': 6, 'R': 8, 'S': 12,
'T': 14, 'U': 16, 'V': 10, 'W': 22, 'X': 25, 'Y': 24, 'Z': 23
}
# Chars from 'A' to 'Z'
ssn_check_digits = [chr(x) for x in range(65, 91)]
ssn = value.upper()
total = 0
for i in range(0,15):
try:
if i % 2 == 0:
total += ssn_odd_chars[ssn[i]]
else:
total += ssn_even_chars[ssn[i]]
except KeyError:
msg = "Character '%(char)s' is not allowed." % {'char': ssn[i]}
raise ValueError(msg)
return ssn_check_digits[total % 26]
def vat_number_check_digit(vat_number):
"Calculate Italian VAT number check digit."
normalized_vat_number = str(vat_number).zfill(10)
total = 0
for i in range(0, 10, 2):
total += int(normalized_vat_number[i])
for i in range(1, 11, 2):
quotient , remainder = divmod(int(normalized_vat_number[i]) * 2, 10)
total += quotient + remainder
return str((10 - total % 10) % 10)

View File

@ -15,7 +15,7 @@ STATE_CHOICES = (
('CA', 'California'), ('CA', 'California'),
('CO', 'Colorado'), ('CO', 'Colorado'),
('CT', 'Connecticut'), ('CT', 'Connecticut'),
('DE', 'Deleware'), ('DE', 'Delaware'),
('DC', 'District of Columbia'), ('DC', 'District of Columbia'),
('FM', 'Federated States of Micronesia'), ('FM', 'Federated States of Micronesia'),
('FL', 'Florida'), ('FL', 'Florida'),
@ -97,6 +97,7 @@ STATES_NORMALIZED = {
'de': 'DE', 'de': 'DE',
'del': 'DE', 'del': 'DE',
'delaware': 'DE', 'delaware': 'DE',
'deleware': 'DE',
'district of columbia': 'DC', 'district of columbia': 'DC',
'federated states of micronesia': 'FM', 'federated states of micronesia': 'FM',
'fl': 'FL', 'fl': 'FL',

View File

@ -70,6 +70,7 @@ class Feed(object):
feed = self.feed_type( feed = self.feed_type(
title = self.__get_dynamic_attr('title', obj), title = self.__get_dynamic_attr('title', obj),
subtitle = self.__get_dynamic_attr('subtitle', obj),
link = link, link = link,
description = self.__get_dynamic_attr('description', obj), description = self.__get_dynamic_attr('description', obj),
language = settings.LANGUAGE_CODE.decode(), language = settings.LANGUAGE_CODE.decode(),

View File

@ -42,10 +42,6 @@ def send_mail(subject, message, from_email, recipient_list, fail_silently=False,
If auth_user is None, the EMAIL_HOST_USER setting is used. If auth_user is None, the EMAIL_HOST_USER setting is used.
If auth_password is None, the EMAIL_HOST_PASSWORD setting is used. If auth_password is None, the EMAIL_HOST_PASSWORD setting is used.
""" """
if auth_user is None:
auth_user = settings.EMAIL_HOST_USER
if auth_password is None:
auth_password = settings.EMAIL_HOST_PASSWORD
return send_mass_mail([[subject, message, from_email, recipient_list]], fail_silently, auth_user, auth_password) return send_mass_mail([[subject, message, from_email, recipient_list]], fail_silently, auth_user, auth_password)
def send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None): def send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None):

View File

@ -789,11 +789,12 @@ def startapp(app_name, directory):
# Determine the project_name a bit naively -- by looking at the name of # Determine the project_name a bit naively -- by looking at the name of
# the parent directory. # the parent directory.
project_dir = os.path.normpath(os.path.join(directory, '..')) project_dir = os.path.normpath(os.path.join(directory, '..'))
project_name = os.path.basename(project_dir) parent_dir = os.path.basename(project_dir)
if app_name == os.path.basename(directory): project_name = os.path.basename(directory)
if app_name == project_name:
sys.stderr.write(style.ERROR("Error: You cannot create an app with the same name (%r) as your project.\n" % app_name)) sys.stderr.write(style.ERROR("Error: You cannot create an app with the same name (%r) as your project.\n" % app_name))
sys.exit(1) sys.exit(1)
_start_helper('app', app_name, directory, project_name) _start_helper('app', app_name, directory, parent_dir)
startapp.help_doc = "Creates a Django app directory structure for the given app name in the current directory." startapp.help_doc = "Creates a Django app directory structure for the given app name in the current directory."
startapp.args = "[appname]" startapp.args = "[appname]"

View File

@ -85,7 +85,7 @@ DATA_TYPES_REVERSE = {
FIELD_TYPE.LONG: 'IntegerField', FIELD_TYPE.LONG: 'IntegerField',
FIELD_TYPE.LONGLONG: 'IntegerField', FIELD_TYPE.LONGLONG: 'IntegerField',
FIELD_TYPE.SHORT: 'IntegerField', FIELD_TYPE.SHORT: 'IntegerField',
FIELD_TYPE.STRING: 'TextField', FIELD_TYPE.STRING: 'CharField',
FIELD_TYPE.TIMESTAMP: 'DateTimeField', FIELD_TYPE.TIMESTAMP: 'DateTimeField',
FIELD_TYPE.TINY: 'IntegerField', FIELD_TYPE.TINY: 'IntegerField',
FIELD_TYPE.TINY_BLOB: 'TextField', FIELD_TYPE.TINY_BLOB: 'TextField',

View File

@ -202,7 +202,7 @@ def get_sql_flush(style, tables, sequences):
sql.append("%s %s %s %s %s %s;" % \ sql.append("%s %s %s %s %s %s;" % \
(style.SQL_KEYWORD('ALTER'), (style.SQL_KEYWORD('ALTER'),
style.SQL_KEYWORD('SEQUENCE'), style.SQL_KEYWORD('SEQUENCE'),
style.SQL_FIELD('%s_%s_seq' % (table_name, column_name)), style.SQL_FIELD(quote_name('%s_%s_seq' % (table_name, column_name))),
style.SQL_KEYWORD('RESTART'), style.SQL_KEYWORD('RESTART'),
style.SQL_KEYWORD('WITH'), style.SQL_KEYWORD('WITH'),
style.SQL_FIELD('1') style.SQL_FIELD('1')
@ -213,7 +213,7 @@ def get_sql_flush(style, tables, sequences):
sql.append("%s %s %s %s %s %s;" % \ sql.append("%s %s %s %s %s %s;" % \
(style.SQL_KEYWORD('ALTER'), (style.SQL_KEYWORD('ALTER'),
style.SQL_KEYWORD('SEQUENCE'), style.SQL_KEYWORD('SEQUENCE'),
style.SQL_FIELD('%s_id_seq' % table_name), style.SQL_FIELD(quote_name('%s_id_seq' % table_name)),
style.SQL_KEYWORD('RESTART'), style.SQL_KEYWORD('RESTART'),
style.SQL_KEYWORD('WITH'), style.SQL_KEYWORD('WITH'),
style.SQL_FIELD('1') style.SQL_FIELD('1')

View File

@ -153,7 +153,7 @@ def get_sql_flush(style, tables, sequences):
sql.append("%s %s %s %s %s %s;" % \ sql.append("%s %s %s %s %s %s;" % \
(style.SQL_KEYWORD('ALTER'), (style.SQL_KEYWORD('ALTER'),
style.SQL_KEYWORD('SEQUENCE'), style.SQL_KEYWORD('SEQUENCE'),
style.SQL_FIELD('%s_%s_seq' % (table_name, column_name)), style.SQL_FIELD(quote_name('%s_%s_seq' % (table_name, column_name))),
style.SQL_KEYWORD('RESTART'), style.SQL_KEYWORD('RESTART'),
style.SQL_KEYWORD('WITH'), style.SQL_KEYWORD('WITH'),
style.SQL_FIELD('1') style.SQL_FIELD('1')
@ -164,7 +164,7 @@ def get_sql_flush(style, tables, sequences):
sql.append("%s %s %s %s %s %s;" % \ sql.append("%s %s %s %s %s %s;" % \
(style.SQL_KEYWORD('ALTER'), (style.SQL_KEYWORD('ALTER'),
style.SQL_KEYWORD('SEQUENCE'), style.SQL_KEYWORD('SEQUENCE'),
style.SQL_FIELD('%s_id_seq' % table_name), style.SQL_FIELD(quote_name('%s_id_seq' % table_name)),
style.SQL_KEYWORD('RESTART'), style.SQL_KEYWORD('RESTART'),
style.SQL_KEYWORD('WITH'), style.SQL_KEYWORD('WITH'),
style.SQL_FIELD('1') style.SQL_FIELD('1')

View File

@ -27,32 +27,3 @@ def permalink(func):
viewname = bits[0] viewname = bits[0]
return reverse(bits[0], None, *bits[1:3]) return reverse(bits[0], None, *bits[1:3])
return inner return inner
class LazyDate(object):
"""
Use in limit_choices_to to compare the field to dates calculated at run time
instead of when the model is loaded. For example::
... limit_choices_to = {'date__gt' : models.LazyDate(days=-3)} ...
which will limit the choices to dates greater than three days ago.
"""
def __init__(self, **kwargs):
self.delta = datetime.timedelta(**kwargs)
def __str__(self):
return str(self.__get_value__())
def __repr__(self):
return "<LazyDate: %s>" % self.delta
def __get_value__(self):
return (datetime.datetime.now() + self.delta).date()
def __getattr__(self, attr):
if attr == 'delta':
# To fix ticket #3377. Note that normal accesses to LazyDate.delta
# (after construction) will still work, because they don't go
# through __getattr__). This is mainly needed for unpickling.
raise AttributeError
return getattr(self.__get_value__(), attr)

View File

@ -189,7 +189,7 @@ class QuerySet(object):
raise StopIteration raise StopIteration
for row in rows: for row in rows:
if fill_cache: if fill_cache:
obj, index_end = get_cached_row(klass=self.model, row=row, obj, index_end = get_cached_row(klass=self.model, row=row,
index_start=0, max_depth=self._max_related_depth) index_start=0, max_depth=self._max_related_depth)
else: else:
obj = self.model(*row[:index_end]) obj = self.model(*row[:index_end])
@ -201,14 +201,14 @@ class QuerySet(object):
""" """
Performs a SELECT COUNT() and returns the number of records as an Performs a SELECT COUNT() and returns the number of records as an
integer. integer.
If the queryset is already cached (i.e. self._result_cache is set) this If the queryset is already cached (i.e. self._result_cache is set) this
simply returns the length of the cached results set to avoid multiple simply returns the length of the cached results set to avoid multiple
SELECT COUNT(*) calls. SELECT COUNT(*) calls.
""" """
if self._result_cache is not None: if self._result_cache is not None:
return len(self._result_cache) return len(self._result_cache)
counter = self._clone() counter = self._clone()
counter._order_by = () counter._order_by = ()
counter._select_related = False counter._select_related = False
@ -488,9 +488,9 @@ class QuerySet(object):
# Add additional tables and WHERE clauses based on select_related. # Add additional tables and WHERE clauses based on select_related.
if self._select_related: if self._select_related:
fill_table_cache(opts, select, tables, where, fill_table_cache(opts, select, tables, where,
old_prefix=opts.db_table, old_prefix=opts.db_table,
cache_tables_seen=[opts.db_table], cache_tables_seen=[opts.db_table],
max_depth=self._max_related_depth) max_depth=self._max_related_depth)
# Add any additional SELECTs. # Add any additional SELECTs.
@ -738,11 +738,11 @@ def get_where_clause(lookup_type, table_prefix, field_name, value):
def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0): def get_cached_row(klass, row, index_start, max_depth=0, cur_depth=0):
"""Helper function that recursively returns an object with cache filled""" """Helper function that recursively returns an object with cache filled"""
# If we've got a max_depth set and we've exceeded that depth, bail now. # If we've got a max_depth set and we've exceeded that depth, bail now.
if max_depth and cur_depth > max_depth: if max_depth and cur_depth > max_depth:
return None return None
index_end = index_start + len(klass._meta.fields) index_end = index_start + len(klass._meta.fields)
obj = klass(*row[index_start:index_end]) obj = klass(*row[index_start:index_end])
for f in klass._meta.fields: for f in klass._meta.fields:
@ -758,11 +758,11 @@ def fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen,
Helper function that recursively populates the select, tables and where (in Helper function that recursively populates the select, tables and where (in
place) for select_related queries. place) for select_related queries.
""" """
# If we've got a max_depth set and we've exceeded that depth, bail now. # If we've got a max_depth set and we've exceeded that depth, bail now.
if max_depth and cur_depth > max_depth: if max_depth and cur_depth > max_depth:
return None return None
qn = backend.quote_name qn = backend.quote_name
for f in opts.fields: for f in opts.fields:
if f.rel and not f.null: if f.rel and not f.null:
@ -827,6 +827,8 @@ def parse_lookup(kwarg_items, opts):
# all uses of None as a query value. # all uses of None as a query value.
if lookup_type != 'exact': if lookup_type != 'exact':
raise ValueError, "Cannot use None as a query value" raise ValueError, "Cannot use None as a query value"
elif callable(value):
value = value()
joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None) joins2, where2, params2 = lookup_inner(path, lookup_type, value, opts, opts.db_table, None)
joins.update(joins2) joins.update(joins2)

View File

@ -66,8 +66,10 @@ class CommonMiddleware(object):
path = request.get_full_path() path = request.get_full_path()
if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer): if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer):
ua = request.META.get('HTTP_USER_AGENT', '<none>') ua = request.META.get('HTTP_USER_AGENT', '<none>')
ip = request.META.get('REMOTE_ADDR', '<none>')
mail_managers("Broken %slink on %s" % ((is_internal and 'INTERNAL ' or ''), domain), mail_managers("Broken %slink on %s" % ((is_internal and 'INTERNAL ' or ''), domain),
"Referrer: %s\nRequested URL: %s\nUser agent: %s\n" % (referer, request.get_full_path(), ua)) "Referrer: %s\nRequested URL: %s\nUser agent: %s\nIP address: %s\n" \
% (referer, request.get_full_path(), ua, ip))
return response return response
# Use ETags, if requested. # Use ETags, if requested.

View File

@ -332,7 +332,9 @@ class NullBooleanField(BooleanField):
return {True: True, False: False}.get(value, None) return {True: True, False: False}.get(value, None)
class ChoiceField(Field): class ChoiceField(Field):
def __init__(self, choices=(), required=True, widget=Select, label=None, initial=None, help_text=None): widget = Select
def __init__(self, choices=(), required=True, widget=None, label=None, initial=None, help_text=None):
super(ChoiceField, self).__init__(required, widget, label, initial, help_text) super(ChoiceField, self).__init__(required, widget, label, initial, help_text)
self.choices = choices self.choices = choices
@ -364,9 +366,7 @@ class ChoiceField(Field):
class MultipleChoiceField(ChoiceField): class MultipleChoiceField(ChoiceField):
hidden_widget = MultipleHiddenInput hidden_widget = MultipleHiddenInput
widget = SelectMultiple
def __init__(self, choices=(), required=True, widget=SelectMultiple, label=None, initial=None, help_text=None):
super(MultipleChoiceField, self).__init__(choices, required, widget, label, initial, help_text)
def clean(self, value): def clean(self, value):
""" """

View File

@ -42,7 +42,10 @@ class FilterNode(Node):
def render(self, context): def render(self, context):
output = self.nodelist.render(context) output = self.nodelist.render(context)
# apply filters # apply filters
return self.filter_expr.resolve(Context({'var': output})) context.update({'var': output})
filtered = self.filter_expr.resolve(context)
context.pop()
return filtered
class FirstOfNode(Node): class FirstOfNode(Node):
def __init__(self, vars): def __init__(self, vars):
@ -991,7 +994,7 @@ def do_with(parser, token):
""" """
Add a value to the context (inside of this block) for caching and easy Add a value to the context (inside of this block) for caching and easy
access. access.
For example:: For example::
{% with person.some_sql_method as total %} {% with person.some_sql_method as total %}
@ -1000,7 +1003,7 @@ def do_with(parser, token):
""" """
bits = list(token.split_contents()) bits = list(token.split_contents())
if len(bits) != 4 or bits[2] != "as": if len(bits) != 4 or bits[2] != "as":
raise TemplateSyntaxError, "%r expected format is 'value as name'" % tagname raise TemplateSyntaxError, "%r expected format is 'value as name'" % bits[0]
var = parser.compile_filter(bits[1]) var = parser.compile_filter(bits[1])
name = bits[3] name = bits[3]
nodelist = parser.parse(('endwith',)) nodelist = parser.parse(('endwith',))

View File

@ -132,6 +132,7 @@ class RssFeed(SyndicationFeed):
handler.addQuickElement(u"category", cat) handler.addQuickElement(u"category", cat)
if self.feed['feed_copyright'] is not None: if self.feed['feed_copyright'] is not None:
handler.addQuickElement(u"copyright", self.feed['feed_copyright']) handler.addQuickElement(u"copyright", self.feed['feed_copyright'])
handler.addQuickElement(u"lastBuildDate", rfc2822_date(self.latest_post_date()).decode('ascii'))
self.write_items(handler) self.write_items(handler)
self.endChannelElement(handler) self.endChannelElement(handler)
handler.endElement(u"rss") handler.endElement(u"rss")

View File

@ -90,11 +90,18 @@ def technical_500_response(request, exc_type, exc_value, tb):
exc_type, exc_value, tb, template_info = get_template_exception_info(exc_type, exc_value, tb) exc_type, exc_value, tb, template_info = get_template_exception_info(exc_type, exc_value, tb)
frames = [] frames = []
while tb is not None: while tb is not None:
# support for __traceback_hide__ which is used by a few libraries
# to hide internal frames.
if tb.tb_frame.f_locals.get('__traceback_hide__'):
tb = tb.tb_next
continue
filename = tb.tb_frame.f_code.co_filename filename = tb.tb_frame.f_code.co_filename
function = tb.tb_frame.f_code.co_name function = tb.tb_frame.f_code.co_name
lineno = tb.tb_lineno - 1 lineno = tb.tb_lineno - 1
pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7) loader = tb.tb_frame.f_globals.get('__loader__')
if pre_context_lineno: module_name = tb.tb_frame.f_globals.get('__name__')
pre_context_lineno, pre_context, context_line, post_context = _get_lines_from_file(filename, lineno, 7, loader, module_name)
if pre_context_lineno is not None:
frames.append({ frames.append({
'tb': tb, 'tb': tb,
'filename': filename, 'filename': filename,
@ -161,24 +168,35 @@ def empty_urlconf(request):
}) })
return HttpResponseNotFound(t.render(c), mimetype='text/html') return HttpResponseNotFound(t.render(c), mimetype='text/html')
def _get_lines_from_file(filename, lineno, context_lines): def _get_lines_from_file(filename, lineno, context_lines, loader=None, module_name=None):
""" """
Returns context_lines before and after lineno from file. Returns context_lines before and after lineno from file.
Returns (pre_context_lineno, pre_context, context_line, post_context). Returns (pre_context_lineno, pre_context, context_line, post_context).
""" """
try: source = None
source = open(filename).readlines() if loader is not None:
lower_bound = max(0, lineno - context_lines) source = loader.get_source(module_name).splitlines()
upper_bound = lineno + context_lines else:
try:
pre_context = [line.strip('\n') for line in source[lower_bound:lineno]] f = open(filename)
context_line = source[lineno].strip('\n') try:
post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]] source = f.readlines()
finally:
return lower_bound, pre_context, context_line, post_context f.close()
except (OSError, IOError): except (OSError, IOError):
pass
if source is None:
return None, [], None, [] return None, [], None, []
lower_bound = max(0, lineno - context_lines)
upper_bound = lineno + context_lines
pre_context = [line.strip('\n') for line in source[lower_bound:lineno]]
context_line = source[lineno].strip('\n')
post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]]
return lower_bound, pre_context, context_line, post_context
# #
# Templates are embedded in the file so that we know the error handler will # Templates are embedded in the file so that we know the error handler will
# always work even if the template loader is broken. # always work even if the template loader is broken.
@ -314,7 +332,7 @@ TECHNICAL_500_TEMPLATE = """
</tr> </tr>
<tr> <tr>
<th>Exception Location:</th> <th>Exception Location:</th>
<td>{{ lastframe.filename }} in {{ lastframe.function }}, line {{ lastframe.lineno }}</td> <td>{{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }}</td>
</tr> </tr>
</table> </table>
</div> </div>
@ -361,7 +379,7 @@ TECHNICAL_500_TEMPLATE = """
<ul class="traceback"> <ul class="traceback">
{% for frame in frames %} {% for frame in frames %}
<li class="frame"> <li class="frame">
<code>{{ frame.filename }}</code> in <code>{{ frame.function }}</code> <code>{{ frame.filename|escape }}</code> in <code>{{ frame.function|escape }}</code>
{% if frame.context_line %} {% if frame.context_line %}
<div class="context" id="c{{ frame.id }}"> <div class="context" id="c{{ frame.id }}">

View File

@ -1,8 +1,8 @@
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template import RequestContext from django.template import loader, RequestContext
from django.http import HttpResponse, HttpResponsePermanentRedirect, HttpResponseGone from django.http import HttpResponse, HttpResponsePermanentRedirect, HttpResponseGone
def direct_to_template(request, template, extra_context={}, **kwargs): def direct_to_template(request, template, extra_context={}, mimetype=None, **kwargs):
""" """
Render a given template with any extra URL parameters in the context as Render a given template with any extra URL parameters in the context as
``{{ params }}``. ``{{ params }}``.
@ -13,7 +13,9 @@ def direct_to_template(request, template, extra_context={}, **kwargs):
dictionary[key] = value() dictionary[key] = value()
else: else:
dictionary[key] = value dictionary[key] = value
return render_to_response(template, dictionary, context_instance=RequestContext(request)) c = RequestContext(request, dictionary)
t = loader.get_template(template)
return HttpResponse(t.render(c), mimetype=mimetype)
def redirect_to(request, url, **kwargs): def redirect_to(request, url, **kwargs):
""" """

View File

@ -24,7 +24,7 @@ admin
The automatic Django administrative interface. For more information, see The automatic Django administrative interface. For more information, see
`Tutorial 2`_. `Tutorial 2`_.
.. _Tutorial 2: ../tutorial2/ .. _Tutorial 2: ../tutorial02/
auth auth
==== ====

View File

@ -101,7 +101,7 @@ change:
.. _caching: ../cache/ .. _caching: ../cache/
.. _custom template tags and libraries: ../templates_python/ .. _custom template tags and libraries: ../templates_python/
.. _database lookup: ../db_api/ .. _database lookup: ../db_api/
.. _django-admin utility: ../django_admin/ .. _django-admin utility: ../django-admin/
.. _fastcgi integration: ../fastcgi/ .. _fastcgi integration: ../fastcgi/
.. _flatpages: ../flatpages/ .. _flatpages: ../flatpages/
.. _generic views: ../generic_views/ .. _generic views: ../generic_views/

View File

@ -69,9 +69,12 @@ For now, InnoDB is probably your best choice.
MySQLdb MySQLdb
------- -------
`MySQLdb`_ is the Python interface to MySQL. 1.2.1 is the first version that `MySQLdb`_ is the Python interface to MySQL. Version 1.2.1p2 or later is
has support for MySQL 4.1 and newer. If you are trying to use an older version required for full MySQL support in Django. Earlier versions will not work with
of MySQL, then 1.2.0 *might* work for you. the ``mysql`` backend.
If you are trying to use an older version of MySQL and the ``mysql_old``
backend, then 1.2.0 *might* work for you.
.. _MySQLdb: http://sourceforge.net/projects/mysql-python .. _MySQLdb: http://sourceforge.net/projects/mysql-python

56
docs/databrowse.txt Normal file
View File

@ -0,0 +1,56 @@
==========
Databrowse
==========
Databrowse is a Django application that lets you browse your data.
As the Django admin dynamically creates an admin interface by introspecting
your models, Databrowse dynamically creates a rich, browsable Web site by
introspecting your models.
.. admonition:: Note
Databrowse is **very** new and is currently under active development. It
may change substantially before the next Django release.
With that said, it's easy to use, and it doesn't require writing any
code. So you can play around with it today, with very little investment in
time or coding.
How to use Databrowse
=====================
1. Point Django at the default Databrowse templates. There are two ways to
do this:
* Add ``'django.contrib.databrowse'`` to your ``INSTALLED_APPS``
setting. This will work if your ``TEMPLATE_LOADERS`` setting includes
the ``app_directories`` template loader (which is the case by
default). See the `template loader docs`_ for more.
* Otherwise, determine the full filesystem path to the
``django/contrib/databrowse/templates`` directory, and add that
directory to your ``TEMPLATE_DIRS`` setting.
2. Register a number of models with the Databrowse site::
from django.contrib import databrowse
databrowse.site.register(SomeModel)
databrowse.site.register(SomeOtherModel)
Note that you should register the model *classes*, not instances.
It doesn't matter where you put this, as long as it gets executed at
some point. A good place for it is in your URLconf file (``urls.py``).
3. Add the following line to your URLconf::
(r'^databrowse/(.*)', databrowse.site.root),
The prefix doesn't matter -- you can use ``databrowse/`` or ``db/`` or
whatever you'd like.
4. Run the Django server and visit ``/databrowse/`` in your browser.
.. _template loader docs: ../templates_python/#loader-types

View File

@ -47,16 +47,18 @@ Fedora
------ ------
A Django package is available for `Fedora Linux`_, in the "Fedora Extras" A Django package is available for `Fedora Linux`_, in the "Fedora Extras"
repository. The `current Fedora package`_ is based on Django 0.95.1, and can be repository. The `current Fedora package`_ is based on Django 0.96, and can be
installed by typing ``yum install Django``. installed by typing ``yum install Django``. The previous link is for the i386
binary. Users of other architectures should be able to use that as a starting
point to find their preferred version.
.. _Fedora Linux: http://fedora.redhat.com/ .. _Fedora Linux: http://fedora.redhat.com/
.. _current Fedora package: http://fedoraproject.org/extras/6/i386/repodata/repoview/Django-0-0.95.1-1.fc6.html .. _current Fedora package: http://download.fedora.redhat.com/pub/fedora/linux/extras/6/i386/repoview/Django.html
Gentoo 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.96.
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/

View File

@ -61,7 +61,7 @@ Prints the admin-index template snippet for the given appnames.
Use admin-index template snippets if you want to customize the look and feel of Use admin-index template snippets if you want to customize the look and feel of
your admin's index page. See `Tutorial 2`_ for more information. your admin's index page. See `Tutorial 2`_ for more information.
.. _Tutorial 2: ../tutorial2/ .. _Tutorial 2: ../tutorial02/
createcachetable [tablename] createcachetable [tablename]
---------------------------- ----------------------------
@ -109,7 +109,8 @@ application(s).
By default, the database will be dumped in JSON format. If you want the output By default, the database will be dumped in JSON format. If you want the output
to be in another format, use the ``--format`` option (e.g., ``format=xml``). to be in another format, use the ``--format`` option (e.g., ``format=xml``).
You may specify any Django serialization backend (including any user specified You may specify any Django serialization backend (including any user specified
serialization backends named in the ``SERIALIZATION_MODULES`` setting). serialization backends named in the ``SERIALIZATION_MODULES`` setting). The
``--indent`` option can be used to pretty-print the output.
If no application name is provided, all installed applications will be dumped. If no application name is provided, all installed applications will be dumped.
@ -220,6 +221,8 @@ one fixture can reference data in another fixture. If the database backend
supports row-level constraints, these constraints will be checked at the supports row-level constraints, these constraints will be checked at the
end of the transaction. end of the transaction.
The ``dumpdata`` command can be used to generate input for ``loaddata``.
.. admonition:: MySQL and Fixtures .. admonition:: MySQL and Fixtures
Unfortunately, MySQL isn't capable of completely supporting all the Unfortunately, MySQL isn't capable of completely supporting all the
@ -329,7 +332,7 @@ sqlall [appname appname ...]
Prints the CREATE TABLE and initial-data SQL statements for the given appnames. Prints the CREATE TABLE and initial-data SQL statements for the given appnames.
Refer to the description of ``sqlinitialdata`` for an explanation of how to Refer to the description of ``sqlcustom`` for an explanation of how to
specify initial data. specify initial data.
sqlclear [appname appname ...] sqlclear [appname appname ...]

View File

@ -278,7 +278,7 @@ How do I get started?
.. _`Download the code`: http://www.djangoproject.com/download/ .. _`Download the code`: http://www.djangoproject.com/download/
.. _`installation guide`: ../install/ .. _`installation guide`: ../install/
.. _tutorial: ../tutorial1/ .. _tutorial: ../tutorial01/
.. _documentation: ../ .. _documentation: ../
.. _ask questions: http://www.djangoproject.com/community/ .. _ask questions: http://www.djangoproject.com/community/

View File

@ -44,7 +44,7 @@ simple weblog app that drives the blog on djangoproject.com::
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', 'archive_day', info_dict), (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', 'archive_day', info_dict),
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'archive_month', info_dict), (r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'archive_month', info_dict),
(r'^(?P<year>\d{4})/$', 'archive_year', info_dict), (r'^(?P<year>\d{4})/$', 'archive_year', info_dict),
(r'^/?$', 'archive_index', info_dict), (r'^$', 'archive_index', info_dict),
) )
As you can see, this URLconf defines a few options in ``info_dict``. As you can see, this URLconf defines a few options in ``info_dict``.

View File

@ -58,6 +58,7 @@ installed.
If you're on Windows, check out the unofficial `compiled Windows version`_. If you're on Windows, check out the unofficial `compiled Windows version`_.
* If you're using MySQL, you'll need MySQLdb_, version 1.2.1p2 or higher. * If you're using MySQL, you'll need MySQLdb_, version 1.2.1p2 or higher.
You will also want to read the database-specific notes for the `MySQL backend`_.
* If you're using SQLite, you'll need pysqlite_. Use version 2.0.3 or higher. * If you're using SQLite, you'll need pysqlite_. Use version 2.0.3 or higher.
@ -69,6 +70,34 @@ installed.
.. _MySQLdb: http://sourceforge.net/projects/mysql-python .. _MySQLdb: http://sourceforge.net/projects/mysql-python
.. _SQLite: http://www.sqlite.org/ .. _SQLite: http://www.sqlite.org/
.. _pysqlite: http://initd.org/tracker/pysqlite .. _pysqlite: http://initd.org/tracker/pysqlite
.. _MySQL backend: ../databases/
Remove any old versions of Django
=================================
If you are upgrading your installation of Django from a previous version,
you will need to uninstall the old Django version before installing the
new version.
If you installed Django using ``setup.py install``, uninstalling
is as simple as deleting the ``django`` directory from your Python
``site-packages``.
If you installed Django from a Python Egg, remove the Django ``.egg` file,
and remove the reference to the egg in the file named ``easy-install.pth``.
This file should also be located in your ``site-packages`` directory.
.. admonition:: Where are my ``site-packages`` stored?
The location of the ``site-packages`` directory depends on the operating
system, and the location in which Python was installed. However, the
following locations are common:
* If you're using Linux: ``/usr/lib/python2.X/site-packages``
* If you're using Windows: ``C:\Python2.X\lib\site-packages``
* If you're using MacOSX: ``/Library/Python2.X/site-packages``
Install the Django code Install the Django code
======================= =======================

View File

@ -9,7 +9,7 @@ utilities to automate as much of this process as possible.
This document assumes you know the Django basics, as covered in the This document assumes you know the Django basics, as covered in the
`official tutorial`_. `official tutorial`_.
.. _official tutorial: ../tutorial1/ .. _official tutorial: ../tutorial01/
Give Django your database parameters Give Django your database parameters
==================================== ====================================
@ -52,7 +52,7 @@ Once you've cleaned up your models, name the file ``models.py`` and put it in
the Python package that holds your app. Then add the app to your the Python package that holds your app. Then add the app to your
``INSTALLED_APPS`` setting. ``INSTALLED_APPS`` setting.
.. _django-admin.py documentation: ../django_admin/ .. _django-admin.py documentation: ../django-admin/
Install the core Django tables Install the core Django tables
============================== ==============================

View File

@ -21,7 +21,7 @@ A companion to this document is the `official repository of model examples`_.
(In the Django source distribution, these examples are in the (In the Django source distribution, these examples are in the
``tests/modeltests`` directory.) ``tests/modeltests`` directory.)
.. _Database API reference: http://www.djangoproject.com/documentation/db_api/ .. _Database API reference: ../db-api/
.. _official repository of model examples: http://www.djangoproject.com/documentation/models/ .. _official repository of model examples: http://www.djangoproject.com/documentation/models/
Quick example Quick example
@ -57,7 +57,7 @@ Some technical notes:
syntax, but it's worth noting Django uses SQL tailored to the database syntax, but it's worth noting Django uses SQL tailored to the database
backend specified in your `settings file`_. backend specified in your `settings file`_.
.. _settings file: http://www.djangoproject.com/documentation/settings/ .. _settings file: ../settings/
Fields Fields
====== ======
@ -501,7 +501,7 @@ For each model field that has ``choices`` set, Django will add a method to
retrieve the human-readable name for the field's current value. See retrieve the human-readable name for the field's current value. See
`get_FOO_display`_ in the database API documentation. `get_FOO_display`_ in the database API documentation.
.. _get_FOO_display: ../db_api/#get-foo-display .. _get_FOO_display: ../db-api/#get-foo-display
Finally, note that choices can be any iterable object -- not necessarily a Finally, note that choices can be any iterable object -- not necessarily a
list or tuple. This lets you construct choices dynamically. But if you find list or tuple. This lets you construct choices dynamically. But if you find
@ -626,7 +626,7 @@ that takes the parameters ``field_data, all_data`` and raises
Django comes with quite a few validators. They're in ``django.core.validators``. Django comes with quite a few validators. They're in ``django.core.validators``.
.. _validator docs: http://www.djangoproject.com/documentation/forms/#validators .. _validator docs: ../forms/#validators
Verbose field names Verbose field names
------------------- -------------------
@ -734,10 +734,10 @@ relationship should work. All are optional:
``limit_choices_to`` A dictionary of lookup arguments and values (see ``limit_choices_to`` A dictionary of lookup arguments and values (see
the `Database API reference`_) that limit the the `Database API reference`_) that limit the
available admin choices for this object. Use this available admin choices for this object. Use this
with ``models.LazyDate`` to limit choices of objects with functions from the Python ``datetime`` module
by date. For example:: to limit choices of objects by date. For example::
limit_choices_to = {'pub_date__lte': models.LazyDate()} limit_choices_to = {'pub_date__lte': datetime.now}
only allows the choice of related objects with a only allows the choice of related objects with a
``pub_date`` before the current date/time to be ``pub_date`` before the current date/time to be
@ -792,8 +792,8 @@ relationship should work. All are optional:
the related object. the related object.
======================= ============================================================ ======================= ============================================================
.. _`Database API reference`: http://www.djangoproject.com/documentation/db_api/ .. _`Database API reference`: ../db-api/
.. _related objects documentation: http://www.djangoproject.com/documentation/db_api/#related-objects .. _related objects documentation: ../db-api/#related-objects
Many-to-many relationships Many-to-many relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -963,7 +963,7 @@ Example::
See the `docs for latest()`_ for more. See the `docs for latest()`_ for more.
.. _docs for latest(): http://www.djangoproject.com/documentation/db_api/#latest-field-name-none .. _docs for latest(): ../db-api/#latest-field-name-none
``order_with_respect_to`` ``order_with_respect_to``
------------------------- -------------------------
@ -1397,7 +1397,7 @@ if one of the ``list_display`` fields is a ``ForeignKey``.
For more on ``select_related()``, see `the select_related() docs`_. For more on ``select_related()``, see `the select_related() docs`_.
.. _the select_related() docs: http://www.djangoproject.com/documentation/db_api/#select-related .. _the select_related() docs: ../db-api/#select-related
``ordering`` ``ordering``
------------ ------------
@ -1502,7 +1502,7 @@ The way ``Manager`` classes work is documented in the `Retrieving objects`_
section of the database API docs, but this section specifically touches on section of the database API docs, but this section specifically touches on
model options that customize ``Manager`` behavior. model options that customize ``Manager`` behavior.
.. _Retrieving objects: http://www.djangoproject.com/documentation/db_api/#retrieving-objects .. _Retrieving objects: ../db-api/#retrieving-objects
Manager names Manager names
------------- -------------
@ -1825,7 +1825,7 @@ just the ``where``, ``tables`` and ``params`` arguments to the standard lookup
API. See `Other lookup options`_. API. See `Other lookup options`_.
.. _Python DB-API: http://www.python.org/peps/pep-0249.html .. _Python DB-API: http://www.python.org/peps/pep-0249.html
.. _Other lookup options: http://www.djangoproject.com/documentation/db_api/#extra-params-select-where-tables .. _Other lookup options: ../db-api/#extra-params-select-where-tables
Overriding default model methods Overriding default model methods
-------------------------------- --------------------------------
@ -1858,7 +1858,7 @@ You can also prevent saving::
else: else:
super(Blog, self).save() # Call the "real" save() method. super(Blog, self).save() # Call the "real" save() method.
.. _database API docs: http://www.djangoproject.com/documentation/db_api/ .. _database API docs: ../db-api/
Models across files Models across files
=================== ===================
@ -1915,7 +1915,7 @@ Each SQL file, if given, is expected to contain valid SQL. The SQL files are
piped directly into the database after all of the models' table-creation piped directly into the database after all of the models' table-creation
statements have been executed. statements have been executed.
The SQL files are read by the ``sqlinitialdata``, ``sqlreset``, ``sqlall`` and The SQL files are read by the ``sqlcustom``, ``sqlreset``, ``sqlall`` and
``reset`` commands in ``manage.py``. Refer to the `manage.py documentation`_ ``reset`` commands in ``manage.py``. Refer to the `manage.py documentation`_
for more information. for more information.
@ -1924,7 +1924,7 @@ order in which they're executed. The only thing you can assume is that, by the
time your custom data files are executed, all the database tables already will time your custom data files are executed, all the database tables already will
have been created. have been created.
.. _`manage.py documentation`: http://www.djangoproject.com/documentation/django_admin/#sqlinitialdata-appname-appname .. _`manage.py documentation`: ../django-admin/#sqlcustom-appname-appname
Database-backend-specific SQL data Database-backend-specific SQL data
---------------------------------- ----------------------------------

View File

@ -297,5 +297,5 @@ The next obvious steps are for you to `download Django`_, read `the tutorial`_
and join `the community`_. Thanks for your interest! and join `the community`_. Thanks for your interest!
.. _download Django: http://www.djangoproject.com/download/ .. _download Django: http://www.djangoproject.com/download/
.. _the tutorial: http://www.djangoproject.com/documentation/tutorial1/ .. _the tutorial: http://www.djangoproject.com/documentation/tutorial01/
.. _the community: http://www.djangoproject.com/community/ .. _the community: http://www.djangoproject.com/community/

View File

@ -59,7 +59,7 @@ Use the ``--settings`` command-line argument to specify the settings manually::
django-admin.py runserver --settings=mysite.settings django-admin.py runserver --settings=mysite.settings
.. _django-admin.py: ../django_admin/ .. _django-admin.py: ../django-admin/
On the server (mod_python) On the server (mod_python)
-------------------------- --------------------------
@ -102,7 +102,7 @@ between the current settings file and Django's default settings.
For more, see the `diffsettings documentation`_. For more, see the `diffsettings documentation`_.
.. _diffsettings documentation: ../django_admin/#diffsettings .. _diffsettings documentation: ../django-admin/#diffsettings
Using settings in Python code Using settings in Python code
============================= =============================
@ -462,7 +462,7 @@ A tuple of strings designating all applications that are enabled in this Django
installation. Each string should be a full Python path to a Python package that installation. Each string should be a full Python path to a Python package that
contains a Django application, as created by `django-admin.py startapp`_. contains a Django application, as created by `django-admin.py startapp`_.
.. _django-admin.py startapp: ../django_admin/#startapp-appname .. _django-admin.py startapp: ../django-admin/#startapp-appname
INTERNAL_IPS INTERNAL_IPS
------------ ------------

View File

@ -114,6 +114,9 @@ Note:
`object-relational mapper`_, ``items()`` doesn't have to return model `object-relational mapper`_, ``items()`` doesn't have to return model
instances. Although you get a few bits of functionality "for free" by instances. Although you get a few bits of functionality "for free" by
using Django models, ``items()`` can return any type of object you want. using Django models, ``items()`` can return any type of object you want.
* If you're creating an Atom feed, rather than an RSS feed, set the
``subtitle`` attribute instead of the ``description`` attribute. See
`Publishing Atom and RSS feeds in tandem`_, later, for an example.
One thing's left to do. In an RSS feed, each ``<item>`` has a ``<title>``, One thing's left to do. In an RSS feed, each ``<item>`` has a ``<title>``,
``<link>`` and ``<description>``. We need to tell the framework what data to ``<link>`` and ``<description>``. We need to tell the framework what data to
@ -298,7 +301,7 @@ Publishing Atom and RSS feeds in tandem
--------------------------------------- ---------------------------------------
Some developers like to make available both Atom *and* RSS versions of their Some developers like to make available both Atom *and* RSS versions of their
feeds. That's easy to do with Django: Just create a subclass of your ``feed`` feeds. That's easy to do with Django: Just create a subclass of your ``Feed``
class and set the ``feed_type`` to something different. Then update your class and set the ``feed_type`` to something different. Then update your
URLconf to add the extra versions. URLconf to add the extra versions.
@ -318,6 +321,20 @@ Here's a full example::
class AtomSiteNewsFeed(RssSiteNewsFeed): class AtomSiteNewsFeed(RssSiteNewsFeed):
feed_type = Atom1Feed feed_type = Atom1Feed
subtitle = RssSiteNewsFeed.description
.. Note::
In this example, the RSS feed uses a ``description`` while the Atom feed
uses a ``subtitle``. That's because Atom feeds don't provide for a
feed-level "description," but they *do* provide for a "subtitle."
If you provide a ``description`` in your ``Feed`` class, Django will *not*
automatically put that into the ``subtitle`` element, because a subtitle
and description are not necessarily the same thing. Instead, you should
define a ``subtitle`` attribute.
In the above example, we simply set the Atom feed's ``subtitle`` to the
RSS feed's ``description``, because it's quite short already.
And the accompanying URLconf:: And the accompanying URLconf::

View File

@ -702,11 +702,11 @@ Example::
Note that you can backslash-escape a format string if you want to use the Note that you can backslash-escape a format string if you want to use the
"raw" value. In this example, "f" is backslash-escaped, because otherwise "raw" value. In this example, "f" is backslash-escaped, because otherwise
"f" is a format string that displays the time. The "o" doesn't need to be "f" is a format string that displays the time. The "o" doesn't need to be
escaped, because it's not a format character.:: escaped, because it's not a format character::
It is the {% now "jS o\f F" %} It is the {% now "jS o\f F" %}
(Displays "It is the 4th of September" %} This would display as "It is the 4th of September".
regroup regroup
~~~~~~~ ~~~~~~~
@ -1293,3 +1293,11 @@ A collection of template filters that implement these common markup languages:
* Textile * Textile
* Markdown * Markdown
* ReST (ReStructured Text) * ReST (ReStructured Text)
django.contrib.webdesign
------------------------
A collection of template tags that can be useful while designing a website,
such as a generator of Lorem Ipsum text. See the `webdesign documentation`_.
.. _webdesign documentation: ../webdesign/

View File

@ -1020,7 +1020,7 @@ The ``takes_context`` parameter defaults to ``False``. When it's set to *True*,
the tag is passed the context object, as in this example. That's the only the tag is passed the context object, as in this example. That's the only
difference between this case and the previous ``inclusion_tag`` example. difference between this case and the previous ``inclusion_tag`` example.
.. _tutorials: ../tutorial1/#creating-models .. _tutorials: ../tutorial01/#creating-models
Setting a variable in the context Setting a variable in the context
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -404,7 +404,7 @@ In this example, any JSON fixture called ``mammals``, and any fixture
named ``birds`` will be installed. See the documentation on named ``birds`` will be installed. See the documentation on
`loading fixtures`_ for more details on defining and installing fixtures. `loading fixtures`_ for more details on defining and installing fixtures.
.. _`loading fixtures`: ../django_admin/#loaddata-fixture-fixture .. _`loading fixtures`: ../django-admin/#loaddata-fixture-fixture
This flush/load procedure is repeated for each test in the test case, so you This flush/load procedure is repeated for each test in the test case, so you
can be certain that the outcome of a test will not be affected by can be certain that the outcome of a test will not be affected by

View File

@ -124,7 +124,7 @@ It worked!
Full docs for the development server are at `django-admin documentation`_. Full docs for the development server are at `django-admin documentation`_.
.. _django-admin documentation: ../django_admin/ .. _django-admin documentation: ../django-admin/
Database setup Database setup
-------------- --------------
@ -382,7 +382,7 @@ If you're interested, also run the following commands:
statements for this app. statements for this app.
* ``python manage.py sqlall polls`` -- A combination of all the SQL from * ``python manage.py sqlall polls`` -- A combination of all the SQL from
the 'sql', 'sqlinitialdata', and 'sqlindexes' commands. the 'sql', 'sqlcustom', and 'sqlindexes' commands.
Looking at the output of those commands can help you understand what's actually Looking at the output of those commands can help you understand what's actually
happening under the hood. happening under the hood.
@ -400,7 +400,7 @@ as you like, and it will only ever create the tables that don't exist.
Read the `django-admin.py documentation`_ for full information on what the Read the `django-admin.py documentation`_ for full information on what the
``manage.py`` utility can do. ``manage.py`` utility can do.
.. _django-admin.py documentation: ../django_admin/ .. _django-admin.py documentation: ../django-admin/
Playing with the API Playing with the API
==================== ====================
@ -578,4 +578,4 @@ When you're comfortable with the API, read `part 2 of this tutorial`_ to get
Django's automatic admin working. Django's automatic admin working.
.. _Database API reference: ../db_api/ .. _Database API reference: ../db_api/
.. _part 2 of this tutorial: ../tutorial2/ .. _part 2 of this tutorial: ../tutorial02/

View File

@ -5,7 +5,7 @@ Writing your first Django app, part 2
This tutorial begins where `Tutorial 1`_ left off. We're continuing the Web-poll This tutorial begins where `Tutorial 1`_ left off. We're continuing the Web-poll
application and will focus on Django's automatically-generated admin site. application and will focus on Django's automatically-generated admin site.
.. _Tutorial 1: ../tutorial1/ .. _Tutorial 1: ../tutorial01/
.. admonition:: Philosophy .. admonition:: Philosophy
@ -61,8 +61,8 @@ tutorial, remember?) You should see the Django admin index page:
:alt: Django admin index page :alt: Django admin index page
:target: http://media.djangoproject.com/img/doc/tutorial/admin02.png :target: http://media.djangoproject.com/img/doc/tutorial/admin02.png
By default, you should see two types of editable content: groups and users. You should see a few other types of editable content, including groups, users
These are core features Django ships with by default. and sites. These are core features Django ships with by default.
.. _"I can't log in" questions: ../faq/#the-admin-site .. _"I can't log in" questions: ../faq/#the-admin-site
@ -434,4 +434,4 @@ When you're comfortable with the admin site, read `part 3 of this tutorial`_ to
start working on public poll views. start working on public poll views.
.. _Django admin CSS guide: ../admin_css/ .. _Django admin CSS guide: ../admin_css/
.. _part 3 of this tutorial: ../tutorial3/ .. _part 3 of this tutorial: ../tutorial03/

View File

@ -5,7 +5,7 @@ Writing your first Django app, part 3
This tutorial begins where `Tutorial 2`_ left off. We're continuing the Web-poll This tutorial begins where `Tutorial 2`_ left off. We're continuing the Web-poll
application and will focus on creating the public interface -- "views." application and will focus on creating the public interface -- "views."
.. _Tutorial 2: ../tutorial2/ .. _Tutorial 2: ../tutorial02/
Philosophy Philosophy
========== ==========
@ -463,4 +463,4 @@ All the poll app cares about is its relative URLs, not its absolute URLs.
When you're comfortable with writing views, read `part 4 of this tutorial`_ to When you're comfortable with writing views, read `part 4 of this tutorial`_ to
learn about simple form processing and generic views. learn about simple form processing and generic views.
.. _part 4 of this tutorial: ../tutorial4/ .. _part 4 of this tutorial: ../tutorial04/

View File

@ -256,4 +256,4 @@ installments:
* Advanced admin features: Permissions * Advanced admin features: Permissions
* Advanced admin features: Custom JavaScript * Advanced admin features: Custom JavaScript
.. _Tutorial 3: ../tutorial3/ .. _Tutorial 3: ../tutorial03/

View File

@ -7,6 +7,13 @@ class Animal(models.Model):
def __str__(self): def __str__(self):
return self.common_name return self.common_name
class Plant(models.Model):
name = models.CharField(maxlength=150)
class Meta:
# For testing when upper case letter in app name; regression for #4057
db_table = "Fixtures_regress_plant"
__test__ = {'API_TESTS':""" __test__ = {'API_TESTS':"""
>>> from django.core import management >>> from django.core import management

View File

@ -193,7 +193,7 @@ as its choices.
<option value="CA">California</option> <option value="CA">California</option>
<option value="CO">Colorado</option> <option value="CO">Colorado</option>
<option value="CT">Connecticut</option> <option value="CT">Connecticut</option>
<option value="DE">Deleware</option> <option value="DE">Delaware</option>
<option value="DC">District of Columbia</option> <option value="DC">District of Columbia</option>
<option value="FM">Federated States of Micronesia</option> <option value="FM">Federated States of Micronesia</option>
<option value="FL">Florida</option> <option value="FL">Florida</option>
@ -633,7 +633,7 @@ u'00100'
>>> f.clean(' 00100') >>> f.clean(' 00100')
Traceback (most recent call last): Traceback (most recent call last):
... ...
ValidationError: [u'Enter a zip code in the format XXXXX.'] ValidationError: [u'Enter a valid zip code.']
# ITRegionSelect ############################################################# # ITRegionSelect #############################################################
@ -642,6 +642,46 @@ ValidationError: [u'Enter a zip code in the format XXXXX.']
>>> w.render('regions', 'PMN') >>> w.render('regions', 'PMN')
u'<select name="regions">\n<option value="ABR">Abruzzo</option>\n<option value="BAS">Basilicata</option>\n<option value="CAL">Calabria</option>\n<option value="CAM">Campania</option>\n<option value="EMR">Emilia-Romagna</option>\n<option value="FVG">Friuli-Venezia Giulia</option>\n<option value="LAZ">Lazio</option>\n<option value="LIG">Liguria</option>\n<option value="LOM">Lombardia</option>\n<option value="MAR">Marche</option>\n<option value="MOL">Molise</option>\n<option value="PMN" selected="selected">Piemonte</option>\n<option value="PUG">Puglia</option>\n<option value="SAR">Sardegna</option>\n<option value="SIC">Sicilia</option>\n<option value="TOS">Toscana</option>\n<option value="TAA">Trentino-Alto Adige</option>\n<option value="UMB">Umbria</option>\n<option value="VAO">Valle d\u2019Aosta</option>\n<option value="VEN">Veneto</option>\n</select>' u'<select name="regions">\n<option value="ABR">Abruzzo</option>\n<option value="BAS">Basilicata</option>\n<option value="CAL">Calabria</option>\n<option value="CAM">Campania</option>\n<option value="EMR">Emilia-Romagna</option>\n<option value="FVG">Friuli-Venezia Giulia</option>\n<option value="LAZ">Lazio</option>\n<option value="LIG">Liguria</option>\n<option value="LOM">Lombardia</option>\n<option value="MAR">Marche</option>\n<option value="MOL">Molise</option>\n<option value="PMN" selected="selected">Piemonte</option>\n<option value="PUG">Puglia</option>\n<option value="SAR">Sardegna</option>\n<option value="SIC">Sicilia</option>\n<option value="TOS">Toscana</option>\n<option value="TAA">Trentino-Alto Adige</option>\n<option value="UMB">Umbria</option>\n<option value="VAO">Valle d\u2019Aosta</option>\n<option value="VEN">Veneto</option>\n</select>'
# ITSocialSecurityNumberField #################################################
>>> from django.contrib.localflavor.it.forms import ITSocialSecurityNumberField
>>> f = ITSocialSecurityNumberField()
>>> f.clean('LVSGDU99T71H501L')
u'LVSGDU99T71H501L'
>>> f.clean('LBRRME11A01L736W')
u'LBRRME11A01L736W'
>>> f.clean('lbrrme11a01l736w')
u'LBRRME11A01L736W'
>>> f.clean('LBR RME 11A01 L736W')
u'LBRRME11A01L736W'
>>> f.clean('LBRRME11A01L736A')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid Social Security number.']
>>> f.clean('%BRRME11A01L736W')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid Social Security number.']
# ITVatNumberField ###########################################################
>>> from django.contrib.localflavor.it.forms import ITVatNumberField
>>> f = ITVatNumberField()
>>> f.clean('07973780013')
u'07973780013'
>>> f.clean('7973780013')
u'07973780013'
>>> f.clean(7973780013)
u'07973780013'
>>> f.clean('07973780014')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid VAT number.']
>>> f.clean('A7973780013')
Traceback (most recent call last):
...
ValidationError: [u'Enter a valid VAT number.']
# FIZipCodeField ############################################################# # FIZipCodeField #############################################################
FIZipCodeField validates that the data is a valid FI zipcode. FIZipCodeField validates that the data is a valid FI zipcode.

View File

@ -265,6 +265,7 @@ class Templates(unittest.TestCase):
'filter01': ('{% filter upper %}{% endfilter %}', {}, ''), 'filter01': ('{% filter upper %}{% endfilter %}', {}, ''),
'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'), 'filter02': ('{% filter upper %}django{% endfilter %}', {}, 'DJANGO'),
'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'), 'filter03': ('{% filter upper|lower %}django{% endfilter %}', {}, 'django'),
'filter04': ('{% filter cut:remove %}djangospam{% endfilter %}', {'remove': 'spam'}, 'django'),
### FIRSTOF TAG ########################################################### ### FIRSTOF TAG ###########################################################
'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''), 'firstof01': ('{% firstof a b c %}', {'a':0,'b':0,'c':0}, ''),
@ -660,6 +661,9 @@ class Templates(unittest.TestCase):
'with01': ('{% with dict.key as key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, '50'), 'with01': ('{% with dict.key as key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, '50'),
'with02': ('{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}', {'dict': {'key':50}}, ('50-50-50', 'INVALID50-50-50INVALID')), 'with02': ('{{ key }}{% with dict.key as key %}{{ key }}-{{ dict.key }}-{{ key }}{% endwith %}{{ key }}', {'dict': {'key':50}}, ('50-50-50', 'INVALID50-50-50INVALID')),
'with-error01': ('{% with dict.key xx key %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError),
'with-error02': ('{% with dict.key as %}{{ key }}{% endwith %}', {'dict': {'key':50}}, template.TemplateSyntaxError),
### NOW TAG ######################################################## ### NOW TAG ########################################################
# Simple case # Simple case
'now01' : ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)), 'now01' : ('{% now "j n Y"%}', {}, str(datetime.now().day) + ' ' + str(datetime.now().month) + ' ' + str(datetime.now().year)),