mirror of
https://github.com/django/django.git
synced 2025-07-04 01:39:20 +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:
parent
349bf5a355
commit
5860a5a4be
9
AUTHORS
9
AUTHORS
@ -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
|
||||||
|
@ -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 *
|
||||||
|
@ -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')),
|
||||||
|
Binary file not shown.
@ -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
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ko/LC_MESSAGES/django.mo
Normal file
BIN
django/conf/locale/ko/LC_MESSAGES/django.mo
Normal file
Binary file not shown.
2735
django/conf/locale/ko/LC_MESSAGES/django.po
Normal file
2735
django/conf/locale/ko/LC_MESSAGES/django.po
Normal file
File diff suppressed because it is too large
Load Diff
BIN
django/conf/locale/ko/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/ko/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
118
django/conf/locale/ko/LC_MESSAGES/djangojs.po
Normal file
118
django/conf/locale/ko/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2007-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 "내일"
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -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
|
||||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -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 "Vybrať 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 "Vybrať č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šiť"
|
||||||
|
|
||||||
#: 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"
|
||||||
|
|
||||||
|
BIN
django/conf/locale/sl/LC_MESSAGES/djangojs.mo
Normal file
BIN
django/conf/locale/sl/LC_MESSAGES/djangojs.mo
Normal file
Binary file not shown.
107
django/conf/locale/sl/LC_MESSAGES/djangojs.po
Normal file
107
django/conf/locale/sl/LC_MESSAGES/djangojs.po
Normal 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"
|
||||||
|
|
@ -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 */
|
||||||
|
@ -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)
|
||||||
|
1
django/contrib/databrowse/__init__.py
Normal file
1
django/contrib/databrowse/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from django.contrib.databrowse.sites import DatabrowsePlugin, ModelDatabrowse, DatabrowseSite, site
|
192
django/contrib/databrowse/datastructures.py
Normal file
192
django/contrib/databrowse/datastructures.py
Normal 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
|
0
django/contrib/databrowse/plugins/__init__.py
Normal file
0
django/contrib/databrowse/plugins/__init__.py
Normal file
84
django/contrib/databrowse/plugins/calendars.py
Normal file
84
django/contrib/databrowse/plugins/calendars.py
Normal 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))
|
72
django/contrib/databrowse/plugins/fieldchoices.py
Normal file
72
django/contrib/databrowse/plugins/fieldchoices.py
Normal 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})
|
14
django/contrib/databrowse/plugins/objects.py
Normal file
14
django/contrib/databrowse/plugins/objects.py
Normal 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})
|
148
django/contrib/databrowse/sites.py
Normal file
148
django/contrib/databrowse/sites.py
Normal 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()}
|
58
django/contrib/databrowse/templates/databrowse/base.html
Normal file
58
django/contrib/databrowse/templates/databrowse/base.html
Normal 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>
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
@ -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 %}
|
21
django/contrib/databrowse/templates/databrowse/homepage.html
Normal file
21
django/contrib/databrowse/templates/databrowse/homepage.html
Normal 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 →</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -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 %}
|
@ -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 %}
|
20
django/contrib/databrowse/urls.py
Normal file
20
django/contrib/databrowse/urls.py
Normal 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),
|
||||||
|
)
|
23
django/contrib/databrowse/views.py
Normal file
23
django/contrib/databrowse/views.py
Normal 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})
|
@ -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)
|
||||||
|
40
django/contrib/localflavor/it/util.py
Normal file
40
django/contrib/localflavor/it/util.py
Normal 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)
|
@ -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',
|
||||||
|
@ -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(),
|
||||||
|
@ -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):
|
||||||
|
@ -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]"
|
||||||
|
|
||||||
|
@ -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',
|
||||||
|
@ -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')
|
||||||
|
@ -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')
|
||||||
|
@ -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)
|
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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):
|
||||||
@ -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',))
|
||||||
|
@ -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")
|
||||||
|
@ -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 }}">
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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
|
||||||
====
|
====
|
||||||
|
@ -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/
|
||||||
|
@ -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
56
docs/databrowse.txt
Normal 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
|
@ -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/
|
||||||
|
@ -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 ...]
|
||||||
|
@ -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/
|
||||||
|
|
||||||
|
@ -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``.
|
||||||
|
@ -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
|
||||||
=======================
|
=======================
|
||||||
|
@ -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
|
||||||
==============================
|
==============================
|
||||||
|
@ -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
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
@ -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/
|
||||||
|
@ -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
|
||||||
------------
|
------------
|
||||||
|
@ -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::
|
||||||
|
|
||||||
|
@ -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/
|
||||||
|
@ -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
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -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
|
||||||
|
@ -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/
|
||||||
|
@ -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/
|
||||||
|
@ -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/
|
||||||
|
@ -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/
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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)),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user